#include #include #ifndef CONFIG_H_ #define CONFIG_H_ #define I2C_TX_MAX_PACKET_SIZE (8) #define I2C_RX_MAX_PACKET_SIZE (12) #define BATTERY_THRESHOLD (20) #define TEMPERATURE_MAX_C (60) #define MAX_CYCLES (2) #define TARGET_BASE_ADDRESS (0x48) #define MEASUREMENT_CHECK_INTERVAL 160000 //Do not know yet the exact timing #define HEALTHY_BATTERY_VALUE (3800) /* * https://www.embedded.com/introduction-to-the-volatile-keyword/ * https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/393364/avoid-race-condition-between-isr-and-main * https://www.omi.me/blogs/firmware-guides/how-to-handle-race-conditions-in-embedded-c-without-using-an-rtos * A variable should be declared as volatile if the value could change unexpectedly. * In practice, only three types of variable could change: * Memory-mapped peripheral registers * Global variables modified by an ISR * Global variables within a multi-threaded application * The volatile keyword in C is used to inform the compiler not to optimize access to a variable that might change unexpectedly. * This is particularly useful for variables shared between an interrupt service routine (ISR) and the main program. Observation Noted are: - Race condition while reading and storing the buffers, leading to lag the Rx Buffer during the execution at times or completely lagging by 1 for each slots; incorrect Read */ typedef struct{ volatile uint8_t txBuffer[I2C_TX_MAX_PACKET_SIZE]; volatile uint8_t txLen; volatile uint8_t txCount; volatile bool txComplete; }tx_Packet; typedef struct{ volatile uint8_t rxBuffer[I2C_RX_MAX_PACKET_SIZE]; volatile uint8_t rxLen; volatile uint8_t rxCount; volatile bool rxComplete; }rx_Packet; // Global variables declared in i2c_hal.c extern tx_Packet txPacket; extern rx_Packet rxPacket; #endif