Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4884c0b
added ecc and iwdg
georgevigelette May 19, 2026
5f1d698
aded long watchdog need to fix this
georgevigelette May 19, 2026
d461d83
monitor bit flips
georgevigelette May 19, 2026
20b4ef7
reset after 10 Double bit errors in one session
georgevigelette May 19, 2026
a7400fc
fix build script
georgevigelette May 19, 2026
02e93de
Merge pull request #39 from OpenwaterHealth/eft-testing
georgevigelette May 19, 2026
91a82b4
docs: spec and plan for DFU deploy script
boringethan May 21, 2026
ff3f677
feat(deploy): add scripts/deploy.py for sensor module
boringethan May 21, 2026
99f7309
build: add flash-left/flash-right CMake targets
boringethan May 21, 2026
95903fa
fix(deploy): use current omotion API + verify --dfu-util override exists
boringethan May 21, 2026
054328d
fix(deploy): UTF-8 stdout for Windows + add Deploy Sensor VS Code tasks
boringethan May 21, 2026
5989e1d
feat(deploy): prefer omotion-bundled dfu-util over PATH
boringethan May 21, 2026
99cb45b
fix(deploy): fix connection race and treat dfu-util exit 74 as warning
boringethan May 21, 2026
cc9c8ff
change fsin to have a pulldown
boringethan Jun 3, 2026
975e9a4
Merge branch 'eft-testing' into next
boringethan Jun 3, 2026
940a968
update to support factory programming nvcm
georgevigelette Jun 4, 2026
f6280a8
update to support camera selection
georgevigelette Jun 4, 2026
4bb11e4
rename to OW_FPGA_PROG
georgevigelette Jun 4, 2026
b47f75c
Merge pull request #40 from OpenwaterHealth/feature-nvcm
georgevigelette Jun 4, 2026
0eb5a92
feat: add NVCM auto-detection via I2C probe (on-demand only)
boringethan Jun 9, 2026
0f3e54e
feat(nvcm): add OW_FACTORY_NVCM_CHECK direct read-back probe
boringethan Jun 9, 2026
a2ad553
feat(nvcm): add behaviorally-definitive auto-boot test to probe
boringethan Jun 9, 2026
ffd26f9
docs(nvcm): iteration-2 result — camera 8 NVCM is PROGRAMMED
boringethan Jun 9, 2026
f5df6f1
docs(nvcm): blank-control attempt (cam1 wedges TCA) + resume checkpoint
boringethan Jun 9, 2026
fb17430
docs(nvcm): add START-HERE handoff for logic2-equipped next agent
boringethan Jun 9, 2026
c40a6b4
fix(nvcm): rewrite fpga_detect_nvcm to use Done bit instead of boot test
boringethan Jun 9, 2026
51ddedf
Merge pull request #41 from OpenwaterHealth/feature/fpga-autodetect
boringethan Jun 9, 2026
1cb7700
fix(i2c): correct off-by-one in OW_FACTORY_I2C_WRRD write_data offset
boringethan Jun 9, 2026
e29c8ee
docs(nvcm): update handoff with off-by-one root cause and successful …
boringethan Jun 9, 2026
6d42564
feat(nvcm): rewrite NVCM detect to use SPI/USART pin sampling
boringethan Jun 9, 2026
628f4e3
fix(i2c): add TCA9548A bus recovery and prevent CRESETB glitches
boringethan Jun 9, 2026
1c83d0a
fix(i2c): stop selecting TCA mux channel at camera power-on
boringethan Jun 9, 2026
d6f7b39
docs(nvcm): write up the NVCM row-drop incident and root cause
boringethan Jun 9, 2026
0bd210a
docs(nvcm): record virgin-module positive validation of the burn path
boringethan Jun 9, 2026
86b5116
docs(nvcm): add right-module USART validation to incident writeup
boringethan Jun 10, 2026
4483ada
fix(nvcm): reset USART after positive NVCM detect
boringethan Jun 10, 2026
d7c2daf
Merge pull request #42 from OpenwaterHealth/feature/nvcm-autodetect
boringethan Jun 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/build-firmware.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ on:
branches: [ "main", "next" ]
tags:
- "*.*.*"
- "v*.*.*"
- "pre-*"
- "*.*.*-rc.*"
- "*.*.*-dev.*"
release:
types: [created]

Expand Down Expand Up @@ -65,7 +65,7 @@ jobs:

echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT

if [[ "$TAG_NAME" == pre-* ]] || [[ "$TAG_NAME" == *"-rc"* ]] || [[ "$TAG_NAME" == *"-beta"* ]]; then
if [[ "$TAG_NAME" == *"-rc."* ]] || [[ "$TAG_NAME" == *"-dev."* ]]; then
echo "prerelease=true" >> $GITHUB_OUTPUT
else
echo "prerelease=false" >> $GITHUB_OUTPUT
Expand Down
4 changes: 2 additions & 2 deletions .mxproject

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ target_sources(${CMAKE_PROJECT_NAME} PRIVATE
Core/Src/uart_comms.c
Core/Src/flash_eeprom.c
Core/Src/motion_config.c
Core/Src/system_monitor.c
Core/Src/if_factory_prog.c
Core/Src/ram_scrub.c
Core/Src/utils.c
USB/Core/Src/usbd_ioreq.c
USB/Core/Src/usbd_desc.c
Expand Down Expand Up @@ -196,3 +199,20 @@ add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
COMMENT "Generating .hex/.bin and merging FPGA bitstream at ${FPGA_BITSTREAM_ADDR}"
)

# Build + DFU-flash targets, one per sensor side. Invokes scripts/deploy.py.
# `--device` is required by the script, so we expose two separate targets.
find_program(PYTHON_FOR_DEPLOY NAMES python3 python)
if(PYTHON_FOR_DEPLOY)
foreach(SIDE left right)
add_custom_target(flash-${SIDE}
COMMAND ${PYTHON_FOR_DEPLOY} ${CMAKE_SOURCE_DIR}/scripts/deploy.py
--device ${SIDE} --config $<CONFIG> --no-build
DEPENDS ${CMAKE_PROJECT_NAME}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
USES_TERMINAL
COMMENT "Flashing ${CMAKE_PROJECT_NAME} (${SIDE} sensor) via DFU"
)
endforeach()
else()
message(WARNING "Python not found — `flash-left`/`flash-right` targets will not be available")
endif()
6 changes: 6 additions & 0 deletions Core/Inc/camera_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ typedef struct {
uint8_t exposure;
uint8_t *pRecieveHistoBuffer;
size_t receiveBufferSize; // Size of the buffer
GPIO_TypeDef * detect_clk_port;
uint16_t detect_clk_pin;
uint32_t detect_clk_af;
GPIO_TypeDef * detect_data_port;
uint16_t detect_data_pin;
uint32_t detect_data_af;
} CameraDevice;

#define CAMERA_COUNT 8
Expand Down
10 changes: 10 additions & 0 deletions Core/Inc/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ typedef enum {
OW_IMU = 0xE8,
OW_I2C_PASSTHRU = 0xE9,
OW_CONTROLLER = 0xEA,
OW_FPGA_PROG = 0xEB,
OW_BAD_PARSE = 0xEC,
OW_BAD_CRC = 0xED,
OW_UNKNOWN = 0xEE,
Expand Down Expand Up @@ -153,6 +154,15 @@ typedef enum {

} MotionCameraCommands;

typedef enum {
OW_FACTORY_I2C_SCAN = 0x60,
OW_FACTORY_CRESET = 0x68,
OW_FACTORY_I2C_RD = 0x69,
OW_FACTORY_I2C_WR = 0x6A,
OW_FACTORY_I2C_WRRD = 0x6B,
OW_FACTORY_NVCM_CHECK = 0x6C,
} MotionFactoryCommands;

typedef enum {
OW_CTRL_FAN_CTL = 0x0A,

Expand Down
45 changes: 45 additions & 0 deletions Core/Inc/crosslink.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,47 @@
#include "main.h"
#include <stdbool.h>

/* ---- NVCM (non-volatile config memory) read-back / detection ------------- */
/* Maximum NVCM array rows the probe will read back (16 bytes each). */
#define FPGA_NVCM_MAX_ROWS 8

/* step_status bits — which probe steps completed (HAL_OK) */
#define FPGA_NVCM_STEP_ACTIVATION (1u << 0)
#define FPGA_NVCM_STEP_IDCODE (1u << 1)
#define FPGA_NVCM_STEP_ISC_ENABLE (1u << 2)
#define FPGA_NVCM_STEP_STATUS (1u << 3)
#define FPGA_NVCM_STEP_FEATROW (1u << 4)
#define FPGA_NVCM_STEP_FEABITS (1u << 5)
#define FPGA_NVCM_STEP_USERCODE (1u << 6)

/* Raw read-back of every NVCM discriminator (all bytes in I2C wire order). */
typedef struct {
uint8_t idcode[4]; /* 0xE0 read */
uint8_t idcode_ok; /* 1 if idcode == {01,2C,00,43} */
uint8_t step_status; /* FPGA_NVCM_STEP_* bitmask */
uint8_t status[4]; /* 0x3C LSC_READ_STATUS */
uint8_t feature_row[8]; /* 0xE7 LSC_READ_FEATURE */
uint8_t feabits[2]; /* 0xFB LSC_READ_FEABITS */
uint8_t usercode[4]; /* 0xC0 USERCODE */
uint8_t boot_probe_done; /* 1 if the boot-behavior test ran */
uint8_t boot_0x40_responds; /* after auto-boot: 1=ACK (blank), 0=gone (programmed) */
uint8_t num_rows_read; /* NVCM array rows actually read */
uint8_t nvcm_rows[FPGA_NVCM_MAX_ROWS * 16]; /* 0x73 LSC_READ_INCR_NV */
} fpga_nvcm_probe_t;

/*
* Probe the NVCM state of one CrossLink FPGA WITHOUT booting it and WITHOUT
* touching camera power. Holds the config port in slave mode (activation key
* around the CRESETB transition), enters ISC access mode with the given
* isc_operand (0x08 = NVCM, 0x00 = SRAM), and reads every discriminator.
* Caller must have already selected the camera's TCA mux channel and powered it.
* Every step is best-effort; results land in *out (zeroed first).
*/
int fpga_nvcm_probe(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin,
uint8_t isc_operand, uint8_t num_rows, uint8_t do_boot_test,
fpga_nvcm_probe_t *out);

int fpga_send_activation(I2C_HandleTypeDef *hi2c, uint16_t DevAddress);
int fpga_checkid(I2C_HandleTypeDef *hi2c, uint16_t DevAddress);
int fpga_enter_sram_prog_mode(I2C_HandleTypeDef *hi2c, uint16_t DevAddress);
Expand All @@ -20,4 +61,8 @@ uint32_t fpga_read_usercode(I2C_HandleTypeDef *hi2c, uint16_t DevAddress);
int fpga_program_sram(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, bool rom_bitstream, uint8_t* pData, uint32_t Data_Len);
int fpga_configure(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin);

int xi2c_write_bytes(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *data, uint16_t length);
int xi2c_read_bytes(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *data, uint16_t length);
int xi2c_write_and_read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *wbuf, uint16_t wlen, uint8_t *rbuf, uint16_t rlen);

#endif /* INC_CROSSLINK_H_ */
7 changes: 6 additions & 1 deletion Core/Inc/i2c_master.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ uint8_t read_data_register_of_slave(I2C_HandleTypeDef * pI2c, uint8_t slave_addr
void reset_slaves(I2C_HandleTypeDef * pI2c);
HAL_StatusTypeDef TCA9548A_SelectChannel(I2C_HandleTypeDef *hi2c, uint8_t address, uint8_t channel);
HAL_StatusTypeDef TCA9548A_SelectBroadcast(I2C_HandleTypeDef *hi2c, uint8_t address);
HAL_StatusTypeDef TCA9548A_EnableChannel(I2C_HandleTypeDef *hi2c, uint8_t address, uint8_t channel);
/* NOTE: there is intentionally no TCA9548A_EnableChannel (additive select).
* Selecting multiple channels in parallel puts several FPGAs on the shared
* bus at once — see docs/tca9548a-bus-issues.md. Use SelectChannel (exactly
* one channel) or DisableChannel/DisableAll. */
HAL_StatusTypeDef TCA9548A_DisableChannel(I2C_HandleTypeDef *hi2c, uint8_t address, uint8_t channel);
HAL_StatusTypeDef TCA9548A_DisableAll(I2C_HandleTypeDef *hi2c, uint8_t address);
void I2C_BusRecovery(I2C_HandleTypeDef *hi2c);

#endif /* INC_I2C_MASTER_H_ */
8 changes: 8 additions & 0 deletions Core/Inc/if_factory_prog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef INC_IF_FACTORY_PROG_COMMANDS_H_
#define INC_IF_FACTORY_PROG_COMMANDS_H_

#include "common.h"

_Bool process_factory_command(UartPacket *response, UartPacket *cmd);

#endif /* INC_IF_FPGA_PROG_COMMANDS_H_ */
4 changes: 2 additions & 2 deletions Core/Inc/stm32h7xx_hal_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@
/* #define HAL_OSPI_MODULE_ENABLED */
/* #define HAL_I2S_MODULE_ENABLED */
/* #define HAL_SMBUS_MODULE_ENABLED */
/* #define HAL_IWDG_MODULE_ENABLED */
#define HAL_IWDG_MODULE_ENABLED
/* #define HAL_LPTIM_MODULE_ENABLED */
/* #define HAL_LTDC_MODULE_ENABLED */
/* #define HAL_QSPI_MODULE_ENABLED */
/* #define HAL_RAMECC_MODULE_ENABLED */
#define HAL_RAMECC_MODULE_ENABLED
#define HAL_RNG_MODULE_ENABLED
/* #define HAL_RTC_MODULE_ENABLED */
/* #define HAL_SAI_MODULE_ENABLED */
Expand Down
1 change: 1 addition & 0 deletions Core/Inc/stm32h7xx_it.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ void TIM15_IRQHandler(void);
void TIM16_IRQHandler(void);
void TIM17_IRQHandler(void);
void BDMA_Channel0_IRQHandler(void);
void ECC_IRQHandler(void);
/* USER CODE BEGIN EFP */

/* USER CODE END EFP */
Expand Down
38 changes: 38 additions & 0 deletions Core/Inc/system_monitor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* system_monitor.h
*
* Persistent reset-cause counters, RAMECC SBE/DBE monitoring and DMA
* transfer-error scanning. Counters live in .noinit RAM so they survive
* IWDG/soft resets but are reinitialised on a power-on / brown-out reset
* (detected via a magic value check at boot).
*/

#ifndef CORE_INC_SYSTEM_MONITOR_H_
#define CORE_INC_SYSTEM_MONITOR_H_

#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

/* Snapshot RCC->CSR and increment per-cause counters. Must be called BEFORE
* __HAL_RCC_CLEAR_RESET_FLAGS(). Safe to call before printf is up. */
void system_monitor_capture_reset_cause(void);

/* Print accumulated reset-cause / ECC / DMA counters to stdout. */
void system_monitor_print_history(void);

/* Start RAMECC monitoring on all 12 monitors and enable the ECC NVIC IRQ. */
void system_monitor_ecc_enable(void);

/* Periodic poll: prints any pending ECC events and scans DMA1/DMA2/BDMA for
* transfer-error / FIFO-error flags. Call from the main loop. */
void system_monitor_poll(void);

#ifdef __cplusplus
}
#endif

#endif /* CORE_INC_SYSTEM_MONITOR_H_ */
4 changes: 2 additions & 2 deletions Core/Src/0X02C1B.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ int X02C1B_FSIN_EXT_enable()
/* Configure the FSIN pin (the internal frame sync generator) to an input to rx the frame sync*/
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = FSIN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; // Set to input mode, rising edge trigger
GPIO_InitStruct.Pull = GPIO_NOPULL; // No pull-up or pull-down resistors
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(FSIN_GPIO_Port, &GPIO_InitStruct);

Expand Down
Loading
Loading