Implement EEPROM bytewise read/write
This commit is contained in:
		
							
								
								
									
										41
									
								
								Core/Inc/EEPROM.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								Core/Inc/EEPROM.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					#ifndef INC_EEPROM_H_
 | 
				
			||||||
 | 
					#define INC_EEPROM_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "stm32f4xx_hal.h"
 | 
				
			||||||
 | 
					#include "stm32f4xx_hal_def.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EEPROM_BASE_ADDR 0b1010000
 | 
				
			||||||
 | 
					// Device address must be shifted left before being passed to the HAL
 | 
				
			||||||
 | 
					#define EEPROM_DEV_ADDR (EEPROM_BASE_ADDR << 1)
 | 
				
			||||||
 | 
					#define EEPROM_TIMEOUT 200 /* ms */
 | 
				
			||||||
 | 
					#define EEPROM_READ_TRIES 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EEPROM_ADDR_SLAVE_ID 0x000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef enum { EEPROM_OFF, EEPROM_READY, EEPROM_ERROR } EEPROM_State;
 | 
				
			||||||
 | 
					extern EEPROM_State eeprom_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void eeprom_init(I2C_HandleTypeDef* handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Write a byte to the EEPROM.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param addr 9-bit address (1 bit page select + 8 bit address)
 | 
				
			||||||
 | 
					 * @param data The byte to write
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					HAL_StatusTypeDef eeprom_write(uint16_t addr, uint8_t data);
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read a byte from the next address in the EEPROM.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param data 1-byte buffer into which the read byte is written.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					HAL_StatusTypeDef eeprom_read_curr(uint8_t* data);
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @brief Read a byte from the EEPROM (random-access).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param addr 9-bit address (1 bit page select + 8 bit address)
 | 
				
			||||||
 | 
					 * @param data 1-byte buffer into which the read byte is written.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					HAL_StatusTypeDef eeprom_read_random(uint16_t addr, uint8_t* data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // INC_EEPROM_H_
 | 
				
			||||||
@ -57,6 +57,7 @@ void PendSV_Handler(void);
 | 
				
			|||||||
void SysTick_Handler(void);
 | 
					void SysTick_Handler(void);
 | 
				
			||||||
void CAN1_RX0_IRQHandler(void);
 | 
					void CAN1_RX0_IRQHandler(void);
 | 
				
			||||||
void CAN1_RX1_IRQHandler(void);
 | 
					void CAN1_RX1_IRQHandler(void);
 | 
				
			||||||
 | 
					void I2C1_EV_IRQHandler(void);
 | 
				
			||||||
void USART1_IRQHandler(void);
 | 
					void USART1_IRQHandler(void);
 | 
				
			||||||
void USART3_IRQHandler(void);
 | 
					void USART3_IRQHandler(void);
 | 
				
			||||||
void CAN2_RX0_IRQHandler(void);
 | 
					void CAN2_RX0_IRQHandler(void);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										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 ----------------------------------------------------------*/
 | 
					/* Private includes ----------------------------------------------------------*/
 | 
				
			||||||
/* USER CODE BEGIN Includes */
 | 
					/* USER CODE BEGIN Includes */
 | 
				
			||||||
#include "BQ_Abstraction_Layer.h"
 | 
					#include "BQ_Abstraction_Layer.h"
 | 
				
			||||||
 | 
					#include "EEPROM.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "stm32f4xx_hal.h"
 | 
					#include "stm32f4xx_hal.h"
 | 
				
			||||||
#include "stm32f4xx_hal_gpio.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_GPIO_WritePin(DCDC_CTRL_GPIO_Port, DCDC_CTRL_Pin, GPIO_PIN_SET);
 | 
				
			||||||
  HAL_Delay(100);
 | 
					  HAL_Delay(100);
 | 
				
			||||||
  afe_init(&huart2);
 | 
					  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 */
 | 
					  /* USER CODE END 2 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Infinite loop */
 | 
					  /* Infinite loop */
 | 
				
			||||||
 | 
				
			|||||||
@ -246,6 +246,9 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* Peripheral clock enable */
 | 
					    /* Peripheral clock enable */
 | 
				
			||||||
    __HAL_RCC_I2C1_CLK_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 BEGIN I2C1_MspInit 1 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* USER CODE END 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);
 | 
					    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* I2C1 interrupt DeInit */
 | 
				
			||||||
 | 
					    HAL_NVIC_DisableIRQ(I2C1_EV_IRQn);
 | 
				
			||||||
  /* USER CODE BEGIN I2C1_MspDeInit 1 */
 | 
					  /* USER CODE BEGIN I2C1_MspDeInit 1 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* USER CODE END I2C1_MspDeInit 1 */
 | 
					  /* USER CODE END I2C1_MspDeInit 1 */
 | 
				
			||||||
 | 
				
			|||||||
@ -57,6 +57,7 @@
 | 
				
			|||||||
/* External variables --------------------------------------------------------*/
 | 
					/* External variables --------------------------------------------------------*/
 | 
				
			||||||
extern CAN_HandleTypeDef hcan1;
 | 
					extern CAN_HandleTypeDef hcan1;
 | 
				
			||||||
extern CAN_HandleTypeDef hcan2;
 | 
					extern CAN_HandleTypeDef hcan2;
 | 
				
			||||||
 | 
					extern I2C_HandleTypeDef hi2c1;
 | 
				
			||||||
extern UART_HandleTypeDef huart1;
 | 
					extern UART_HandleTypeDef huart1;
 | 
				
			||||||
extern UART_HandleTypeDef huart3;
 | 
					extern UART_HandleTypeDef huart3;
 | 
				
			||||||
/* USER CODE BEGIN EV */
 | 
					/* USER CODE BEGIN EV */
 | 
				
			||||||
@ -228,6 +229,20 @@ void CAN1_RX1_IRQHandler(void)
 | 
				
			|||||||
  /* USER CODE END CAN1_RX1_IRQn 1 */
 | 
					  /* 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.
 | 
					  * @brief This function handles USART1 global interrupt.
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@ -1,5 +1,5 @@
 | 
				
			|||||||
##########################################################################################################################
 | 
					##########################################################################################################################
 | 
				
			||||||
# File automatically-generated by tool: [projectgenerator] version: [3.16.0] date: [Thu Jun 09 23:03:25 CEST 2022] 
 | 
					# File automatically-generated by tool: [projectgenerator] version: [3.16.0] date: [Sun Jun 12 16:56:47 CEST 2022] 
 | 
				
			||||||
##########################################################################################################################
 | 
					##########################################################################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# ------------------------------------------------
 | 
					# ------------------------------------------------
 | 
				
			||||||
 | 
				
			|||||||
@ -40,6 +40,7 @@ Core/Src/AMS_CAN.c \
 | 
				
			|||||||
Core/Src/BQ_Abstraction_Layer.c \
 | 
					Core/Src/BQ_Abstraction_Layer.c \
 | 
				
			||||||
Core/Src/BQ_Communication.c \
 | 
					Core/Src/BQ_Communication.c \
 | 
				
			||||||
Core/Src/BatteryManagement.c \
 | 
					Core/Src/BatteryManagement.c \
 | 
				
			||||||
 | 
					Core/Src/EEPROM.c \
 | 
				
			||||||
Core/Src/SoftI2C.c \
 | 
					Core/Src/SoftI2C.c \
 | 
				
			||||||
Core/Src/TMP144.c \
 | 
					Core/Src/TMP144.c \
 | 
				
			||||||
Core/Src/main.c \
 | 
					Core/Src/main.c \
 | 
				
			||||||
 | 
				
			|||||||
@ -73,6 +73,7 @@ NVIC.CAN2_SCE_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
 | 
				
			|||||||
NVIC.DebugMonitor_IRQn=true\:1\:0\:true\:false\:true\:false\:false\:true
 | 
					NVIC.DebugMonitor_IRQn=true\:1\:0\:true\:false\:true\:false\:false\:true
 | 
				
			||||||
NVIC.ForceEnableDMAVector=true
 | 
					NVIC.ForceEnableDMAVector=true
 | 
				
			||||||
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
 | 
					NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
 | 
				
			||||||
 | 
					NVIC.I2C1_EV_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
 | 
				
			||||||
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
 | 
					NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
 | 
				
			||||||
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
 | 
					NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
 | 
				
			||||||
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
 | 
					NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user