stm32_hal_mock.c
1 /******************************************************************************* 2 * stm32_hal_mock.c -- Spy/recording implementation of STM32 HAL stubs 3 ******************************************************************************/ 4 #include "stm32_hal_mock.h" 5 #include "ad_driver_mock.h" 6 #include <stdio.h> 7 #include <stdlib.h> 8 9 /* ========================= GPIO port instances ==================== */ 10 GPIO_TypeDef gpio_a = { .id = 0xA }; 11 GPIO_TypeDef gpio_b = { .id = 0xB }; 12 GPIO_TypeDef gpio_c = { .id = 0xC }; 13 GPIO_TypeDef gpio_d = { .id = 0xD }; 14 GPIO_TypeDef gpio_e = { .id = 0xE }; 15 GPIO_TypeDef gpio_f = { .id = 0xF }; 16 GPIO_TypeDef gpio_g = { .id = 0x6 }; /* 0x6 for GPIOG -- avoids overlap */ 17 18 /* ========================= Peripheral instances =================== */ 19 SPI_HandleTypeDef hspi1 = { .id = 1 }; 20 SPI_HandleTypeDef hspi4 = { .id = 4 }; 21 I2C_HandleTypeDef hi2c1 = { .id = 1 }; 22 I2C_HandleTypeDef hi2c2 = { .id = 2 }; 23 UART_HandleTypeDef huart3 = { .id = 3 }; 24 ADC_HandleTypeDef hadc3 = { .id = 3 }; 25 TIM_HandleTypeDef htim3 = { .id = 3 }; 26 27 /* ========================= Spy log ================================ */ 28 SpyRecord spy_log[SPY_MAX_RECORDS]; 29 int spy_count = 0; 30 31 /* ========================= Mock tick (forward decl for spy_reset) == */ 32 uint32_t mock_tick = 0; 33 34 /* ========================= Printf control ========================= */ 35 int mock_printf_enabled = 0; 36 37 /* ========================= Mock GPIO read ========================= */ 38 #define GPIO_READ_TABLE_SIZE 32 39 static struct { 40 GPIO_TypeDef *port; 41 uint16_t pin; 42 GPIO_PinState val; 43 } gpio_read_table[GPIO_READ_TABLE_SIZE]; 44 45 void spy_reset(void) 46 { 47 spy_count = 0; 48 memset(spy_log, 0, sizeof(spy_log)); 49 mock_tick = 0; 50 mock_printf_enabled = 0; 51 memset(gpio_read_table, 0, sizeof(gpio_read_table)); 52 } 53 54 const SpyRecord *spy_get(int index) 55 { 56 if (index < 0 || index >= spy_count) return NULL; 57 return &spy_log[index]; 58 } 59 60 int spy_count_type(SpyCallType type) 61 { 62 int count = 0; 63 for (int i = 0; i < spy_count; i++) { 64 if (spy_log[i].type == type) count++; 65 } 66 return count; 67 } 68 69 int spy_find_nth(SpyCallType type, int n) 70 { 71 int found = 0; 72 for (int i = 0; i < spy_count; i++) { 73 if (spy_log[i].type == type) { 74 if (found == n) return i; 75 found++; 76 } 77 } 78 return -1; 79 } 80 81 static void spy_push(SpyRecord rec) 82 { 83 if (spy_count < SPY_MAX_RECORDS) { 84 spy_log[spy_count++] = rec; 85 } 86 } 87 88 /* ========================= Mock tick API ========================== */ 89 90 void mock_set_tick(uint32_t tick) { mock_tick = tick; } 91 void mock_advance_tick(uint32_t d) { mock_tick += d; } 92 93 /* ========================= Mock GPIO read API ===================== */ 94 95 void mock_gpio_set_read(GPIO_TypeDef *port, uint16_t pin, GPIO_PinState val) 96 { 97 for (int i = 0; i < GPIO_READ_TABLE_SIZE; i++) { 98 if (gpio_read_table[i].port == port && gpio_read_table[i].pin == pin) { 99 gpio_read_table[i].val = val; 100 return; 101 } 102 if (gpio_read_table[i].port == NULL) { 103 gpio_read_table[i].port = port; 104 gpio_read_table[i].pin = pin; 105 gpio_read_table[i].val = val; 106 return; 107 } 108 } 109 } 110 111 /* ========================= HAL Implementations ==================== */ 112 113 void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) 114 { 115 spy_push((SpyRecord){ 116 .type = SPY_GPIO_WRITE, 117 .port = GPIOx, 118 .pin = GPIO_Pin, 119 .value = (uint32_t)PinState, 120 .extra = NULL 121 }); 122 } 123 124 GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 125 { 126 GPIO_PinState result = GPIO_PIN_RESET; 127 for (int i = 0; i < GPIO_READ_TABLE_SIZE; i++) { 128 if (gpio_read_table[i].port == GPIOx && gpio_read_table[i].pin == GPIO_Pin) { 129 result = gpio_read_table[i].val; 130 break; 131 } 132 } 133 spy_push((SpyRecord){ 134 .type = SPY_GPIO_READ, 135 .port = GPIOx, 136 .pin = GPIO_Pin, 137 .value = (uint32_t)result, 138 .extra = NULL 139 }); 140 return result; 141 } 142 143 void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin) 144 { 145 spy_push((SpyRecord){ 146 .type = SPY_GPIO_TOGGLE, 147 .port = GPIOx, 148 .pin = GPIO_Pin, 149 .value = 0, 150 .extra = NULL 151 }); 152 } 153 154 uint32_t HAL_GetTick(void) 155 { 156 spy_push((SpyRecord){ 157 .type = SPY_HAL_GET_TICK, 158 .port = NULL, 159 .pin = 0, 160 .value = mock_tick, 161 .extra = NULL 162 }); 163 return mock_tick; 164 } 165 166 void HAL_Delay(uint32_t Delay) 167 { 168 spy_push((SpyRecord){ 169 .type = SPY_HAL_DELAY, 170 .port = NULL, 171 .pin = 0, 172 .value = Delay, 173 .extra = NULL 174 }); 175 mock_tick += Delay; 176 } 177 178 HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, 179 uint16_t Size, uint32_t Timeout) 180 { 181 spy_push((SpyRecord){ 182 .type = SPY_UART_TX, 183 .port = NULL, 184 .pin = Size, 185 .value = Timeout, 186 .extra = huart 187 }); 188 return HAL_OK; 189 } 190 191 /* ========================= no_os delay stubs ====================== */ 192 193 void no_os_udelay(uint32_t usecs) 194 { 195 spy_push((SpyRecord){ 196 .type = SPY_NO_OS_UDELAY, 197 .port = NULL, 198 .pin = 0, 199 .value = usecs, 200 .extra = NULL 201 }); 202 } 203 204 void no_os_mdelay(uint32_t msecs) 205 { 206 spy_push((SpyRecord){ 207 .type = SPY_HAL_DELAY, 208 .port = NULL, 209 .pin = 0, 210 .value = msecs, 211 .extra = NULL 212 }); 213 mock_tick += msecs; 214 } 215 216 /* ========================= ADS7830 stub =========================== */ 217 218 uint8_t ADS7830_Measure_SingleEnded(ADC_HandleTypeDef *hadc, uint8_t channel) 219 { 220 spy_push((SpyRecord){ 221 .type = SPY_ADS7830_MEASURE, 222 .port = NULL, 223 .pin = channel, 224 .value = 100, /* stub: always return 100 (~64.7 C) */ 225 .extra = hadc 226 }); 227 return 100; 228 } 229 230 /* ========================= TIM PWM stubs ========================== */ 231 232 HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel) 233 { 234 spy_push((SpyRecord){ 235 .type = SPY_TIM_PWM_START, 236 .port = NULL, 237 .pin = (uint16_t)Channel, 238 .value = htim->id, 239 .extra = htim 240 }); 241 return HAL_OK; 242 } 243 244 HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel) 245 { 246 spy_push((SpyRecord){ 247 .type = SPY_TIM_PWM_STOP, 248 .port = NULL, 249 .pin = (uint16_t)Channel, 250 .value = htim->id, 251 .extra = htim 252 }); 253 return HAL_OK; 254 } 255 256 void mock_tim_set_compare(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t Compare) 257 { 258 spy_push((SpyRecord){ 259 .type = SPY_TIM_SET_COMPARE, 260 .port = NULL, 261 .pin = (uint16_t)Channel, 262 .value = Compare, 263 .extra = htim 264 }); 265 } 266 267 /* ========================= SPI stubs ============================== */ 268 269 HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout) 270 { 271 spy_push((SpyRecord){ 272 .type = SPY_SPI_TRANSMIT_RECEIVE, 273 .port = NULL, 274 .pin = Size, 275 .value = Timeout, 276 .extra = hspi 277 }); 278 return HAL_OK; 279 } 280 281 HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout) 282 { 283 spy_push((SpyRecord){ 284 .type = SPY_SPI_TRANSMIT, 285 .port = NULL, 286 .pin = Size, 287 .value = Timeout, 288 .extra = hspi 289 }); 290 return HAL_OK; 291 } 292 293 /* Stub for platform_noos_stm32.c GPIO functions */ 294 void hal_set_gpio_by_index(uint8_t idx, uint8_t value) { 295 (void)idx; (void)value; 296 } 297 298 /* ========================= Mock stm32_spi_ops ===================== */ 299 300 /* Stub SPI platform ops -- real adf4382a_manager.c references &stm32_spi_ops. 301 * In tests, adf4382_init() is mocked so no_os_spi_init() is never called. 302 * We provide a non-NULL struct so tests can assert platform_ops != NULL. */ 303 static int mock_spi_init_stub(void) { return 0; } 304 305 const struct no_os_spi_platform_ops stm32_spi_ops = { 306 .init = mock_spi_init_stub, 307 };