PingPong/Core/Src/EEPROM.c
2024-12-01 15:56:31 +03:00

457 lines
14 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "EEPROM.h"
#include "pca9685.h"
#include "usbd_cdc_if.h"
#include "Print.h"
#include "RobotFunctions.h"
#include "Indicator.h"
InfoBlock infoBlock;
extern IWDG_HandleTypeDef hiwdg;
//*********************** EEPROM_INIT ********************************//
MemoryStatus EEPROM_INIT() {
uint8_t attempts = EEPROM_REED_RETRY; retry:
memset(&infoBlock, 0x00, sizeof(infoBlock));
MemoryStatus status = getInfoBlock(&infoBlock);
if (status != EEPROM_OK) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
char errorMsg[] = "Error reading InfoBlock from EEPROM\n";
CDC_Transmit_FS((uint8_t*) errorMsg, strlen(errorMsg));
return status;
}
char uid_ref[11] = "Stack_Sport";
if (memcmp(&(infoBlock.init_uid), &uid_ref, 11) != 0) {
char errorMsg[] = "uid non equal\n\n";
CDC_Transmit_FS((uint8_t*) errorMsg, strlen(errorMsg));
EEPROM_EARSE();
memset(&infoBlock, 0x00, sizeof(InfoBlock));
char uid[] = "Stack_Sport";
memcpy(infoBlock.init_uid, uid, 11);
infoBlock.hwInfo.timings.preRun = 3500;
infoBlock.hwInfo.motors.speed_Rollers_min = 0;
infoBlock.hwInfo.motors.speed_Screw_min = 0;
infoBlock.hwInfo.servos[SERVO_AXIAL].invert = 0;
infoBlock.hwInfo.servos[SERVO_AXIAL].min = 0;
infoBlock.hwInfo.servos[SERVO_AXIAL].def = 90;
infoBlock.hwInfo.servos[SERVO_AXIAL].max = 180;
infoBlock.hwInfo.servos[SERVO_HORIZONTAL].invert = 0;
infoBlock.hwInfo.servos[SERVO_HORIZONTAL].min = 0;
infoBlock.hwInfo.servos[SERVO_HORIZONTAL].def = 90;
infoBlock.hwInfo.servos[SERVO_HORIZONTAL].max = 180;
infoBlock.hwInfo.servos[SERVO_VERTICAL].invert = 0;
infoBlock.hwInfo.servos[SERVO_VERTICAL].min = 0;
infoBlock.hwInfo.servos[SERVO_VERTICAL].def = 90;
infoBlock.hwInfo.servos[SERVO_VERTICAL].max = 180;
infoBlock.statInfo.shotsInShot = 0;
infoBlock.statInfo.shotsInProgram = 0;
infoBlock.statInfo.shotInMacro = 0;
status = saveInfoBlock(&infoBlock);
if (status != EEPROM_OK) {
char errorMsg[] = "EEPROM FAIL\n";
CDC_Transmit_FS((uint8_t*) errorMsg, strlen(errorMsg));
return status;
}
status = getInfoBlock(&infoBlock);
if (status != EEPROM_OK) {
char errorMsg[] = "Error reading InfoBlock from EEPROM\n";
CDC_Transmit_FS((uint8_t*) errorMsg, strlen(errorMsg));
return status;
}
}
// Буфер для строки вывода
char buffer[128];
// Вывод информации о HardwareInit_t
snprintf(buffer, sizeof(buffer), "Hardware Initialization:\n");
CDC_Transmit_FS((uint8_t*) buffer, strlen(buffer));
char char_tmp[12];
memcpy(char_tmp, infoBlock.init_uid, 11);
char_tmp[11] = '\0';
snprintf(buffer, sizeof(buffer), "init_uid: %s\n", char_tmp);
CDC_Transmit_FS((uint8_t*) buffer, strlen(buffer));
snprintf(buffer, sizeof(buffer),
"Servo 1: Invert=%u, Min=%u, Default=%u, Max=%u\n",
infoBlock.hwInfo.servos[0].invert, infoBlock.hwInfo.servos[0].min,
infoBlock.hwInfo.servos[0].def, infoBlock.hwInfo.servos[0].max);
CDC_Transmit_FS((uint8_t*) buffer, strlen(buffer));
snprintf(buffer, sizeof(buffer),
"Servo 2: Invert=%u, Min=%u, Default=%u, Max=%u\n",
infoBlock.hwInfo.servos[1].invert, infoBlock.hwInfo.servos[1].min,
infoBlock.hwInfo.servos[1].def, infoBlock.hwInfo.servos[1].max);
CDC_Transmit_FS((uint8_t*) buffer, strlen(buffer));
snprintf(buffer, sizeof(buffer),
"Servo 3: Invert=%u, Min=%u, Default=%u, Max=%u\n",
infoBlock.hwInfo.servos[2].invert, infoBlock.hwInfo.servos[2].min,
infoBlock.hwInfo.servos[2].def, infoBlock.hwInfo.servos[2].max);
CDC_Transmit_FS((uint8_t*) buffer, strlen(buffer));
snprintf(buffer, sizeof(buffer),
"Motors: Speed_Rollers_Min=%u, Speed_Screw_Min=%u\n",
infoBlock.hwInfo.motors.speed_Rollers_min,
infoBlock.hwInfo.motors.speed_Screw_min);
CDC_Transmit_FS((uint8_t*) buffer, strlen(buffer));
// Вывод информации о DelayTimes
snprintf(buffer, sizeof(buffer), "Timings: PreRun=%u\n",
infoBlock.hwInfo.timings.preRun);
CDC_Transmit_FS((uint8_t*) buffer, strlen(buffer));
// Вывод информации о Statistics
snprintf(buffer, sizeof(buffer), "Statistics:\n");
CDC_Transmit_FS((uint8_t*) buffer, strlen(buffer));
snprintf(buffer, sizeof(buffer), "Total Shots: %lu\n",
infoBlock.statInfo.shotsInShot);
CDC_Transmit_FS((uint8_t*) buffer, strlen(buffer));
snprintf(buffer, sizeof(buffer), "Total Programs: %lu\n",
infoBlock.statInfo.shotsInProgram);
CDC_Transmit_FS((uint8_t*) buffer, strlen(buffer));
snprintf(buffer, sizeof(buffer), "Total Macros: %lu\n\n",
infoBlock.statInfo.shotInMacro);
CDC_Transmit_FS((uint8_t*) buffer, strlen(buffer));
return status;
}
//************************************************************//
MemoryStatus saveInfoBlock() {
return FLASH_WriteBlock(START_ADR_STAT, 0, (uint8_t*) &infoBlock,
sizeof(InfoBlock), sizeof(InfoBlock));
}
MemoryStatus getInfoBlock() {
uint8_t attempts = EEPROM_REED_RETRY; retry:
memset(&infoBlock, 0x00, sizeof(InfoBlock));
MemoryStatus status = FLASH_ReadBlock(START_ADR_STAT, 0,
(uint8_t*) &infoBlock, sizeof(InfoBlock));
if (status != EEPROM_OK) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
return EEPROM_OK;
}
MemoryStatus saveShot(unsigned char number, Shot *shot) {
uint8_t attempts = EEPROM_REED_RETRY; retry:
if (FLASH_WriteBlock(START_ADR_SHOT, number, (uint8_t*) shot,
SHOT_BLOCKSIZE, SHOT_BLOCKSIZE) == EEPROM_OK) {
return EEPROM_OK;
}
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
MemoryStatus getShot(unsigned char number, Shot *shot) {
uint8_t attempts = EEPROM_REED_RETRY; retry:
HAL_IWDG_Refresh(&hiwdg);
memset(shot, 0x00, sizeof(Shot));
if (FLASH_ReadBlock(START_ADR_SHOT, number, (uint8_t*) shot, SHOT_BLOCKSIZE)
!= EEPROM_OK) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
if (!shot->isExist) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_MISSING_ELEMENT;
}
return EEPROM_OK;
}
MemoryStatus delShot(unsigned char number) {
uint8_t attempts = EEPROM_REED_RETRY; retry:
if (FLASH_DelBlock(START_ADR_SHOT, number, SHOT_BLOCKSIZE) == EEPROM_OK) {
return EEPROM_OK;
}
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
MemoryStatus saveProg(unsigned char number, Program *prog) {
uint8_t attempts = EEPROM_REED_RETRY; retry:
MemoryStatus result = EEPROM_OK;
for (uint16_t i = 0; i < prog->header.shotCount; ++i) {
HAL_IWDG_Refresh(&hiwdg);
Shot shot;
MemoryStatus stat = getShot(prog->shots[i].id, &shot);
if (!(stat == EEPROM_OK || stat == EEPROM_MISSING_ELEMENT)) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
if (!shot.isExist) {
// todo: добавить в запросы для загрузки снимков
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
result = EEPROM_MISSING_ELEMENT;
}
}
HAL_IWDG_Refresh(&hiwdg);
uint16_t totalSize = sizeof(ProgramHeader)
+ sizeof(ProgramShot) * prog->header.shotCount;
if (FLASH_WriteBlock(START_ADR_PROGRAM, number, (uint8_t*) prog, totalSize,
PROGRAM_BLOCKSIZE) != EEPROM_OK) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
return result;
}
MemoryStatus getProg(unsigned char number, Program *prog) {
uint8_t attempts = EEPROM_REED_RETRY; retry:
memset(prog, 0x00, sizeof(Program));
if (FLASH_ReadBlock(START_ADR_PROGRAM, number, (uint8_t*) prog,
PROGRAM_BLOCKSIZE) != EEPROM_OK) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
if (!prog->header.shotCount) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_MISSING_ELEMENT;
}
return EEPROM_OK;
}
MemoryStatus delProg(unsigned char number) {
uint8_t attempts = EEPROM_REED_RETRY; retry:
if (FLASH_DelBlock(START_ADR_PROGRAM, number, PROGRAM_BLOCKSIZE)
== EEPROM_OK) {
return EEPROM_OK;
}
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
MemoryStatus saveMacro(unsigned char number, Macro *macro) {
uint8_t attempts = EEPROM_REED_RETRY; retry:
MemoryStatus result = EEPROM_OK;
for (uint16_t i = 0; i < macro->header.programmCount; ++i) {
HAL_IWDG_Refresh(&hiwdg);
Program prog;
MemoryStatus stat = getProg(macro->programs[i].id, &prog);
if (!(stat == EEPROM_OK || stat == EEPROM_MISSING_ELEMENT)) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
if (!prog.header.shotCount) {
result = EEPROM_MISSING_ELEMENT;
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
// todo: добавить в запросы для загрузки программ
}
}
uint16_t totalSize = sizeof(MacroHeader)
+ sizeof(MacroProgram) * macro->header.programmCount;
if (FLASH_WriteBlock(START_ADR_MACRO, number, (uint8_t*) macro, totalSize,
MACRO_BLOCKSIZE) != EEPROM_OK) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
return result;
}
MemoryStatus getMacro(unsigned char number, Macro *macro) {
uint8_t attempts = EEPROM_REED_RETRY; retry:
memset(macro, 0x00, sizeof(Macro));
if (FLASH_ReadBlock(START_ADR_MACRO, number, (uint8_t*) macro,
MACRO_BLOCKSIZE) != EEPROM_OK) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
if (!macro->header.programmCount) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_MISSING_ELEMENT;
}
return EEPROM_OK;
}
MemoryStatus delMacro(unsigned char number) {
uint8_t attempts = EEPROM_REED_RETRY; retry:
if (FLASH_DelBlock(START_ADR_MACRO, number, MACRO_BLOCKSIZE) == EEPROM_OK) {
return EEPROM_OK;
}
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
MemoryStatus EEPROM_EARSE() {
uint16_t addr = 0;
const uint16_t EEPROM_MAX_ADDR = 1024*32;
led_PingPong_start(7, 12);
do {
uint8_t Buf[64];
HAL_IWDG_Refresh(&hiwdg);
memset(Buf, 0x00, sizeof(Buf));
FLASH_WriteBlock(addr, 0, Buf, sizeof(Buf), sizeof(Buf));
HAL_IWDG_Refresh(&hiwdg);
led_PingPong_next();
uint8_t progress = (addr * 100) / EEPROM_MAX_ADDR;
led_progressbar(00, 06, progress<50 ? 100 : 100-(progress-50)*2);
led_progressbar(13, 19, progress<50 ? 100-progress*2 : 0);
addr += sizeof(Buf);
} while (addr < EEPROM_MAX_ADDR);
led_clear();
return EEPROM_OK;
}
MemoryStatus FLASH_WriteBlock(uint16_t startAddr, uint8_t number,
uint8_t *writeData, uint16_t dataSize, uint16_t blockSize) {
uint8_t attempts = EEPROM_REED_RETRY; retry:
HAL_StatusTypeDef result;
const uint16_t maxWriteSize = 64; // Максимальный размер блока для EEPROM AT24
uint16_t currentAddr = startAddr + (number * blockSize);
uint16_t bytesWritten = 0;
// Проверка на корректность входных данных
if ((startAddr == START_ADR_SHOT && number >= MAX_SHOT_COUNT) ||
(startAddr == START_ADR_PROGRAM && number >= MAX_PROGRAM_COUNT) ||
(startAddr == START_ADR_MACRO && number >= MAX_MACRO_COUNT)) {
return EEPROM_OUT_OF_RANGE;
}
while (bytesWritten < dataSize) {
uint16_t chunkSize = (dataSize - bytesWritten > maxWriteSize) ? maxWriteSize : (dataSize - bytesWritten);
uint16_t blockAddr16 = currentAddr;
uint8_t blockAddr[2] = { HIBYTE(blockAddr16), LOBYTE(blockAddr16) };
unsigned char Buf[chunkSize + 2];
memset(Buf, 0x00, sizeof(Buf));
Buf[0] = blockAddr[0];
Buf[1] = blockAddr[1];
for (uint16_t i = 0; i < chunkSize; i++) {
Buf[i + 2] = writeData[bytesWritten + i];
}
result = HAL_I2C_Master_Transmit(&hi2c1, (AT24C_ADRESS << 1), Buf, (chunkSize + 2), 10);
HAL_Delay(1);
if (result != HAL_OK) {
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
bytesWritten += chunkSize;
currentAddr += chunkSize;
}
return EEPROM_OK;
}
MemoryStatus FLASH_DelBlock(uint16_t startAddr, uint8_t number,
uint16_t dataSize) {
uint8_t attempts = EEPROM_REED_RETRY; retry:
HAL_StatusTypeDef result;
// Проверка на корректность входных данных
if ((startAddr == START_ADR_SHOT && number >= MAX_SHOT_COUNT)
|| (startAddr == START_ADR_PROGRAM && number >= MAX_PROGRAM_COUNT)
|| (startAddr == START_ADR_MACRO && number >= MAX_MACRO_COUNT)) {
return EEPROM_OUT_OF_RANGE;
}
uint16_t blockAddr16 = (uint16_t) (startAddr
+ (uint16_t) (number * dataSize));
uint8_t blockAddr[2] = { HIBYTE(blockAddr16), LOBYTE(blockAddr16) };
unsigned char Buf[2 + 1];
memset(Buf, 0x00, sizeof(Buf));
Buf[0] = blockAddr[0];
Buf[1] = blockAddr[1];
Buf[2] = 0;
result = HAL_I2C_Master_Transmit(&hi2c1, (AT24C_ADRESS << 1), Buf,
sizeof(Buf), 10);
HAL_Delay(1);
if (result != HAL_OK) {
if (--attempts > 0) goto retry;
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
return EEPROM_OK;
}
MemoryStatus FLASH_ReadBlock(uint16_t startAddr, uint8_t number,
uint8_t *readData, uint16_t dataSize) {
uint8_t attempts = EEPROM_REED_RETRY; retry:
HAL_StatusTypeDef result;
// Проверка на корректность входных данных
if ((startAddr == START_ADR_SHOT && number > MAX_SHOT_COUNT)
|| (startAddr == START_ADR_PROGRAM && number > MAX_PROGRAM_COUNT)
|| (startAddr == START_ADR_MACRO && number > MAX_MACRO_COUNT)) {
// print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11");
return EEPROM_OUT_OF_RANGE;
}
// memset(readData, 0x00, !!!!dataSize!!!!);
uint16_t blockAddr16 = (uint16_t) (startAddr
+ (uint16_t) (number * dataSize));
uint8_t blockAddr[2] = { HIBYTE(blockAddr16), LOBYTE(blockAddr16) };
result = HAL_I2C_Master_Transmit(&hi2c1, (AT24C_ADRESS << 1), blockAddr, 2,
10);
HAL_Delay(1);
result = HAL_I2C_Master_Receive(&hi2c1, (AT24C_ADRESS << 1) | 1, readData,
dataSize, 10);
// print("FLASH_ReadBlock: ");
// printNumber(blockAddr16);
// print("\n");
HAL_Delay(1);
if (result != HAL_OK) {
// print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11");
EEPROM_FAIL_HANDLER(); if (--attempts > 0) goto retry;
return EEPROM_FAIL;
}
return EEPROM_OK;
}
extern I2C_HandleTypeDef hi2c1;
extern void Error_Handler(void);
void EEPROM_FAIL_HANDLER(){
// NVIC_SystemReset();
// return;
__HAL_RCC_I2C1_FORCE_RESET();
HAL_Delay(1);
__HAL_RCC_I2C1_RELEASE_RESET();
HAL_Delay(1);
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
HAL_Delay(1);
}