From dc5b52a7870f03d970a646cf9a2ef92a3df696aa Mon Sep 17 00:00:00 2001 From: Mohamed-dek Mohamed Date: Mon, 4 May 2026 14:43:28 -0500 Subject: [PATCH 01/22] add dcp folder --- .../amds/daisy-chain-protocol/index.md | 155 ++++++++++++++++++ .../tutorials/profiling-tasks/index.md | 4 + 2 files changed, 159 insertions(+) create mode 100644 source/accessories/amds/daisy-chain-protocol/index.md diff --git a/source/accessories/amds/daisy-chain-protocol/index.md b/source/accessories/amds/daisy-chain-protocol/index.md new file mode 100644 index 00000000..a61440a0 --- /dev/null +++ b/source/accessories/amds/daisy-chain-protocol/index.md @@ -0,0 +1,155 @@ +# Daisy Chain Protocol + +This document describes the design consideration, implementation details, and board interface details for the sensor mainboard. A block diagram is presented and each component is discussed in detail. + +## Relevant Hardware Versions + +AMDS REV D + +## Application / Purpose + +The mainboard is specifically designed to interface directly to the [GPIO expansion port on the AMDC](/hardware/subsystems/expansion-port.md). + +## Features + +- Can connect up to 8 sensor cards. +- Can communicate with an external controller (like AMDC). An external controller can obtain the measurement results and also is allowed to control the digital conversion process. +- Robust differential IO communication is used to transmit sensor data to an external controller. +- High throughput of up to 1 MSPS (depending on ADC device on sensor cards). + +## Block Diagram and SPI Connection Configuration + +The eight sensor cards transmit data to the STM32 MCU using standard SPI protocol. The sensor cards are grouped into four pairs of daisy chain connections. See the following block diagram. + +![](images/Measurementboard_REVD.svg) + +![](images/Motherboard_3d.png) + +The sensor cards can be connected in daisy chain pair configuration (D) or single SPI configuration (S). The daisy chain configuration will have a throughput of 500 kSPS. If the number of sensor cards is less than or equal to four, then a single SPI configuration can be used to get higher throughput. This single SPI configuration will have a throughput of 1 MSPS. The configuration can be changed using jumpers (P9, P10, P15, P16) as shown in the following figure. + +![](images/Jumper_modes.png) + +## External Connections + +There are two interfacing DB-15 connectors on the measurement board. The first connector is used for interfacing with the controller (the AMDC driver) via differential I/O. The second connector is intended to connect to an external expansion for the AMDS, and is connected back to the GPIO port of the MCU on the AMDS mainboard. + +### DB15 Connector 1: AMDC Link (connects to a GPIO port on the AMDC) + +| Pin number | Signal name | Voltage level | Protocol | +|------------|--------|--------|--------| +| 1 | 5V_IN | 5V | - | +| 2 | DATA0_P | 5V | Differential IO | +| 3 | DATA0_N | 5V | Differential IO | +| 4 | DATA1_P | 5V | Differential IO | +| 5 | DATA1_N | 5V | Differential IO | +| 6 | NC | - | - | +| 7 | isoSPI2_P | 5V | IsoSPI | +| 8 | isoSPI2_N | 5V | IsoSPI | +| 9 | isoSPI3_P | 5V | IsoSPI | +| 10 | isoSPI3_N | 5V | IsoSPI | +| 11 | GND | - | - | +| 12 | SYNC_ADC_P | 5V | Differential IO | +| 13 | SYNC_ADC_N | 5V | Differential IO | +| 14 | SYNC_TX_P | 5V | Differential IO | +| 15 | SYNC_TX_N | 5V | Differential IO | + +> **NOTE:** The IsoSPI interface on pins 7-10 is a legacy interface and is not used. Only the differential I/O pins are used for signals between the AMDC and AMDS. + +### DB15 Connector 2: AMDS GPIO Link + +| Pin number | Signal name | Voltage level | +|------------|--------|--------| +| 1 | 3V3 | 3.3V | +| 2 | GPIO_1 | 3.3V | +| 3 | GPIO_2 | 3.3V | +| 4 | GPIO_3 | 3.3V | +| 5 | GPIO_4 | 3.3V | +| 6 | GPIO_5 | 3.3V | +| 7 | GPIO_6 | 3.3V | +| 8 | GPIO_7 | 3.3V | +| 9 | GPIO_8 | 3.3V | +| 10 | GPIO_9 | 3.3V | +| 11 | GPIO_10 | 3.3V | +| 12 | GPIO_11 | 3.3V | +| 13 | GPIO_12 | 3.3V | +| 14 | GND | - | +| 15 | GND | - | + +Implementation details of [IsoSPI](#isospi_comm_interface) and [Differential IO](#diff-io-transceiver) is described later in the document. + +## Systems on Board + +Per the block diagram above, the mainboard is made of several systems, as explained below. + +### STM32F7 Microcontroller + +STM32F7 microcontroller is used as an interface between the sensor card and an external controller. This MCU has a core ARM 32-bit Cortex M7 CPU. This IC can operate at a supply voltage of 1.7 V to 3.6 V. JTAG / SWD interface is used for debugging and programming the MCU. It has 6 SPIs which is used for sensor card and AMDC isoSPI interfaces. The maximum speed of the MCU SPI interface is 54 Mbps. It has 4 USART with a maximum baud rate of 26 Mbps, which are used to transmit sensor card data to the AMDC. GPIO pins of the MCU can be accessed using GPIO connector. More information on this MCU can be found [here](https://www.st.com/content/ccc/resource/technical/document/datasheet/group3/c5/37/9c/1d/a6/09/4e/1a/DM00273119/files/DM00273119.pdf/jcr:content/translations/en.DM00273119.pdf). + +(diff-io-transceiver)= +### Differential IO Isolated Transceiver + +The MCU transmits sensor data via USART communication. These USART signals are converted to differential IO using differential transceiver [ISO3086T](https://www.ti.com/lit/ds/symlink/iso3086t.pdf?HQS=TI-null-null-digikeymode-df-pf-null-wwe&ts=1596613093516). Differential IO has the ability to communicate over long distances and at faster communication rate compared to standard USART. This IC has an in-built isolation barrier. A signaling rate of up to 20 Mbps is obtained from this IC. The operating voltage is provided in the following table. + +| Parameter | Conditions | MIN | MAX | +|---------------------------------------|-------------------|---------|-------| +| Supply voltage VCC2 (Bus-side) | | 4.5 V | 5.5 V | +| IO supply voltage VCC1 (UART side) | 3.3V operation | 3 V | 3.6 V | +| IO supply voltage VCC1 (UART side) | 5V operation | 4.5 V | 5 V | + +The maximum supply current consumed by the IC including to drive currents for differential lines is 60 mA, which corresponds to 300 mW for 5 V supply. + +(isospi_comm_interface)= +### IsoSPI Communication Interface + +The isoSPI communication interface is implemented using [LTC6820](https://www.analog.com/media/en/technical-documentation/data-sheets/LTC6820.pdf). This IC provides a bi-directional interface between standard SPI signals and differential pulses. The operating conditions are provided in the following table. + +| Parameter | Conditions | MIN | MAX | +|---------------------------------------|-------------------|---------|-------| +| Supply voltage VDD (Differential side)| | 2.7 V | 5.5 V | +| IO supply voltage VDDS (SPI side) | | 1.7 V | 5.5 V | +| High-level input voltage |VDDS = 2.7V to 5V | 0.7 VDDS| VDDS | +| High-level input voltage |VDDS = 1.7V to 2.7V| 0.8 VDDS| VDDS | +| Low-level input voltage |VDDS = 2.7V to 5V | 0 | 0.3 VDDS | +| Low-level input voltage |VDDS = 1.7V to 2.7V| 0 | 0.2 VDDS | + +This IC can operate at a maximum SPI communication speed of 1 Mbps. The bias resistors (`RB1` and `RB2`) are used to adjust the drive currents to the differential lines. These resistors are selected such that the drive currents are set at 10 mA. These resistors are on the schematic, see the following figure. + +![](images/Schematic_RB.png) + +The maximum supply current consumed by the IC including to drive currents for differential lines is 17 mA, which corresponds to 85 mW for 5 V supply. + +### IsoSPI Isolation Transformer + +A transformer is required for implementing isoSPI. This will provide an isolation barrier to the differential SPI signals. This is implemented by adding pulse transformer HX1188NLT, which has 1:1 turns ratio. More information on the pulse transformer is found in the [datasheet](https://media.digikey.com/pdf/Data%20Sheets/Pulse%20PDFs/10_100BASE-T%20Single%20Port%20SMD%20Magnetics_Rev2008.pdf). + +## Sensor Card Interface + +In order to design a daugter card, the interface information provided in this section will be useful. Each sensor card slot has two headers, where the sensor card can be plugged in. See the following figure. + +![](images/DC_hdr.png) + +One header is used to supply power to the cards and the other header is used for SPI interface. + +### Header 1: Power Supply + +| Pin number | Signal name | +|------------|--------| +| 1 | +15V | +| 2 | GND | +| 3 | -15V | + +### Header 2: SPI interface + +| Pin number | Signal name | +|------------|--------| +| 1 | 5V | +| 2 | 3V3 | +| 3 | GND | +| 4 | DIN (ADC IN, MOSI) | +| 5 | SCLK | +| 6 | DOUT (ADC OUT, MISO) | +| 7 | CONVST (Conversion start) | + +For information regarding the placement of the headers, refer to the mainboard PCB Altium file in the AMDS repo located: `/Mainboard/altium/SensorMotherBoard.PcbDoc`. + +For more information on designing a sensor card, refer the [sensor card documentation](/accessories/amds/sensor-cards/index.md). \ No newline at end of file diff --git a/source/getting-started/tutorials/profiling-tasks/index.md b/source/getting-started/tutorials/profiling-tasks/index.md index 34c817e5..990ab0de 100644 --- a/source/getting-started/tutorials/profiling-tasks/index.md +++ b/source/getting-started/tutorials/profiling-tasks/index.md @@ -64,6 +64,10 @@ int task_controller_init(void) // ... ``` +```{warning} +Ensure that you +``` + Next, add task functions which wrap the `print()` and `reset()` functions for the timing stats: `task_controller.c`: From 6b51838b24318d35a0a0a7d032b3cf273c9c6375 Mon Sep 17 00:00:00 2001 From: Mohamed-dek Mohamed Date: Mon, 4 May 2026 15:32:23 -0500 Subject: [PATCH 02/22] add initial docs and changes to firmware docs --- .../amds/daisy-chain-protocol/index.md | 161 +++--------------- source/accessories/amds/firmware/index.md | 6 + source/accessories/amds/index.md | 1 + 3 files changed, 30 insertions(+), 138 deletions(-) diff --git a/source/accessories/amds/daisy-chain-protocol/index.md b/source/accessories/amds/daisy-chain-protocol/index.md index a61440a0..57167e2e 100644 --- a/source/accessories/amds/daisy-chain-protocol/index.md +++ b/source/accessories/amds/daisy-chain-protocol/index.md @@ -1,155 +1,40 @@ # Daisy Chain Protocol -This document describes the design consideration, implementation details, and board interface details for the sensor mainboard. A block diagram is presented and each component is discussed in detail. +This document outlines the architecture, setup, and features of the Daisy Chain protocol implementation, allowing robust data routing, selective sampling, and high-speed multi-board communication. -## Relevant Hardware Versions +## Multi-Target Firmware Project (Custom Build Configurations) -AMDS REV D +The firmware is designed to operate on multiple target hardware platforms using a single, unified codebase. -## Application / Purpose +- **Target Definitions**: The firmware uses `TARGET_AMDS` and `TARGET_2S` preprocessor macros to conditionally compile board-specific configurations. +- **Dynamic Peripheral Assignment**: Depending on the selected target, the system correctly configures the corresponding hardware peripherals. For example, `TARGET_AMDS` utilizes `UART4` and `UART5` for the Daisy Chain RX lines, while `TARGET_2S` relies on `USART6` and `USART1`. +- **Custom Run Configurations**: You can program either an AMDS or other devices without creating separate project branches, simply by toggling the target macro in your build/run configurations. -The mainboard is specifically designed to interface directly to the [GPIO expansion port on the AMDC](/hardware/subsystems/expansion-port.md). +## Direct Memory Access (DMA) Setup for Receiving Data -## Features +To ensure zero-CPU overhead when receiving incoming UART data, the protocol utilizes DMA streams. -- Can connect up to 8 sensor cards. -- Can communicate with an external controller (like AMDC). An external controller can obtain the measurement results and also is allowed to control the digital conversion process. -- Robust differential IO communication is used to transmit sensor data to an external controller. -- High throughput of up to 1 MSPS (depending on ADC device on sensor cards). +- **Circular Buffers**: Incoming daisy-chain data is placed into `DAISY_RX1_Pool` and `DAISY_RX2_Pool`, both of which are 256-byte circular buffers (`AMDS_RX_BUF_SIZE`). Utilizing a 256-byte size allows for 8-bit integer math to handle wrap-around without complex modulo logic. +- **Error Recovery**: In high-noise environments, UART hardware errors (Parity, Overrun, Noise, or Frame errors) can cause the hardware to drop the `DMAR` (DMA Receiver) bit, halting the stream. The UART Interrupt Service Routines (ISRs) actively monitor for these flags, clear them, and immediately re-enable the DMA requests to ensure continuous stream operation without resetting the device. -## Block Diagram and SPI Connection Configuration +## Selective Channel Transmitting -The eight sensor cards transmit data to the STM32 MCU using standard SPI protocol. The sensor cards are grouped into four pairs of daisy chain connections. See the following block diagram. +To optimize processing and transmission bandwidth, the system supports disabling unused sensor channels. -![](images/Measurementboard_REVD.svg) +- **Active Sensor Mask**: A global variable `active_sensor_mask` acts as a bitmask where `1 = Active` and `0 = Inactive`. +- **Target Defaults**: By default, `TARGET_AMDS` activates all 8 channels (`0xFF`), while `TARGET_2S` activates a subset of channels (`0x11`). -![](images/Motherboard_3d.png) +## Modified Sample-and-Transmit Fast Path -The sensor cards can be connected in daisy chain pair configuration (D) or single SPI configuration (S). The daisy chain configuration will have a throughput of 500 kSPS. If the number of sensor cards is less than or equal to four, then a single SPI configuration can be used to get higher throughput. This single SPI configuration will have a throughput of 1 MSPS. The configuration can be changed using jumpers (P9, P10, P15, P16) as shown in the following figure. +The firmware bypasses standard abstraction overhead to achieve low latency during critical sampling and transmission windows via the `adc_sample_and_transmit_fast_path` function. -![](images/Jumper_modes.png) +- **Hardware Cycle Counting**: Rather than using `NOP` loops for the mandatory 1300ns ADC wait time, the fast path uses the Cortex-M7 DWT Cycle Counter (`DWT->CYCCNT`) for deterministic waiting. +- **Instruction Interleaving**: The code optimizes wait states by starting SPI reads, and transmitting UART header bytes (`0x90`) while the CPU is waiting for the SPI RX buffers to fill. -## External Connections +## Process Routing Architecture -There are two interfacing DB-15 connectors on the measurement board. The first connector is used for interfacing with the controller (the AMDC driver) via differential I/O. The second connector is intended to connect to an external expansion for the AMDS, and is connected back to the GPIO port of the MCU on the AMDS mainboard. +Handling high-speed daisy-chained data relies on the `try_process_routing()` and `process_routing()` implementations. -### DB15 Connector 1: AMDC Link (connects to a GPIO port on the AMDC) - -| Pin number | Signal name | Voltage level | Protocol | -|------------|--------|--------|--------| -| 1 | 5V_IN | 5V | - | -| 2 | DATA0_P | 5V | Differential IO | -| 3 | DATA0_N | 5V | Differential IO | -| 4 | DATA1_P | 5V | Differential IO | -| 5 | DATA1_N | 5V | Differential IO | -| 6 | NC | - | - | -| 7 | isoSPI2_P | 5V | IsoSPI | -| 8 | isoSPI2_N | 5V | IsoSPI | -| 9 | isoSPI3_P | 5V | IsoSPI | -| 10 | isoSPI3_N | 5V | IsoSPI | -| 11 | GND | - | - | -| 12 | SYNC_ADC_P | 5V | Differential IO | -| 13 | SYNC_ADC_N | 5V | Differential IO | -| 14 | SYNC_TX_P | 5V | Differential IO | -| 15 | SYNC_TX_N | 5V | Differential IO | - -> **NOTE:** The IsoSPI interface on pins 7-10 is a legacy interface and is not used. Only the differential I/O pins are used for signals between the AMDC and AMDS. - -### DB15 Connector 2: AMDS GPIO Link - -| Pin number | Signal name | Voltage level | -|------------|--------|--------| -| 1 | 3V3 | 3.3V | -| 2 | GPIO_1 | 3.3V | -| 3 | GPIO_2 | 3.3V | -| 4 | GPIO_3 | 3.3V | -| 5 | GPIO_4 | 3.3V | -| 6 | GPIO_5 | 3.3V | -| 7 | GPIO_6 | 3.3V | -| 8 | GPIO_7 | 3.3V | -| 9 | GPIO_8 | 3.3V | -| 10 | GPIO_9 | 3.3V | -| 11 | GPIO_10 | 3.3V | -| 12 | GPIO_11 | 3.3V | -| 13 | GPIO_12 | 3.3V | -| 14 | GND | - | -| 15 | GND | - | - -Implementation details of [IsoSPI](#isospi_comm_interface) and [Differential IO](#diff-io-transceiver) is described later in the document. - -## Systems on Board - -Per the block diagram above, the mainboard is made of several systems, as explained below. - -### STM32F7 Microcontroller - -STM32F7 microcontroller is used as an interface between the sensor card and an external controller. This MCU has a core ARM 32-bit Cortex M7 CPU. This IC can operate at a supply voltage of 1.7 V to 3.6 V. JTAG / SWD interface is used for debugging and programming the MCU. It has 6 SPIs which is used for sensor card and AMDC isoSPI interfaces. The maximum speed of the MCU SPI interface is 54 Mbps. It has 4 USART with a maximum baud rate of 26 Mbps, which are used to transmit sensor card data to the AMDC. GPIO pins of the MCU can be accessed using GPIO connector. More information on this MCU can be found [here](https://www.st.com/content/ccc/resource/technical/document/datasheet/group3/c5/37/9c/1d/a6/09/4e/1a/DM00273119/files/DM00273119.pdf/jcr:content/translations/en.DM00273119.pdf). - -(diff-io-transceiver)= -### Differential IO Isolated Transceiver - -The MCU transmits sensor data via USART communication. These USART signals are converted to differential IO using differential transceiver [ISO3086T](https://www.ti.com/lit/ds/symlink/iso3086t.pdf?HQS=TI-null-null-digikeymode-df-pf-null-wwe&ts=1596613093516). Differential IO has the ability to communicate over long distances and at faster communication rate compared to standard USART. This IC has an in-built isolation barrier. A signaling rate of up to 20 Mbps is obtained from this IC. The operating voltage is provided in the following table. - -| Parameter | Conditions | MIN | MAX | -|---------------------------------------|-------------------|---------|-------| -| Supply voltage VCC2 (Bus-side) | | 4.5 V | 5.5 V | -| IO supply voltage VCC1 (UART side) | 3.3V operation | 3 V | 3.6 V | -| IO supply voltage VCC1 (UART side) | 5V operation | 4.5 V | 5 V | - -The maximum supply current consumed by the IC including to drive currents for differential lines is 60 mA, which corresponds to 300 mW for 5 V supply. - -(isospi_comm_interface)= -### IsoSPI Communication Interface - -The isoSPI communication interface is implemented using [LTC6820](https://www.analog.com/media/en/technical-documentation/data-sheets/LTC6820.pdf). This IC provides a bi-directional interface between standard SPI signals and differential pulses. The operating conditions are provided in the following table. - -| Parameter | Conditions | MIN | MAX | -|---------------------------------------|-------------------|---------|-------| -| Supply voltage VDD (Differential side)| | 2.7 V | 5.5 V | -| IO supply voltage VDDS (SPI side) | | 1.7 V | 5.5 V | -| High-level input voltage |VDDS = 2.7V to 5V | 0.7 VDDS| VDDS | -| High-level input voltage |VDDS = 1.7V to 2.7V| 0.8 VDDS| VDDS | -| Low-level input voltage |VDDS = 2.7V to 5V | 0 | 0.3 VDDS | -| Low-level input voltage |VDDS = 1.7V to 2.7V| 0 | 0.2 VDDS | - -This IC can operate at a maximum SPI communication speed of 1 Mbps. The bias resistors (`RB1` and `RB2`) are used to adjust the drive currents to the differential lines. These resistors are selected such that the drive currents are set at 10 mA. These resistors are on the schematic, see the following figure. - -![](images/Schematic_RB.png) - -The maximum supply current consumed by the IC including to drive currents for differential lines is 17 mA, which corresponds to 85 mW for 5 V supply. - -### IsoSPI Isolation Transformer - -A transformer is required for implementing isoSPI. This will provide an isolation barrier to the differential SPI signals. This is implemented by adding pulse transformer HX1188NLT, which has 1:1 turns ratio. More information on the pulse transformer is found in the [datasheet](https://media.digikey.com/pdf/Data%20Sheets/Pulse%20PDFs/10_100BASE-T%20Single%20Port%20SMD%20Magnetics_Rev2008.pdf). - -## Sensor Card Interface - -In order to design a daugter card, the interface information provided in this section will be useful. Each sensor card slot has two headers, where the sensor card can be plugged in. See the following figure. - -![](images/DC_hdr.png) - -One header is used to supply power to the cards and the other header is used for SPI interface. - -### Header 1: Power Supply - -| Pin number | Signal name | -|------------|--------| -| 1 | +15V | -| 2 | GND | -| 3 | -15V | - -### Header 2: SPI interface - -| Pin number | Signal name | -|------------|--------| -| 1 | 5V | -| 2 | 3V3 | -| 3 | GND | -| 4 | DIN (ADC IN, MOSI) | -| 5 | SCLK | -| 6 | DOUT (ADC OUT, MISO) | -| 7 | CONVST (Conversion start) | - -For information regarding the placement of the headers, refer to the mainboard PCB Altium file in the AMDS repo located: `/Mainboard/altium/SensorMotherBoard.PcbDoc`. - -For more information on designing a sensor card, refer the [sensor card documentation](/accessories/amds/sensor-cards/index.md). \ No newline at end of file +- **Thread-safe Invocation**: The main `while(1)` loop constantly checks `drv_uart_has_dma_data()` and invokes `try_process_routing()`. This wrapper uses an atomic lock (`is_routing_active`) to safely avert reentrancy without stalling the CPU or permanently blinding interrupts. +- **Dual-Stream Optimization**: Inside `process_routing()`, if both UART streams have at least a full 3-byte packet ready, the logic processes them completely interleaved. This keeps both hardware TX lines saturated simultaneously. +- **Single-Stream and Slow Path**: If one UART runs slightly faster, it employs a Single-Stream Fast Path. If a packet gets fragmented across a DMA boundary or becomes misaligned, the system reverts to a 1-byte-at-a-time State Machine (the "Slow Path") to recover the stream automatically. diff --git a/source/accessories/amds/firmware/index.md b/source/accessories/amds/firmware/index.md index 328de436..16fcb0e0 100644 --- a/source/accessories/amds/firmware/index.md +++ b/source/accessories/amds/firmware/index.md @@ -64,6 +64,12 @@ The message structure is equal between both `DATA0` and `DATA1`. However, each m _NOTE: there is no full CRC included in the transmission. The simple protocol relies on the parity check in the UART packet. This is not a terribly robust approach, but has worked well is moderate EMI environments._ +### Daisy Chain Protocol Implementation + +The physical routing, interleaving, and transmission of the sensor data across the dual UART TX lines are managed by a specialized firmware implementation known as the Daisy Chain Protocol. This protocol leverages DMA (Direct Memory Access) streams, selective channel masking, and a thread-safe routing architecture to ensure zero-CPU-overhead data receiving. + +For a comprehensive breakdown of the DMA setup and the modified sample-and-transmit fast path, please refer to the detailed [Daisy Chain Protocol Documentation](../daisy-chain-protocol/index.md). + ### Interrupt-Driven Design After start-up, the AMDS firmware is completely interrupt driven. This means that all processing occurs within an interrupt context, not the main loop. The interrupt which used to drive the firmware occurs on the rising and falling edges of the `SYNC_ADC` signal. diff --git a/source/accessories/amds/index.md b/source/accessories/amds/index.md index bc617c53..7ce6d861 100644 --- a/source/accessories/amds/index.md +++ b/source/accessories/amds/index.md @@ -40,6 +40,7 @@ However, it is a complete system which could be interfaced to any other host dev amds-in-action/index firmware/index +daisy-chain-protocol/index mainboard/index sensor-cards/index ``` \ No newline at end of file From 73a01e9c0384f4582a9391cf7f1c393d63fc0242 Mon Sep 17 00:00:00 2001 From: Mohamed-dek Mohamed Date: Mon, 4 May 2026 15:58:58 -0500 Subject: [PATCH 03/22] add initial building and flashing documentation --- source/accessories/amds/firmware/index.md | 2 + source/accessories/amds/flashing/index.md | 64 +++++++++++++++++++++++ source/accessories/amds/index.md | 1 + 3 files changed, 67 insertions(+) create mode 100644 source/accessories/amds/flashing/index.md diff --git a/source/accessories/amds/firmware/index.md b/source/accessories/amds/firmware/index.md index 16fcb0e0..3f55ecf3 100644 --- a/source/accessories/amds/firmware/index.md +++ b/source/accessories/amds/firmware/index.md @@ -70,6 +70,8 @@ The physical routing, interleaving, and transmission of the sensor data across t For a comprehensive breakdown of the DMA setup and the modified sample-and-transmit fast path, please refer to the detailed [Daisy Chain Protocol Documentation](../daisy-chain-protocol/index.md). +For instructions on programming the AMDS, please refer to [Building and Flashing Documentation](../flashing/index.md) + ### Interrupt-Driven Design After start-up, the AMDS firmware is completely interrupt driven. This means that all processing occurs within an interrupt context, not the main loop. The interrupt which used to drive the firmware occurs on the rising and falling edges of the `SYNC_ADC` signal. diff --git a/source/accessories/amds/flashing/index.md b/source/accessories/amds/flashing/index.md new file mode 100644 index 00000000..777f9470 --- /dev/null +++ b/source/accessories/amds/flashing/index.md @@ -0,0 +1,64 @@ +# Building and Flashing + +This guide provides step-by-step instructions on how to configure, build, and flash the AMDS firmware onto different hardware targets (e.g., AMDS and 2S). + +## Prerequisites + +- **IDE:** STM32CubeIDE (or your preferred C/C++ IDE configured for ARM Cortex-M development). +- **Hardware:** ST-Link V2/V3 or equivalent hardware debugger/programmer. +- **Target Board:** Either an AMDS board or AMDS-compatible board. + +## Step 1: Open the Project + +1. Launch STM32CubeIDE. +2. Go to **File > Open Projects from File System...** +3. Select the directory containing the firmware source code and click **Finish**. + +## Step 2: Set the Build Configuration (Target Macro) + +The firmware uses preprocessor macros to conditionally compile the correct peripheral assignments and active sensor masks for your specific board. + +1. Right-click on `motherboard_v1` and go to **Build Configuration > Set Active > AMDS or 2S** + +*Note: Alternatively, simply select the appropriate active configuration the Build "hammer" dropdown menu.* + +## Step 3: Build the Project + +1. **Clean** the project to ensure no artifact mix-ups from previous board builds: Go to **Project > Clean...** and select your project. +2. **Build** the project: Click the **Build** (hammer) icon or go to **Project > Build Project**. +3. Check the console output to ensure there are no compilation errors and that the build finishes successfully. + +```{important} +If you did not set the build configuration in the previous steps you will see many compilation errors that look like this: + +#error "Please define a target board (TARGET_AMDS or TARGET_2S)!" +``` + +## Step 4: Configure the Run/Debug Settings + +1. Connect your ST-Link to your PC and the target board's SWD (Serial Wire Debug) header. +2. Power on the target board. +3. In STM32CubeIDE, go to **Run > Debug Configurations...** +4. Double-click **STM32 Cortex-M C/C++ Application** to create a new configuration. +5. In the **Main** tab, ensure the correct `.elf` file is selected from your recent build. +6. In the **Debugger** tab, ensure the Debug probe is set to **ST-LINK** and the interface is set to **SWD**. +7. Click **Apply**. + +## Step 5: Flash and Verify + +1. Click **Debug** (or **Run**) from the configuration window to flash the firmware. +2. The IDE will connect to the board, erase the necessary flash sectors, and write the new firmware. +3. Once flashing is complete, if you are in Debug mode, click the **Resume** (play) button to start execution. +4. **Verification:** Observe the board's behavior. Depending on your configuration, verify that the active sensor mask operates correctly (AMDS enables all 8 channels `0xFF`, 2S enables a subset `0x11`) and that UART/DMA streams begin processing as expected. + +```{tip} +For the AMDS board, a good indicator that things are running smoothly is the 4 LEDS near the MCU blinking in order. +``` + +## Switching Between Boards + +Because the project shares a single codebase, programming a different board type is simple: + +1. Disconnect the current board and connect the new one. +2. Return to **Step 2** and swap the target macro. +3. Rebuild (Step 3) and Flash (Step 5). diff --git a/source/accessories/amds/index.md b/source/accessories/amds/index.md index 7ce6d861..4dcaf2da 100644 --- a/source/accessories/amds/index.md +++ b/source/accessories/amds/index.md @@ -41,6 +41,7 @@ However, it is a complete system which could be interfaced to any other host dev amds-in-action/index firmware/index daisy-chain-protocol/index +flashing/index mainboard/index sensor-cards/index ``` \ No newline at end of file From b994a35b27cd5a938a6895573cc262a434dbdcef Mon Sep 17 00:00:00 2001 From: Mohamed-dek Mohamed Date: Mon, 4 May 2026 16:24:48 -0500 Subject: [PATCH 04/22] remove future improvement 4 --- source/accessories/amds/firmware/index.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/accessories/amds/firmware/index.md b/source/accessories/amds/firmware/index.md index 3f55ecf3..36e7c78c 100644 --- a/source/accessories/amds/firmware/index.md +++ b/source/accessories/amds/firmware/index.md @@ -125,5 +125,3 @@ The AMDS firmware works, albeit with limitations as described above. Some ideas 2. The total sampling and data transmission latency as seen by the master (AMDC) could be improved. In the current firmware, the time from when the `SYNC_ADC` line is toggled to when the newly sampled data has fully been received by the master is about 11 µs. This places limitations on the control rate of the master (AMDC). The improvements can come in several parts: 1) the actual ADC sampling time can be shorten by using the `BUSY` signal from each ADC in an ISR to end the ADC sampling window. These are not used in the current firmware. Instead, the simpler approach of busy waiting until the max timeout occurs is used (i.e. wait for 1300 ns). However, the nominal wait time is only about 50% of this. 2) The data transmission time could be shorten by removing/reducing the overhead in the packet format, i.e., removing the header bytes. 3. There is no robust CRC error detection on the data transmission from the AMDS to the master device, although the UART parity is used. Future improvements could add a footer CRC to ensure the received message at the master is valid. Error correction codes could also be used to further increase the communication robustness in high EMI environments (e.g. SECDED). There is no free lunch: all of these methods would increase the data transmission latency from the AMDS. - -4. There is no need to transmit the data from all eight sensor cards if they are not all populated. Theoretically, a user could run the AMDS interface MUCH faster with fewer sensor cards installed, if changes are made such that only real data acquired from populated sensor cards are transmitted back to the master. From 9524282a4a2d6012e124603f1f8788c0354671af Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Wed, 13 May 2026 16:40:28 -0500 Subject: [PATCH 05/22] Edit flashing instructions --- .../images/debugger-config-options.svg | 59 +++++++++++++++++++ source/accessories/amds/flashing/index.md | 25 +++++--- 2 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 source/accessories/amds/flashing/images/debugger-config-options.svg diff --git a/source/accessories/amds/flashing/images/debugger-config-options.svg b/source/accessories/amds/flashing/images/debugger-config-options.svg new file mode 100644 index 00000000..598f3df9 --- /dev/null +++ b/source/accessories/amds/flashing/images/debugger-config-options.svg @@ -0,0 +1,59 @@ + + + + diff --git a/source/accessories/amds/flashing/index.md b/source/accessories/amds/flashing/index.md index 777f9470..b29ad2fb 100644 --- a/source/accessories/amds/flashing/index.md +++ b/source/accessories/amds/flashing/index.md @@ -12,13 +12,20 @@ This guide provides step-by-step instructions on how to configure, build, and fl 1. Launch STM32CubeIDE. 2. Go to **File > Open Projects from File System...** -3. Select the directory containing the firmware source code and click **Finish**. +3. Select the directory containing the firmware source code (`AMDS\Mainboard\Firmware\mainboard\`) and click **Finish**. ## Step 2: Set the Build Configuration (Target Macro) -The firmware uses preprocessor macros to conditionally compile the correct peripheral assignments and active sensor masks for your specific board. +The firmware uses preprocessor macros to conditionally compile the correct peripheral assignments and active sensor masks for your specific board. Two targets are currently supported: -1. Right-click on `motherboard_v1` and go to **Build Configuration > Set Active > AMDS or 2S** +- `AMDS`: This is the standard AMDS hardware as documented on this website. +- `2S`: This is a new target that has only two sensor cards on hardware that is not yet publicly released. + +```{tip} +Nearly all users are on AMDS hardware. When in doubt, select the `AMDS` option. +``` + +1. Right-click on `mainboard` and go to **Build Configuration > Set Active > AMDS or 2S** *Note: Alternatively, simply select the appropriate active configuration the Build "hammer" dropdown menu.* @@ -40,10 +47,14 @@ If you did not set the build configuration in the previous steps you will see ma 2. Power on the target board. 3. In STM32CubeIDE, go to **Run > Debug Configurations...** 4. Double-click **STM32 Cortex-M C/C++ Application** to create a new configuration. -5. In the **Main** tab, ensure the correct `.elf` file is selected from your recent build. +5. In the **Main** tab, ensure the correct `.elf` file is selected in `C/C++ Application` as either `AMDS/mainboard.elf` or `2S/mainboard.elf`. 6. In the **Debugger** tab, ensure the Debug probe is set to **ST-LINK** and the interface is set to **SWD**. 7. Click **Apply**. +```{image} images/debugger-config-options.svg +:width: 75% +``` + ## Step 5: Flash and Verify 1. Click **Debug** (or **Run**) from the configuration window to flash the firmware. @@ -55,10 +66,10 @@ If you did not set the build configuration in the previous steps you will see ma For the AMDS board, a good indicator that things are running smoothly is the 4 LEDS near the MCU blinking in order. ``` -## Switching Between Boards +## Switching Between Targets -Because the project shares a single codebase, programming a different board type is simple: +Because the project shares a single codebase, programming a different target (`AMDS` vs `2S`) is simple: 1. Disconnect the current board and connect the new one. 2. Return to **Step 2** and swap the target macro. -3. Rebuild (Step 3) and Flash (Step 5). +3. Rebuild (**Step 3**) and Flash (**Step 5**). From 4869149fe28caaf0f4266c644d13d6b83774969b Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Wed, 13 May 2026 16:52:04 -0500 Subject: [PATCH 06/22] Edit daisy chain doc and make svg diagram --- .../images/daisy-chain.svg | 497 ++++++++++++++++++ .../amds/daisy-chain-protocol/index.md | 16 +- 2 files changed, 511 insertions(+), 2 deletions(-) create mode 100644 source/accessories/amds/daisy-chain-protocol/images/daisy-chain.svg diff --git a/source/accessories/amds/daisy-chain-protocol/images/daisy-chain.svg b/source/accessories/amds/daisy-chain-protocol/images/daisy-chain.svg new file mode 100644 index 00000000..f2aa5270 --- /dev/null +++ b/source/accessories/amds/daisy-chain-protocol/images/daisy-chain.svg @@ -0,0 +1,497 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + AMDS1 + + AMDC + + + + SYNC_ADC + DATA0 + DATA1 + + AMDS2 + + + + SYNC_ADC + DATA0 + DATA1 + + AMDS3 + + + + SYNC_ADC + DATA0 + DATA1 + + diff --git a/source/accessories/amds/daisy-chain-protocol/index.md b/source/accessories/amds/daisy-chain-protocol/index.md index 57167e2e..a149eacc 100644 --- a/source/accessories/amds/daisy-chain-protocol/index.md +++ b/source/accessories/amds/daisy-chain-protocol/index.md @@ -1,6 +1,18 @@ -# Daisy Chain Protocol +# Daisy Chaining AMDS Boards -This document outlines the architecture, setup, and features of the Daisy Chain protocol implementation, allowing robust data routing, selective sampling, and high-speed multi-board communication. +This document outlines the architecture, setup, and salient details of the AMDS's Daisy Chain capability. + +## Overview + +The AMDC and AMDS allow up to three AMDS boards to be daisy chained together on each of the AMDC's GPIO ports, as shown below. + +```{image} images/daisy-chain.svg +:width: 100% +``` + +Each AMDS board can run the same firmware, and does not need to know it is in a daisy chain. The cabling between each pair of boards runs at the same baudrate (20 Mbps). + +Currently released AMDS hardware relies on a daisy chain adapter board placed between AMDS's to add the necessary transceivers. Details on this board can be found in the AMDS git repo's [`AMDS/Accessories/DaisyChainAdapter` directory](https://github.com/Severson-Group/AMDS/tree/develop/Accessories/DaisyChainAdapter). ## Multi-Target Firmware Project (Custom Build Configurations) From 2bb87918edbe1bd10b4a59a05f8bda5a0f6e2d4b Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 08:34:21 -0500 Subject: [PATCH 07/22] add daisy chain info, remove 10khz host rate --- source/accessories/amds/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/accessories/amds/index.md b/source/accessories/amds/index.md index 4dcaf2da..9e6ef57b 100644 --- a/source/accessories/amds/index.md +++ b/source/accessories/amds/index.md @@ -32,8 +32,8 @@ However, it is a complete system which could be interfaced to any other host dev - Low voltage - Current +- Up to 3 AMDS boards daisy chained per AMDC port (up to 24 sensor cards) - Synchronous sensor sampling to PWM carrier waveform (up to 100 kHz) -- Data request rate up to 10 kHz to host device ```{toctree} :hidden: @@ -44,4 +44,4 @@ daisy-chain-protocol/index flashing/index mainboard/index sensor-cards/index -``` \ No newline at end of file +``` From 59700eeab85deda71559613d0139897b51d0c324 Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 09:20:39 -0500 Subject: [PATCH 08/22] Make flash and daisy chain be subarticles of firmware --- .../building-and-running-firmware.md} | 0 .../index.md => firmware/daisy-chain.md} | 0 .../images/daisy-chain.svg | 0 .../images/debugger-config-options.svg | 0 source/accessories/amds/firmware/index.md | 11 +++++++++-- source/accessories/amds/index.md | 2 -- 6 files changed, 9 insertions(+), 4 deletions(-) rename source/accessories/amds/{flashing/index.md => firmware/building-and-running-firmware.md} (100%) rename source/accessories/amds/{daisy-chain-protocol/index.md => firmware/daisy-chain.md} (100%) rename source/accessories/amds/{daisy-chain-protocol => firmware}/images/daisy-chain.svg (100%) rename source/accessories/amds/{flashing => firmware}/images/debugger-config-options.svg (100%) diff --git a/source/accessories/amds/flashing/index.md b/source/accessories/amds/firmware/building-and-running-firmware.md similarity index 100% rename from source/accessories/amds/flashing/index.md rename to source/accessories/amds/firmware/building-and-running-firmware.md diff --git a/source/accessories/amds/daisy-chain-protocol/index.md b/source/accessories/amds/firmware/daisy-chain.md similarity index 100% rename from source/accessories/amds/daisy-chain-protocol/index.md rename to source/accessories/amds/firmware/daisy-chain.md diff --git a/source/accessories/amds/daisy-chain-protocol/images/daisy-chain.svg b/source/accessories/amds/firmware/images/daisy-chain.svg similarity index 100% rename from source/accessories/amds/daisy-chain-protocol/images/daisy-chain.svg rename to source/accessories/amds/firmware/images/daisy-chain.svg diff --git a/source/accessories/amds/flashing/images/debugger-config-options.svg b/source/accessories/amds/firmware/images/debugger-config-options.svg similarity index 100% rename from source/accessories/amds/flashing/images/debugger-config-options.svg rename to source/accessories/amds/firmware/images/debugger-config-options.svg diff --git a/source/accessories/amds/firmware/index.md b/source/accessories/amds/firmware/index.md index 36e7c78c..8164252d 100644 --- a/source/accessories/amds/firmware/index.md +++ b/source/accessories/amds/firmware/index.md @@ -68,9 +68,9 @@ _NOTE: there is no full CRC included in the transmission. The simple protocol re The physical routing, interleaving, and transmission of the sensor data across the dual UART TX lines are managed by a specialized firmware implementation known as the Daisy Chain Protocol. This protocol leverages DMA (Direct Memory Access) streams, selective channel masking, and a thread-safe routing architecture to ensure zero-CPU-overhead data receiving. -For a comprehensive breakdown of the DMA setup and the modified sample-and-transmit fast path, please refer to the detailed [Daisy Chain Protocol Documentation](../daisy-chain-protocol/index.md). +For a comprehensive breakdown of the DMA setup and the modified sample-and-transmit fast path, please refer to the detailed [Daisy Chain Protocol Documentation](daisy-chain.md). -For instructions on programming the AMDS, please refer to [Building and Flashing Documentation](../flashing/index.md) +For instructions on programming the AMDS, please refer to [Building and Flashing Documentation](building-and-running-firmware.md) ### Interrupt-Driven Design @@ -125,3 +125,10 @@ The AMDS firmware works, albeit with limitations as described above. Some ideas 2. The total sampling and data transmission latency as seen by the master (AMDC) could be improved. In the current firmware, the time from when the `SYNC_ADC` line is toggled to when the newly sampled data has fully been received by the master is about 11 µs. This places limitations on the control rate of the master (AMDC). The improvements can come in several parts: 1) the actual ADC sampling time can be shorten by using the `BUSY` signal from each ADC in an ISR to end the ADC sampling window. These are not used in the current firmware. Instead, the simpler approach of busy waiting until the max timeout occurs is used (i.e. wait for 1300 ns). However, the nominal wait time is only about 50% of this. 2) The data transmission time could be shorten by removing/reducing the overhead in the packet format, i.e., removing the header bytes. 3. There is no robust CRC error detection on the data transmission from the AMDS to the master device, although the UART parity is used. Future improvements could add a footer CRC to ensure the received message at the master is valid. Error correction codes could also be used to further increase the communication robustness in high EMI environments (e.g. SECDED). There is no free lunch: all of these methods would increase the data transmission latency from the AMDS. + +```{toctree} +:hidden: + +daisy-chain +building-and-running-firmware +``` diff --git a/source/accessories/amds/index.md b/source/accessories/amds/index.md index 9e6ef57b..7ea38e0c 100644 --- a/source/accessories/amds/index.md +++ b/source/accessories/amds/index.md @@ -40,8 +40,6 @@ However, it is a complete system which could be interfaced to any other host dev amds-in-action/index firmware/index -daisy-chain-protocol/index -flashing/index mainboard/index sensor-cards/index ``` From 53ffb9460d7f78a265af3c89bcfa42df7694ad98 Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 09:23:21 -0500 Subject: [PATCH 09/22] Rename articles to be consistent with AMDC docs --- .../accessories/amds/firmware/building-and-running-firmware.md | 2 +- source/accessories/amds/firmware/daisy-chain.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/accessories/amds/firmware/building-and-running-firmware.md b/source/accessories/amds/firmware/building-and-running-firmware.md index b29ad2fb..001e7d32 100644 --- a/source/accessories/amds/firmware/building-and-running-firmware.md +++ b/source/accessories/amds/firmware/building-and-running-firmware.md @@ -1,4 +1,4 @@ -# Building and Flashing +# Building and Running Firmware This guide provides step-by-step instructions on how to configure, build, and flash the AMDS firmware onto different hardware targets (e.g., AMDS and 2S). diff --git a/source/accessories/amds/firmware/daisy-chain.md b/source/accessories/amds/firmware/daisy-chain.md index a149eacc..7472d9f6 100644 --- a/source/accessories/amds/firmware/daisy-chain.md +++ b/source/accessories/amds/firmware/daisy-chain.md @@ -1,4 +1,4 @@ -# Daisy Chaining AMDS Boards +# AMDS Daisy Chain This document outlines the architecture, setup, and salient details of the AMDS's Daisy Chain capability. From c0fb6128d57c0a4d85c38320181427f76cbb9b13 Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 09:23:35 -0500 Subject: [PATCH 10/22] Clarify that baud rate is no 20 Mbps --- source/accessories/amds/firmware/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/accessories/amds/firmware/index.md b/source/accessories/amds/firmware/index.md index 8164252d..507f2dd9 100644 --- a/source/accessories/amds/firmware/index.md +++ b/source/accessories/amds/firmware/index.md @@ -30,7 +30,7 @@ After all sensorcards have been sampled, the AMDS streams all sampled data back The two TX signals are controlled by the AMDS and go to the master. These are only used to send ADC sample data to the master. As soon as all ADCs are sampled, the AMDS starts sending the latest data to the master using the two TX wires. Two lanes are used so that the data can be transmitted at twice the speed, thus reducing latency. -The format of the data sent on the TX signals is UART. This means there is no clock line between the master and AMDS: the interface is completely asynchronous. The UART is configured to run at 25 Mbps. Conceptually, the TX lines are actually two distinct UART devices, each with only one-way communication. Both UARTs are configured as 8-bit data, 2 stop bits, and odd parity. +The format of the data sent on the TX signals is UART. This means there is no clock line between the master and AMDS: the interface is completely asynchronous. The UART is configured to run at 20 Mbps. Conceptually, the TX lines are actually two distinct UART devices, each with only one-way communication. Both UARTs are configured as 8-bit data, 2 stop bits, and odd parity. ##### Data Format From 3595726ae07dca1a93644d7280bcce4b081ba0c5 Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 09:57:25 -0500 Subject: [PATCH 11/22] Reorganize firmware article for daisy chain --- source/accessories/amds/firmware/index.md | 28 +++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/source/accessories/amds/firmware/index.md b/source/accessories/amds/firmware/index.md index 507f2dd9..0d6d49a9 100644 --- a/source/accessories/amds/firmware/index.md +++ b/source/accessories/amds/firmware/index.md @@ -32,7 +32,7 @@ The two TX signals are controlled by the AMDS and go to the master. These are on The format of the data sent on the TX signals is UART. This means there is no clock line between the master and AMDS: the interface is completely asynchronous. The UART is configured to run at 20 Mbps. Conceptually, the TX lines are actually two distinct UART devices, each with only one-way communication. Both UARTs are configured as 8-bit data, 2 stop bits, and odd parity. -##### Data Format +### Data Format The ADCs on the sensor cards are assumed to be 16-bit devices which are all compatible with each other (i.e. they can be daisy-chained and support equal clock rates). See each sensor card's hardware design files for specs on the specific ADCs which are supported. The 16-bit raw data from the ADCs are packed into bytes which are sent across the `DATA0` and `DATA1` UART lines. `DATA0` is used to send the contents of the first four sensor cards and `DATA1` sends the last four sensor card data. The transmissions happen in parallel between the data lines. @@ -64,13 +64,23 @@ The message structure is equal between both `DATA0` and `DATA1`. However, each m _NOTE: there is no full CRC included in the transmission. The simple protocol relies on the parity check in the UART packet. This is not a terribly robust approach, but has worked well is moderate EMI environments._ -### Daisy Chain Protocol Implementation +#### Selective Channel Transmitting -The physical routing, interleaving, and transmission of the sensor data across the dual UART TX lines are managed by a specialized firmware implementation known as the Daisy Chain Protocol. This protocol leverages DMA (Direct Memory Access) streams, selective channel masking, and a thread-safe routing architecture to ensure zero-CPU-overhead data receiving. +To optimize processing and transmission bandwidth, the system supports disabling unused sensor channels. -For a comprehensive breakdown of the DMA setup and the modified sample-and-transmit fast path, please refer to the detailed [Daisy Chain Protocol Documentation](daisy-chain.md). +**Active Sensor Mask**: The AMDS codebase contains a global variable `active_sensor_mask` that acts as a bitmask where `1 = Active` and `0 = Inactive` for each of the 8 AMDS sensor cards. This variable determines which sensor cards' data are sent to the master each time a `SYNC_ADC` is received by the AMDS. For example, -For instructions on programming the AMDS, please refer to [Building and Flashing Documentation](building-and-running-firmware.md) +- `active_sensor_mask = 0xFF;`: AMDS will send all 8 channels +- `active_sensor_mask = 0x01;`: AMDS will only send sensor card channel 1 +- `active_sensor_mask = 0x06;`: AMDS will only send sensor card channels 2 and 3 + +```{hint} +The AMDC platform system default is to send all 8 channels. If a reduced number of channels are being sent, the user must alert the AMDC to this by calling `amdc_set_enabled()`, as the AMDS does not communicate configuration settings with master. +``` + +### Daisy Chain + +The AMDS firmware includes support for up to three AMDS boards to be connected in series into a "daisy chain," allowing for 24 sensor cards worth of data to be sent to master. Details of this are provided in [AMDS Daisy Chain](daisy-chain.md). ### Interrupt-Driven Design @@ -78,7 +88,11 @@ After start-up, the AMDS firmware is completely interrupt driven. This means tha In the typical flow, the master is operating its PWM output and thus triggering the `SYNC_ADC` ISR periodically. The ADCs on the sensor cards start their conversions and store the latest data in the AMDS memory. Once this is complete, the AMDS sends the data back to the master. Then the AMDS will wait for the next `SYNC_ADC` interrupt. -### Performance Limitations +## Building and Flashing + +For instructions on programming the AMDS, please refer to [Building and Flashing Documentation](building-and-running-firmware.md). + +## Performance Limitations The AMDS firmware design directly affects the operation limits of the `SYNC_ADC` signal. It will continue to work up to some threshold, at which point some ISRs will be missed and the performance will drop. However, the system will not "crash" -- it will continue to work, albeit not as well. @@ -105,7 +119,7 @@ The channels in the above scope capture show the following signals from top to b **Note**: The AMDS firmware always assumes all eight sensor cards must be sampled. Even when they are not populated, the firmware timing remains as if all sensor cards were in pairs of daisy chains. This acts to limit the overall sampling throughput. -#### Performance Specifications +### Performance Specifications Given a control frequency of `Fs` and PWM switching frequency of `Fsw`, the following constraints must be satisfied for the AMDS firmware to perform well: From cd29423436972f09751935f41d71e3c70ae7b91e Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 09:57:50 -0500 Subject: [PATCH 12/22] Move build information from daisy chain to build article --- .../amds/firmware/building-and-running-firmware.md | 8 ++++++++ source/accessories/amds/firmware/daisy-chain.md | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/accessories/amds/firmware/building-and-running-firmware.md b/source/accessories/amds/firmware/building-and-running-firmware.md index 001e7d32..46914707 100644 --- a/source/accessories/amds/firmware/building-and-running-firmware.md +++ b/source/accessories/amds/firmware/building-and-running-firmware.md @@ -8,6 +8,14 @@ This guide provides step-by-step instructions on how to configure, build, and fl - **Hardware:** ST-Link V2/V3 or equivalent hardware debugger/programmer. - **Target Board:** Either an AMDS board or AMDS-compatible board. +## Multi-Target Firmware Project (Custom Build Configurations) + +The firmware is designed to operate on multiple target hardware platforms using a single, unified codebase. + +- **Target Definitions**: The firmware uses `TARGET_AMDS` and `TARGET_2S` preprocessor macros to conditionally compile board-specific configurations. +- **Dynamic Peripheral Assignment**: Depending on the selected target, the system correctly configures the corresponding hardware peripherals. For example, `TARGET_AMDS` utilizes `UART4` and `UART5` for the Daisy Chain RX lines, while `TARGET_2S` relies on `USART6` and `USART1`. +- **Custom Run Configurations**: You can program either an AMDS or other devices without creating separate project branches, simply by toggling the target macro in your build/run configurations. + ## Step 1: Open the Project 1. Launch STM32CubeIDE. diff --git a/source/accessories/amds/firmware/daisy-chain.md b/source/accessories/amds/firmware/daisy-chain.md index 7472d9f6..707032b0 100644 --- a/source/accessories/amds/firmware/daisy-chain.md +++ b/source/accessories/amds/firmware/daisy-chain.md @@ -14,14 +14,6 @@ Each AMDS board can run the same firmware, and does not need to know it is in a Currently released AMDS hardware relies on a daisy chain adapter board placed between AMDS's to add the necessary transceivers. Details on this board can be found in the AMDS git repo's [`AMDS/Accessories/DaisyChainAdapter` directory](https://github.com/Severson-Group/AMDS/tree/develop/Accessories/DaisyChainAdapter). -## Multi-Target Firmware Project (Custom Build Configurations) - -The firmware is designed to operate on multiple target hardware platforms using a single, unified codebase. - -- **Target Definitions**: The firmware uses `TARGET_AMDS` and `TARGET_2S` preprocessor macros to conditionally compile board-specific configurations. -- **Dynamic Peripheral Assignment**: Depending on the selected target, the system correctly configures the corresponding hardware peripherals. For example, `TARGET_AMDS` utilizes `UART4` and `UART5` for the Daisy Chain RX lines, while `TARGET_2S` relies on `USART6` and `USART1`. -- **Custom Run Configurations**: You can program either an AMDS or other devices without creating separate project branches, simply by toggling the target macro in your build/run configurations. - ## Direct Memory Access (DMA) Setup for Receiving Data To ensure zero-CPU overhead when receiving incoming UART data, the protocol utilizes DMA streams. From ee9154dacd39645a7f6c1113af300d4f7773c03d Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 10:03:13 -0500 Subject: [PATCH 13/22] update firmware article formatting --- source/accessories/amds/firmware/index.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/source/accessories/amds/firmware/index.md b/source/accessories/amds/firmware/index.md index 0d6d49a9..71c02fd5 100644 --- a/source/accessories/amds/firmware/index.md +++ b/source/accessories/amds/firmware/index.md @@ -62,7 +62,9 @@ The message structure is equal between both `DATA0` and `DATA1`. However, each m | ---- | ---- | ---- | | 0x93 | MSB of sample 4 | LSB of sample 4| -_NOTE: there is no full CRC included in the transmission. The simple protocol relies on the parity check in the UART packet. This is not a terribly robust approach, but has worked well is moderate EMI environments._ +```{note} +There is no full CRC included in the transmission. The simple protocol relies on the parity check in the UART packet. This is not a terribly robust approach, but has worked well is moderate EMI environments. +``` #### Selective Channel Transmitting @@ -117,7 +119,9 @@ The channels in the above scope capture show the following signals from top to b - C2: The `DATA0` line from the AMDS back to the AMDC, showing 12 bytes (4 x 3-Byte packets) of UART data. This is the data for AMDS sensor card channels 1-4. - C3: The `DATA1` line from the AMDS back to the AMDC, showing 12 bytes (4 x 3-Byte packets) of UART data. This is the data for AMDS sensor card channels 5-8. -**Note**: The AMDS firmware always assumes all eight sensor cards must be sampled. Even when they are not populated, the firmware timing remains as if all sensor cards were in pairs of daisy chains. This acts to limit the overall sampling throughput. +```{hint} +The default value of `active_sensor_mask` will have the AMDS assume that all eight sensor cards must be sampled. Even when they are not populated, the firmware timing remains as if all sensor cards were in pairs of daisy chains. The only way to improve sample throughput when fewer cards are used is to update `active_sensor_mask` as described [above](#selective-channel-transmitting). +``` ### Performance Specifications @@ -128,11 +132,13 @@ Given a control frequency of `Fs` and PWM switching frequency of `Fsw`, the foll For application with SiC or GaN inverters where `Fsw` is typically much faster than `Fs`, the AMDS firmware works well. -**Warning:** When `Fs` is close to `Fsw` (i.e. control frequency is equal to PWM frequency), **the current AMDS firmware design will not work well.** +```{warning} +When `Fs` is close to `Fsw` (i.e. control frequency is equal to PWM frequency), **the current AMDS firmware design will not work well.** +``` ## Future Improvements -The AMDS firmware works, albeit with limitations as described above. Some ideas to improve the system are now described: +The AMDS firmware works, albeit with limitations as described above. Some ideas to improve the system are now listed: 1. The AMDS cannot be configured from the master. Improvements could use an additional TX/RX pair to enable simple register protocol for config. This could be used to set digital filter bandwidths, turn on/off sensor card slots for faster sampling, etc. From 4309fcc0fed0b3f5f38cdb152c60ac031110c374 Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 10:15:31 -0500 Subject: [PATCH 14/22] update link images to be consistent --- .../amds/firmware/images/daisy-chain.svg | 97 ++--- .../images/firmware-arch-interface.svg | 363 ++++++++++++++++++ .../images/firmware_arch_interface.svg | 212 ---------- source/accessories/amds/firmware/index.md | 2 +- 4 files changed, 415 insertions(+), 259 deletions(-) create mode 100644 source/accessories/amds/firmware/images/firmware-arch-interface.svg delete mode 100644 source/accessories/amds/firmware/images/firmware_arch_interface.svg diff --git a/source/accessories/amds/firmware/images/daisy-chain.svg b/source/accessories/amds/firmware/images/daisy-chain.svg index f2aa5270..fb47f1c7 100644 --- a/source/accessories/amds/firmware/images/daisy-chain.svg +++ b/source/accessories/amds/firmware/images/daisy-chain.svg @@ -222,17 +222,17 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1.979899" - inkscape:cx="558.61435" - inkscape:cy="92.176419" + inkscape:cx="497.50013" + inkscape:cy="90.156114" inkscape:document-units="mm" inkscape:current-layer="layer1" showgrid="true" units="in" - inkscape:window-width="3008" - inkscape:window-height="1692" + inkscape:window-width="2560" + inkscape:window-height="1382" inkscape:window-x="0" - inkscape:window-y="0" - inkscape:window-maximized="0" + inkscape:window-y="30" + inkscape:window-maximized="1" inkscape:showpageshadow="2" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1"> @@ -295,15 +295,20 @@ y="236.94722" /> AMDC + x="17.264069" + y="244.11252" + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.64444px;font-family:'Segoe UI';-inkscape-font-specification:'Segoe UI';stroke-width:0.264583">Master(AMDC) SYNC_ADC DATA0 DATA1 SYNC_ADC DATA0 DATA1 SYNC_ADC DATA0 DATA1 diff --git a/source/accessories/amds/firmware/images/firmware-arch-interface.svg b/source/accessories/amds/firmware/images/firmware-arch-interface.svg new file mode 100644 index 00000000..a44bb4e4 --- /dev/null +++ b/source/accessories/amds/firmware/images/firmware-arch-interface.svg @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + AMDS + + Master(AMDC) + + + + SYNC_ADC + DATA0 + DATA1 + + diff --git a/source/accessories/amds/firmware/images/firmware_arch_interface.svg b/source/accessories/amds/firmware/images/firmware_arch_interface.svg deleted file mode 100644 index 19dd05c2..00000000 --- a/source/accessories/amds/firmware/images/firmware_arch_interface.svg +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - AMDS - - Master - (AMDC) - - - - SYNC_ADC - DATA0 - DATA1 - - diff --git a/source/accessories/amds/firmware/index.md b/source/accessories/amds/firmware/index.md index 71c02fd5..86778e4a 100644 --- a/source/accessories/amds/firmware/index.md +++ b/source/accessories/amds/firmware/index.md @@ -18,7 +18,7 @@ While the architecture of the AMDS firmware is fairly simple, the I/O interface, The AMDS firmware is designed to interface to the master controller over three logical wires: one signal from the master, and two data lines to the master. Physically, these signals are all differential pairs for noise immunity. -![](images/firmware_arch_interface.svg) +![](images/firmware-arch-interface.svg) #### RX Signal: `SYNC_ADC` From 6c87bc21ab768e74c589658df03bd5276873b4a5 Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 10:27:03 -0500 Subject: [PATCH 15/22] Clarify interrupt driven nature of AMDS --- source/accessories/amds/firmware/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/accessories/amds/firmware/index.md b/source/accessories/amds/firmware/index.md index 86778e4a..17dab80c 100644 --- a/source/accessories/amds/firmware/index.md +++ b/source/accessories/amds/firmware/index.md @@ -86,7 +86,7 @@ The AMDS firmware includes support for up to three AMDS boards to be connected i ### Interrupt-Driven Design -After start-up, the AMDS firmware is completely interrupt driven. This means that all processing occurs within an interrupt context, not the main loop. The interrupt which used to drive the firmware occurs on the rising and falling edges of the `SYNC_ADC` signal. +After start-up, the AMDS firmware is interrupt driven. This means that all critical processing occurs within an interrupt context, not the main loop. The interrupt which used to drive the firmware occurs on the rising and falling edges of the `SYNC_ADC` signal. In the typical flow, the master is operating its PWM output and thus triggering the `SYNC_ADC` ISR periodically. The ADCs on the sensor cards start their conversions and store the latest data in the AMDS memory. Once this is complete, the AMDS sends the data back to the master. Then the AMDS will wait for the next `SYNC_ADC` interrupt. From 50f0a9932ea610f43accfe046d3a9a6b878566d2 Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 10:31:40 -0500 Subject: [PATCH 16/22] Restructure daisy chain article --- source/accessories/amds/firmware/daisy-chain.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/source/accessories/amds/firmware/daisy-chain.md b/source/accessories/amds/firmware/daisy-chain.md index 707032b0..cb70bbde 100644 --- a/source/accessories/amds/firmware/daisy-chain.md +++ b/source/accessories/amds/firmware/daisy-chain.md @@ -10,24 +10,21 @@ The AMDC and AMDS allow up to three AMDS boards to be daisy chained together on :width: 100% ``` -Each AMDS board can run the same firmware, and does not need to know it is in a daisy chain. The cabling between each pair of boards runs at the same baudrate (20 Mbps). +Each AMDS can run the same firmware, and does not need to know it is in a daisy chain. To each AMDS, the board "downstream" from it (i.e., the board with a lower number in the image above) appears as `master`. -Currently released AMDS hardware relies on a daisy chain adapter board placed between AMDS's to add the necessary transceivers. Details on this board can be found in the AMDS git repo's [`AMDS/Accessories/DaisyChainAdapter` directory](https://github.com/Severson-Group/AMDS/tree/develop/Accessories/DaisyChainAdapter). +## Hardware + +The cabling between each pair of boards runs at the same baudrate (20 Mbps). + +Currently released AMDS hardware relies on a daisy chain adapter board placed between each pair of AMDS boards to add the necessary transceivers. Details on this board can be found in the AMDS git repo's [`AMDS/Accessories/DaisyChainAdapter` directory](https://github.com/Severson-Group/AMDS/tree/develop/Accessories/DaisyChainAdapter). ## Direct Memory Access (DMA) Setup for Receiving Data -To ensure zero-CPU overhead when receiving incoming UART data, the protocol utilizes DMA streams. +To ensure near zero-CPU overhead when receiving incoming UART data, the firmware utilizes DMA streams. - **Circular Buffers**: Incoming daisy-chain data is placed into `DAISY_RX1_Pool` and `DAISY_RX2_Pool`, both of which are 256-byte circular buffers (`AMDS_RX_BUF_SIZE`). Utilizing a 256-byte size allows for 8-bit integer math to handle wrap-around without complex modulo logic. - **Error Recovery**: In high-noise environments, UART hardware errors (Parity, Overrun, Noise, or Frame errors) can cause the hardware to drop the `DMAR` (DMA Receiver) bit, halting the stream. The UART Interrupt Service Routines (ISRs) actively monitor for these flags, clear them, and immediately re-enable the DMA requests to ensure continuous stream operation without resetting the device. -## Selective Channel Transmitting - -To optimize processing and transmission bandwidth, the system supports disabling unused sensor channels. - -- **Active Sensor Mask**: A global variable `active_sensor_mask` acts as a bitmask where `1 = Active` and `0 = Inactive`. -- **Target Defaults**: By default, `TARGET_AMDS` activates all 8 channels (`0xFF`), while `TARGET_2S` activates a subset of channels (`0x11`). - ## Modified Sample-and-Transmit Fast Path The firmware bypasses standard abstraction overhead to achieve low latency during critical sampling and transmission windows via the `adc_sample_and_transmit_fast_path` function. From 384fc335ccc7bfb83828b1d297979e8159b051c5 Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 13:54:14 -0500 Subject: [PATCH 17/22] Explain sample-and-transmit fast path --- source/accessories/amds/firmware/index.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/source/accessories/amds/firmware/index.md b/source/accessories/amds/firmware/index.md index 17dab80c..f9dee07f 100644 --- a/source/accessories/amds/firmware/index.md +++ b/source/accessories/amds/firmware/index.md @@ -80,6 +80,19 @@ To optimize processing and transmission bandwidth, the system supports disabling The AMDC platform system default is to send all 8 channels. If a reduced number of channels are being sent, the user must alert the AMDC to this by calling `amdc_set_enabled()`, as the AMDS does not communicate configuration settings with master. ``` +#### Optimized Sample-and-Transmit Fast Path + +The AMDS firmware has been optimized to minimize time from `SYNC_ADC` until the last bit of data is transmitted to the master. The code path used depends on the value of `active_sensor_mask`: + +- `active_sensor_mask != OxFF`: a generalized function `adc_sample_all_daughtercards()` is used. +- `active_sensor_mask == OxFF`: a highly optimized function `adc_sample_and_transmit_fast_path()` is used. + +As compared to the generalized `adc_sample_all_daughtercards()` function, `adc_sample_and_transmit_fast_path` decreases latency by doing the following: + +- **Avoid `active_sensor_mask` Conditional Checks**: to remove processor time associated with `if` statements. +- **Hardware Cycle Counting**: Rather than using `NOP` loops for the 1300ns ADC wait time, the fast path uses the Cortex-M7 DWT Cycle Counter (`DWT->CYCCNT`) for deterministic waiting. +- **Instruction Interleaving**: The code optimizes wait states by starting SPI reads, and transmitting UART header bytes (`0x90`) while the CPU is waiting for the SPI RX buffers to fill. + ### Daisy Chain The AMDS firmware includes support for up to three AMDS boards to be connected in series into a "daisy chain," allowing for 24 sensor cards worth of data to be sent to master. Details of this are provided in [AMDS Daisy Chain](daisy-chain.md). From 419ec98c5fb105a32f12ca45eaf6e2d9b892b7fc Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 13:55:21 -0500 Subject: [PATCH 18/22] Remove unnecessary reference to building and running firmware --- source/accessories/amds/firmware/index.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/source/accessories/amds/firmware/index.md b/source/accessories/amds/firmware/index.md index f9dee07f..c565c504 100644 --- a/source/accessories/amds/firmware/index.md +++ b/source/accessories/amds/firmware/index.md @@ -103,10 +103,6 @@ After start-up, the AMDS firmware is interrupt driven. This means that all criti In the typical flow, the master is operating its PWM output and thus triggering the `SYNC_ADC` ISR periodically. The ADCs on the sensor cards start their conversions and store the latest data in the AMDS memory. Once this is complete, the AMDS sends the data back to the master. Then the AMDS will wait for the next `SYNC_ADC` interrupt. -## Building and Flashing - -For instructions on programming the AMDS, please refer to [Building and Flashing Documentation](building-and-running-firmware.md). - ## Performance Limitations The AMDS firmware design directly affects the operation limits of the `SYNC_ADC` signal. It will continue to work up to some threshold, at which point some ISRs will be missed and the performance will drop. However, the system will not "crash" -- it will continue to work, albeit not as well. From bde84dcd112b8532ffdb641520032db9c2d5e358 Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 14:05:58 -0500 Subject: [PATCH 19/22] Explain optimized use of the uart --- source/accessories/amds/firmware/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/accessories/amds/firmware/index.md b/source/accessories/amds/firmware/index.md index c565c504..7929d5a5 100644 --- a/source/accessories/amds/firmware/index.md +++ b/source/accessories/amds/firmware/index.md @@ -93,6 +93,8 @@ As compared to the generalized `adc_sample_all_daughtercards()` function, `adc_s - **Hardware Cycle Counting**: Rather than using `NOP` loops for the 1300ns ADC wait time, the fast path uses the Cortex-M7 DWT Cycle Counter (`DWT->CYCCNT`) for deterministic waiting. - **Instruction Interleaving**: The code optimizes wait states by starting SPI reads, and transmitting UART header bytes (`0x90`) while the CPU is waiting for the SPI RX buffers to fill. +Both code paths optimize timing by using the ST32 MCU's UART transmit shift register to queue up two bytes of UART transmit data at a time. This is done by optimizing calls to the inline `drv_uart_putc_fast()` function. When the shift register is empty, the function accepts new data without delay. When the shift register is occupied, the function blocks until it can take the new data byte. If the UART tranmit interface is idle, two back-to-back calls can be made to this function without any blocking delay. + ### Daisy Chain The AMDS firmware includes support for up to three AMDS boards to be connected in series into a "daisy chain," allowing for 24 sensor cards worth of data to be sent to master. Details of this are provided in [AMDS Daisy Chain](daisy-chain.md). From ba6d6850aa6258203ebf64e93e758460b4fd777e Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 14:17:19 -0500 Subject: [PATCH 20/22] Add further more daisy chain details - further information on theory of operation - architecture details - move comments that apply to non-daisy-chain AMDC mode to firmware article --- .../accessories/amds/firmware/daisy-chain.md | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/source/accessories/amds/firmware/daisy-chain.md b/source/accessories/amds/firmware/daisy-chain.md index cb70bbde..0e92d19e 100644 --- a/source/accessories/amds/firmware/daisy-chain.md +++ b/source/accessories/amds/firmware/daisy-chain.md @@ -12,30 +12,41 @@ The AMDC and AMDS allow up to three AMDS boards to be daisy chained together on Each AMDS can run the same firmware, and does not need to know it is in a daisy chain. To each AMDS, the board "downstream" from it (i.e., the board with a lower number in the image above) appears as `master`. +## Theory of Operation + +Upon receiving a `SYNC_ADC` signal, the AMDS performs the following operations: + +1. Assert `SYNC_ADC` on its upstream port +2. Collect and transmit sensor card ADC data as described in the [AMDC firmware article](index.md). +3. Process data received on its incoming `DATA0` and `DATA1` ports from any upstream AMDS boards + - Header packets are incremented by `0x04` + - Data is transmitted to the corresponding downstream port; for example, if the packet arrived via the upstream `DATA0` port, it will go out the downstream `DATA0` port + ## Hardware The cabling between each pair of boards runs at the same baudrate (20 Mbps). Currently released AMDS hardware relies on a daisy chain adapter board placed between each pair of AMDS boards to add the necessary transceivers. Details on this board can be found in the AMDS git repo's [`AMDS/Accessories/DaisyChainAdapter` directory](https://github.com/Severson-Group/AMDS/tree/develop/Accessories/DaisyChainAdapter). -## Direct Memory Access (DMA) Setup for Receiving Data +Custom cabling must be used between AMDS boards to transpose the UART `RX` and `TX` pins. -To ensure near zero-CPU overhead when receiving incoming UART data, the firmware utilizes DMA streams. +## Architecture -- **Circular Buffers**: Incoming daisy-chain data is placed into `DAISY_RX1_Pool` and `DAISY_RX2_Pool`, both of which are 256-byte circular buffers (`AMDS_RX_BUF_SIZE`). Utilizing a 256-byte size allows for 8-bit integer math to handle wrap-around without complex modulo logic. -- **Error Recovery**: In high-noise environments, UART hardware errors (Parity, Overrun, Noise, or Frame errors) can cause the hardware to drop the `DMAR` (DMA Receiver) bit, halting the stream. The UART Interrupt Service Routines (ISRs) actively monitor for these flags, clear them, and immediately re-enable the DMA requests to ensure continuous stream operation without resetting the device. +### Direct Memory Access (DMA) for Receiving Data -## Modified Sample-and-Transmit Fast Path +To ensure near zero-CPU overhead when receiving incoming UART data, the firmware utilizes DMA streams to receive `DATA0` and `DATA1` data from upstream AMDS boards. -The firmware bypasses standard abstraction overhead to achieve low latency during critical sampling and transmission windows via the `adc_sample_and_transmit_fast_path` function. +- **Circular Buffers**: Incoming daisy-chain data is placed into `DAISY_RX1_Pool` and `DAISY_RX2_Pool`, both of which are 256-byte circular buffers (`AMDS_RX_BUF_SIZE`). Utilizing a 256-byte size allows for 8-bit integer math to handle wrap-around without complex modulo logic. +- **Error Recovery**: In high-noise environments, UART hardware errors (Parity, Overrun, Noise, or Frame errors) can cause the hardware to drop the `DMAR` (DMA Receiver) bit, halting the stream. The UART Interrupt Service Routines (ISRs) actively monitor for these flags, clear them, and immediately re-enable the DMA requests to ensure continuous stream operation without resetting the device. -- **Hardware Cycle Counting**: Rather than using `NOP` loops for the mandatory 1300ns ADC wait time, the fast path uses the Cortex-M7 DWT Cycle Counter (`DWT->CYCCNT`) for deterministic waiting. -- **Instruction Interleaving**: The code optimizes wait states by starting SPI reads, and transmitting UART header bytes (`0x90`) while the CPU is waiting for the SPI RX buffers to fill. +### Processing Data from Upstream AMDS Devices -## Process Routing Architecture +Data received from upstream devices is processed immediately after transmitting all data collected from local sensor cards. This is handled by the `process_routing()` function. The timing of this code is carefully optimized to minimize the total transmit time to the AMDC across the enitre link. -Handling high-speed daisy-chained data relies on the `try_process_routing()` and `process_routing()` implementations. +Implementation details: -- **Thread-safe Invocation**: The main `while(1)` loop constantly checks `drv_uart_has_dma_data()` and invokes `try_process_routing()`. This wrapper uses an atomic lock (`is_routing_active`) to safely avert reentrancy without stalling the CPU or permanently blinding interrupts. -- **Dual-Stream Optimization**: Inside `process_routing()`, if both UART streams have at least a full 3-byte packet ready, the logic processes them completely interleaved. This keeps both hardware TX lines saturated simultaneously. -- **Single-Stream and Slow Path**: If one UART runs slightly faster, it employs a Single-Stream Fast Path. If a packet gets fragmented across a DMA boundary or becomes misaligned, the system reverts to a 1-byte-at-a-time State Machine (the "Slow Path") to recover the stream automatically. +- **Collection of Complete Packets**: The code attempts to collect complete three byte packets prior to processing. Wait timeouts are implemented. +- **Dual-Stream Optimization**: If both UART streams have at least a full 3-byte packet ready, the logic processes them completely interleaved. This keeps both hardware TX lines saturated simultaneously. +- **Single-Stream Optimization**: If only one UART has a 3 byte packet (i.e., a different number of packets are broadcast due to `active_sensor_mask != 0xFF` on an upstream AMDS), the code follows a Single-Stream Fast Path. +- **Fall-Back, Slow Path**: If a packet gets fragmented across a DMA boundary or becomes misaligned, the system reverts to a 1-byte-at-a-time State Machine (the "Slow Path") to recover the stream. +- **Thread-safe Invocation**: The AMDS attempts to broadcast all DMA data within a single call to `process_routing()` from the `SYNC_ADC` interrupt context. However, if this times out, the firmware provides a fall-back path: the main `while(1)` loop constantly checks `drv_uart_has_dma_data()` and invokes `process_routing()` in a thread-safe manner if any further data arrives. From ed375e1e822915890171274bc14c4bdc18e52a40 Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 14:23:49 -0500 Subject: [PATCH 21/22] Add preliminary benchmark data --- source/accessories/amds/firmware/daisy-chain.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/source/accessories/amds/firmware/daisy-chain.md b/source/accessories/amds/firmware/daisy-chain.md index 0e92d19e..09dce5c8 100644 --- a/source/accessories/amds/firmware/daisy-chain.md +++ b/source/accessories/amds/firmware/daisy-chain.md @@ -50,3 +50,10 @@ Implementation details: - **Single-Stream Optimization**: If only one UART has a 3 byte packet (i.e., a different number of packets are broadcast due to `active_sensor_mask != 0xFF` on an upstream AMDS), the code follows a Single-Stream Fast Path. - **Fall-Back, Slow Path**: If a packet gets fragmented across a DMA boundary or becomes misaligned, the system reverts to a 1-byte-at-a-time State Machine (the "Slow Path") to recover the stream. - **Thread-safe Invocation**: The AMDS attempts to broadcast all DMA data within a single call to `process_routing()` from the `SYNC_ADC` interrupt context. However, if this times out, the firmware provides a fall-back path: the main `while(1)` loop constantly checks `drv_uart_has_dma_data()` and invokes `process_routing()` in a thread-safe manner if any further data arrives. + +## Performance + +Daisy chain benchmark testing shows the following complete transmission times from assertion of `SYNC_ADC` to the last bit arriving at the AMDC: + +- **24 sensors** (3x AMDS boards, each with 8 sensor cards): `27 us` +- **6 sensors** (3x 2S boards, each with 2 sensor cards): `13.7 us` From 4b6b617450ccbaa83a3d868108a66c34817818f5 Mon Sep 17 00:00:00 2001 From: Eric Severson Date: Sun, 17 May 2026 14:33:15 -0500 Subject: [PATCH 22/22] Remove unintended change Removed warning block from profiling tasks tutorial. --- source/getting-started/tutorials/profiling-tasks/index.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/source/getting-started/tutorials/profiling-tasks/index.md b/source/getting-started/tutorials/profiling-tasks/index.md index 990ab0de..34c817e5 100644 --- a/source/getting-started/tutorials/profiling-tasks/index.md +++ b/source/getting-started/tutorials/profiling-tasks/index.md @@ -64,10 +64,6 @@ int task_controller_init(void) // ... ``` -```{warning} -Ensure that you -``` - Next, add task functions which wrap the `print()` and `reset()` functions for the timing stats: `task_controller.c`: