Implement EEPROM bytewise read/write
This commit is contained in:
71
Core/Src/EEPROM.c
Normal file
71
Core/Src/EEPROM.c
Normal file
@ -0,0 +1,71 @@
|
||||
#include "EEPROM.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#include "stm32f4xx_hal_def.h"
|
||||
#include "stm32f4xx_hal_i2c.h"
|
||||
|
||||
EEPROM_State eeprom_state = EEPROM_OFF;
|
||||
|
||||
I2C_HandleTypeDef* i2c;
|
||||
|
||||
void eeprom_init(I2C_HandleTypeDef* handle) {
|
||||
i2c = handle;
|
||||
eeprom_state = EEPROM_READY;
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef eeprom_write(uint16_t addr, uint8_t data) {
|
||||
uint8_t page = (addr >> 8) & 0b1;
|
||||
uint8_t mem_addr = addr & 0xFF;
|
||||
// Address must be shifted left for the HAL
|
||||
uint8_t dev_addr = EEPROM_DEV_ADDR | (page << 1);
|
||||
|
||||
uint8_t msg[2] = {mem_addr, data};
|
||||
return HAL_I2C_Master_Transmit(i2c, dev_addr, msg, 2, EEPROM_TIMEOUT);
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef eeprom_read_curr(uint8_t* data) {
|
||||
return HAL_I2C_Master_Receive(i2c, EEPROM_DEV_ADDR, data, 1, EEPROM_TIMEOUT);
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef eeprom_read_random(uint16_t addr, uint8_t* data) {
|
||||
// This is basically an SMBus Read Byte, see
|
||||
// https://www.kernel.org/doc/html/latest/i2c/smbus-protocol.html#smbus-read-byte
|
||||
|
||||
uint8_t page = (addr >> 8) & 0b1;
|
||||
uint8_t mem_addr = addr & 0xFF;
|
||||
// Address must be shifted left for the HAL
|
||||
uint8_t dev_addr = EEPROM_DEV_ADDR | (page << 1);
|
||||
|
||||
HAL_StatusTypeDef status = HAL_I2C_Master_Seq_Transmit_IT(
|
||||
i2c, dev_addr, &mem_addr, 1, I2C_FIRST_FRAME);
|
||||
if (status != HAL_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// Wait for write to be complete
|
||||
while (HAL_I2C_GetState(i2c) != HAL_I2C_STATE_READY) {
|
||||
}
|
||||
|
||||
// Try up to EEPROM_READ_TRIES times to get an acknowledgement from the slave.
|
||||
// If we don't abort and return the error.
|
||||
for (int i = 0; i < EEPROM_READ_TRIES; i++) {
|
||||
status =
|
||||
HAL_I2C_Master_Seq_Receive_IT(i2c, dev_addr, data, 1, I2C_LAST_FRAME);
|
||||
if (status == HAL_OK) {
|
||||
break;
|
||||
} else if (HAL_I2C_GetError(i2c) != HAL_I2C_ERROR_AF) {
|
||||
// Not an acknowledge failure -> timeout, abort
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (status != HAL_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// Wait for read to be complete
|
||||
while (HAL_I2C_GetState(i2c) != HAL_I2C_STATE_READY) {
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
@ -22,6 +22,7 @@
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "BQ_Abstraction_Layer.h"
|
||||
#include "EEPROM.h"
|
||||
|
||||
#include "stm32f4xx_hal.h"
|
||||
#include "stm32f4xx_hal_gpio.h"
|
||||
@ -139,6 +140,11 @@ int main(void) {
|
||||
HAL_GPIO_WritePin(DCDC_CTRL_GPIO_Port, DCDC_CTRL_Pin, GPIO_PIN_SET);
|
||||
HAL_Delay(100);
|
||||
afe_init(&huart2);
|
||||
eeprom_init(&hi2c1);
|
||||
uint8_t id;
|
||||
if (eeprom_read_random(EEPROM_ADDR_SLAVE_ID, &id) == HAL_OK) {
|
||||
HAL_GPIO_WritePin(STAT_LED4_GPIO_Port, STAT_LED4_Pin, GPIO_PIN_SET);
|
||||
}
|
||||
/* USER CODE END 2 */
|
||||
|
||||
/* Infinite loop */
|
||||
|
||||
@ -246,6 +246,9 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
|
||||
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_I2C1_CLK_ENABLE();
|
||||
/* I2C1 interrupt Init */
|
||||
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
|
||||
/* USER CODE BEGIN I2C1_MspInit 1 */
|
||||
|
||||
/* USER CODE END I2C1_MspInit 1 */
|
||||
@ -277,6 +280,8 @@ void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c)
|
||||
|
||||
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7);
|
||||
|
||||
/* I2C1 interrupt DeInit */
|
||||
HAL_NVIC_DisableIRQ(I2C1_EV_IRQn);
|
||||
/* USER CODE BEGIN I2C1_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END I2C1_MspDeInit 1 */
|
||||
|
||||
@ -57,6 +57,7 @@
|
||||
/* External variables --------------------------------------------------------*/
|
||||
extern CAN_HandleTypeDef hcan1;
|
||||
extern CAN_HandleTypeDef hcan2;
|
||||
extern I2C_HandleTypeDef hi2c1;
|
||||
extern UART_HandleTypeDef huart1;
|
||||
extern UART_HandleTypeDef huart3;
|
||||
/* USER CODE BEGIN EV */
|
||||
@ -228,6 +229,20 @@ void CAN1_RX1_IRQHandler(void)
|
||||
/* USER CODE END CAN1_RX1_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles I2C1 event interrupt.
|
||||
*/
|
||||
void I2C1_EV_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN I2C1_EV_IRQn 0 */
|
||||
|
||||
/* USER CODE END I2C1_EV_IRQn 0 */
|
||||
HAL_I2C_EV_IRQHandler(&hi2c1);
|
||||
/* USER CODE BEGIN I2C1_EV_IRQn 1 */
|
||||
|
||||
/* USER CODE END I2C1_EV_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles USART1 global interrupt.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user