i2c_application_system_stm32.c
Go to the documentation of this file.
1 // Copyright (c) Acconeer AB, 2023-2024
2 // All rights reserved
3 // This file is subject to the terms and conditions defined in the file
4 // 'LICENSES/license_acconeer.txt', (BSD 3-Clause License) which is part
5 // of this source code package.
6
7 #include <inttypes.h>
8 #include <stdbool.h>
9 #include <stddef.h>
10 #include <stdio.h>
11
12 #include "main.h"
13
14 #include "acc_integration.h"
15 #include "acc_reg_protocol.h"
16 #include "i2c_application_system.h"
17
18 #define I2C_SLAVE_BUFFER_SIZE 4
19 #define WAIT_FOR_IDLE_RETRIES 10U
20 #define WAIT_FOR_IDLE_RETRY_INTERNAL_MS 10U
21 #define GPIO_BANK_COUNT 3U
22
23 #define I2C_ADDRESS_FLOATING (0x52)
24 #define I2C_ADDRESS_LOW (0x51)
25 #define I2C_ADDRESS_HIGH (0x53)
26
27 typedef enum
28 {
29 PIN_STATE_LOW,
30 PIN_STATE_HIGH,
31 PIN_STATE_FLOATING,
32 } pin_state_t;
33
34 typedef struct
35 {
36 uint32_t MODER; /*!< GPIO port mode register */
37 uint32_t OTYPER; /*!< GPIO port output type register */
38 uint32_t OSPEEDR; /*!< GPIO port output speed register */
39 uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register */
40 uint32_t AFR[2]; /*!< GPIO alternate function registers */
41 uint32_t ASCR; /*!< GPIO analog switch control register */
42 uint32_t RCC_GPIO_CLK_ENABLE; /*!< GPIO Port Clock Enable */
43 } gpio_config_t;
44
45 extern SPI_HandleTypeDef A121_SPI_HANDLE;
46 extern I2C_HandleTypeDef MODULE_I2C_HANDLE;
47 extern UART_HandleTypeDef MODULE_UART1_HANDLE;
48 extern UART_HandleTypeDef MODULE_UART2_HANDLE;
49 extern RTC_HandleTypeDef MODULE_RTC_HANDLE;
50 static RCC_OscInitTypeDef low_power_saved_rcc_oscinitstruct;
51 static RCC_ClkInitTypeDef low_power_saved_rcc_clkinitstruct;
52 static uint32_t low_power_saved_flatency;
53 static gpio_config_t low_power_saved_gpio_bank[GPIO_BANK_COUNT] = {0};
54 static GPIO_TypeDef *gpio_banks[GPIO_BANK_COUNT] = {GPIOA, GPIOB, GPIOH};
55
56 static uint8_t i2c_slave_buffer[I2C_SLAVE_BUFFER_SIZE];
57 static volatile bool i2c_idle = true;
58
59 static uint32_t rtc_period_time_ms = 0;
60 static volatile bool rtc_wakeup_triggered = false;
61
62 /**
63 * @brief Disable interrupts
64 */
65 static inline void disable_interrupts(void);
66
67 /**
68 * @brief Enable interrupts
69 */
70 static inline void enable_interrupts(void);
71
72 /**
73 * @brief Prepare power down state
74 */
75 static inline void prepare_power_down(void);
76
77 /**
78 * @brief Resume power down state
79 */
80 static inline void resume_power_down(void);
81
82 /**
83 * @brief Get RTC ticks based on current RTC time
84 *
85 * @return The current RTC ticks in ms
86 */
87 static uint32_t get_rtc_tick(void);
88
89 /**
90 * @brief Convert RTC ticks to RTC time
91 *
92 * @param[in] tick rtc ticks in ms
93 * @param[out] time RTC time
94 */
95 static void rtc_tick_to_time(uint32_t tick, RTC_TimeTypeDef *time);
96
97 /**
98 * @brief Function for setting the next wakeup time from the RTC interrupt.
99 */
100 static void rtc_set_next_wakeup_time(void);
101
102 /**
103 * @brief Wait for I2C interface to be idle
104 */
105 static void wait_for_i2c_idle(void);
106
107 /**
108 * @brief Helper function to prepare transmit of register data
109 *
110 * @param[in] hi2c The I2C handle
111 */
112 static void prepare_register_data(I2C_HandleTypeDef *hi2c);
113
114 /**
115 * @brief Helper function to get i2c address from I2C_ADDRESS pin pin state
116 *
117 * @return The i2c address to use
118 */
119 static uint32_t get_i2c_address(void);
120
121 /**
122 * @brief Helper function to the state (HIGH/LOW/FLOATING) of a gpio pin
123 *
124 * @param[in] gpio_port The GPIO port
125 * @param[in] gpio_pin The GPIO pin
126 * @return The pin state
127 */
128 static pin_state_t get_pin_state(GPIO_TypeDef *gpio_port, uint32_t gpio_pin);
129
130 void i2c_application_system_init(void)
131 {
132 /* Disable unused functionality in MCU */
133 HAL_UART_DeInit(&MODULE_UART1_HANDLE);
134
135 /* Set and print I2C Address */
136 MODULE_I2C_HANDLE.Init.OwnAddress1 = get_i2c_address() << 1;
137 printf("I2C Address = 0x%" PRIx32 "\n", (MODULE_I2C_HANDLE.Init.OwnAddress1 >> 1));
138
139 /* Re-init I2C block after addres supdate */
140 if (HAL_I2C_Init(&MODULE_I2C_HANDLE) != HAL_OK)
141 {
142 Error_Handler();
143 }
144
145 /* Start I2C */
146 if (HAL_I2C_EnableListen_IT(&MODULE_I2C_HANDLE) != HAL_OK)
147 {
148 /**
149 * Calling this function with wrong parameters will return HAL_ERROR
150 * Calling this function when the i2c module is in the wrong state return HAL_BUSY
151 */
152 Error_Handler();
153 }
154
155 i2c_application_system_set_ready_pin(true);
156 }
157
158 void i2c_application_system_reset(void)
159 {
160 /**
161 * Wait for the i2c interface to be idle,
162 * if not idle after retries, reset anyway!
163 */
164 wait_for_i2c_idle();
165
166 NVIC_SystemReset();
167 }
168
169 void i2c_application_system_wait_for_interrupt(void)
170 {
171 __WFI();
172 }
173
174 bool i2c_application_system_test_wakeup_pin(void)
175 {
176 GPIO_PinState pin_state = HAL_GPIO_ReadPin(WAKE_UP_GPIO_Port, WAKE_UP_Pin);
177
178 return pin_state == GPIO_PIN_SET;
179 }
180
181 void i2c_application_system_set_ready_pin(bool enable)
182 {
183 GPIO_PinState pin_state = enable ? GPIO_PIN_SET : GPIO_PIN_RESET;
184
185 HAL_GPIO_WritePin(MCU_INT_GPIO_Port, MCU_INT_Pin, pin_state);
186 }
187
188 void i2c_application_system_setup_generic_gpio_pin(bool enable)
189 {
190 /* Setup generic gpio pin (MISC_GPIO0) */
191 GPIO_InitTypeDef GPIO_InitStruct = {0};
192
193 GPIO_InitStruct.Pin = MISC_GPIO0_Pin;
194 GPIO_InitStruct.Pull = GPIO_NOPULL;
195
196 if (enable)
197 {
198 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
199 }
200 else
201 {
202 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
203 }
204
205 HAL_GPIO_Init(MISC_GPIO0_GPIO_Port, &GPIO_InitStruct);
206 }
207
208 void i2c_application_system_set_generic_gpio_pin(bool enable)
209 {
210 GPIO_PinState pin_state = enable ? GPIO_PIN_SET : GPIO_PIN_RESET;
211
212 HAL_GPIO_WritePin(MISC_GPIO0_GPIO_Port, MISC_GPIO0_Pin, pin_state);
213 }
214
215 void i2c_application_enter_low_power_state(void)
216 {
217 /**
218 * Wait for the i2c interface to be idle,
219 * if not idle after retries, power down anyway!
220 */
221 wait_for_i2c_idle();
222
223 prepare_power_down();
224
225 disable_interrupts();
226
227 /* Do a final test of the wakeup pin and rtc wakeup before going to sleep */
228 if (!i2c_application_system_test_wakeup_pin() && !rtc_wakeup_triggered)
229 {
230 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
231 }
232
233 enable_interrupts();
234
235 resume_power_down();
236 }
237
238 void i2c_application_set_periodic_wakeup(uint32_t period_ms)
239 {
240 rtc_period_time_ms = period_ms;
241 rtc_set_next_wakeup_time();
242 }
243
244 bool i2c_application_is_periodic_wakeup(void)
245 {
246 acc_integration_critical_section_enter();
247 bool periodic_wakeup = rtc_wakeup_triggered;
248 rtc_wakeup_triggered = false;
249 acc_integration_critical_section_exit();
250
251 if (periodic_wakeup)
252 {
253 rtc_set_next_wakeup_time();
254 }
255
256 return periodic_wakeup;
257 }
258
259 /**
260 * @brief IRQ Handler for RTC B Alarm
261 */
262 void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *rtc)
263 {
264 (void)rtc;
265 rtc_wakeup_triggered = true;
266 }
267
268 static inline void disable_interrupts(void)
269 {
270 __disable_irq();
271 __DSB();
272 __ISB();
273 }
274
275 static inline void enable_interrupts(void)
276 {
277 __enable_irq();
278 __DSB();
279 __ISB();
280 }
281
282 static inline void prepare_power_down(void)
283 {
284 HAL_RCC_GetOscConfig(&low_power_saved_rcc_oscinitstruct);
285 HAL_RCC_GetClockConfig(&low_power_saved_rcc_clkinitstruct, &low_power_saved_flatency);
286
287 HAL_I2C_DeInit(&MODULE_I2C_HANDLE);
288 HAL_SPI_DeInit(&A121_SPI_HANDLE);
289 HAL_UART_DeInit(&MODULE_UART1_HANDLE);
290
291 /* Save GPIO bank state */
292 for (size_t idx = 0; idx < GPIO_BANK_COUNT; idx++)
293 {
294 GPIO_TypeDef *gpio_bank = gpio_banks[idx];
295 gpio_config_t *gpio_config = &low_power_saved_gpio_bank[idx];
296 gpio_config->MODER = READ_REG(gpio_bank->MODER);
297 gpio_config->OTYPER = READ_REG(gpio_bank->OTYPER);
298 gpio_config->OSPEEDR = READ_REG(gpio_bank->OSPEEDR);
299 gpio_config->PUPDR = READ_REG(gpio_bank->PUPDR);
300 gpio_config->AFR[0] = READ_REG(gpio_bank->AFR[0]);
301 gpio_config->AFR[1] = READ_REG(gpio_bank->AFR[1]);
302 }
303
304 /* Turn GPIO off */
305 GPIO_InitTypeDef GPIO_InitStructOff;
306
307 /* Set all unused GPIO pins in the lowest power consuming state according to AN4899*/
308 GPIO_InitStructOff.Mode = GPIO_MODE_ANALOG;
309 GPIO_InitStructOff.Pull = GPIO_NOPULL;
310
311 /* GPIO A */
312 GPIO_InitStructOff.Pin = GPIO_PIN_All;
313 GPIO_InitStructOff.Pin &= (uint16_t) ~(WAKE_UP_Pin | SPI_SCK_Pin | SPI_MISO_Pin | SPI_MOSI_Pin);
314 HAL_GPIO_Init(GPIOA, &GPIO_InitStructOff);
315
316 /* GPIO B */
317 GPIO_InitStructOff.Pin = GPIO_PIN_All;
318 GPIO_InitStructOff.Pin &= (uint16_t) ~(MCU_INT_Pin | ENABLE_Pin | SPI_SS_Pin | MISC_GPIO0_Pin);
319 HAL_GPIO_Init(GPIOB, &GPIO_InitStructOff);
320
321 /* GPIO H */
322 GPIO_InitStructOff.Pin = GPIO_PIN_All;
323 HAL_GPIO_Init(GPIOH, &GPIO_InitStructOff);
324
325 /* Disable Clocks */
326 __HAL_RCC_GPIOA_CLK_DISABLE();
327 __HAL_RCC_GPIOB_CLK_DISABLE();
328 __HAL_RCC_GPIOH_CLK_DISABLE();
329
330 HAL_SuspendTick();
331 }
332
333 static inline void resume_power_down(void)
334 {
335 HAL_ResumeTick();
336
337 HAL_RCC_OscConfig(&low_power_saved_rcc_oscinitstruct);
338 HAL_RCC_ClockConfig(&low_power_saved_rcc_clkinitstruct, low_power_saved_flatency);
339
340 __HAL_RCC_GPIOA_CLK_ENABLE();
341 __HAL_RCC_GPIOB_CLK_ENABLE();
342 __HAL_RCC_GPIOH_CLK_ENABLE();
343
344 /* Save GPIO bank state */
345 for (size_t idx = 0; idx < GPIO_BANK_COUNT; idx++)
346 {
347 GPIO_TypeDef *gpio_bank = gpio_banks[idx];
348 gpio_config_t *gpio_config = &low_power_saved_gpio_bank[idx];
349
350 WRITE_REG(gpio_bank->MODER, gpio_config->MODER);
351 WRITE_REG(gpio_bank->OTYPER, gpio_config->OTYPER);
352 WRITE_REG(gpio_bank->OSPEEDR, gpio_config->OSPEEDR);
353 WRITE_REG(gpio_bank->PUPDR, gpio_config->PUPDR);
354 WRITE_REG(gpio_bank->AFR[0], gpio_config->AFR[0]);
355 WRITE_REG(gpio_bank->AFR[1], gpio_config->AFR[1]);
356 }
357
358 HAL_I2C_Init(&MODULE_I2C_HANDLE);
359 HAL_SPI_Init(&A121_SPI_HANDLE);
360 HAL_UART_Init(&MODULE_UART2_HANDLE);
361
362 /* Start I2C */
363 if (HAL_I2C_EnableListen_IT(&MODULE_I2C_HANDLE) != HAL_OK)
364 {
365 /**
366 * Calling this function with wrong parameters will return HAL_ERROR
367 * Calling this function when the i2c module is in the wrong state return HAL_BUSY
368 */
369 Error_Handler();
370 }
371 }
372
373 static uint32_t get_rtc_tick(void)
374 {
375 RTC_DateTypeDef rtc_date = {0};
376 RTC_TimeTypeDef rtc_time = {0};
377
378 /* Wait until any pending shift operation is completed */
379 while ((MODULE_RTC_HANDLE.Instance->ISR & RTC_ISR_SHPF) != RESET)
380 {
381 ;
382 }
383
384 if (HAL_RTC_GetTime(&MODULE_RTC_HANDLE, &rtc_time, RTC_FORMAT_BIN) != HAL_OK)
385 {
386 Error_Handler();
387 }
388
389 if (HAL_RTC_GetDate(&MODULE_RTC_HANDLE, &rtc_date, RTC_FORMAT_BIN) != HAL_OK)
390 {
391 Error_Handler();
392 }
393
394 uint32_t rtc_ticks_ms = 0;
395
396 if (rtc_time.Hours)
397 {
398 rtc_ticks_ms += rtc_time.Hours * 60 * 60 * 1000;
399 }
400
401 if (rtc_time.Minutes)
402 {
403 rtc_ticks_ms += rtc_time.Minutes * 60 * 1000;
404 }
405
406 if (rtc_time.Seconds)
407 {
408 rtc_ticks_ms += rtc_time.Seconds * 1000;
409 }
410
411 rtc_ticks_ms += ((rtc_time.SecondFraction - rtc_time.SubSeconds) * 1000) / (rtc_time.SecondFraction + 1);
412
413 return rtc_ticks_ms;
414 }
415
416 static void rtc_tick_to_time(uint32_t tick, RTC_TimeTypeDef *time)
417 {
418 uint32_t rtc_ticks_ms = tick;
419
420 time->SecondFraction = MODULE_RTC_HANDLE.Init.SynchPrediv;
421
422 time->Hours = (rtc_ticks_ms / (60 * 60 * 1000)) % 24;
423
424 rtc_ticks_ms = rtc_ticks_ms % (60 * 60 * 1000);
425
426 time->Minutes = (rtc_ticks_ms / (60 * 1000)) % 60;
427
428 rtc_ticks_ms = rtc_ticks_ms % (60 * 1000);
429
430 time->Seconds = (rtc_ticks_ms / 1000) % 60;
431
432 rtc_ticks_ms = rtc_ticks_ms % 1000;
433
434 time->SubSeconds = time->SecondFraction - (rtc_ticks_ms * (time->SecondFraction + 1)) / 1000;
435 }
436
437 static void rtc_set_next_wakeup_time(void)
438 {
439 RTC_AlarmTypeDef alarm = {{0}, 0, 0, 0, 0, 0, 0};
440
441 if (rtc_period_time_ms > 0)
442 {
443 rtc_tick_to_time(get_rtc_tick() + rtc_period_time_ms, &alarm.AlarmTime);
444
445 alarm.Alarm = RTC_ALARM_B;
446 alarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY;
447 alarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_SS14;
448
449 if (HAL_RTC_DeactivateAlarm(&MODULE_RTC_HANDLE, RTC_ALARM_B) != HAL_OK)
450 {
451 Error_Handler();
452 }
453
454 if (HAL_RTC_SetAlarm_IT(&MODULE_RTC_HANDLE, &alarm, RTC_FORMAT_BIN) != HAL_OK)
455 {
456 Error_Handler();
457 }
458 }
459 else
460 {
461 if (HAL_RTC_DeactivateAlarm(&MODULE_RTC_HANDLE, RTC_ALARM_B) != HAL_OK)
462 {
463 Error_Handler();
464 }
465 }
466 }
467
468 static void wait_for_i2c_idle(void)
469 {
470 for (size_t idx = 0U; idx < WAIT_FOR_IDLE_RETRIES; idx++)
471 {
472 /* Make sure we do not have a race for i2c_idle */
473 acc_integration_critical_section_enter();
474 bool idle = i2c_idle;
475 acc_integration_critical_section_exit();
476
477 if (idle)
478 {
479 break;
480 }
481
482 /* Wait before next retry */
483 HAL_Delay(WAIT_FOR_IDLE_RETRY_INTERNAL_MS);
484 }
485 }
486
487 static void prepare_register_data(I2C_HandleTypeDef *hi2c)
488 {
489 /* Read register and put in buffer */
490 acc_reg_protocol_data_out(i2c_slave_buffer, ACC_REG_PROTOCOL_REGDATA_LENGTH);
491
492 /* Prepare buffer for transmit */
493 if (HAL_I2C_Slave_Seq_Transmit_IT(hi2c, i2c_slave_buffer, ACC_REG_PROTOCOL_REGDATA_LENGTH, I2C_NEXT_FRAME) != HAL_OK)
494 {
495 /**
496 * Calling this function with wrong parameters will return HAL_ERROR
497 * Calling this function when the i2c module is in the wrong state return HAL_BUSY
498 */
499 Error_Handler();
500 }
501 }
502
503 static uint32_t get_i2c_address(void)
504 {
505 uint32_t address = I2C_ADDRESS_FLOATING;
506
507 switch (get_pin_state(I2C_ADDRESS_GPIO_Port, I2C_ADDRESS_Pin))
508 {
509 case PIN_STATE_LOW:
510 address = I2C_ADDRESS_LOW;
511 break;
512 case PIN_STATE_HIGH:
513 address = I2C_ADDRESS_HIGH;
514 break;
515 case PIN_STATE_FLOATING:
516 address = I2C_ADDRESS_FLOATING;
517 break;
518 default:
519 break;
520 }
521
522 return address;
523 }
524
525 static pin_state_t get_pin_state(GPIO_TypeDef *gpio_port, uint32_t gpio_pin)
526 {
527 pin_state_t pin_state = PIN_STATE_FLOATING;
528 GPIO_InitTypeDef GPIO_InitStruct = {0};
529
530 GPIO_InitStruct.Pin = gpio_pin;
531 GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
532 GPIO_InitStruct.Pull = GPIO_PULLUP;
533 HAL_GPIO_Init(gpio_port, &GPIO_InitStruct);
534
535 // Delay in order to stabilize
536 HAL_Delay(1);
537 GPIO_PinState Pin_Pullup = HAL_GPIO_ReadPin(gpio_port, gpio_pin);
538
539 GPIO_InitStruct.Pull = GPIO_PULLDOWN;
540 HAL_GPIO_Init(gpio_port, &GPIO_InitStruct);
541
542 // Delay in order to stabilize
543 HAL_Delay(1);
544 GPIO_PinState Pin_Pulldown = HAL_GPIO_ReadPin(gpio_port, gpio_pin);
545
546 if ((Pin_Pulldown == GPIO_PIN_RESET) && (Pin_Pullup == GPIO_PIN_RESET))
547 {
548 // Pin is low with both pull-up and and pull-down which means that it is tied to GND
549 pin_state = PIN_STATE_LOW;
550 }
551 else if ((Pin_Pulldown == GPIO_PIN_SET) && (Pin_Pullup == GPIO_PIN_SET))
552 {
553 // Pin is high with both pull-up and and pull-down which means that it is tied to VIO
554 pin_state = PIN_STATE_HIGH;
555 }
556
557 // Configure to analog in order to minimize power consumtion
558 GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
559 GPIO_InitStruct.Pull = GPIO_NOPULL;
560 HAL_GPIO_Init(gpio_port, &GPIO_InitStruct);
561
562 return pin_state;
563 }
564
565 /*
566 * STM32 I2C Interrupt callbacks
567 */
568
569 void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
570 {
571 (void)AddrMatchCode;
572
573 i2c_idle = false;
574
575 /* Our i2c address was detected, transmit or receive? */
576 if (TransferDirection == I2C_DIRECTION_TRANSMIT)
577 {
578 /* Reset protocol before receiving new bytes from master */
579 acc_reg_protocol_reset();
580
581 /* Always start by getting register address, 2 bytes */
582 if (HAL_I2C_Slave_Seq_Receive_IT(hi2c, i2c_slave_buffer, ACC_REG_PROTOCOL_ADDRESS_LENGTH, I2C_NEXT_FRAME) != HAL_OK)
583 {
584 /**
585 * Calling this function with wrong parameters will return HAL_ERROR
586 * Calling this function when the i2c module is in the wrong state return HAL_BUSY
587 */
588 Error_Handler();
589 }
590 }
591 else
592 {
593 /* Prepare register data to be read by master */
594 prepare_register_data(hi2c);
595 }
596 }
597
598 void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
599 {
600 /* Prepare register data to be read by master */
601 prepare_register_data(hi2c);
602 }
603
604 void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
605 {
606 /* Get number of received bytes */
607 uint16_t input_length = (uint16_t)((uintptr_t)hi2c->pBuffPtr - (uintptr_t)i2c_slave_buffer);
608
609 if (input_length == ACC_REG_PROTOCOL_ADDRESS_LENGTH)
610 {
611 /* Handle receive register address */
612 acc_reg_protocol_data_in(i2c_slave_buffer, input_length);
613 }
614 else if (input_length == ACC_REG_PROTOCOL_REGDATA_LENGTH)
615 {
616 /* Handle receive register data (write register) */
617 acc_reg_protocol_data_in(i2c_slave_buffer, input_length);
618 }
619
620 /* NACK next write if an error has occured */
621 if (acc_reg_protocol_data_nack())
622 {
623 __HAL_I2C_GENERATE_NACK(hi2c);
624 }
625
626 /* Prepare to receive register data (4 bytes) */
627 if (HAL_I2C_Slave_Seq_Receive_IT(hi2c, i2c_slave_buffer, ACC_REG_PROTOCOL_REGDATA_LENGTH, I2C_NEXT_FRAME) != HAL_OK)
628 {
629 /**
630 * Calling this function with wrong parameters will return HAL_ERROR
631 * Calling this function when the i2c module is in the wrong state return HAL_BUSY
632 */
633 Error_Handler();
634 }
635 }
636
637 void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
638 {
639 i2c_idle = true;
640
641 /* I2C transaction done, start listening for new */
642 if (HAL_I2C_EnableListen_IT(hi2c) != HAL_OK)
643 {
644 /**
645 * Calling this function with wrong parameters will return HAL_ERROR
646 * Calling this function when the i2c module is in the wrong state return HAL_BUSY
647 */
648 Error_Handler();
649 }
650 }
651
652 void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
653 {
654 /* Has an I2C error occured? */
655 if (HAL_I2C_GetError(hi2c) != HAL_I2C_ERROR_AF)
656 {
657 /**
658 * The data NACK is the only valid error code
659 */
660 Error_Handler();
661 }
662 }
acc_reg_protocol_data_in
void acc_reg_protocol_data_in(uint8_t *buffer, size_t data_in_length)
Handle data input to the register protocol.
Definition: acc_reg_protocol.c:230
rtc_period_time_ms
static uint32_t rtc_period_time_ms
Definition: i2c_application_system_stm32.c:59
SPI_MISO_Pin
#define SPI_MISO_Pin
Definition: main.h:90
low_power_saved_rcc_oscinitstruct
static RCC_OscInitTypeDef low_power_saved_rcc_oscinitstruct
Definition: i2c_application_system_stm32.c:50
I2C_ADDRESS_LOW
#define I2C_ADDRESS_LOW
Definition: i2c_application_system_stm32.c:24
ACC_REG_PROTOCOL_ADDRESS_LENGTH
#define ACC_REG_PROTOCOL_ADDRESS_LENGTH
Definition: acc_reg_protocol.h:11
PIN_STATE_HIGH
@ PIN_STATE_HIGH
Definition: i2c_application_system_stm32.c:30
MISC_GPIO0_GPIO_Port
#define MISC_GPIO0_GPIO_Port
Definition: main.h:97
MCU_INT_GPIO_Port
#define MCU_INT_GPIO_Port
Definition: main.h:73
WAKE_UP_Pin
#define WAKE_UP_Pin
Definition: main.h:67
MODULE_I2C_HANDLE
I2C_HandleTypeDef MODULE_I2C_HANDLE
SPI_SCK_Pin
#define SPI_SCK_Pin
Definition: main.h:92
low_power_saved_gpio_bank
static gpio_config_t low_power_saved_gpio_bank[3U]
Definition: i2c_application_system_stm32.c:53
SPI_MOSI_Pin
#define SPI_MOSI_Pin
Definition: main.h:88
I2C_ADDRESS_Pin
#define I2C_ADDRESS_Pin
Definition: main.h:76
acc_integration_critical_section_exit
void acc_integration_critical_section_exit(void)
Definition: acc_integration_cortex.c:16
resume_power_down
static void resume_power_down(void)
Resume power down state.
Definition: i2c_application_system_stm32.c:333
MODULE_RTC_HANDLE
RTC_HandleTypeDef MODULE_RTC_HANDLE
i2c_application_system_reset
void i2c_application_system_reset(void)
Reset the system.
Definition: i2c_application_system_stm32.c:158
i2c_application_system_init
void i2c_application_system_init(void)
Init the system.
Definition: i2c_application_system_stm32.c:130
I2C_ADDRESS_GPIO_Port
#define I2C_ADDRESS_GPIO_Port
Definition: main.h:77
acc_integration.h
ACC_REG_PROTOCOL_REGDATA_LENGTH
#define ACC_REG_PROTOCOL_REGDATA_LENGTH
Definition: acc_reg_protocol.h:12
MCU_INT_Pin
#define MCU_INT_Pin
Definition: main.h:72
HAL_I2C_AddrCallback
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
Definition: i2c_application_system_stm32.c:569
WAIT_FOR_IDLE_RETRIES
#define WAIT_FOR_IDLE_RETRIES
Definition: i2c_application_system_stm32.c:19
MODULE_UART1_HANDLE
UART_HandleTypeDef MODULE_UART1_HANDLE
prepare_register_data
static void prepare_register_data(I2C_HandleTypeDef *hi2c)
Helper function to prepare transmit of register data.
Definition: i2c_application_system_stm32.c:487
HAL_I2C_SlaveTxCpltCallback
void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
Definition: i2c_application_system_stm32.c:598
rtc_tick_to_time
static void rtc_tick_to_time(uint32_t tick, RTC_TimeTypeDef *time)
Convert RTC ticks to RTC time.
Definition: i2c_application_system_stm32.c:416
A121_SPI_HANDLE
SPI_HandleTypeDef A121_SPI_HANDLE
i2c_application_set_periodic_wakeup
void i2c_application_set_periodic_wakeup(uint32_t period_ms)
Set up a periodic timer used to wake up the system from sleep.
Definition: i2c_application_system_stm32.c:238
acc_reg_protocol_data_nack
bool acc_reg_protocol_data_nack(void)
Should protocol NACK the next data.
Definition: acc_reg_protocol.c:218
I2C_ADDRESS_FLOATING
#define I2C_ADDRESS_FLOATING
Definition: i2c_application_system_stm32.c:23
PIN_STATE_FLOATING
@ PIN_STATE_FLOATING
Definition: i2c_application_system_stm32.c:31
gpio_config_t::PUPDR
uint32_t PUPDR
Definition: i2c_application_system_stm32.c:39
I2C_SLAVE_BUFFER_SIZE
#define I2C_SLAVE_BUFFER_SIZE
Definition: i2c_application_system_stm32.c:18
gpio_config_t::OTYPER
uint32_t OTYPER
Definition: i2c_application_system_stm32.c:37
i2c_application_system.h
get_rtc_tick
static uint32_t get_rtc_tick(void)
Get RTC ticks based on current RTC time.
Definition: i2c_application_system_stm32.c:373
i2c_application_is_periodic_wakeup
bool i2c_application_is_periodic_wakeup(void)
Test if a periodic wake up has occurred.
Definition: i2c_application_system_stm32.c:244
printf
#define printf
Definition: printf.h:60
SPI_SS_Pin
#define SPI_SS_Pin
Definition: main.h:98
disable_interrupts
static void disable_interrupts(void)
Disable interrupts.
Definition: i2c_application_system_stm32.c:268
i2c_application_system_setup_generic_gpio_pin
void i2c_application_system_setup_generic_gpio_pin(bool enable)
Setup the generic gpio pin.
Definition: i2c_application_system_stm32.c:188
gpio_config_t::RCC_GPIO_CLK_ENABLE
uint32_t RCC_GPIO_CLK_ENABLE
Definition: i2c_application_system_stm32.c:42
MODULE_UART2_HANDLE
UART_HandleTypeDef MODULE_UART2_HANDLE
low_power_saved_flatency
static uint32_t low_power_saved_flatency
Definition: i2c_application_system_stm32.c:52
i2c_application_system_wait_for_interrupt
void i2c_application_system_wait_for_interrupt(void)
Wait for interrupt to occur.
Definition: i2c_application_system_stm32.c:169
WAKE_UP_GPIO_Port
#define WAKE_UP_GPIO_Port
Definition: main.h:68
gpio_config_t::AFR
uint32_t AFR[2]
Definition: i2c_application_system_stm32.c:40
rtc_set_next_wakeup_time
static void rtc_set_next_wakeup_time(void)
Function for setting the next wakeup time from the RTC interrupt.
Definition: i2c_application_system_stm32.c:437
GPIO_BANK_COUNT
#define GPIO_BANK_COUNT
Definition: i2c_application_system_stm32.c:21
get_i2c_address
static uint32_t get_i2c_address(void)
Helper function to get i2c address from I2C_ADDRESS pin pin state.
Definition: i2c_application_system_stm32.c:503
low_power_saved_rcc_clkinitstruct
static RCC_ClkInitTypeDef low_power_saved_rcc_clkinitstruct
Definition: i2c_application_system_stm32.c:51
wait_for_i2c_idle
static void wait_for_i2c_idle(void)
Wait for I2C interface to be idle.
Definition: i2c_application_system_stm32.c:468
rtc_wakeup_triggered
static volatile bool rtc_wakeup_triggered
Definition: i2c_application_system_stm32.c:60
i2c_application_enter_low_power_state
void i2c_application_enter_low_power_state(void)
Make the MCU enter its low power state.
Definition: i2c_application_system_stm32.c:215
ENABLE_Pin
#define ENABLE_Pin
Definition: main.h:84
PIN_STATE_LOW
@ PIN_STATE_LOW
Definition: i2c_application_system_stm32.c:29
prepare_power_down
static void prepare_power_down(void)
Prepare power down state.
Definition: i2c_application_system_stm32.c:282
gpio_banks
static GPIO_TypeDef * gpio_banks[3U]
Definition: i2c_application_system_stm32.c:54
i2c_slave_buffer
static uint8_t i2c_slave_buffer[4]
Definition: i2c_application_system_stm32.c:56
HAL_I2C_ListenCpltCallback
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
Definition: i2c_application_system_stm32.c:637
main.h
: Header for main.c file. This file contains the common defines of the application.
Error_Handler
void Error_Handler(void)
gpio_config_t
GPIO config status, maps directly to the GPIO registers.
Definition: i2c_application_system_stm32.c:34
I2C_ADDRESS_HIGH
#define I2C_ADDRESS_HIGH
Definition: i2c_application_system_stm32.c:25
pin_state_t
pin_state_t
Definition: i2c_application_system_stm32.c:27
WAIT_FOR_IDLE_RETRY_INTERNAL_MS
#define WAIT_FOR_IDLE_RETRY_INTERNAL_MS
Definition: i2c_application_system_stm32.c:20
acc_reg_protocol.h
get_pin_state
static pin_state_t get_pin_state(GPIO_TypeDef *gpio_port, uint32_t gpio_pin)
Helper function to the state (HIGH/LOW/FLOATING) of a gpio pin.
Definition: i2c_application_system_stm32.c:525
acc_reg_protocol_data_out
void acc_reg_protocol_data_out(uint8_t *buffer, size_t data_out_length)
Handle data input from the register protocol.
Definition: acc_reg_protocol.c:294
acc_integration_critical_section_enter
void acc_integration_critical_section_enter(void)
Definition: acc_integration_cortex.c:9
HAL_I2C_SlaveRxCpltCallback
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
Definition: i2c_application_system_stm32.c:604
acc_reg_protocol_reset
void acc_reg_protocol_reset(void)
Reset register protocol.
Definition: acc_reg_protocol.c:211
HAL_I2C_ErrorCallback
void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c)
Definition: i2c_application_system_stm32.c:652
i2c_application_system_set_ready_pin
void i2c_application_system_set_ready_pin(bool enable)
Set the ready pin state.
Definition: i2c_application_system_stm32.c:181
MISC_GPIO0_Pin
#define MISC_GPIO0_Pin
Definition: main.h:96
HAL_RTCEx_AlarmBEventCallback
void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *rtc)
IRQ Handler for RTC B Alarm.
Definition: i2c_application_system_stm32.c:262
i2c_application_system_test_wakeup_pin
bool i2c_application_system_test_wakeup_pin(void)
Check if wakeup pin is high.
Definition: i2c_application_system_stm32.c:174
enable_interrupts
static void enable_interrupts(void)
Enable interrupts.
Definition: i2c_application_system_stm32.c:275
gpio_config_t::OSPEEDR
uint32_t OSPEEDR
Definition: i2c_application_system_stm32.c:38
i2c_application_system_set_generic_gpio_pin
void i2c_application_system_set_generic_gpio_pin(bool enable)
Set the generic gpio pin output state.
Definition: i2c_application_system_stm32.c:208
gpio_config_t::MODER
uint32_t MODER
Definition: i2c_application_system_stm32.c:36
gpio_config_t::ASCR
uint32_t ASCR
Definition: i2c_application_system_stm32.c:41
i2c_idle
static volatile bool i2c_idle
Definition: i2c_application_system_stm32.c:57