Files
overwatch/9_Firmware/9_1_Microcontroller/tests/ad_driver_mock.h
Jason 3b32f67087 Fix SPI bugs #9 (NULL platform_ops) and #10 (missing CS toggle), widen chip_select to uint16_t
Bug #9: Both TX and RX SPI init params had platform_ops = NULL, causing
adf4382_init() -> no_os_spi_init() to fail with -EINVAL. Fixed by setting
platform_ops = &stm32_spi_ops and passing stm32_spi_extra with correct CS
port/pin for each device.

Bug #10: stm32_spi_write_and_read() never toggled chip select. Since TX
and RX ADF4382A share SPI4, every register write hit both PLLs. Rewrote
stm32_spi.c to assert CS LOW before transfer and deassert HIGH after,
using stm32_spi_extra metadata. Backward-compatible: legacy callers
(e.g., AD9523) with cs_port=NULL skip CS management.

Also widened chip_select from uint8_t to uint16_t in no_os_spi.h since
STM32 GPIO_PIN_xx values (e.g., GPIO_PIN_14=0x4000) overflow uint8_t.

10/10 tests pass (8 original + 2 new regression tests).
2026-03-19 10:00:05 +02:00

221 lines
6.7 KiB
C

/*******************************************************************************
* ad_driver_mock.h -- Mock declarations for ADF4382 and AD9523 driver APIs
*
* These replace the real driver implementations. The spy layer in
* ad_driver_mock.c records all calls for test assertion.
******************************************************************************/
#ifndef AD_DRIVER_MOCK_H
#define AD_DRIVER_MOCK_H
#include "stm32_hal_mock.h"
#ifdef __cplusplus
extern "C" {
#endif
/* ========================= no_os SPI types ======================== */
enum no_os_spi_mode {
NO_OS_SPI_MODE_0 = 0,
NO_OS_SPI_MODE_1 = 1,
NO_OS_SPI_MODE_2 = 2,
NO_OS_SPI_MODE_3 = 3
};
enum no_os_spi_bit_order {
NO_OS_SPI_BIT_ORDER_MSB_FIRST = 0,
NO_OS_SPI_BIT_ORDER_LSB_FIRST = 1
};
enum no_os_spi_lanes {
NO_OS_SPI_SINGLE = 0,
};
struct no_os_platform_spi_delays {
uint32_t cs_delay_first;
uint32_t cs_delay_last;
};
struct no_os_spi_desc {
uint32_t dummy;
};
struct no_os_spi_platform_ops {
int (*init)(void);
};
struct no_os_spi_init_param {
uint32_t device_id;
uint32_t max_speed_hz;
uint16_t chip_select;
enum no_os_spi_mode mode;
enum no_os_spi_bit_order bit_order;
enum no_os_spi_lanes lanes;
const struct no_os_spi_platform_ops *platform_ops;
struct no_os_platform_spi_delays platform_delays;
void *extra;
struct no_os_spi_desc *parent;
};
/* ========================= ADF4382 types ========================== */
enum adf4382_dev_id {
ID_ADF4382 = 0,
ID_ADF4382A = 1,
ID_ADF4383 = 2,
};
struct adf4382_dev {
struct no_os_spi_desc *spi_desc;
bool spi_3wire_en;
bool cmos_3v3;
uint64_t ref_freq_hz;
uint64_t freq;
bool ref_doubler_en;
uint8_t ref_div;
uint8_t cp_i;
uint16_t bleed_word;
uint8_t ld_count;
uint32_t phase_adj;
uint16_t n_int;
};
struct adf4382_init_param {
struct no_os_spi_init_param *spi_init;
bool spi_3wire_en;
bool cmos_3v3;
uint64_t ref_freq_hz;
uint64_t freq;
bool ref_doubler_en;
uint8_t ref_div;
uint8_t cp_i;
uint16_t bleed_word;
uint8_t ld_count;
uint8_t en_lut_gen;
uint8_t en_lut_cal;
uint8_t max_lpf_cap_value_uf;
enum adf4382_dev_id id;
};
/* Lock detect mask -- from real header */
#define ADF4382_LOCKED_MSK (1U << 0)
/* ========================= AD9523 types =========================== */
#define AD9523_NUM_CHAN 14
struct ad9523_channel_spec {
uint8_t channel_num;
uint8_t divider_output_invert_en;
uint8_t sync_ignore_en;
uint8_t low_power_mode_en;
uint8_t use_alt_clock_src;
uint8_t output_dis;
uint8_t driver_mode;
uint8_t divider_phase;
uint16_t channel_divider;
int8_t extended_name[16];
};
struct ad9523_platform_data {
uint32_t vcxo_freq;
uint8_t spi3wire;
uint8_t refa_diff_rcv_en;
uint8_t refb_diff_rcv_en;
uint8_t zd_in_diff_en;
uint8_t osc_in_diff_en;
uint8_t refa_cmos_neg_inp_en;
uint8_t refb_cmos_neg_inp_en;
uint8_t zd_in_cmos_neg_inp_en;
uint8_t osc_in_cmos_neg_inp_en;
uint16_t refa_r_div;
uint16_t refb_r_div;
uint16_t pll1_feedback_div;
uint16_t pll1_charge_pump_current_nA;
uint8_t zero_delay_mode_internal_en;
uint8_t osc_in_feedback_en;
uint8_t pll1_bypass_en;
uint8_t pll1_loop_filter_rzero;
uint8_t ref_mode;
uint32_t pll2_charge_pump_current_nA;
uint8_t pll2_ndiv_a_cnt;
uint8_t pll2_ndiv_b_cnt;
uint8_t pll2_freq_doubler_en;
uint8_t pll2_r2_div;
uint8_t pll2_vco_diff_m1;
uint8_t pll2_vco_diff_m2;
uint8_t rpole2;
uint8_t rzero;
uint8_t cpole1;
uint8_t rzero_bypass_en;
int32_t num_channels;
struct ad9523_channel_spec *channels;
int8_t name[16];
};
struct ad9523_state {
struct ad9523_platform_data *pdata;
uint32_t vcxo_freq;
uint32_t vco_freq;
uint32_t vco_out_freq[3];
uint8_t vco_out_map[14];
};
struct ad9523_dev {
struct no_os_spi_desc *spi_desc;
struct ad9523_state ad9523_st;
struct ad9523_platform_data *pdata;
};
struct ad9523_init_param {
struct no_os_spi_init_param spi_init;
struct ad9523_platform_data *pdata;
};
/* AD9523 enums needed by test code */
enum outp_drv_mode {
TRISTATE = 0,
LVPECL_8mA, LVDS_4mA, LVDS_7mA,
HSTL0_16mA, HSTL1_8mA,
CMOS_CONF1, CMOS_CONF2, CMOS_CONF3, CMOS_CONF4,
CMOS_CONF5, CMOS_CONF6, CMOS_CONF7, CMOS_CONF8, CMOS_CONF9
};
enum rpole2_resistor { RPOLE2_900_OHM = 0, RPOLE2_450_OHM, RPOLE2_300_OHM, RPOLE2_225_OHM };
enum rzero_resistor { RZERO_3250_OHM = 0, RZERO_2750_OHM, RZERO_2250_OHM, RZERO_2100_OHM,
RZERO_3000_OHM, RZERO_2500_OHM, RZERO_2000_OHM, RZERO_1850_OHM };
enum cpole1_capacitor { CPOLE1_0_PF = 0, CPOLE1_8_PF, CPOLE1_16_PF, CPOLE1_24_PF,
_CPOLE1_24_PF, CPOLE1_32_PF, CPOLE1_40_PF, CPOLE1_48_PF };
/* ========================= Mock return code control =============== */
/* Default return code for mock driver functions (0 = success) */
extern int mock_adf4382_init_retval;
extern int mock_adf4382_set_timed_sync_retval;
extern int mock_ad9523_setup_retval;
/* ========================= ADF4382 mock API ======================= */
int adf4382_init(struct adf4382_dev **device, struct adf4382_init_param *init_param);
int adf4382_remove(struct adf4382_dev *dev);
int adf4382_set_out_power(struct adf4382_dev *dev, uint8_t ch, int32_t pwr);
int adf4382_set_en_chan(struct adf4382_dev *dev, uint8_t ch, bool en);
int adf4382_set_timed_sync_setup(struct adf4382_dev *dev, bool sync);
int adf4382_set_ezsync_setup(struct adf4382_dev *dev, bool sync);
int adf4382_set_sw_sync(struct adf4382_dev *dev, bool sw_sync);
int adf4382_spi_read(struct adf4382_dev *dev, uint16_t reg_addr, uint8_t *data);
/* ========================= AD9523 mock API ======================== */
int32_t ad9523_init(struct ad9523_init_param *init_param);
int32_t ad9523_setup(struct ad9523_dev **device, const struct ad9523_init_param *init_param);
int32_t ad9523_status(struct ad9523_dev *dev);
int32_t ad9523_sync(struct ad9523_dev *dev);
int32_t ad9523_remove(struct ad9523_dev *dev);
#ifdef __cplusplus
}
#endif
#endif /* AD_DRIVER_MOCK_H */