Add bring-up diagnostic instrumentation to clocking/LO subsystem and main init

Observe-before-fix instrumentation for bench bring-up: adds timestamped
DIAG logging to the AD9523 clock config, ADF4382A LO manager, power
sequencing, lock monitoring, temperature monitoring, and safe-mode entry.
Annotates known bugs (double ad9523_setup call, timed-sync init ordering,
TriggerTimedSync no-op, phase-shift before init-check, last_check timer
collision) without changing any runtime behavior.
This commit is contained in:
Jason
2026-03-19 08:32:25 +02:00
parent 981bd271fa
commit bf912067cc
3 changed files with 912 additions and 518 deletions
@@ -1,4 +1,5 @@
#include "adf4382a_manager.h" #include "adf4382a_manager.h"
#include "diag_log.h"
#include "no_os_delay.h" #include "no_os_delay.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -16,8 +17,14 @@ int ADF4382A_Manager_Init(ADF4382A_Manager *manager, SyncMethod method)
{ {
struct adf4382_init_param tx_param, rx_param; struct adf4382_init_param tx_param, rx_param;
int ret; int ret;
uint32_t t_start = HAL_GetTick();
DIAG_SECTION("ADF4382A LO MANAGER INIT");
DIAG("LO", "Init called with sync_method=%d (%s)",
method, (method == SYNC_METHOD_TIMED) ? "TIMED" : "EZSYNC");
if (!manager) { if (!manager) {
DIAG_ERR("LO", "Init called with NULL manager pointer");
return ADF4382A_MANAGER_ERROR_INVALID; return ADF4382A_MANAGER_ERROR_INVALID;
} }
@@ -29,6 +36,8 @@ int ADF4382A_Manager_Init(ADF4382A_Manager *manager, SyncMethod method)
manager->tx_phase_shift_ps = 0; manager->tx_phase_shift_ps = 0;
manager->rx_phase_shift_ps = 0; manager->rx_phase_shift_ps = 0;
DIAG("LO", "Manager struct zeroed, initialized=%s", manager->initialized ? "true" : "false");
// Initialize SPI parameters in manager // Initialize SPI parameters in manager
memset(&manager->spi_tx_param, 0, sizeof(manager->spi_tx_param)); memset(&manager->spi_tx_param, 0, sizeof(manager->spi_tx_param));
memset(&manager->spi_rx_param, 0, sizeof(manager->spi_rx_param)); memset(&manager->spi_rx_param, 0, sizeof(manager->spi_rx_param));
@@ -51,6 +60,9 @@ int ADF4382A_Manager_Init(ADF4382A_Manager *manager, SyncMethod method)
manager->spi_rx_param.platform_ops = NULL; manager->spi_rx_param.platform_ops = NULL;
manager->spi_rx_param.extra = &hspi4; manager->spi_rx_param.extra = &hspi4;
DIAG("LO", "SPI4 params: TX_CS=0x%04X RX_CS=0x%04X speed=%lu Hz",
TX_CS_Pin, RX_CS_Pin, (unsigned long)ADF4382A_SPI_SPEED_HZ);
// Configure TX parameters (10.5 GHz) // Configure TX parameters (10.5 GHz)
memset(&tx_param, 0, sizeof(tx_param)); memset(&tx_param, 0, sizeof(tx_param));
tx_param.spi_3wire_en = 0; tx_param.spi_3wire_en = 0;
@@ -79,70 +91,113 @@ int ADF4382A_Manager_Init(ADF4382A_Manager *manager, SyncMethod method)
rx_param.ld_count = 0x07; rx_param.ld_count = 0x07;
rx_param.spi_init = &manager->spi_rx_param; rx_param.spi_init = &manager->spi_rx_param;
DIAG("LO", "TX target: %llu Hz, ref=%llu Hz, cp_i=%d, bleed=%d",
(unsigned long long)TX_FREQ_HZ, (unsigned long long)REF_FREQ_HZ,
tx_param.cp_i, tx_param.bleed_word);
DIAG("LO", "RX target: %llu Hz, ref=%llu Hz, cp_i=%d, bleed=%d",
(unsigned long long)RX_FREQ_HZ, (unsigned long long)REF_FREQ_HZ,
rx_param.cp_i, rx_param.bleed_word);
// Enable chips // Enable chips
DIAG("LO", "Asserting CE pins (TX + RX)...");
set_chip_enable(TX_CE_Pin, true); set_chip_enable(TX_CE_Pin, true);
set_chip_enable(RX_CE_Pin, true); set_chip_enable(RX_CE_Pin, true);
no_os_udelay(1000); no_os_udelay(1000);
DIAG("LO", "CE pins asserted, waited 1 ms");
// Initialize DELADJ and DELSTR pins // Initialize DELADJ and DELSTR pins
set_deladj_pin(0, false); // TX device set_deladj_pin(0, false); // TX device
set_deladj_pin(1, false); // RX device set_deladj_pin(1, false); // RX device
set_delstr_pin(0, false); // TX device set_delstr_pin(0, false); // TX device
set_delstr_pin(1, false); // RX device set_delstr_pin(1, false); // RX device
DIAG("LO", "DELADJ/DELSTR pins initialized to LOW");
// Initialize TX device first // Initialize TX device first
DIAG("LO", "--- TX ADF4382A init (10.5 GHz) ---");
uint32_t t_tx = HAL_GetTick();
printf("Initializing TX ADF4382A (10.5 GHz) on SPI4...\n"); printf("Initializing TX ADF4382A (10.5 GHz) on SPI4...\n");
ret = adf4382_init(&manager->tx_dev, &tx_param); ret = adf4382_init(&manager->tx_dev, &tx_param);
DIAG("LO", "TX adf4382_init() returned %d (took %lu ms)",
ret, (unsigned long)(HAL_GetTick() - t_tx));
if (ret) { if (ret) {
DIAG_ERR("LO", "TX init FAILED: %d -- disabling CE pins", ret);
printf("TX ADF4382A initialization failed: %d\n", ret); printf("TX ADF4382A initialization failed: %d\n", ret);
set_chip_enable(TX_CE_Pin, false); set_chip_enable(TX_CE_Pin, false);
set_chip_enable(RX_CE_Pin, false); set_chip_enable(RX_CE_Pin, false);
return ADF4382A_MANAGER_ERROR_SPI; return ADF4382A_MANAGER_ERROR_SPI;
} }
DIAG("LO", "TX init OK, dev_ptr=%p", (void*)manager->tx_dev);
// Small delay between initializations // Small delay between initializations
no_os_udelay(5000); no_os_udelay(5000);
DIAG("LO", "5 ms inter-device delay complete");
// Initialize RX device // Initialize RX device
DIAG("LO", "--- RX ADF4382A init (10.38 GHz) ---");
uint32_t t_rx = HAL_GetTick();
printf("Initializing RX ADF4382A (10.38 GHz) on SPI4...\n"); printf("Initializing RX ADF4382A (10.38 GHz) on SPI4...\n");
ret = adf4382_init(&manager->rx_dev, &rx_param); ret = adf4382_init(&manager->rx_dev, &rx_param);
DIAG("LO", "RX adf4382_init() returned %d (took %lu ms)",
ret, (unsigned long)(HAL_GetTick() - t_rx));
if (ret) { if (ret) {
DIAG_ERR("LO", "RX init FAILED: %d -- cleaning up TX dev", ret);
printf("RX ADF4382A initialization failed: %d\n", ret); printf("RX ADF4382A initialization failed: %d\n", ret);
adf4382_remove(manager->tx_dev); adf4382_remove(manager->tx_dev);
set_chip_enable(TX_CE_Pin, false); set_chip_enable(TX_CE_Pin, false);
set_chip_enable(RX_CE_Pin, false); set_chip_enable(RX_CE_Pin, false);
return ADF4382A_MANAGER_ERROR_SPI; return ADF4382A_MANAGER_ERROR_SPI;
} }
DIAG("LO", "RX init OK, dev_ptr=%p", (void*)manager->rx_dev);
// Set output power // Set output power
DIAG("LO", "Setting output power (both ch0=12, ch1=12)...");
adf4382_set_out_power(manager->tx_dev, 0, 12); adf4382_set_out_power(manager->tx_dev, 0, 12);
adf4382_set_out_power(manager->tx_dev, 1, 12); adf4382_set_out_power(manager->tx_dev, 1, 12);
adf4382_set_out_power(manager->rx_dev, 0, 12); adf4382_set_out_power(manager->rx_dev, 0, 12);
adf4382_set_out_power(manager->rx_dev, 1, 12); adf4382_set_out_power(manager->rx_dev, 1, 12);
// Enable outputs // Enable outputs
DIAG("LO", "Enabling outputs: TX_ch0=ON TX_ch1=OFF, RX_ch0=ON RX_ch1=OFF");
adf4382_set_en_chan(manager->tx_dev, 0, true); adf4382_set_en_chan(manager->tx_dev, 0, true);
adf4382_set_en_chan(manager->tx_dev, 1, false); adf4382_set_en_chan(manager->tx_dev, 1, false);
adf4382_set_en_chan(manager->rx_dev, 0, true); adf4382_set_en_chan(manager->rx_dev, 0, true);
adf4382_set_en_chan(manager->rx_dev, 1, false); adf4382_set_en_chan(manager->rx_dev, 1, false);
// Setup synchronization based on selected method // Setup synchronization based on selected method
// BUG DIAGNOSTIC: At this point manager->initialized is still false.
// ADF4382A_SetupTimedSync() and ADF4382A_SetupEZSync() both check
// manager->initialized and will return -2 (NOT_INIT) if false.
// This means sync setup ALWAYS SILENTLY FAILS during init.
DIAG_WARN("LO", "About to call sync setup -- manager->initialized=%s (BUG: will fail -2 if false)",
manager->initialized ? "true" : "false");
if (method == SYNC_METHOD_TIMED) { if (method == SYNC_METHOD_TIMED) {
ret = ADF4382A_SetupTimedSync(manager); ret = ADF4382A_SetupTimedSync(manager);
DIAG("LO", "ADF4382A_SetupTimedSync() returned %d", ret);
if (ret) { if (ret) {
DIAG_ERR("LO", "Timed sync setup FAILED: %d (expected -2 due to init ordering bug)", ret);
printf("Timed sync setup failed: %d\n", ret); printf("Timed sync setup failed: %d\n", ret);
// NOTE: Error is logged but swallowed -- init continues
} }
} else { } else {
ret = ADF4382A_SetupEZSync(manager); ret = ADF4382A_SetupEZSync(manager);
DIAG("LO", "ADF4382A_SetupEZSync() returned %d", ret);
if (ret) { if (ret) {
DIAG_ERR("LO", "EZSync setup FAILED: %d (expected -2 due to init ordering bug)", ret);
printf("EZSync setup failed: %d\n", ret); printf("EZSync setup failed: %d\n", ret);
} }
} }
manager->initialized = true; manager->initialized = true;
DIAG("LO", "manager->initialized set to true (sync setup was called BEFORE this)");
printf("ADF4382A Manager initialized with %s synchronization on SPI4\n", printf("ADF4382A Manager initialized with %s synchronization on SPI4\n",
(method == SYNC_METHOD_TIMED) ? "TIMED" : "EZSYNC"); (method == SYNC_METHOD_TIMED) ? "TIMED" : "EZSYNC");
DIAG_ELAPSED("LO", "Total Manager_Init", t_start);
DIAG("LO", "Init returning OK (but sync setup was %s)",
(ret == 0) ? "successful" : "FAILED -- sync NOT configured");
return ADF4382A_MANAGER_OK; return ADF4382A_MANAGER_OK;
} }
@@ -150,7 +205,12 @@ int ADF4382A_SetupTimedSync(ADF4382A_Manager *manager)
{ {
int ret; int ret;
DIAG("LO", "SetupTimedSync called, manager=%p initialized=%s",
(void*)manager, (manager ? (manager->initialized ? "true" : "false") : "N/A"));
if (!manager || !manager->initialized) { if (!manager || !manager->initialized) {
DIAG_ERR("LO", "SetupTimedSync REJECTED: %s",
!manager ? "NULL manager" : "not initialized (initialized=false)");
return ADF4382A_MANAGER_ERROR_NOT_INIT; return ADF4382A_MANAGER_ERROR_NOT_INIT;
} }
@@ -158,20 +218,25 @@ int ADF4382A_SetupTimedSync(ADF4382A_Manager *manager)
// Setup TX for timed sync // Setup TX for timed sync
ret = adf4382_set_timed_sync_setup(manager->tx_dev, true); ret = adf4382_set_timed_sync_setup(manager->tx_dev, true);
DIAG("LO", "TX adf4382_set_timed_sync_setup() returned %d", ret);
if (ret) { if (ret) {
DIAG_ERR("LO", "TX timed sync register write FAILED: %d", ret);
printf("TX timed sync setup failed: %d\n", ret); printf("TX timed sync setup failed: %d\n", ret);
return ret; return ret;
} }
// Setup RX for timed sync // Setup RX for timed sync
ret = adf4382_set_timed_sync_setup(manager->rx_dev, true); ret = adf4382_set_timed_sync_setup(manager->rx_dev, true);
DIAG("LO", "RX adf4382_set_timed_sync_setup() returned %d", ret);
if (ret) { if (ret) {
DIAG_ERR("LO", "RX timed sync register write FAILED: %d", ret);
printf("RX timed sync setup failed: %d\n", ret); printf("RX timed sync setup failed: %d\n", ret);
return ret; return ret;
} }
manager->sync_method = SYNC_METHOD_TIMED; manager->sync_method = SYNC_METHOD_TIMED;
printf("Timed synchronization configured for 60 MHz SYNCP/SYNCN\n"); printf("Timed synchronization configured for 60 MHz SYNCP/SYNCN\n");
DIAG("LO", "Timed sync setup complete for both TX and RX");
return ADF4382A_MANAGER_OK; return ADF4382A_MANAGER_OK;
} }
@@ -180,7 +245,12 @@ int ADF4382A_SetupEZSync(ADF4382A_Manager *manager)
{ {
int ret; int ret;
DIAG("LO", "SetupEZSync called, manager=%p initialized=%s",
(void*)manager, (manager ? (manager->initialized ? "true" : "false") : "N/A"));
if (!manager || !manager->initialized) { if (!manager || !manager->initialized) {
DIAG_ERR("LO", "SetupEZSync REJECTED: %s",
!manager ? "NULL manager" : "not initialized (initialized=false)");
return ADF4382A_MANAGER_ERROR_NOT_INIT; return ADF4382A_MANAGER_ERROR_NOT_INIT;
} }
@@ -188,6 +258,7 @@ int ADF4382A_SetupEZSync(ADF4382A_Manager *manager)
// Setup TX for EZSync // Setup TX for EZSync
ret = adf4382_set_ezsync_setup(manager->tx_dev, true); ret = adf4382_set_ezsync_setup(manager->tx_dev, true);
DIAG("LO", "TX adf4382_set_ezsync_setup() returned %d", ret);
if (ret) { if (ret) {
printf("TX EZSync setup failed: %d\n", ret); printf("TX EZSync setup failed: %d\n", ret);
return ret; return ret;
@@ -195,6 +266,7 @@ int ADF4382A_SetupEZSync(ADF4382A_Manager *manager)
// Setup RX for EZSync // Setup RX for EZSync
ret = adf4382_set_ezsync_setup(manager->rx_dev, true); ret = adf4382_set_ezsync_setup(manager->rx_dev, true);
DIAG("LO", "RX adf4382_set_ezsync_setup() returned %d", ret);
if (ret) { if (ret) {
printf("RX EZSync setup failed: %d\n", ret); printf("RX EZSync setup failed: %d\n", ret);
return ret; return ret;
@@ -202,6 +274,7 @@ int ADF4382A_SetupEZSync(ADF4382A_Manager *manager)
manager->sync_method = SYNC_METHOD_EZSYNC; manager->sync_method = SYNC_METHOD_EZSYNC;
printf("EZSync configured\n"); printf("EZSync configured\n");
DIAG("LO", "EZSync setup complete for both TX and RX");
return ADF4382A_MANAGER_OK; return ADF4382A_MANAGER_OK;
} }
@@ -209,9 +282,20 @@ int ADF4382A_SetupEZSync(ADF4382A_Manager *manager)
int ADF4382A_TriggerTimedSync(ADF4382A_Manager *manager) int ADF4382A_TriggerTimedSync(ADF4382A_Manager *manager)
{ {
if (!manager || !manager->initialized || manager->sync_method != SYNC_METHOD_TIMED) { if (!manager || !manager->initialized || manager->sync_method != SYNC_METHOD_TIMED) {
DIAG_ERR("LO", "TriggerTimedSync REJECTED: init=%s method=%d",
(manager && manager->initialized) ? "true" : "false",
manager ? manager->sync_method : -1);
return ADF4382A_MANAGER_ERROR_NOT_INIT; return ADF4382A_MANAGER_ERROR_NOT_INIT;
} }
// NOTE: This function currently does NOT trigger anything -- it only prints.
// The assumption is that the 60 MHz SYNCP/SYNCN from AD9523 are always present
// and timed sync happens automatically once the timed_sync_setup registers are
// programmed. But if SetupTimedSync failed (init ordering bug), this is a no-op
// on top of a no-op.
DIAG_WARN("LO", "TriggerTimedSync called -- NOTE: function body is advisory only, no hardware trigger issued");
DIAG_WARN("LO", "If SetupTimedSync failed during init, timed sync registers were NEVER written");
printf("Timed sync ready - SYNC pin will trigger synchronization\n"); printf("Timed sync ready - SYNC pin will trigger synchronization\n");
printf("Ensure 60 MHz phase-aligned clocks are present on SYNCP/SYNCN pins\n"); printf("Ensure 60 MHz phase-aligned clocks are present on SYNCP/SYNCN pins\n");
@@ -223,18 +307,23 @@ int ADF4382A_TriggerEZSync(ADF4382A_Manager *manager)
int ret; int ret;
if (!manager || !manager->initialized || manager->sync_method != SYNC_METHOD_EZSYNC) { if (!manager || !manager->initialized || manager->sync_method != SYNC_METHOD_EZSYNC) {
DIAG_ERR("LO", "TriggerEZSync REJECTED");
return ADF4382A_MANAGER_ERROR_NOT_INIT; return ADF4382A_MANAGER_ERROR_NOT_INIT;
} }
DIAG("LO", "Triggering EZSync via SPI...");
// Trigger software sync on both devices // Trigger software sync on both devices
ret = adf4382_set_sw_sync(manager->tx_dev, true); ret = adf4382_set_sw_sync(manager->tx_dev, true);
if (ret) { if (ret) {
DIAG_ERR("LO", "TX sw_sync SET failed: %d", ret);
printf("TX software sync failed: %d\n", ret); printf("TX software sync failed: %d\n", ret);
return ADF4382A_MANAGER_ERROR_SPI; return ADF4382A_MANAGER_ERROR_SPI;
} }
ret = adf4382_set_sw_sync(manager->rx_dev, true); ret = adf4382_set_sw_sync(manager->rx_dev, true);
if (ret) { if (ret) {
DIAG_ERR("LO", "RX sw_sync SET failed: %d", ret);
printf("RX software sync failed: %d\n", ret); printf("RX software sync failed: %d\n", ret);
return ADF4382A_MANAGER_ERROR_SPI; return ADF4382A_MANAGER_ERROR_SPI;
} }
@@ -245,17 +334,20 @@ int ADF4382A_TriggerEZSync(ADF4382A_Manager *manager)
// Clear software sync // Clear software sync
ret = adf4382_set_sw_sync(manager->tx_dev, false); ret = adf4382_set_sw_sync(manager->tx_dev, false);
if (ret) { if (ret) {
DIAG_ERR("LO", "TX sw_sync CLEAR failed: %d", ret);
printf("TX sync clear failed: %d\n", ret); printf("TX sync clear failed: %d\n", ret);
return ADF4382A_MANAGER_ERROR_SPI; return ADF4382A_MANAGER_ERROR_SPI;
} }
ret = adf4382_set_sw_sync(manager->rx_dev, false); ret = adf4382_set_sw_sync(manager->rx_dev, false);
if (ret) { if (ret) {
DIAG_ERR("LO", "RX sw_sync CLEAR failed: %d", ret);
printf("RX sync clear failed: %d\n", ret); printf("RX sync clear failed: %d\n", ret);
return ADF4382A_MANAGER_ERROR_SPI; return ADF4382A_MANAGER_ERROR_SPI;
} }
printf("EZSync triggered via SPI\n"); printf("EZSync triggered via SPI\n");
DIAG("LO", "EZSync trigger complete (set + 10us + clear)");
return ADF4382A_MANAGER_OK; return ADF4382A_MANAGER_OK;
} }
@@ -265,6 +357,8 @@ int ADF4382A_Manager_Deinit(ADF4382A_Manager *manager)
return ADF4382A_MANAGER_ERROR_NOT_INIT; return ADF4382A_MANAGER_ERROR_NOT_INIT;
} }
DIAG("LO", "Manager deinit starting...");
// Disable outputs first // Disable outputs first
if (manager->tx_dev) { if (manager->tx_dev) {
adf4382_set_en_chan(manager->tx_dev, 0, false); adf4382_set_en_chan(manager->tx_dev, 0, false);
@@ -298,6 +392,7 @@ int ADF4382A_Manager_Deinit(ADF4382A_Manager *manager)
manager->initialized = false; manager->initialized = false;
printf("ADF4382A Manager deinitialized\n"); printf("ADF4382A Manager deinitialized\n");
DIAG("LO", "Manager deinit complete");
return ADF4382A_MANAGER_OK; return ADF4382A_MANAGER_OK;
} }
@@ -313,26 +408,45 @@ int ADF4382A_CheckLockStatus(ADF4382A_Manager *manager, bool *tx_locked, bool *r
// Read lock status from registers // Read lock status from registers
ret = adf4382_spi_read(manager->tx_dev, 0x58, &tx_status); ret = adf4382_spi_read(manager->tx_dev, 0x58, &tx_status);
if (ret) { if (ret) {
DIAG_ERR("LO", "TX lock status SPI read FAILED: %d", ret);
printf("TX lock status read failed: %d\n", ret); printf("TX lock status read failed: %d\n", ret);
return ADF4382A_MANAGER_ERROR_SPI; return ADF4382A_MANAGER_ERROR_SPI;
} }
ret = adf4382_spi_read(manager->rx_dev, 0x58, &rx_status); ret = adf4382_spi_read(manager->rx_dev, 0x58, &rx_status);
if (ret) { if (ret) {
DIAG_ERR("LO", "RX lock status SPI read FAILED: %d", ret);
printf("RX lock status read failed: %d\n", ret); printf("RX lock status read failed: %d\n", ret);
return ADF4382A_MANAGER_ERROR_SPI; return ADF4382A_MANAGER_ERROR_SPI;
} }
*tx_locked = (tx_status & ADF4382_LOCKED_MSK) != 0; bool tx_reg_locked = (tx_status & ADF4382_LOCKED_MSK) != 0;
*rx_locked = (rx_status & ADF4382_LOCKED_MSK) != 0; bool rx_reg_locked = (rx_status & ADF4382_LOCKED_MSK) != 0;
// Also check GPIO lock detect pins as backup // Also check GPIO lock detect pins as backup
bool tx_gpio_locked = HAL_GPIO_ReadPin(TX_LKDET_GPIO_Port, TX_LKDET_Pin) == GPIO_PIN_SET; bool tx_gpio_locked = HAL_GPIO_ReadPin(TX_LKDET_GPIO_Port, TX_LKDET_Pin) == GPIO_PIN_SET;
bool rx_gpio_locked = HAL_GPIO_ReadPin(RX_LKDET_GPIO_Port, RX_LKDET_Pin) == GPIO_PIN_SET; bool rx_gpio_locked = HAL_GPIO_ReadPin(RX_LKDET_GPIO_Port, RX_LKDET_Pin) == GPIO_PIN_SET;
// Diagnostic: show both register and GPIO readings independently
DIAG("LO", "Lock check: TX reg[0x58]=0x%02X(%s) GPIO=%s | RX reg[0x58]=0x%02X(%s) GPIO=%s",
tx_status, tx_reg_locked ? "LK" : "UNL", tx_gpio_locked ? "HI" : "LO",
rx_status, rx_reg_locked ? "LK" : "UNL", rx_gpio_locked ? "HI" : "LO");
// Flag disagreement between register and GPIO
if (tx_reg_locked != tx_gpio_locked) {
DIAG_WARN("LO", "TX LOCK DISAGREE: reg=%s GPIO=%s -- possible pin mapping issue",
tx_reg_locked ? "LOCKED" : "UNLOCKED",
tx_gpio_locked ? "HIGH" : "LOW");
}
if (rx_reg_locked != rx_gpio_locked) {
DIAG_WARN("LO", "RX LOCK DISAGREE: reg=%s GPIO=%s -- possible pin mapping issue",
rx_reg_locked ? "LOCKED" : "UNLOCKED",
rx_gpio_locked ? "HIGH" : "LOW");
}
// Use both register and GPIO status // Use both register and GPIO status
*tx_locked = *tx_locked && tx_gpio_locked; *tx_locked = tx_reg_locked && tx_gpio_locked;
*rx_locked = *rx_locked && rx_gpio_locked; *rx_locked = rx_reg_locked && rx_gpio_locked;
return ADF4382A_MANAGER_OK; return ADF4382A_MANAGER_OK;
} }
@@ -349,6 +463,8 @@ int ADF4382A_SetOutputPower(ADF4382A_Manager *manager, uint8_t tx_power, uint8_t
tx_power = (tx_power > 15) ? 15 : tx_power; tx_power = (tx_power > 15) ? 15 : tx_power;
rx_power = (rx_power > 15) ? 15 : rx_power; rx_power = (rx_power > 15) ? 15 : rx_power;
DIAG("LO", "SetOutputPower: TX=%d RX=%d", tx_power, rx_power);
// Set TX power for both channels // Set TX power for both channels
ret = adf4382_set_out_power(manager->tx_dev, 0, tx_power); ret = adf4382_set_out_power(manager->tx_dev, 0, tx_power);
if (ret) return ret; if (ret) return ret;
@@ -372,6 +488,9 @@ int ADF4382A_EnableOutputs(ADF4382A_Manager *manager, bool tx_enable, bool rx_en
return ADF4382A_MANAGER_ERROR_NOT_INIT; return ADF4382A_MANAGER_ERROR_NOT_INIT;
} }
DIAG("LO", "EnableOutputs: TX=%s RX=%s",
tx_enable ? "ON" : "OFF", rx_enable ? "ON" : "OFF");
// Enable/disable TX outputs // Enable/disable TX outputs
ret = adf4382_set_en_chan(manager->tx_dev, 0, tx_enable); ret = adf4382_set_en_chan(manager->tx_dev, 0, tx_enable);
if (ret) return ret; if (ret) return ret;
@@ -401,15 +520,21 @@ int ADF4382A_SetPhaseShift(ADF4382A_Manager *manager, uint16_t tx_phase_ps, uint
tx_phase_ps = (tx_phase_ps > PHASE_SHIFT_MAX_PS) ? PHASE_SHIFT_MAX_PS : tx_phase_ps; tx_phase_ps = (tx_phase_ps > PHASE_SHIFT_MAX_PS) ? PHASE_SHIFT_MAX_PS : tx_phase_ps;
rx_phase_ps = (rx_phase_ps > PHASE_SHIFT_MAX_PS) ? PHASE_SHIFT_MAX_PS : rx_phase_ps; rx_phase_ps = (rx_phase_ps > PHASE_SHIFT_MAX_PS) ? PHASE_SHIFT_MAX_PS : rx_phase_ps;
DIAG("LO", "SetPhaseShift: TX=%d ps, RX=%d ps", tx_phase_ps, rx_phase_ps);
// Convert phase shift to duty cycle and apply // Convert phase shift to duty cycle and apply
if (tx_phase_ps != manager->tx_phase_shift_ps) { if (tx_phase_ps != manager->tx_phase_shift_ps) {
uint16_t duty_cycle = phase_ps_to_duty_cycle(tx_phase_ps); uint16_t duty_cycle = phase_ps_to_duty_cycle(tx_phase_ps);
DIAG_WARN("LO", "TX phase: %d ps -> duty_cycle=%d/%d (SIMPLIFIED -- not real PWM)",
tx_phase_ps, duty_cycle, DELADJ_MAX_DUTY_CYCLE);
ADF4382A_SetFinePhaseShift(manager, 0, duty_cycle); // 0 = TX device ADF4382A_SetFinePhaseShift(manager, 0, duty_cycle); // 0 = TX device
manager->tx_phase_shift_ps = tx_phase_ps; manager->tx_phase_shift_ps = tx_phase_ps;
} }
if (rx_phase_ps != manager->rx_phase_shift_ps) { if (rx_phase_ps != manager->rx_phase_shift_ps) {
uint16_t duty_cycle = phase_ps_to_duty_cycle(rx_phase_ps); uint16_t duty_cycle = phase_ps_to_duty_cycle(rx_phase_ps);
DIAG_WARN("LO", "RX phase: %d ps -> duty_cycle=%d/%d (SIMPLIFIED -- not real PWM)",
rx_phase_ps, duty_cycle, DELADJ_MAX_DUTY_CYCLE);
ADF4382A_SetFinePhaseShift(manager, 1, duty_cycle); // 1 = RX device ADF4382A_SetFinePhaseShift(manager, 1, duty_cycle); // 1 = RX device
manager->rx_phase_shift_ps = rx_phase_ps; manager->rx_phase_shift_ps = rx_phase_ps;
} }
@@ -445,12 +570,16 @@ int ADF4382A_SetFinePhaseShift(ADF4382A_Manager *manager, uint8_t device, uint16
if (duty_cycle == 0) { if (duty_cycle == 0) {
set_deladj_pin(device, false); set_deladj_pin(device, false);
DIAG("LO", "Dev%d DELADJ=LOW (duty=0)", device);
} else if (duty_cycle >= DELADJ_MAX_DUTY_CYCLE) { } else if (duty_cycle >= DELADJ_MAX_DUTY_CYCLE) {
set_deladj_pin(device, true); set_deladj_pin(device, true);
DIAG("LO", "Dev%d DELADJ=HIGH (duty=max)", device);
} else { } else {
// For intermediate values, you would need PWM generation // For intermediate values, you would need PWM generation
// This is a simplified implementation // This is a simplified implementation
set_deladj_pin(device, true); set_deladj_pin(device, true);
DIAG_WARN("LO", "Dev%d DELADJ=HIGH for duty=%d/%d -- PLACEHOLDER: intermediate values need real PWM",
device, duty_cycle, DELADJ_MAX_DUTY_CYCLE);
} }
printf("Device %d DELADJ duty cycle set to %d/%d\n", printf("Device %d DELADJ duty cycle set to %d/%d\n",
@@ -465,6 +594,8 @@ int ADF4382A_StrobePhaseShift(ADF4382A_Manager *manager, uint8_t device)
return ADF4382A_MANAGER_ERROR_NOT_INIT; return ADF4382A_MANAGER_ERROR_NOT_INIT;
} }
DIAG("LO", "Dev%d DELSTR strobe (%d us pulse)", device, DELADJ_PULSE_WIDTH_US);
// Generate a pulse on DELSTR pin to latch the current DELADJ value // Generate a pulse on DELSTR pin to latch the current DELADJ value
set_delstr_pin(device, true); set_delstr_pin(device, true);
no_os_udelay(DELADJ_PULSE_WIDTH_US); no_os_udelay(DELADJ_PULSE_WIDTH_US);
@@ -0,0 +1,126 @@
/***************************************************************************//**
* @file diag_log.h
* @brief Bring-up diagnostic logging macros for AERIS-10 radar system.
*
* Provides timestamped, subsystem-tagged diagnostic output over USART3.
* All output is observation-only instrumentation -- no behavioral changes.
*
* Usage:
* #include "diag_log.h"
* DIAG("LO", "TX init returned %d", ret);
* DIAG_WARN("CLK", "PLL2 not locked after %lu ms", timeout);
* DIAG_ERR("PA", "IDQ out of range: %d mA", idq_ma);
* DIAG_REG("LO", "TX reg 0x58", reg_val);
* DIAG_GPIO("LO", "TX_LKDET", port, pin);
*
* Compile-time control:
* #define DIAG_DISABLE -- suppress all DIAG output
* #define DIAG_VERBOSE -- include file:line in every message
*
* @author AERIS-10 Bring-up Instrumentation
* @date 2026
*******************************************************************************/
#ifndef DIAG_LOG_H
#define DIAG_LOG_H
#include <stdio.h>
#include <stdint.h>
#include "stm32f7xx_hal.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Core DIAG macro -- timestamped, subsystem-tagged printf.
* Uses HAL_GetTick() for millisecond timestamps.
* Output format: "[ 12345 ms] LO: TX init returned -2\n"
*/
#ifndef DIAG_DISABLE
#ifdef DIAG_VERBOSE
#define DIAG(subsys, fmt, ...) \
printf("[%7lu ms] %s: " fmt " (%s:%d)\n", \
(unsigned long)HAL_GetTick(), subsys, ##__VA_ARGS__, __FILE__, __LINE__)
#else
#define DIAG(subsys, fmt, ...) \
printf("[%7lu ms] %s: " fmt "\n", \
(unsigned long)HAL_GetTick(), subsys, ##__VA_ARGS__)
#endif
/* Severity-tagged variants */
#define DIAG_WARN(subsys, fmt, ...) \
printf("[%7lu ms] %s WARN: " fmt "\n", \
(unsigned long)HAL_GetTick(), subsys, ##__VA_ARGS__)
#define DIAG_ERR(subsys, fmt, ...) \
printf("[%7lu ms] %s **ERR**: " fmt "\n", \
(unsigned long)HAL_GetTick(), subsys, ##__VA_ARGS__)
/* Register read diagnostic -- prints hex value */
#define DIAG_REG(subsys, name, val) \
printf("[%7lu ms] %s: %s = 0x%02X\n", \
(unsigned long)HAL_GetTick(), subsys, name, (unsigned int)(val))
/* Register read diagnostic -- 32-bit variant */
#define DIAG_REG32(subsys, name, val) \
printf("[%7lu ms] %s: %s = 0x%08lX\n", \
(unsigned long)HAL_GetTick(), subsys, name, (unsigned long)(val))
/* GPIO pin state diagnostic */
#define DIAG_GPIO(subsys, name, port, pin) \
printf("[%7lu ms] %s: GPIO %s = %s\n", \
(unsigned long)HAL_GetTick(), subsys, name, \
(HAL_GPIO_ReadPin(port, pin) == GPIO_PIN_SET) ? "HIGH" : "LOW")
/* Boolean condition diagnostic */
#define DIAG_BOOL(subsys, name, val) \
printf("[%7lu ms] %s: %s = %s\n", \
(unsigned long)HAL_GetTick(), subsys, name, (val) ? "YES" : "NO")
/* Section separator for init sequence readability */
#define DIAG_SECTION(title) \
printf("[%7lu ms] ======== %s ========\n", \
(unsigned long)HAL_GetTick(), title)
/* Elapsed time helper -- use with a captured start tick */
#define DIAG_ELAPSED(subsys, label, start_tick) \
printf("[%7lu ms] %s: %s took %lu ms\n", \
(unsigned long)HAL_GetTick(), subsys, label, \
(unsigned long)(HAL_GetTick() - (start_tick)))
#else /* DIAG_DISABLE */
#define DIAG(subsys, fmt, ...) ((void)0)
#define DIAG_WARN(subsys, fmt, ...) ((void)0)
#define DIAG_ERR(subsys, fmt, ...) ((void)0)
#define DIAG_REG(subsys, name, val) ((void)0)
#define DIAG_REG32(subsys, name, val) ((void)0)
#define DIAG_GPIO(subsys, name, port, pin) ((void)0)
#define DIAG_BOOL(subsys, name, val) ((void)0)
#define DIAG_SECTION(title) ((void)0)
#define DIAG_ELAPSED(subsys, label, start) ((void)0)
#endif /* DIAG_DISABLE */
/*
* Subsystem tag constants -- use these for consistency:
* "CLK" -- AD9523 clock generator
* "LO" -- ADF4382A LO synthesizers (manager level)
* "LO_DRV" -- ADF4382 low-level driver
* "BF" -- ADAR1000 beamformer
* "PA" -- Power amplifier bias/monitoring
* "FPGA" -- FPGA communication and handshake
* "USB" -- FT601 USB data path
* "PWR" -- Power sequencing and rail monitoring
* "IMU" -- IMU/GPS/barometer sensors
* "MOT" -- Stepper motor/scan mechanics
* "SYS" -- System-level init, health, safe-mode
*/
#ifdef __cplusplus
}
#endif
#endif /* DIAG_LOG_H */
@@ -59,6 +59,7 @@ extern "C" {
#include "adf4382.h" #include "adf4382.h"
#include "no_os_delay.h" #include "no_os_delay.h"
#include "no_os_error.h" #include "no_os_error.h"
#include "diag_log.h"
} }
#include <cmath> #include <cmath>
#include "DAC5578.h" #include "DAC5578.h"
@@ -1041,34 +1042,65 @@ static int configure_ad9523(void)
init_param.pdata = &pdata; init_param.pdata = &pdata;
DIAG_SECTION("AD9523 CONFIGURE");
DIAG("CLK", "VCXO=%lu Hz, PLL2 N=%d (4*%d+%d)=%d, R2=%d",
(unsigned long)pdata.vcxo_freq,
4 * pdata.pll2_ndiv_b_cnt + pdata.pll2_ndiv_a_cnt,
pdata.pll2_ndiv_b_cnt, pdata.pll2_ndiv_a_cnt,
4 * pdata.pll2_ndiv_b_cnt + pdata.pll2_ndiv_a_cnt,
pdata.pll2_r2_div);
DIAG("CLK", "Enabled channels: 0,1(/12=300M) 4,5(/9=400M) 6(/36=100M) 7(/180=20M) 8,9(/60=60M) 10,11(/30=120M)");
// init ad9523 defaults (fills any missing pdata defaults) // init ad9523 defaults (fills any missing pdata defaults)
DIAG("CLK", "Calling ad9523_init() -- fills pdata defaults");
ad9523_init(&init_param); ad9523_init(&init_param);
/* [BUG ANNOTATION] First ad9523_setup() call -- chip is still in reset
* (AD9523_RESET_RELEASE() hasn't been called yet).
* SPI writes here likely fail silently or go to a reset device. */
DIAG_WARN("CLK", "[BUG] Calling ad9523_setup() #1 BEFORE reset release -- chip in reset, writes likely lost");
uint32_t setup1_start = HAL_GetTick();
ret = ad9523_setup(&dev, &init_param); ret = ad9523_setup(&dev, &init_param);
DIAG("CLK", "ad9523_setup() #1 returned %ld (took %lu ms)",
(long)ret, (unsigned long)(HAL_GetTick() - setup1_start));
// Bring AD9523 out of reset // Bring AD9523 out of reset
DIAG("CLK", "Releasing AD9523 reset (AD9523_RESET_RELEASE)");
AD9523_RESET_RELEASE(); AD9523_RESET_RELEASE();
HAL_Delay(5); HAL_Delay(5);
DIAG("CLK", "AD9523 reset released, waited 5 ms");
// Select REFB (100MHz) using REF_SEL pin (true selects REFB here) // Select REFB (100MHz) using REF_SEL pin (true selects REFB here)
DIAG("CLK", "Selecting REFB (100 MHz) via REF_SEL pin");
AD9523_REF_SEL(true); AD9523_REF_SEL(true);
// Call setup which uses no_os_spi to write registers, io_update, calibrate, sync // Call setup which uses no_os_spi to write registers, io_update, calibrate, sync
DIAG("CLK", "Calling ad9523_setup() #2 -- post-reset, actual configuration");
uint32_t setup2_start = HAL_GetTick();
ret = ad9523_setup(&dev, &init_param); ret = ad9523_setup(&dev, &init_param);
DIAG("CLK", "ad9523_setup() #2 returned %ld (took %lu ms)",
(long)ret, (unsigned long)(HAL_GetTick() - setup2_start));
if (ret != 0) { if (ret != 0) {
// handle error: lock missing or SPI error // handle error: lock missing or SPI error
DIAG_ERR("CLK", "ad9523_setup() #2 FAILED (ret=%ld) -- lock missing or SPI error", (long)ret);
return -1; return -1;
} }
// Final check // Final check
DIAG("CLK", "Checking AD9523 status (PLL lock, etc.)");
ret = ad9523_status(dev); ret = ad9523_status(dev);
DIAG("CLK", "ad9523_status() returned %ld", (long)ret);
if (ret != 0) { if (ret != 0) {
// log/handle // log/handle
DIAG_ERR("CLK", "AD9523 status check FAILED (ret=%ld)", (long)ret);
return -1; return -1;
} }
// optionally manual sync // optionally manual sync
DIAG("CLK", "Triggering manual ad9523_sync()");
ad9523_sync(dev); ad9523_sync(dev);
DIAG("CLK", "AD9523 configuration complete -- all outputs should be active");
// keep device pointer globally if needed (dev) // keep device pointer globally if needed (dev)
return 0; return 0;
@@ -1232,17 +1264,32 @@ int main(void)
/* --- Enable DWT cycle counter for accurate microsecond delays --- */ /* --- Enable DWT cycle counter for accurate microsecond delays --- */
DWT_Init(); DWT_Init();
DIAG_SECTION("SYSTEM INIT");
DIAG("SYS", "DWT cycle counter initialized, TIM1 started");
DIAG("SYS", "HAL tick at init start: %lu ms", (unsigned long)HAL_GetTick());
//Wait for OCXO 3mn //Wait for OCXO 3mn
DIAG("CLK", "OCXO warmup starting -- waiting 180 s (3 min)");
uint32_t ocxo_start = HAL_GetTick();
HAL_Delay(180000); HAL_Delay(180000);
DIAG_ELAPSED("CLK", "OCXO warmup", ocxo_start);
DIAG_SECTION("AD9523 POWER SEQUENCING");
DIAG("PWR", "Asserting AD9523 reset (pin LOW)");
HAL_GPIO_WritePin(AD9523_RESET_GPIO_Port,AD9523_RESET_Pin,GPIO_PIN_RESET); HAL_GPIO_WritePin(AD9523_RESET_GPIO_Port,AD9523_RESET_Pin,GPIO_PIN_RESET);
//Power sequencing AD9523 //Power sequencing AD9523
DIAG("PWR", "Enabling 1.8V clock rail");
HAL_GPIO_WritePin(EN_P_1V8_CLOCK_GPIO_Port,EN_P_1V8_CLOCK_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(EN_P_1V8_CLOCK_GPIO_Port,EN_P_1V8_CLOCK_Pin,GPIO_PIN_SET);
HAL_Delay(100); HAL_Delay(100);
DIAG("PWR", "Enabling 3.3V clock rail");
HAL_GPIO_WritePin(EN_P_3V3_CLOCK_GPIO_Port,EN_P_3V3_CLOCK_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(EN_P_3V3_CLOCK_GPIO_Port,EN_P_3V3_CLOCK_Pin,GPIO_PIN_SET);
HAL_Delay(100); HAL_Delay(100);
DIAG("PWR", "Releasing AD9523 reset (pin HIGH)");
HAL_GPIO_WritePin(AD9523_RESET_GPIO_Port,AD9523_RESET_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(AD9523_RESET_GPIO_Port,AD9523_RESET_Pin,GPIO_PIN_SET);
HAL_Delay(100); HAL_Delay(100);
DIAG("PWR", "AD9523 power sequencing complete -- all rails up, reset released");
//Set planned Clocks on AD9523 //Set planned Clocks on AD9523
/* /*
@@ -1261,24 +1308,38 @@ int main(void)
// Ensure stm32_spi.c and stm32_delay.c are compiled and linked // Ensure stm32_spi.c and stm32_delay.c are compiled and linked
DIAG("CLK", "Calling configure_ad9523()...");
uint32_t ad9523_cfg_start = HAL_GetTick();
if (configure_ad9523() != 0) { if (configure_ad9523() != 0) {
// configuration error - handle as needed // configuration error - handle as needed
DIAG_ERR("CLK", "configure_ad9523() FAILED -- entering infinite halt loop");
while (1) { HAL_Delay(1000); } while (1) { HAL_Delay(1000); }
} }
DIAG_ELAPSED("CLK", "configure_ad9523()", ad9523_cfg_start);
DIAG("CLK", "AD9523 configured successfully");
//Power sequencing FPGA //Power sequencing FPGA
DIAG_SECTION("FPGA POWER SEQUENCING");
DIAG("PWR", "Enabling 1.0V FPGA rail");
HAL_GPIO_WritePin(EN_P_1V0_FPGA_GPIO_Port,EN_P_1V0_FPGA_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(EN_P_1V0_FPGA_GPIO_Port,EN_P_1V0_FPGA_Pin,GPIO_PIN_SET);
HAL_Delay(100); HAL_Delay(100);
DIAG("PWR", "Enabling 1.8V FPGA rail");
HAL_GPIO_WritePin(EN_P_1V8_FPGA_GPIO_Port,EN_P_1V8_FPGA_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(EN_P_1V8_FPGA_GPIO_Port,EN_P_1V8_FPGA_Pin,GPIO_PIN_SET);
HAL_Delay(100); HAL_Delay(100);
DIAG("PWR", "Enabling 3.3V FPGA rail");
HAL_GPIO_WritePin(EN_P_3V3_FPGA_GPIO_Port,EN_P_3V3_FPGA_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(EN_P_3V3_FPGA_GPIO_Port,EN_P_3V3_FPGA_Pin,GPIO_PIN_SET);
HAL_Delay(100); HAL_Delay(100);
DIAG("PWR", "FPGA power sequencing complete -- 1.0V -> 1.8V -> 3.3V");
// Initialize module IMU // Initialize module IMU
DIAG_SECTION("IMU INIT (GY-85)");
DIAG("IMU", "Initializing GY-85 IMU...");
if (!GY85_Init()) { if (!GY85_Init()) {
DIAG_ERR("IMU", "GY85_Init() FAILED -- calling Error_Handler()");
Error_Handler(); Error_Handler();
} }
DIAG("IMU", "GY-85 initialized OK, running 10 calibration samples");
for(int i=0; i<10;i++){ for(int i=0; i<10;i++){
if (!GY85_Update(&imu)) { if (!GY85_Update(&imu)) {
Error_Handler(); Error_Handler();
@@ -1391,40 +1452,63 @@ int main(void)
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////BAROMETER BMP180//////////////////////////////// ///////////////////////////////////BAROMETER BMP180////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
DIAG_SECTION("BAROMETER INIT (BMP180)");
DIAG("IMU", "Reading 5 barometer samples for altitude baseline");
for(int i = 0; i<5 ; i++){ for(int i = 0; i<5 ; i++){
float BMP_Perssure = myBMP.getPressure(); float BMP_Perssure = myBMP.getPressure();
RADAR_Altitude = 44330*(1-(pow((BMP_Perssure/101325),(1/5.255)))); RADAR_Altitude = 44330*(1-(pow((BMP_Perssure/101325),(1/5.255))));
HAL_Delay(100); HAL_Delay(100);
} }
DIAG("IMU", "Barometer init complete, RADAR_Altitude baseline set");
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////ADF4382///////////////////////////////////// ///////////////////////////////////////ADF4382/////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
DIAG_SECTION("ADF4382A LO INIT");
printf("Starting ADF4382A Radar LO System...\n"); printf("Starting ADF4382A Radar LO System...\n");
printf("Using SPI4 with TIMED SYNCHRONIZATION (60 MHz clocks)\n"); printf("Using SPI4 with TIMED SYNCHRONIZATION (60 MHz clocks)\n");
// Initialize LO manager with TIMED synchronization // Initialize LO manager with TIMED synchronization
DIAG("LO", "Calling ADF4382A_Manager_Init(sync=SYNC_METHOD_TIMED)");
uint32_t lo_init_start = HAL_GetTick();
int ret = ADF4382A_Manager_Init(&lo_manager, SYNC_METHOD_TIMED); int ret = ADF4382A_Manager_Init(&lo_manager, SYNC_METHOD_TIMED);
DIAG("LO", "ADF4382A_Manager_Init returned %d (took %lu ms)",
ret, (unsigned long)(HAL_GetTick() - lo_init_start));
/* [BUG ANNOTATION] The following SetPhaseShift/StrobePhaseShift calls happen
* BEFORE the init return code is checked (line below with 'if ret !=').
* If init failed, these operate on an uninitialized manager. */
DIAG_WARN("LO", "[BUG] SetPhaseShift/Strobe called BEFORE checking init return code (ret=%d)", ret);
// Set phase shift (e.g., 500 ps for TX, 500 ps for RX) // Set phase shift (e.g., 500 ps for TX, 500 ps for RX)
ADF4382A_SetPhaseShift(&lo_manager, 500, 500); int ps_ret = ADF4382A_SetPhaseShift(&lo_manager, 500, 500);
DIAG("LO", "ADF4382A_SetPhaseShift(500, 500) returned %d", ps_ret);
// Strobe to apply phase shifts // Strobe to apply phase shifts
ADF4382A_StrobePhaseShift(&lo_manager, 0); // TX device int strobe_tx_ret = ADF4382A_StrobePhaseShift(&lo_manager, 0); // TX device
ADF4382A_StrobePhaseShift(&lo_manager, 1); // RX device int strobe_rx_ret = ADF4382A_StrobePhaseShift(&lo_manager, 1); // RX device
DIAG("LO", "StrobePhaseShift TX returned %d, RX returned %d", strobe_tx_ret, strobe_rx_ret);
if (ret != ADF4382A_MANAGER_OK) { if (ret != ADF4382A_MANAGER_OK) {
printf("LO Manager initialization failed: %d\n", ret); printf("LO Manager initialization failed: %d\n", ret);
DIAG_ERR("LO", "Manager init FAILED (ret=%d) -- calling Error_Handler()", ret);
Error_Handler(); Error_Handler();
} }
// Check initial lock status // Check initial lock status
bool tx_locked, rx_locked; bool tx_locked, rx_locked;
DIAG("LO", "Checking initial lock status...");
ret = ADF4382A_CheckLockStatus(&lo_manager, &tx_locked, &rx_locked); ret = ADF4382A_CheckLockStatus(&lo_manager, &tx_locked, &rx_locked);
if (ret == ADF4382A_MANAGER_OK) { if (ret == ADF4382A_MANAGER_OK) {
printf("Initial Lock Status - TX: %s, RX: %s\n", printf("Initial Lock Status - TX: %s, RX: %s\n",
tx_locked ? "LOCKED" : "UNLOCKED", tx_locked ? "LOCKED" : "UNLOCKED",
rx_locked ? "LOCKED" : "UNLOCKED"); rx_locked ? "LOCKED" : "UNLOCKED");
DIAG("LO", "Initial lock: TX=%s RX=%s", tx_locked ? "LOCKED" : "UNLOCKED", rx_locked ? "LOCKED" : "UNLOCKED");
} else {
DIAG_ERR("LO", "CheckLockStatus returned %d", ret);
} }
// Wait for both LOs to lock // Wait for both LOs to lock
DIAG("LO", "Entering lock-wait loop (max 10 s = 100 x 100 ms)");
uint32_t lock_wait_start = HAL_GetTick();
uint32_t lock_timeout = 0; uint32_t lock_timeout = 0;
while (!(tx_locked && rx_locked) && lock_timeout < 100) { while (!(tx_locked && rx_locked) && lock_timeout < 100) {
HAL_Delay(100); HAL_Delay(100);
@@ -1435,44 +1519,65 @@ int main(void)
printf("Waiting for LO lock... TX: %s, RX: %s\n", printf("Waiting for LO lock... TX: %s, RX: %s\n",
tx_locked ? "LOCKED" : "UNLOCKED", tx_locked ? "LOCKED" : "UNLOCKED",
rx_locked ? "LOCKED" : "UNLOCKED"); rx_locked ? "LOCKED" : "UNLOCKED");
DIAG("LO", "Lock poll #%lu: TX=%s RX=%s",
(unsigned long)lock_timeout,
tx_locked ? "LOCKED" : "UNLOCKED",
rx_locked ? "LOCKED" : "UNLOCKED");
} }
} }
DIAG_ELAPSED("LO", "Lock wait loop", lock_wait_start);
if (tx_locked && rx_locked) { if (tx_locked && rx_locked) {
printf("Both LOs locked successfully!\n"); printf("Both LOs locked successfully!\n");
printf("Synchronization ready - 60 MHz clocks on SYNCP/SYNCN pins\n"); printf("Synchronization ready - 60 MHz clocks on SYNCP/SYNCN pins\n");
DIAG("LO", "Both LOs LOCKED after %lu iterations", (unsigned long)lock_timeout);
// - 60 MHz phase-aligned clocks on SYNCP/SYNCN pins // - 60 MHz phase-aligned clocks on SYNCP/SYNCN pins
// - SYNC pin connected for triggering // - SYNC pin connected for triggering
// When ready to synchronize: // When ready to synchronize:
/* [BUG ANNOTATION] TriggerTimedSync is a no-op -- it only prints
* messages but does not actually toggle any sync pin or register. */
DIAG_WARN("LO", "[BUG] Calling TriggerTimedSync -- known NO-OP, does nothing hardware-related");
ADF4382A_TriggerTimedSync(&lo_manager); ADF4382A_TriggerTimedSync(&lo_manager);
// At this point, the SYNC pin can be toggled to trigger synchronization // At this point, the SYNC pin can be toggled to trigger synchronization
} else { } else {
printf("LO lock timeout! TX: %s, RX: %s\n", printf("LO lock timeout! TX: %s, RX: %s\n",
tx_locked ? "LOCKED" : "UNLOCKED", tx_locked ? "LOCKED" : "UNLOCKED",
rx_locked ? "LOCKED" : "UNLOCKED"); rx_locked ? "LOCKED" : "UNLOCKED");
DIAG_ERR("LO", "Lock TIMEOUT after %lu iterations! TX=%s RX=%s",
(unsigned long)lock_timeout,
tx_locked ? "LOCKED" : "UNLOCKED",
rx_locked ? "LOCKED" : "UNLOCKED");
} }
// check if there is a lock
// check if there is a lock via direct GPIO (independent of register read above)
DIAG("LO", "Direct GPIO lock detect pins:");
DIAG_GPIO("LO", "ADF4382_TX_LKDET", ADF4382_TX_LKDET_GPIO_Port, ADF4382_TX_LKDET_Pin);
DIAG_GPIO("LO", "ADF4382_RX_LKDET", ADF4382_RX_LKDET_GPIO_Port, ADF4382_RX_LKDET_Pin);
if(HAL_GPIO_ReadPin (ADF4382_TX_LKDET_GPIO_Port, ADF4382_TX_LKDET_Pin)) if(HAL_GPIO_ReadPin (ADF4382_TX_LKDET_GPIO_Port, ADF4382_TX_LKDET_Pin))
{ {
// Set The LED_1 ON! // Set The LED_1 ON!
HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin, GPIO_PIN_SET);
DIAG("LO", "TX lock detected via GPIO -- LED_1 ON");
} }
else else
{ {
// Else .. Turn LED_1 OFF! // Else .. Turn LED_1 OFF!
HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin, GPIO_PIN_RESET);
DIAG_WARN("LO", "TX NOT locked via GPIO -- LED_1 OFF");
} }
if(HAL_GPIO_ReadPin (ADF4382_RX_LKDET_GPIO_Port, ADF4382_RX_LKDET_Pin)) if(HAL_GPIO_ReadPin (ADF4382_RX_LKDET_GPIO_Port, ADF4382_RX_LKDET_Pin))
{ {
// Set The LED_2 ON! // Set The LED_2 ON!
HAL_GPIO_WritePin(LED_2_GPIO_Port, LED_2_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(LED_2_GPIO_Port, LED_2_Pin, GPIO_PIN_SET);
DIAG("LO", "RX lock detected via GPIO -- LED_2 ON");
} }
else else
{ {
// Else .. Turn LED_2 OFF! // Else .. Turn LED_2 OFF!
HAL_GPIO_WritePin(LED_2_GPIO_Port, LED_2_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(LED_2_GPIO_Port, LED_2_Pin, GPIO_PIN_RESET);
DIAG_WARN("LO", "RX NOT locked via GPIO -- LED_2 OFF");
} }
@@ -1481,28 +1586,36 @@ int main(void)
////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////
//Power sequencing ADAR1000 //Power sequencing ADAR1000
DIAG_SECTION("ADAR1000 POWER SEQUENCING");
//Tell FPGA to turn off TX RF signal by disabling Mixers //Tell FPGA to turn off TX RF signal by disabling Mixers
DIAG("BF", "Disabling TX mixers (GPIOD pin 11 LOW)");
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_RESET);
DIAG("PWR", "Enabling 3.3V ADAR12 + ADAR34 rails");
HAL_GPIO_WritePin(EN_P_3V3_ADAR12_GPIO_Port,EN_P_3V3_ADAR12_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(EN_P_3V3_ADAR12_GPIO_Port,EN_P_3V3_ADAR12_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(EN_P_3V3_ADAR34_GPIO_Port,EN_P_3V3_ADAR34_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(EN_P_3V3_ADAR34_GPIO_Port,EN_P_3V3_ADAR34_Pin,GPIO_PIN_SET);
HAL_Delay(500); HAL_Delay(500);
DIAG("PWR", "Enabling 5.0V ADAR rail");
HAL_GPIO_WritePin(EN_P_5V0_ADAR_GPIO_Port,EN_P_5V0_ADAR_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(EN_P_5V0_ADAR_GPIO_Port,EN_P_5V0_ADAR_Pin,GPIO_PIN_SET);
HAL_Delay(500); HAL_Delay(500);
DIAG("PWR", "ADAR1000 power sequencing complete");
// System startup message // System startup message
uint8_t startup_msg[] = "Starting Phased Array RADAR System...\r\n"; uint8_t startup_msg[] = "Starting Phased Array RADAR System...\r\n";
HAL_UART_Transmit(&huart3, startup_msg, sizeof(startup_msg)-1, 1000); HAL_UART_Transmit(&huart3, startup_msg, sizeof(startup_msg)-1, 1000);
DIAG("BF", "Calling systemPowerUpSequence()");
// Power up sequence // Power up sequence
systemPowerUpSequence(); systemPowerUpSequence();
DIAG("BF", "Calling initializeBeamMatrices()");
// Initialize beam matrices // Initialize beam matrices
initializeBeamMatrices(); initializeBeamMatrices();
// Print system status // Print system status
printSystemStatus(); printSystemStatus();
DIAG("SYS", "System init complete -- entering main loop");
////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////GPS///////////////////////////////////////// //////////////////////////////////////////GPS/////////////////////////////////////////
@@ -1663,13 +1776,16 @@ int main(void)
} }
//RESET FPGA //RESET FPGA
DIAG("FPGA", "Resetting FPGA (GPIOD pin 12: LOW -> 10ms -> HIGH)");
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
HAL_Delay(10); HAL_Delay(10);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
DIAG("FPGA", "FPGA reset complete");
//Tell FPGA to apply TX RF by enabling Mixers //Tell FPGA to apply TX RF by enabling Mixers
DIAG("FPGA", "Enabling TX mixers (GPIOD pin 11 HIGH)");
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_SET);
/* T°C sensor TMP37 ADC3: Address 0x49, Single-Ended mode, Internal Ref ON + ADC ON */ /* T°C sensor TMP37 ADC3: Address 0x49, Single-Ended mode, Internal Ref ON + ADC ON */
@@ -1717,11 +1833,15 @@ int main(void)
if (!checkSystemHealthStatus()) { if (!checkSystemHealthStatus()) {
// System is in bad state, enter safe mode // System is in bad state, enter safe mode
//Tell FPGA to turn off TX RF signal by disabling Mixers //Tell FPGA to turn off TX RF signal by disabling Mixers
DIAG_ERR("SYS", "checkSystemHealthStatus() FAILED -- entering SAFE MODE");
DIAG("SYS", "Disabling TX mixers (GPIOD pin 11 LOW)");
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_RESET);
DIAG("SYS", "Calling systemPowerDownSequence()");
systemPowerDownSequence(); systemPowerDownSequence();
char emergency_msg[] = "SYSTEM IN SAFE MODE - Manual intervention required\r\n"; char emergency_msg[] = "SYSTEM IN SAFE MODE - Manual intervention required\r\n";
HAL_UART_Transmit(&huart3, (uint8_t*)emergency_msg, strlen(emergency_msg), 1000); HAL_UART_Transmit(&huart3, (uint8_t*)emergency_msg, strlen(emergency_msg), 1000);
DIAG_ERR("SYS", "SAFE MODE ACTIVE -- blinking all LEDs, waiting for system_emergency_state clear");
// Blink all LEDs to indicate safe mode // Blink all LEDs to indicate safe mode
while (system_emergency_state) { while (system_emergency_state) {
@@ -1730,6 +1850,7 @@ int main(void)
HAL_GPIO_TogglePin(LED_3_GPIO_Port, LED_3_Pin); HAL_GPIO_TogglePin(LED_3_GPIO_Port, LED_3_Pin);
HAL_GPIO_TogglePin(LED_4_GPIO_Port, LED_4_Pin); HAL_GPIO_TogglePin(LED_4_GPIO_Port, LED_4_Pin);
} }
DIAG("SYS", "Exited safe mode blink loop -- system_emergency_state cleared");
} }
////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////
////////////////////////// Monitor ADF4382A lock status periodically////////////////// ////////////////////////// Monitor ADF4382A lock status periodically//////////////////
@@ -1744,6 +1865,13 @@ int main(void)
printf("LO Lock Lost! TX: %s, RX: %s\n", printf("LO Lock Lost! TX: %s, RX: %s\n",
tx_locked ? "LOCKED" : "UNLOCKED", tx_locked ? "LOCKED" : "UNLOCKED",
rx_locked ? "LOCKED" : "UNLOCKED"); rx_locked ? "LOCKED" : "UNLOCKED");
DIAG_ERR("LO", "Lock LOST in main loop! TX=%s RX=%s",
tx_locked ? "LOCKED" : "UNLOCKED",
rx_locked ? "LOCKED" : "UNLOCKED");
DIAG_GPIO("LO", "TX_LKDET (direct)", ADF4382_TX_LKDET_GPIO_Port, ADF4382_TX_LKDET_Pin);
DIAG_GPIO("LO", "RX_LKDET (direct)", ADF4382_RX_LKDET_GPIO_Port, ADF4382_RX_LKDET_Pin);
} else {
DIAG("LO", "Lock poll OK: TX=LOCKED RX=LOCKED");
} }
last_check = HAL_GetTick(); last_check = HAL_GetTick();
@@ -1765,18 +1893,27 @@ int main(void)
Temperature_7 = ADS7830_Measure_SingleEnded(&hadc3, 6)*0.64705f; Temperature_7 = ADS7830_Measure_SingleEnded(&hadc3, 6)*0.64705f;
Temperature_8 = ADS7830_Measure_SingleEnded(&hadc3, 7)*0.64705f; Temperature_8 = ADS7830_Measure_SingleEnded(&hadc3, 7)*0.64705f;
DIAG("PA", "Temps: T1=%.1f T2=%.1f T3=%.1f T4=%.1f T5=%.1f T6=%.1f T7=%.1f T8=%.1f",
(double)Temperature_1, (double)Temperature_2, (double)Temperature_3, (double)Temperature_4,
(double)Temperature_5, (double)Temperature_6, (double)Temperature_7, (double)Temperature_8);
//(20 mV/°C on TMP37) QPA2962 RF amplifier Operating Temp. Range, TBASE min40 normal+25 max+85 °C //(20 mV/°C on TMP37) QPA2962 RF amplifier Operating Temp. Range, TBASE min40 normal+25 max+85 °C
int Max_Temp = 25; int Max_Temp = 25;
if((Temperature_1>Max_Temp)||(Temperature_2>Max_Temp)||(Temperature_3>Max_Temp)||(Temperature_4>Max_Temp) if((Temperature_1>Max_Temp)||(Temperature_2>Max_Temp)||(Temperature_3>Max_Temp)||(Temperature_4>Max_Temp)
||(Temperature_5>Max_Temp)||(Temperature_6>Max_Temp)||(Temperature_7>Max_Temp)||(Temperature_8>Max_Temp)) ||(Temperature_5>Max_Temp)||(Temperature_6>Max_Temp)||(Temperature_7>Max_Temp)||(Temperature_8>Max_Temp))
{ {
HAL_GPIO_WritePin(EN_DIS_COOLING_GPIO_Port, EN_DIS_COOLING_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(EN_DIS_COOLING_GPIO_Port, EN_DIS_COOLING_Pin, GPIO_PIN_SET);
DIAG_WARN("PA", "Over-temp detected (>%d C) -- cooling ENABLED", Max_Temp);
} }
else{ else{
HAL_GPIO_WritePin(EN_DIS_COOLING_GPIO_Port, EN_DIS_COOLING_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(EN_DIS_COOLING_GPIO_Port, EN_DIS_COOLING_Pin, GPIO_PIN_RESET);
} }
/* [BUG ANNOTATION] Line below writes to 'last_check' instead of 'last_check1'.
* This causes the temperature timer to share state with the lock-check timer above.
* Temperature reads may run at incorrect intervals. */
DIAG_WARN("PA", "[BUG] Timer uses 'last_check' instead of 'last_check1' -- temp interval corrupted");
last_check = HAL_GetTick(); last_check = HAL_GetTick();
} }
////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////