wip
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* debug.c
|
||||
*
|
||||
* Created on: Apr 20, 2026
|
||||
* Author: user
|
||||
*/
|
||||
#include "main.h"
|
||||
|
||||
extern UART_HandleTypeDef huart1;
|
||||
|
||||
void debug(void){
|
||||
char s [100];
|
||||
HAL_UART_Transmit(&huart1, s, 1, HAL_MAX_DELAY);
|
||||
}
|
||||
@@ -0,0 +1,390 @@
|
||||
#include "eeprom.h"
|
||||
|
||||
/*
|
||||
* Record format (4 bytes):
|
||||
* [0] VirtAddress (uint16_t)
|
||||
* [2] Data (uint16_t)
|
||||
*
|
||||
* Page layout:
|
||||
* [0] PageStatus (uint16_t)
|
||||
* [2..] Records...
|
||||
*/
|
||||
|
||||
extern uint16_t m1pwmap;
|
||||
extern uint16_t m1pwmch;
|
||||
extern uint16_t m2pwmap;
|
||||
extern uint16_t m2pwmch;
|
||||
extern uint16_t m3pwmap;
|
||||
extern uint16_t m3pwmch;
|
||||
extern uint16_t m4pwmap;
|
||||
extern uint16_t m4pwmch;
|
||||
extern uint16_t t1ap;
|
||||
extern uint16_t t2ap;
|
||||
extern uint16_t t3ap;
|
||||
extern uint16_t t4ap;
|
||||
extern uint16_t twap;
|
||||
extern uint16_t tramp;
|
||||
extern uint16_t t1ch;
|
||||
extern uint16_t t2ch;
|
||||
extern uint16_t t3ch;
|
||||
extern uint16_t t4ch;
|
||||
extern uint16_t twch;
|
||||
extern uint16_t tramp1;
|
||||
extern uint16_t trampman;
|
||||
extern uint16_t m1pwmMan;
|
||||
extern uint16_t m2pwmMan;
|
||||
extern uint16_t m3pwmMan;
|
||||
extern uint16_t m4pwmMan;
|
||||
|
||||
const uint8_t deftab[32]={
|
||||
40, //m1pwmap
|
||||
60, //m1pwmch
|
||||
70, //m2pwmap
|
||||
70, //m2pwmch
|
||||
35, //m3pwmap
|
||||
40, //m3pwmch
|
||||
40, //m4pwmap
|
||||
40, //m4pwmch
|
||||
20, //m1rampstart
|
||||
20, //m2rampstart
|
||||
20, //m3rampstart
|
||||
20, //m4rampstart
|
||||
26, //t1ap
|
||||
4, //t2ap
|
||||
10, //t3ap
|
||||
40, //t4ap
|
||||
1, //twap
|
||||
26, //t1ch
|
||||
10, //t2ch
|
||||
30, //t3ch
|
||||
1, //t4ch
|
||||
1, //twch
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
100, //tramp1
|
||||
60, //m1pwmMan
|
||||
70, //m2pwmMan
|
||||
40, //m3pwmMan
|
||||
40, //m4pwmMan
|
||||
50, //trampman
|
||||
10, //tramp
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t VirtAddress;
|
||||
uint16_t Data;
|
||||
} EE_Record_t;
|
||||
|
||||
/* Active page base address (runtime selected in EE_Init) */
|
||||
static uint32_t EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
|
||||
/* 32 sequential virtual addresses */
|
||||
const uint16_t EE_VirtAddrs[EE_NUM_VIRTUAL_ADDR] =
|
||||
{
|
||||
0x0001, 0x0002, 0x0003, 0x0004,
|
||||
0x0005, 0x0006, 0x0007, 0x0008,
|
||||
0x0009, 0x000A, 0x000B, 0x000C,
|
||||
0x000D, 0x000E, 0x000F, 0x0010,
|
||||
0x0011, 0x0012, 0x0013, 0x0014,
|
||||
0x0015, 0x0016, 0x0017, 0x0018,
|
||||
0x0019, 0x001A, 0x001B, 0x001C,
|
||||
0x001D, 0x001E, 0x001F, 0x0020
|
||||
};
|
||||
/* ========================================================================= */
|
||||
|
||||
/* --- Internal helpers ---------------------------------------------------- */
|
||||
|
||||
static uint16_t EE_GetPageStatus(uint32_t pageBase)
|
||||
{
|
||||
return *(__IO uint16_t *)pageBase;
|
||||
}
|
||||
|
||||
static HAL_StatusTypeDef EE_FlashProgramHalfWord(uint32_t Address, uint16_t Data)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, Data);
|
||||
HAL_FLASH_Lock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static HAL_StatusTypeDef EE_FlashErasePage(uint32_t PageAddress)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
FLASH_EraseInitTypeDef EraseInit;
|
||||
uint32_t PageError = 0;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
|
||||
EraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
EraseInit.PageAddress = PageAddress;
|
||||
EraseInit.NbPages = 1;
|
||||
|
||||
status = HAL_FLASHEx_Erase(&EraseInit, &PageError);
|
||||
|
||||
HAL_FLASH_Lock();
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Find first free record address in given page (returns 0 if full) */
|
||||
static uint32_t EE_FindFreeAddress(uint32_t pageBase)
|
||||
{
|
||||
uint32_t addr = pageBase + 2U; /* Skip status word */
|
||||
uint32_t pageEnd = pageBase + EE_PAGE_SIZE;
|
||||
|
||||
while (addr < (pageEnd - sizeof(EE_Record_t) + 1U))
|
||||
{
|
||||
uint16_t vaddr = *(__IO uint16_t *)addr;
|
||||
|
||||
if (vaddr == 0xFFFFU)
|
||||
{
|
||||
/* Empty slot */
|
||||
return addr;
|
||||
}
|
||||
addr += sizeof(EE_Record_t);
|
||||
}
|
||||
|
||||
return 0U; /* No space */
|
||||
}
|
||||
|
||||
/* Find latest value of VirtAddress in a specific page (internal, uses EE_Status) */
|
||||
/* Find latest value of VirtAddress in a specific page (scan forward) */
|
||||
static EE_Status EE_FindInPage(uint32_t pageBase, uint16_t VirtAddress, uint16_t *Data)
|
||||
{
|
||||
uint32_t addr = pageBase + 2U; // skip status halfword
|
||||
uint32_t pageEnd = pageBase + EE_PAGE_SIZE;
|
||||
EE_Status result = EE_NOT_FOUND;
|
||||
uint16_t lastVal = 0;
|
||||
|
||||
if (Data == NULL)
|
||||
return EE_ERROR;
|
||||
|
||||
while (addr <= (pageEnd - sizeof(EE_Record_t)))
|
||||
{
|
||||
uint16_t vaddr = *(__IO uint16_t *)addr;
|
||||
|
||||
if (vaddr == 0xFFFFU)
|
||||
{
|
||||
// First empty slot => no more records in this page
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t value = *(__IO uint16_t *)(addr + 2U);
|
||||
|
||||
if (vaddr == VirtAddress)
|
||||
{
|
||||
lastVal = value; // keep most recent
|
||||
result = EE_OK;
|
||||
}
|
||||
|
||||
addr += sizeof(EE_Record_t); // move 4 bytes forward
|
||||
}
|
||||
|
||||
if (result == EE_OK)
|
||||
*Data = lastVal;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Format both pages: erase and set PAGE0 as VALID */
|
||||
static EE_Status EE_Format(void)
|
||||
{
|
||||
if (EE_FlashErasePage(EE_PAGE0_BASE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
if (EE_FlashErasePage(EE_PAGE1_BASE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
if (EE_FlashProgramHalfWord(EE_PAGE0_BASE, EE_PAGE_STATUS_VALID) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* PAGE1 will remain erased (status = 0xFFFF) */
|
||||
EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
|
||||
return EE_STATUS_OK;
|
||||
}
|
||||
|
||||
/* Get the base of the other page */
|
||||
static uint32_t EE_GetOtherPageBase(uint32_t pageBase)
|
||||
{
|
||||
return (pageBase == EE_PAGE0_BASE) ? EE_PAGE1_BASE : EE_PAGE0_BASE;
|
||||
}
|
||||
|
||||
/* Page transfer (garbage collection + new write) */
|
||||
static EE_Status EE_PageTransfer(uint16_t VirtAddress, uint16_t Data)
|
||||
{
|
||||
uint32_t oldBase = EE_ActivePageBase;
|
||||
uint32_t newBase = EE_GetOtherPageBase(oldBase);
|
||||
uint32_t addr;
|
||||
uint16_t value;
|
||||
EE_Status st;
|
||||
|
||||
/* Erase new page */
|
||||
if (EE_FlashErasePage(newBase) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Mark new page as RECEIVE */
|
||||
if (EE_FlashProgramHalfWord(newBase, EE_PAGE_STATUS_RECEIVE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Start writing records just after status */
|
||||
addr = newBase + 2U;
|
||||
|
||||
/* For each known virtual variable */
|
||||
for (uint16_t i = 0; i < EE_NUM_VIRTUAL_ADDR; i++)
|
||||
{
|
||||
uint16_t vaddr = EE_VirtAddrs[i];
|
||||
|
||||
if (vaddr == VirtAddress)
|
||||
{
|
||||
/* Use the new data passed into PageTransfer */
|
||||
value = Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read latest value from old active page */
|
||||
st = EE_FindInPage(oldBase, vaddr, &value);
|
||||
if (st != EE_STATUS_OK)
|
||||
{
|
||||
/* Variable never written -> skip */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write record to new page */
|
||||
if (EE_FlashProgramHalfWord(addr, vaddr) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
if (EE_FlashProgramHalfWord(addr + 2U, value) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
addr += sizeof(EE_Record_t);
|
||||
if (addr >= (newBase + EE_PAGE_SIZE))
|
||||
return EE_STATUS_NO_SPACE;
|
||||
}
|
||||
|
||||
/* Erase old page */
|
||||
if (EE_FlashErasePage(oldBase) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Mark new page as VALID */
|
||||
if (EE_FlashProgramHalfWord(newBase, EE_PAGE_STATUS_VALID) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Update active page */
|
||||
EE_ActivePageBase = newBase;
|
||||
|
||||
return EE_STATUS_OK;
|
||||
}
|
||||
|
||||
/* --- Public API ----------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Initialize the EEPROM emulation.
|
||||
* - Checks page statuses and chooses the active page.
|
||||
* - If inconsistent or blank, formats pages.
|
||||
* PUBLIC RETURN TYPE: uint16_t (EE_OK / EE_ERROR / ...)
|
||||
*/
|
||||
uint16_t EE_Init(void)
|
||||
{
|
||||
uint16_t status0 = EE_GetPageStatus(EE_PAGE0_BASE);
|
||||
uint16_t status1 = EE_GetPageStatus(EE_PAGE1_BASE);
|
||||
|
||||
if ((status0 == EE_PAGE_STATUS_ERASED) && (status1 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
/* Fresh device -> format */
|
||||
return (uint16_t)EE_Format();
|
||||
}
|
||||
else if ((status0 == EE_PAGE_STATUS_VALID) && (status1 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
return EE_OK;
|
||||
}
|
||||
else if ((status1 == EE_PAGE_STATUS_VALID) && (status0 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
EE_ActivePageBase = EE_PAGE1_BASE;
|
||||
return EE_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Any weird or inconsistent state -> reformat */
|
||||
return (uint16_t)EE_Format();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a 16-bit variable by its virtual address.
|
||||
* PUBLIC RETURN: EE_OK / EE_NOT_FOUND / EE_ERROR (as uint16_t)
|
||||
*/
|
||||
uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t *Data)
|
||||
{
|
||||
EE_Status st;
|
||||
|
||||
if (Data == NULL)
|
||||
return EE_ERROR;
|
||||
|
||||
st = EE_FindInPage(EE_ActivePageBase, VirtAddress, Data);
|
||||
return (uint16_t)st;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write (append) a 16-bit variable.
|
||||
* - Writes a new record in the active page.
|
||||
* - If the page is full, triggers a page transfer (GC).
|
||||
* PUBLIC RETURN: EE_OK / EE_ERROR / EE_NO_SPACE (as uint16_t)
|
||||
*/
|
||||
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
|
||||
{
|
||||
uint32_t freeAddr;
|
||||
EE_Status st;
|
||||
|
||||
/* Find free space in active page */
|
||||
freeAddr = EE_FindFreeAddress(EE_ActivePageBase);
|
||||
if (freeAddr != 0U)
|
||||
{
|
||||
/* Write new record */
|
||||
if (EE_FlashProgramHalfWord(freeAddr, VirtAddress) != HAL_OK)
|
||||
return EE_ERROR;
|
||||
if (EE_FlashProgramHalfWord(freeAddr + 2U, Data) != HAL_OK)
|
||||
return EE_ERROR;
|
||||
|
||||
return EE_OK;
|
||||
}
|
||||
|
||||
/* No space -> page transfer */
|
||||
st = EE_PageTransfer(VirtAddress, Data);
|
||||
return (uint16_t)st;
|
||||
}
|
||||
|
||||
void loadEE(void){
|
||||
EEW_Read(M1PWMAP, &m1pwmap);
|
||||
EEW_Read(M1PWMCH, &m1pwmch);
|
||||
EEW_Read(M2PWMAP, &m2pwmap);
|
||||
EEW_Read(M2PWMCH, &m2pwmch);
|
||||
EEW_Read(M3PWMAP, &m3pwmap);
|
||||
EEW_Read(M3PWMCH, &m3pwmch);
|
||||
EEW_Read(M4PWMAP, &m4pwmap);
|
||||
EEW_Read(M4PWMCH, &m4pwmch);
|
||||
EEW_Read(T1AP, &t1ap);
|
||||
EEW_Read(T2AP, &t2ap);
|
||||
EEW_Read(T3AP, &t3ap);
|
||||
EEW_Read(T4AP, &t4ap);
|
||||
EEW_Read(TWAP, &twap);
|
||||
EEW_Read(T1CH, &t1ch);
|
||||
EEW_Read(T2CH, &t2ch);
|
||||
EEW_Read(T3CH, &t3ch);
|
||||
EEW_Read(T4CH, &t4ch);
|
||||
EEW_Read(TWCH, &twch);
|
||||
EEW_Read(TRAMP1, &tramp1);
|
||||
EEW_Read(M1PWMMAN, &m1pwmMan);
|
||||
EEW_Read(M2PWMMAN, &m2pwmMan);
|
||||
EEW_Read(M3PWMMAN, &m3pwmMan);
|
||||
EEW_Read(M4PWMMAN, &m4pwmMan);
|
||||
EEW_Read(TRAMPMAN, &trampman);
|
||||
EEW_Read(TRAMP, &tramp);
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
/*
|
||||
* debug.c
|
||||
*
|
||||
* Created on: Apr 20, 2026
|
||||
* Author: user
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,390 @@
|
||||
#include "eeprom.h"
|
||||
|
||||
/*
|
||||
* Record format (4 bytes):
|
||||
* [0] VirtAddress (uint16_t)
|
||||
* [2] Data (uint16_t)
|
||||
*
|
||||
* Page layout:
|
||||
* [0] PageStatus (uint16_t)
|
||||
* [2..] Records...
|
||||
*/
|
||||
|
||||
extern uint16_t m1pwmap;
|
||||
extern uint16_t m1pwmch;
|
||||
extern uint16_t m2pwmap;
|
||||
extern uint16_t m2pwmch;
|
||||
extern uint16_t m3pwmap;
|
||||
extern uint16_t m3pwmch;
|
||||
extern uint16_t m4pwmap;
|
||||
extern uint16_t m4pwmch;
|
||||
extern uint16_t t1ap;
|
||||
extern uint16_t t2ap;
|
||||
extern uint16_t t3ap;
|
||||
extern uint16_t t4ap;
|
||||
extern uint16_t twap;
|
||||
extern uint16_t tramp;
|
||||
extern uint16_t t1ch;
|
||||
extern uint16_t t2ch;
|
||||
extern uint16_t t3ch;
|
||||
extern uint16_t t4ch;
|
||||
extern uint16_t twch;
|
||||
extern uint16_t tramp1;
|
||||
extern uint16_t trampman;
|
||||
extern uint16_t m1pwmMan;
|
||||
extern uint16_t m2pwmMan;
|
||||
extern uint16_t m3pwmMan;
|
||||
extern uint16_t m4pwmMan;
|
||||
|
||||
const uint8_t deftab[32]={
|
||||
40, //m1pwmap
|
||||
60, //m1pwmch
|
||||
70, //m2pwmap
|
||||
70, //m2pwmch
|
||||
35, //m3pwmap
|
||||
40, //m3pwmch
|
||||
40, //m4pwmap
|
||||
40, //m4pwmch
|
||||
20, //m1rampstart
|
||||
20, //m2rampstart
|
||||
20, //m3rampstart
|
||||
20, //m4rampstart
|
||||
28, //t1ap
|
||||
4, //t2ap
|
||||
10, //t3ap
|
||||
40, //t4ap
|
||||
1, //twap
|
||||
26, //t1ch
|
||||
10, //t2ch
|
||||
30, //t3ch
|
||||
1, //t4ch
|
||||
1, //twch
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
100, //tramp1
|
||||
60, //m1pwmMan
|
||||
70, //m2pwmMan
|
||||
40, //m3pwmMan
|
||||
40, //m4pwmMan
|
||||
50, //trampman
|
||||
10, //tramp
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t VirtAddress;
|
||||
uint16_t Data;
|
||||
} EE_Record_t;
|
||||
|
||||
/* Active page base address (runtime selected in EE_Init) */
|
||||
static uint32_t EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
|
||||
/* 32 sequential virtual addresses */
|
||||
const uint16_t EE_VirtAddrs[EE_NUM_VIRTUAL_ADDR] =
|
||||
{
|
||||
0x0001, 0x0002, 0x0003, 0x0004,
|
||||
0x0005, 0x0006, 0x0007, 0x0008,
|
||||
0x0009, 0x000A, 0x000B, 0x000C,
|
||||
0x000D, 0x000E, 0x000F, 0x0010,
|
||||
0x0011, 0x0012, 0x0013, 0x0014,
|
||||
0x0015, 0x0016, 0x0017, 0x0018,
|
||||
0x0019, 0x001A, 0x001B, 0x001C,
|
||||
0x001D, 0x001E, 0x001F, 0x0020
|
||||
};
|
||||
/* ========================================================================= */
|
||||
|
||||
/* --- Internal helpers ---------------------------------------------------- */
|
||||
|
||||
static uint16_t EE_GetPageStatus(uint32_t pageBase)
|
||||
{
|
||||
return *(__IO uint16_t *)pageBase;
|
||||
}
|
||||
|
||||
static HAL_StatusTypeDef EE_FlashProgramHalfWord(uint32_t Address, uint16_t Data)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, Data);
|
||||
HAL_FLASH_Lock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static HAL_StatusTypeDef EE_FlashErasePage(uint32_t PageAddress)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
FLASH_EraseInitTypeDef EraseInit;
|
||||
uint32_t PageError = 0;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
|
||||
EraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
EraseInit.PageAddress = PageAddress;
|
||||
EraseInit.NbPages = 1;
|
||||
|
||||
status = HAL_FLASHEx_Erase(&EraseInit, &PageError);
|
||||
|
||||
HAL_FLASH_Lock();
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Find first free record address in given page (returns 0 if full) */
|
||||
static uint32_t EE_FindFreeAddress(uint32_t pageBase)
|
||||
{
|
||||
uint32_t addr = pageBase + 2U; /* Skip status word */
|
||||
uint32_t pageEnd = pageBase + EE_PAGE_SIZE;
|
||||
|
||||
while (addr < (pageEnd - sizeof(EE_Record_t) + 1U))
|
||||
{
|
||||
uint16_t vaddr = *(__IO uint16_t *)addr;
|
||||
|
||||
if (vaddr == 0xFFFFU)
|
||||
{
|
||||
/* Empty slot */
|
||||
return addr;
|
||||
}
|
||||
addr += sizeof(EE_Record_t);
|
||||
}
|
||||
|
||||
return 0U; /* No space */
|
||||
}
|
||||
|
||||
/* Find latest value of VirtAddress in a specific page (internal, uses EE_Status) */
|
||||
/* Find latest value of VirtAddress in a specific page (scan forward) */
|
||||
static EE_Status EE_FindInPage(uint32_t pageBase, uint16_t VirtAddress, uint16_t *Data)
|
||||
{
|
||||
uint32_t addr = pageBase + 2U; // skip status halfword
|
||||
uint32_t pageEnd = pageBase + EE_PAGE_SIZE;
|
||||
EE_Status result = EE_NOT_FOUND;
|
||||
uint16_t lastVal = 0;
|
||||
|
||||
if (Data == NULL)
|
||||
return EE_ERROR;
|
||||
|
||||
while (addr <= (pageEnd - sizeof(EE_Record_t)))
|
||||
{
|
||||
uint16_t vaddr = *(__IO uint16_t *)addr;
|
||||
|
||||
if (vaddr == 0xFFFFU)
|
||||
{
|
||||
// First empty slot => no more records in this page
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t value = *(__IO uint16_t *)(addr + 2U);
|
||||
|
||||
if (vaddr == VirtAddress)
|
||||
{
|
||||
lastVal = value; // keep most recent
|
||||
result = EE_OK;
|
||||
}
|
||||
|
||||
addr += sizeof(EE_Record_t); // move 4 bytes forward
|
||||
}
|
||||
|
||||
if (result == EE_OK)
|
||||
*Data = lastVal;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Format both pages: erase and set PAGE0 as VALID */
|
||||
static EE_Status EE_Format(void)
|
||||
{
|
||||
if (EE_FlashErasePage(EE_PAGE0_BASE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
if (EE_FlashErasePage(EE_PAGE1_BASE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
if (EE_FlashProgramHalfWord(EE_PAGE0_BASE, EE_PAGE_STATUS_VALID) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* PAGE1 will remain erased (status = 0xFFFF) */
|
||||
EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
|
||||
return EE_STATUS_OK;
|
||||
}
|
||||
|
||||
/* Get the base of the other page */
|
||||
static uint32_t EE_GetOtherPageBase(uint32_t pageBase)
|
||||
{
|
||||
return (pageBase == EE_PAGE0_BASE) ? EE_PAGE1_BASE : EE_PAGE0_BASE;
|
||||
}
|
||||
|
||||
/* Page transfer (garbage collection + new write) */
|
||||
static EE_Status EE_PageTransfer(uint16_t VirtAddress, uint16_t Data)
|
||||
{
|
||||
uint32_t oldBase = EE_ActivePageBase;
|
||||
uint32_t newBase = EE_GetOtherPageBase(oldBase);
|
||||
uint32_t addr;
|
||||
uint16_t value;
|
||||
EE_Status st;
|
||||
|
||||
/* Erase new page */
|
||||
if (EE_FlashErasePage(newBase) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Mark new page as RECEIVE */
|
||||
if (EE_FlashProgramHalfWord(newBase, EE_PAGE_STATUS_RECEIVE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Start writing records just after status */
|
||||
addr = newBase + 2U;
|
||||
|
||||
/* For each known virtual variable */
|
||||
for (uint16_t i = 0; i < EE_NUM_VIRTUAL_ADDR; i++)
|
||||
{
|
||||
uint16_t vaddr = EE_VirtAddrs[i];
|
||||
|
||||
if (vaddr == VirtAddress)
|
||||
{
|
||||
/* Use the new data passed into PageTransfer */
|
||||
value = Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read latest value from old active page */
|
||||
st = EE_FindInPage(oldBase, vaddr, &value);
|
||||
if (st != EE_STATUS_OK)
|
||||
{
|
||||
/* Variable never written -> skip */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write record to new page */
|
||||
if (EE_FlashProgramHalfWord(addr, vaddr) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
if (EE_FlashProgramHalfWord(addr + 2U, value) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
addr += sizeof(EE_Record_t);
|
||||
if (addr >= (newBase + EE_PAGE_SIZE))
|
||||
return EE_STATUS_NO_SPACE;
|
||||
}
|
||||
|
||||
/* Erase old page */
|
||||
if (EE_FlashErasePage(oldBase) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Mark new page as VALID */
|
||||
if (EE_FlashProgramHalfWord(newBase, EE_PAGE_STATUS_VALID) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Update active page */
|
||||
EE_ActivePageBase = newBase;
|
||||
|
||||
return EE_STATUS_OK;
|
||||
}
|
||||
|
||||
/* --- Public API ----------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Initialize the EEPROM emulation.
|
||||
* - Checks page statuses and chooses the active page.
|
||||
* - If inconsistent or blank, formats pages.
|
||||
* PUBLIC RETURN TYPE: uint16_t (EE_OK / EE_ERROR / ...)
|
||||
*/
|
||||
uint16_t EE_Init(void)
|
||||
{
|
||||
uint16_t status0 = EE_GetPageStatus(EE_PAGE0_BASE);
|
||||
uint16_t status1 = EE_GetPageStatus(EE_PAGE1_BASE);
|
||||
|
||||
if ((status0 == EE_PAGE_STATUS_ERASED) && (status1 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
/* Fresh device -> format */
|
||||
return (uint16_t)EE_Format();
|
||||
}
|
||||
else if ((status0 == EE_PAGE_STATUS_VALID) && (status1 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
return EE_OK;
|
||||
}
|
||||
else if ((status1 == EE_PAGE_STATUS_VALID) && (status0 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
EE_ActivePageBase = EE_PAGE1_BASE;
|
||||
return EE_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Any weird or inconsistent state -> reformat */
|
||||
return (uint16_t)EE_Format();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a 16-bit variable by its virtual address.
|
||||
* PUBLIC RETURN: EE_OK / EE_NOT_FOUND / EE_ERROR (as uint16_t)
|
||||
*/
|
||||
uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t *Data)
|
||||
{
|
||||
EE_Status st;
|
||||
|
||||
if (Data == NULL)
|
||||
return EE_ERROR;
|
||||
|
||||
st = EE_FindInPage(EE_ActivePageBase, VirtAddress, Data);
|
||||
return (uint16_t)st;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write (append) a 16-bit variable.
|
||||
* - Writes a new record in the active page.
|
||||
* - If the page is full, triggers a page transfer (GC).
|
||||
* PUBLIC RETURN: EE_OK / EE_ERROR / EE_NO_SPACE (as uint16_t)
|
||||
*/
|
||||
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
|
||||
{
|
||||
uint32_t freeAddr;
|
||||
EE_Status st;
|
||||
|
||||
/* Find free space in active page */
|
||||
freeAddr = EE_FindFreeAddress(EE_ActivePageBase);
|
||||
if (freeAddr != 0U)
|
||||
{
|
||||
/* Write new record */
|
||||
if (EE_FlashProgramHalfWord(freeAddr, VirtAddress) != HAL_OK)
|
||||
return EE_ERROR;
|
||||
if (EE_FlashProgramHalfWord(freeAddr + 2U, Data) != HAL_OK)
|
||||
return EE_ERROR;
|
||||
|
||||
return EE_OK;
|
||||
}
|
||||
|
||||
/* No space -> page transfer */
|
||||
st = EE_PageTransfer(VirtAddress, Data);
|
||||
return (uint16_t)st;
|
||||
}
|
||||
|
||||
void loadEE(void){
|
||||
EEW_Read(M1PWMAP, &m1pwmap);
|
||||
EEW_Read(M1PWMCH, &m1pwmch);
|
||||
EEW_Read(M2PWMAP, &m2pwmap);
|
||||
EEW_Read(M2PWMCH, &m2pwmch);
|
||||
EEW_Read(M3PWMAP, &m3pwmap);
|
||||
EEW_Read(M3PWMCH, &m3pwmch);
|
||||
EEW_Read(M4PWMAP, &m4pwmap);
|
||||
EEW_Read(M4PWMCH, &m4pwmch);
|
||||
EEW_Read(T1AP, &t1ap);
|
||||
EEW_Read(T2AP, &t2ap);
|
||||
EEW_Read(T3AP, &t3ap);
|
||||
EEW_Read(T4AP, &t4ap);
|
||||
EEW_Read(TWAP, &twap);
|
||||
EEW_Read(T1CH, &t1ch);
|
||||
EEW_Read(T2CH, &t2ch);
|
||||
EEW_Read(T3CH, &t3ch);
|
||||
EEW_Read(T4CH, &t4ch);
|
||||
EEW_Read(TWCH, &twch);
|
||||
EEW_Read(TRAMP1, &tramp1);
|
||||
EEW_Read(M1PWMMAN, &m1pwmMan);
|
||||
EEW_Read(M2PWMMAN, &m2pwmMan);
|
||||
EEW_Read(M3PWMMAN, &m3pwmMan);
|
||||
EEW_Read(M4PWMMAN, &m4pwmMan);
|
||||
EEW_Read(TRAMPMAN, &trampman);
|
||||
EEW_Read(TRAMP, &tramp);
|
||||
}
|
||||
@@ -0,0 +1,390 @@
|
||||
#include "eeprom.h"
|
||||
|
||||
/*
|
||||
* Record format (4 bytes):
|
||||
* [0] VirtAddress (uint16_t)
|
||||
* [2] Data (uint16_t)
|
||||
*
|
||||
* Page layout:
|
||||
* [0] PageStatus (uint16_t)
|
||||
* [2..] Records...
|
||||
*/
|
||||
|
||||
extern uint16_t m1pwmap;
|
||||
extern uint16_t m1pwmch;
|
||||
extern uint16_t m2pwmap;
|
||||
extern uint16_t m2pwmch;
|
||||
extern uint16_t m3pwmap;
|
||||
extern uint16_t m3pwmch;
|
||||
extern uint16_t m4pwmap;
|
||||
extern uint16_t m4pwmch;
|
||||
extern uint16_t t1ap;
|
||||
extern uint16_t t2ap;
|
||||
extern uint16_t t3ap;
|
||||
extern uint16_t t4ap;
|
||||
extern uint16_t twap;
|
||||
extern uint16_t tramp;
|
||||
extern uint16_t t1ch;
|
||||
extern uint16_t t2ch;
|
||||
extern uint16_t t3ch;
|
||||
extern uint16_t t4ch;
|
||||
extern uint16_t twch;
|
||||
extern uint16_t tramp1;
|
||||
extern uint16_t trampman;
|
||||
extern uint16_t m1pwmMan;
|
||||
extern uint16_t m2pwmMan;
|
||||
extern uint16_t m3pwmMan;
|
||||
extern uint16_t m4pwmMan;
|
||||
|
||||
const uint8_t deftab[32]={
|
||||
40, //m1pwmap
|
||||
60, //m1pwmch
|
||||
70, //m2pwmap
|
||||
70, //m2pwmch
|
||||
35, //m3pwmap
|
||||
40, //m3pwmch
|
||||
40, //m4pwmap
|
||||
40, //m4pwmch
|
||||
20, //m1rampstart
|
||||
20, //m2rampstart
|
||||
20, //m3rampstart
|
||||
20, //m4rampstart
|
||||
28, //t1ap
|
||||
4, //t2ap
|
||||
10, //t3ap
|
||||
40, //t4ap
|
||||
1, //twap
|
||||
20, //t1ch
|
||||
10, //t2ch
|
||||
30, //t3ch
|
||||
1, //t4ch
|
||||
1, //twch
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
100, //tramp1
|
||||
60, //m1pwmMan
|
||||
70, //m2pwmMan
|
||||
40, //m3pwmMan
|
||||
40, //m4pwmMan
|
||||
50, //trampman
|
||||
10, //tramp
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t VirtAddress;
|
||||
uint16_t Data;
|
||||
} EE_Record_t;
|
||||
|
||||
/* Active page base address (runtime selected in EE_Init) */
|
||||
static uint32_t EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
|
||||
/* 32 sequential virtual addresses */
|
||||
const uint16_t EE_VirtAddrs[EE_NUM_VIRTUAL_ADDR] =
|
||||
{
|
||||
0x0001, 0x0002, 0x0003, 0x0004,
|
||||
0x0005, 0x0006, 0x0007, 0x0008,
|
||||
0x0009, 0x000A, 0x000B, 0x000C,
|
||||
0x000D, 0x000E, 0x000F, 0x0010,
|
||||
0x0011, 0x0012, 0x0013, 0x0014,
|
||||
0x0015, 0x0016, 0x0017, 0x0018,
|
||||
0x0019, 0x001A, 0x001B, 0x001C,
|
||||
0x001D, 0x001E, 0x001F, 0x0020
|
||||
};
|
||||
/* ========================================================================= */
|
||||
|
||||
/* --- Internal helpers ---------------------------------------------------- */
|
||||
|
||||
static uint16_t EE_GetPageStatus(uint32_t pageBase)
|
||||
{
|
||||
return *(__IO uint16_t *)pageBase;
|
||||
}
|
||||
|
||||
static HAL_StatusTypeDef EE_FlashProgramHalfWord(uint32_t Address, uint16_t Data)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, Data);
|
||||
HAL_FLASH_Lock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static HAL_StatusTypeDef EE_FlashErasePage(uint32_t PageAddress)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
FLASH_EraseInitTypeDef EraseInit;
|
||||
uint32_t PageError = 0;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
|
||||
EraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
EraseInit.PageAddress = PageAddress;
|
||||
EraseInit.NbPages = 1;
|
||||
|
||||
status = HAL_FLASHEx_Erase(&EraseInit, &PageError);
|
||||
|
||||
HAL_FLASH_Lock();
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Find first free record address in given page (returns 0 if full) */
|
||||
static uint32_t EE_FindFreeAddress(uint32_t pageBase)
|
||||
{
|
||||
uint32_t addr = pageBase + 2U; /* Skip status word */
|
||||
uint32_t pageEnd = pageBase + EE_PAGE_SIZE;
|
||||
|
||||
while (addr < (pageEnd - sizeof(EE_Record_t) + 1U))
|
||||
{
|
||||
uint16_t vaddr = *(__IO uint16_t *)addr;
|
||||
|
||||
if (vaddr == 0xFFFFU)
|
||||
{
|
||||
/* Empty slot */
|
||||
return addr;
|
||||
}
|
||||
addr += sizeof(EE_Record_t);
|
||||
}
|
||||
|
||||
return 0U; /* No space */
|
||||
}
|
||||
|
||||
/* Find latest value of VirtAddress in a specific page (internal, uses EE_Status) */
|
||||
/* Find latest value of VirtAddress in a specific page (scan forward) */
|
||||
static EE_Status EE_FindInPage(uint32_t pageBase, uint16_t VirtAddress, uint16_t *Data)
|
||||
{
|
||||
uint32_t addr = pageBase + 2U; // skip status halfword
|
||||
uint32_t pageEnd = pageBase + EE_PAGE_SIZE;
|
||||
EE_Status result = EE_NOT_FOUND;
|
||||
uint16_t lastVal = 0;
|
||||
|
||||
if (Data == NULL)
|
||||
return EE_ERROR;
|
||||
|
||||
while (addr <= (pageEnd - sizeof(EE_Record_t)))
|
||||
{
|
||||
uint16_t vaddr = *(__IO uint16_t *)addr;
|
||||
|
||||
if (vaddr == 0xFFFFU)
|
||||
{
|
||||
// First empty slot => no more records in this page
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t value = *(__IO uint16_t *)(addr + 2U);
|
||||
|
||||
if (vaddr == VirtAddress)
|
||||
{
|
||||
lastVal = value; // keep most recent
|
||||
result = EE_OK;
|
||||
}
|
||||
|
||||
addr += sizeof(EE_Record_t); // move 4 bytes forward
|
||||
}
|
||||
|
||||
if (result == EE_OK)
|
||||
*Data = lastVal;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Format both pages: erase and set PAGE0 as VALID */
|
||||
static EE_Status EE_Format(void)
|
||||
{
|
||||
if (EE_FlashErasePage(EE_PAGE0_BASE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
if (EE_FlashErasePage(EE_PAGE1_BASE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
if (EE_FlashProgramHalfWord(EE_PAGE0_BASE, EE_PAGE_STATUS_VALID) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* PAGE1 will remain erased (status = 0xFFFF) */
|
||||
EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
|
||||
return EE_STATUS_OK;
|
||||
}
|
||||
|
||||
/* Get the base of the other page */
|
||||
static uint32_t EE_GetOtherPageBase(uint32_t pageBase)
|
||||
{
|
||||
return (pageBase == EE_PAGE0_BASE) ? EE_PAGE1_BASE : EE_PAGE0_BASE;
|
||||
}
|
||||
|
||||
/* Page transfer (garbage collection + new write) */
|
||||
static EE_Status EE_PageTransfer(uint16_t VirtAddress, uint16_t Data)
|
||||
{
|
||||
uint32_t oldBase = EE_ActivePageBase;
|
||||
uint32_t newBase = EE_GetOtherPageBase(oldBase);
|
||||
uint32_t addr;
|
||||
uint16_t value;
|
||||
EE_Status st;
|
||||
|
||||
/* Erase new page */
|
||||
if (EE_FlashErasePage(newBase) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Mark new page as RECEIVE */
|
||||
if (EE_FlashProgramHalfWord(newBase, EE_PAGE_STATUS_RECEIVE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Start writing records just after status */
|
||||
addr = newBase + 2U;
|
||||
|
||||
/* For each known virtual variable */
|
||||
for (uint16_t i = 0; i < EE_NUM_VIRTUAL_ADDR; i++)
|
||||
{
|
||||
uint16_t vaddr = EE_VirtAddrs[i];
|
||||
|
||||
if (vaddr == VirtAddress)
|
||||
{
|
||||
/* Use the new data passed into PageTransfer */
|
||||
value = Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read latest value from old active page */
|
||||
st = EE_FindInPage(oldBase, vaddr, &value);
|
||||
if (st != EE_STATUS_OK)
|
||||
{
|
||||
/* Variable never written -> skip */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write record to new page */
|
||||
if (EE_FlashProgramHalfWord(addr, vaddr) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
if (EE_FlashProgramHalfWord(addr + 2U, value) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
addr += sizeof(EE_Record_t);
|
||||
if (addr >= (newBase + EE_PAGE_SIZE))
|
||||
return EE_STATUS_NO_SPACE;
|
||||
}
|
||||
|
||||
/* Erase old page */
|
||||
if (EE_FlashErasePage(oldBase) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Mark new page as VALID */
|
||||
if (EE_FlashProgramHalfWord(newBase, EE_PAGE_STATUS_VALID) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Update active page */
|
||||
EE_ActivePageBase = newBase;
|
||||
|
||||
return EE_STATUS_OK;
|
||||
}
|
||||
|
||||
/* --- Public API ----------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Initialize the EEPROM emulation.
|
||||
* - Checks page statuses and chooses the active page.
|
||||
* - If inconsistent or blank, formats pages.
|
||||
* PUBLIC RETURN TYPE: uint16_t (EE_OK / EE_ERROR / ...)
|
||||
*/
|
||||
uint16_t EE_Init(void)
|
||||
{
|
||||
uint16_t status0 = EE_GetPageStatus(EE_PAGE0_BASE);
|
||||
uint16_t status1 = EE_GetPageStatus(EE_PAGE1_BASE);
|
||||
|
||||
if ((status0 == EE_PAGE_STATUS_ERASED) && (status1 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
/* Fresh device -> format */
|
||||
return (uint16_t)EE_Format();
|
||||
}
|
||||
else if ((status0 == EE_PAGE_STATUS_VALID) && (status1 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
return EE_OK;
|
||||
}
|
||||
else if ((status1 == EE_PAGE_STATUS_VALID) && (status0 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
EE_ActivePageBase = EE_PAGE1_BASE;
|
||||
return EE_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Any weird or inconsistent state -> reformat */
|
||||
return (uint16_t)EE_Format();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a 16-bit variable by its virtual address.
|
||||
* PUBLIC RETURN: EE_OK / EE_NOT_FOUND / EE_ERROR (as uint16_t)
|
||||
*/
|
||||
uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t *Data)
|
||||
{
|
||||
EE_Status st;
|
||||
|
||||
if (Data == NULL)
|
||||
return EE_ERROR;
|
||||
|
||||
st = EE_FindInPage(EE_ActivePageBase, VirtAddress, Data);
|
||||
return (uint16_t)st;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write (append) a 16-bit variable.
|
||||
* - Writes a new record in the active page.
|
||||
* - If the page is full, triggers a page transfer (GC).
|
||||
* PUBLIC RETURN: EE_OK / EE_ERROR / EE_NO_SPACE (as uint16_t)
|
||||
*/
|
||||
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
|
||||
{
|
||||
uint32_t freeAddr;
|
||||
EE_Status st;
|
||||
|
||||
/* Find free space in active page */
|
||||
freeAddr = EE_FindFreeAddress(EE_ActivePageBase);
|
||||
if (freeAddr != 0U)
|
||||
{
|
||||
/* Write new record */
|
||||
if (EE_FlashProgramHalfWord(freeAddr, VirtAddress) != HAL_OK)
|
||||
return EE_ERROR;
|
||||
if (EE_FlashProgramHalfWord(freeAddr + 2U, Data) != HAL_OK)
|
||||
return EE_ERROR;
|
||||
|
||||
return EE_OK;
|
||||
}
|
||||
|
||||
/* No space -> page transfer */
|
||||
st = EE_PageTransfer(VirtAddress, Data);
|
||||
return (uint16_t)st;
|
||||
}
|
||||
|
||||
void loadEE(void){
|
||||
EEW_Read(M1PWMAP, &m1pwmap);
|
||||
EEW_Read(M1PWMCH, &m1pwmch);
|
||||
EEW_Read(M2PWMAP, &m2pwmap);
|
||||
EEW_Read(M2PWMCH, &m2pwmch);
|
||||
EEW_Read(M3PWMAP, &m3pwmap);
|
||||
EEW_Read(M3PWMCH, &m3pwmch);
|
||||
EEW_Read(M4PWMAP, &m4pwmap);
|
||||
EEW_Read(M4PWMCH, &m4pwmch);
|
||||
EEW_Read(T1AP, &t1ap);
|
||||
EEW_Read(T2AP, &t2ap);
|
||||
EEW_Read(T3AP, &t3ap);
|
||||
EEW_Read(T4AP, &t4ap);
|
||||
EEW_Read(TWAP, &twap);
|
||||
EEW_Read(T1CH, &t1ch);
|
||||
EEW_Read(T2CH, &t2ch);
|
||||
EEW_Read(T3CH, &t3ch);
|
||||
EEW_Read(T4CH, &t4ch);
|
||||
EEW_Read(TWCH, &twch);
|
||||
EEW_Read(TRAMP1, &tramp1);
|
||||
EEW_Read(M1PWMMAN, &m1pwmMan);
|
||||
EEW_Read(M2PWMMAN, &m2pwmMan);
|
||||
EEW_Read(M3PWMMAN, &m3pwmMan);
|
||||
EEW_Read(M4PWMMAN, &m4pwmMan);
|
||||
EEW_Read(TRAMPMAN, &trampman);
|
||||
EEW_Read(TRAMP, &tramp);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* debug.c
|
||||
*
|
||||
* Created on: Apr 20, 2026
|
||||
* Author: user
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "main.h"
|
||||
|
||||
extern UART_HandleTypeDef huart1;
|
||||
extern uint8_t pulsanti;
|
||||
void debug(void){
|
||||
static uint8_t mempulsanti;
|
||||
char s [100];
|
||||
if(mempulsanti!=pulsanti){
|
||||
mempulsanti=pulsanti;
|
||||
sprintf(s,"pulsanti=%X",pulsanti);
|
||||
HAL_UART_Transmit(&huart1,(uint8_t*) s, strlen(s), HAL_MAX_DELAY);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* debug.c
|
||||
*
|
||||
* Created on: Apr 20, 2026
|
||||
* Author: user
|
||||
*/
|
||||
#include "main.h"
|
||||
|
||||
extern UART_HandleTypeDef huart1;
|
||||
|
||||
void debug(void){
|
||||
char s [100];
|
||||
HAL_UART_Transmit(&huart1,(uint8_t*) s, 1, HAL_MAX_DELAY);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* debug.c
|
||||
*
|
||||
* Created on: Apr 20, 2026
|
||||
* Author: user
|
||||
*/
|
||||
#include "main.h"
|
||||
|
||||
extern UART_HandleTypeDef huart1;
|
||||
|
||||
void debug(void){
|
||||
char s [100];
|
||||
HAL_UART_Transmit(&huart1,(uint8_t) s, 1, HAL_MAX_DELAY);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* debug.c
|
||||
*
|
||||
* Created on: Apr 20, 2026
|
||||
* Author: user
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "main.h"
|
||||
|
||||
extern UART_HandleTypeDef huart1;
|
||||
extern uint8_t pulsanti;
|
||||
void debug(void){
|
||||
static uint8_t mempulsanti;
|
||||
char s [100];
|
||||
if(mempulsanti!=pulsanti){
|
||||
mempulsanti=pulsanti;
|
||||
sprintf(s,"\npulsanti=%X",pulsanti);
|
||||
HAL_UART_Transmit(&huart1,(uint8_t*) s, strlen(s), HAL_MAX_DELAY);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,6 +45,15 @@ typedef enum{
|
||||
#define P1STOP 0x02
|
||||
#define P2START 0x04
|
||||
#define P2STOP 0x08
|
||||
#define M1FW 0x10
|
||||
#define M1BW 0x20
|
||||
#define M2FW 0x40
|
||||
#define M2BW 0x80
|
||||
#define M3FW 0x100
|
||||
#define M3BW 0x200
|
||||
#define M4FW 0x400
|
||||
#define M4BW 0x800
|
||||
|
||||
#define M1 1
|
||||
#define M2 2
|
||||
#define M3 3
|
||||
@@ -78,6 +87,7 @@ extern uint16_t ch8 ;
|
||||
uint8_t pulsanti=0;
|
||||
volatile uint8_t rtP1=200;
|
||||
volatile uint8_t rtP2=200;
|
||||
volatile uint8_t rtTLC=100;
|
||||
volatile uint16_t rtramp[4];
|
||||
volatile uint16_t rtCiclo;
|
||||
uint16_t m1pwmap;
|
||||
@@ -99,9 +109,14 @@ uint16_t t3ch;
|
||||
uint16_t t4ch;
|
||||
uint16_t twch;
|
||||
uint16_t tramp;
|
||||
uint16_t trampman;
|
||||
uint16_t m1pwmMan;
|
||||
uint16_t m2pwmMan;
|
||||
uint16_t m3pwmMan;
|
||||
uint16_t m4pwmMan;
|
||||
|
||||
uint16_t mrampstart[4];
|
||||
uint8_t stPulsanti=0;
|
||||
uint16_t stPulsanti=0;
|
||||
omCiclo_st stCiclo=omchiuso;
|
||||
omCiclo_st memstCiclo=omchiuso;
|
||||
volatile stBuz_st stBuz=bzoff;
|
||||
@@ -133,7 +148,7 @@ void HAL_SYSTICK_Callback(void){
|
||||
c10ms = 0;
|
||||
if(rtP1)rtP1--;
|
||||
if(rtP2)rtP2--;
|
||||
|
||||
if(rtTLC)rtTLC--;
|
||||
//**** legge i tasti********************************************************************************
|
||||
inidx++;
|
||||
inidx&=0x03;
|
||||
@@ -186,17 +201,159 @@ void managePulsanti(void){
|
||||
else if(rtP2<=190)stPulsanti|=P2STOP;
|
||||
rtP2=200;
|
||||
}
|
||||
stPulsanti&=(!(M1FW|M1BW|M3FW|M3BW|M4FW|M4BW));
|
||||
if(stPulsanti==0){
|
||||
switch(pulsanti&0x3c){
|
||||
case 0x00:
|
||||
rtTLC=100;
|
||||
stPulsanti&=(!(M1FW|M1BW|M3FW|M3BW|M4FW|M4BW));
|
||||
break;
|
||||
case 0x08://tlc1
|
||||
if(rtTLC==0)stPulsanti|=M1FW;
|
||||
break;
|
||||
case 0x10://tlc2
|
||||
if(rtTLC==0)stPulsanti|=M1BW;
|
||||
break;
|
||||
case 0x20://tlc3
|
||||
if(rtTLC==0)stPulsanti|=M3FW;
|
||||
break;
|
||||
case 0x04://tlc4
|
||||
if(rtTLC==0)stPulsanti|=M3BW;
|
||||
break;
|
||||
case 0x30://tlc5
|
||||
if(rtTLC==0)stPulsanti|=M4FW;
|
||||
break;
|
||||
case 0x0c://tlc6
|
||||
if(rtTLC==0)stPulsanti|=M4BW;
|
||||
break;
|
||||
default:
|
||||
rtTLC=100;
|
||||
stPulsanti&=(!(M1FW|M1BW|M3FW|M3BW|M4FW|M4BW));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void manageCiclo(void){
|
||||
|
||||
switch(stCiclo){
|
||||
case omchiuso:
|
||||
if(stPulsanti&P1START){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M2,BW,mrampstart[M2-1],m2pwmap,tramp,RAMPINIT);
|
||||
stCiclo=omapertura1;
|
||||
}else if(stPulsanti&P1STOP)stCiclo=omstopapertura;
|
||||
else if(stPulsanti&M1FW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M1,FW,mrampstart[M1-1],m1pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM1fw1;
|
||||
}else if(stPulsanti&M1BW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M1,BW,mrampstart[M1-1],m1pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM1bw1;
|
||||
}else if(stPulsanti&M2FW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M2,FW,mrampstart[M2-1],m2pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM2fw1;
|
||||
}else if(stPulsanti&M2BW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M2,BW,mrampstart[M2-1],m2pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM2bw1;
|
||||
}else if(stPulsanti&M3FW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M3,FW,mrampstart[M3-1],m3pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM3fw1;
|
||||
}else if(stPulsanti&M3BW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M3,BW,mrampstart[M3-1],m3pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM3bw1;
|
||||
}else if(stPulsanti&M4FW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M4,FW,mrampstart[M4-1],m3pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM4fw1;
|
||||
}else if(stPulsanti&M4BW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M4,BW,mrampstart[M4-1],m3pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM4bw1;
|
||||
}
|
||||
break;
|
||||
case omM1fw1:
|
||||
(void)ramp(M1,FW,mrampstart[M1-1],m1pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti==0)stCiclo=omM1fw2;
|
||||
break;
|
||||
case omM1fw2:
|
||||
(void)ramp(M1,FW,mrampstart[M1-1],m1pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti)stCiclo=omStopMan;
|
||||
break;
|
||||
case omM1bw1:
|
||||
(void)ramp(M1,BW,mrampstart[M1-1],m1pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti==0)stCiclo=omM1bw2;
|
||||
break;
|
||||
case omM1bw2:
|
||||
(void)ramp(M1,BW,mrampstart[M1-1],m1pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti)stCiclo=omStopMan;
|
||||
break;
|
||||
case omM2fw1:
|
||||
(void)ramp(M2,FW,mrampstart[M2-1],m2pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti==0)stCiclo=omM2fw2;
|
||||
break;
|
||||
case omM2fw2:
|
||||
(void)ramp(M2,FW,mrampstart[M2-1],m2pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti)stCiclo=omStopMan;
|
||||
break;
|
||||
case omM2bw1:
|
||||
(void)ramp(M2,BW,mrampstart[M2-1],m2pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti==0)stCiclo=omM2bw2;
|
||||
break;
|
||||
case omM2bw2:
|
||||
(void)ramp(M2,BW,mrampstart[M2-1],m2pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti)stCiclo=omStopMan;
|
||||
break;
|
||||
case omM3fw1:
|
||||
(void)ramp(M3,FW,mrampstart[M3-1],m3pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti==0)stCiclo=omM3fw2;
|
||||
break;
|
||||
case omM3fw2:
|
||||
(void)ramp(M3,FW,mrampstart[M3-1],m3pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti)stCiclo=omStopMan;
|
||||
break;
|
||||
case omM3bw1:
|
||||
(void)ramp(M3,BW,mrampstart[M3-1],m3pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti==0)stCiclo=omM3bw2;
|
||||
break;
|
||||
case omM3bw2:
|
||||
(void)ramp(M3,BW,mrampstart[M3-1],m3pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti)stCiclo=omStopMan;
|
||||
break;
|
||||
case omM4fw1:
|
||||
(void)ramp(M4,FW,mrampstart[M4-1],m4pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti==0)stCiclo=omM4fw2;
|
||||
break;
|
||||
case omM4fw2:
|
||||
(void)ramp(M4,FW,mrampstart[M4-1],m4pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti)stCiclo=omStopMan;
|
||||
break;
|
||||
case omM4bw1:
|
||||
(void)ramp(M4,BW,mrampstart[M4-1],m4pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti==0)stCiclo=omM4bw2;
|
||||
break;
|
||||
case omM4bw2:
|
||||
(void)ramp(M4,BW,mrampstart[M4-1],m4pwmMan,trampman,RAMPRUN);
|
||||
if(pulsanti)stCiclo=omStopMan;
|
||||
break;
|
||||
case omStopMan:
|
||||
SetMotPerc(M1,FW,0);
|
||||
SetMotPerc(M2,FW,0);
|
||||
SetMotPerc(M3,FW,0);
|
||||
SetMotPerc(M4,FW,0);
|
||||
SetMotPerc(M1,BW,0);
|
||||
SetMotPerc(M2,BW,0);
|
||||
SetMotPerc(M3,BW,0);
|
||||
SetMotPerc(M4,BW,0);
|
||||
if(pulsanti==0){
|
||||
stBuz=bzoff;
|
||||
stCiclo=omaperto;
|
||||
}
|
||||
if(stPulsanti&P1STOP)stCiclo=omstopapertura;
|
||||
break;
|
||||
case omapertura1:
|
||||
if(ramp(M2,BW,mrampstart[M2-1],m2pwmap,tramp,RAMPRUN)==DONE){
|
||||
@@ -291,7 +448,7 @@ void manageCiclo(void){
|
||||
if(stPulsanti&P1STOP)stCiclo=omstopapertura;
|
||||
break;
|
||||
case omapertura14:
|
||||
if(rtCiclo==0){
|
||||
if((rtCiclo==0)&&(pulsanti==0)){
|
||||
stBuz=bzoff;
|
||||
stCiclo=omaperto;
|
||||
}
|
||||
@@ -302,9 +459,11 @@ void manageCiclo(void){
|
||||
SetMotPerc(M2,FW,0);
|
||||
SetMotPerc(M3,FW,0);
|
||||
SetMotPerc(M4,FW,0);
|
||||
stBuz=bzoff;
|
||||
stCiclo=omchiuso;
|
||||
stPulsanti&=(~P1STOP);
|
||||
if(pulsanti==0){
|
||||
stBuz=bzoff;
|
||||
stCiclo=omchiuso;
|
||||
stPulsanti&=(~P1STOP);
|
||||
}
|
||||
break;
|
||||
case omaperto:
|
||||
if(stPulsanti&P1START){
|
||||
@@ -313,6 +472,39 @@ void manageCiclo(void){
|
||||
stCiclo=omchiusura1;
|
||||
}
|
||||
if(stPulsanti&P1STOP)stCiclo=omstopchiusura;
|
||||
else if(stPulsanti&M1FW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M1,FW,mrampstart[M1-1],m1pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM1fw1;
|
||||
}else if(stPulsanti&M1BW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M1,BW,mrampstart[M1-1],m1pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM1bw1;
|
||||
}else if(stPulsanti&M2FW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M2,FW,mrampstart[M2-1],m2pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM2fw1;
|
||||
}else if(stPulsanti&M2BW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M2,BW,mrampstart[M2-1],m2pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM2bw1;
|
||||
}else if(stPulsanti&M3FW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M3,FW,mrampstart[M3-1],m3pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM3fw1;
|
||||
}else if(stPulsanti&M3BW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M3,BW,mrampstart[M3-1],m3pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM3bw1;
|
||||
}else if(stPulsanti&M4FW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M4,FW,mrampstart[M4-1],m3pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM4fw1;
|
||||
}else if(stPulsanti&M4BW){
|
||||
stBuz=bzmoving;
|
||||
(void)ramp(M4,BW,mrampstart[M4-1],m3pwmMan,trampman,RAMPINIT);
|
||||
stCiclo=omM4bw1;
|
||||
}
|
||||
break;
|
||||
case omchiusura1:
|
||||
if(ramp(M1,BW,mrampstart[M1-1],m1pwmch,tramp,RAMPRUN)==DONE){
|
||||
@@ -408,7 +600,7 @@ void manageCiclo(void){
|
||||
if(stPulsanti&P1STOP)stCiclo=omstopchiusura;
|
||||
break;
|
||||
case omchiusura14:
|
||||
if(rtCiclo==0){
|
||||
if((rtCiclo==0)&&(pulsanti==0)){
|
||||
stBuz=bzoff;
|
||||
stCiclo=omchiuso;
|
||||
}
|
||||
@@ -419,9 +611,11 @@ void manageCiclo(void){
|
||||
SetMotPerc(M2,FW,0);
|
||||
SetMotPerc(M3,FW,0);
|
||||
SetMotPerc(M4,FW,0);
|
||||
stBuz=bzoff;
|
||||
stCiclo=omaperto;
|
||||
stPulsanti&=(~P1STOP);
|
||||
if(pulsanti==0){
|
||||
stBuz=bzoff;
|
||||
stCiclo=omaperto;
|
||||
stPulsanti&=(~P1STOP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* eeprom.h
|
||||
*
|
||||
* Created on: Dec 7, 2025
|
||||
* Author: user
|
||||
*/
|
||||
|
||||
#ifndef __EEPROM_H
|
||||
#define __EEPROM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/*
|
||||
* Simple EEPROM emulation for STM32F103C8T6 (medium density).
|
||||
* - Uses 2 Flash pages (1 kB each) at the end of Flash.
|
||||
* - Stores variables as 16-bit values identified by 16-bit "virtual addresses".
|
||||
*
|
||||
* You must define the list of virtual addresses in eeprom.c: EE_VirtAddrs[].
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EE_STATUS_OK = 0,
|
||||
EE_STATUS_ERROR,
|
||||
EE_STATUS_NOT_FOUND,
|
||||
EE_STATUS_NO_SPACE
|
||||
} EE_Status;
|
||||
|
||||
/* For compatibility with ST style uint16_t return codes */
|
||||
#define EE_OK ((uint16_t)EE_STATUS_OK)
|
||||
#define EE_ERROR ((uint16_t)EE_STATUS_ERROR)
|
||||
#define EE_NOT_FOUND ((uint16_t)EE_STATUS_NOT_FOUND)
|
||||
#define EE_NO_SPACE ((uint16_t)EE_STATUS_NO_SPACE)
|
||||
|
||||
/* Flash parameters for STM32F103C8T6 */
|
||||
#define EE_FLASH_BASE_ADDR 0x08000000U
|
||||
#define EE_PAGE_SIZE 0x400U /* 1 kB pages */
|
||||
|
||||
/*
|
||||
* Here we assume a 64 kB Flash device (STM32F103C8T6):
|
||||
* Flash range: 0x0800 0000 - 0x0800 FFFF
|
||||
* Pages: 0..63 (64 pages)
|
||||
* We use the last 2 pages for EEPROM:
|
||||
* - Page 62: 0x0800 F800
|
||||
* - Page 63: 0x0800 FC00
|
||||
*/
|
||||
#define EE_PAGE0_BASE (EE_FLASH_BASE_ADDR + (62U * EE_PAGE_SIZE))
|
||||
#define EE_PAGE1_BASE (EE_FLASH_BASE_ADDR + (63U * EE_PAGE_SIZE))
|
||||
|
||||
/* Page status markers (stored in the first halfword of each page) */
|
||||
#define EE_PAGE_STATUS_ERASED 0xFFFFU
|
||||
#define EE_PAGE_STATUS_VALID 0xAAAAU
|
||||
#define EE_PAGE_STATUS_RECEIVE 0x5555U
|
||||
|
||||
/*
|
||||
* Configure how many virtual variables you have.
|
||||
* Example: bytes, words, and array elements mapped to 16-bit variables.
|
||||
* Set EE_NUM_VIRTUAL_ADDR and define EE_VirtAddrs[] in eeprom.c.
|
||||
*/
|
||||
/* 32 virtual variables, sequential addresses */
|
||||
#define EE_NUM_VIRTUAL_ADDR 32U
|
||||
#define EEW_ADDR(i) (uint16_t)(0x0001 + (i)) // i = 0..31
|
||||
|
||||
|
||||
#define M1PWMAP 0 //m1pwmap
|
||||
#define M1PWMCH 1 //m1pwmch
|
||||
#define M2PWMAP 2 //m2pwmap
|
||||
#define M2PWMCH 3 //m2pwmch
|
||||
#define M3PWMAP 4 //m3pwmap
|
||||
#define M3PWMCH 5 //m3pwmch
|
||||
#define M4PWMAP 6 //m4pwmap
|
||||
#define M4PWMCH 7 //m4pwmch
|
||||
#define M1RAMPSTART 8 //m1rampstart
|
||||
#define M2RAMPSTART 9 //m2rampstart
|
||||
#define M3RAMPSTART 10 //m3rampstart
|
||||
#define M4RAMPSTART 11 //m4rampstart
|
||||
#define T1AP 12 //t1ap
|
||||
#define T2AP 13 //t2ap
|
||||
#define T3AP 14 //t3ap
|
||||
#define T4AP 15 //t4ap
|
||||
#define TWAP 16 //twap
|
||||
#define T1CH 17 //t1ch
|
||||
#define T2CH 18 //t2ch
|
||||
#define T3CH 19 //t3ch
|
||||
#define T4CH 20 //t4ch
|
||||
#define TWCH 21 //twch
|
||||
|
||||
#define M1PWMMAN 26 //m1pwmMan
|
||||
#define M2PWMMAN 27 //m2pwmMan
|
||||
#define M3PWMMAN 28 //m3pwmMan
|
||||
#define M4PWMMAN 29 //m4pwmMan
|
||||
#define TRAMPMAN 30 //trampman
|
||||
#define TRAMP 31 //tramp
|
||||
|
||||
|
||||
/* Virtual address table (defined in eeprom.c, can be customized) */
|
||||
extern const uint16_t EE_VirtAddrs[EE_NUM_VIRTUAL_ADDR];
|
||||
|
||||
/* Public API – now using uint16_t like ST examples */
|
||||
uint16_t EE_Init(void);
|
||||
uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t *Data);
|
||||
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data);
|
||||
void loadEE(void);
|
||||
/* Pseudo-array accessor EEW[idx] */
|
||||
static inline uint16_t EEW_Read(uint8_t idx, uint16_t *value)
|
||||
{
|
||||
return EE_ReadVariable(EEW_ADDR(idx), value);
|
||||
}
|
||||
|
||||
static inline uint16_t EEW_Write(uint8_t idx, uint16_t value)
|
||||
{
|
||||
return EE_WriteVariable(EEW_ADDR(idx), value);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __EEPROM_H */
|
||||
@@ -0,0 +1,389 @@
|
||||
#include "eeprom.h"
|
||||
|
||||
/*
|
||||
* Record format (4 bytes):
|
||||
* [0] VirtAddress (uint16_t)
|
||||
* [2] Data (uint16_t)
|
||||
*
|
||||
* Page layout:
|
||||
* [0] PageStatus (uint16_t)
|
||||
* [2..] Records...
|
||||
*/
|
||||
|
||||
extern uint16_t m1pwmap;
|
||||
extern uint16_t m1pwmch;
|
||||
extern uint16_t m2pwmap;
|
||||
extern uint16_t m2pwmch;
|
||||
extern uint16_t m3pwmap;
|
||||
extern uint16_t m3pwmch;
|
||||
extern uint16_t m4pwmap;
|
||||
extern uint16_t m4pwmch;
|
||||
extern uint16_t t1ap;
|
||||
extern uint16_t t2ap;
|
||||
extern uint16_t t3ap;
|
||||
extern uint16_t t4ap;
|
||||
extern uint16_t twap;
|
||||
extern uint16_t tramp;
|
||||
extern uint16_t t1ch;
|
||||
extern uint16_t t2ch;
|
||||
extern uint16_t t3ch;
|
||||
extern uint16_t t4ch;
|
||||
extern uint16_t twch;
|
||||
extern uint16_t trampman;
|
||||
extern uint16_t m1pwmMan;
|
||||
extern uint16_t m2pwmMan;
|
||||
extern uint16_t m3pwmMan;
|
||||
extern uint16_t m4pwmMan;
|
||||
|
||||
const uint8_t deftab[32]={
|
||||
40, //m1pwmap
|
||||
60, //m1pwmch
|
||||
70, //m2pwmap
|
||||
70, //m2pwmch
|
||||
35, //m3pwmap
|
||||
40, //m3pwmch
|
||||
40, //m4pwmap
|
||||
40, //m4pwmch
|
||||
20, //m1rampstart
|
||||
20, //m2rampstart
|
||||
20, //m3rampstart
|
||||
20, //m4rampstart
|
||||
28, //t1ap
|
||||
4, //t2ap
|
||||
10, //t3ap
|
||||
40, //t4ap
|
||||
1, //twap
|
||||
20, //t1ch
|
||||
10, //t2ch
|
||||
30, //t3ch
|
||||
1, //t4ch
|
||||
1, //twch
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
100, //tramp1
|
||||
60, //m1pwmMan
|
||||
70, //m2pwmMan
|
||||
40, //m3pwmMan
|
||||
40, //m4pwmMan
|
||||
50, //trampman
|
||||
10, //tramp
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t VirtAddress;
|
||||
uint16_t Data;
|
||||
} EE_Record_t;
|
||||
|
||||
/* Active page base address (runtime selected in EE_Init) */
|
||||
static uint32_t EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
|
||||
/* 32 sequential virtual addresses */
|
||||
const uint16_t EE_VirtAddrs[EE_NUM_VIRTUAL_ADDR] =
|
||||
{
|
||||
0x0001, 0x0002, 0x0003, 0x0004,
|
||||
0x0005, 0x0006, 0x0007, 0x0008,
|
||||
0x0009, 0x000A, 0x000B, 0x000C,
|
||||
0x000D, 0x000E, 0x000F, 0x0010,
|
||||
0x0011, 0x0012, 0x0013, 0x0014,
|
||||
0x0015, 0x0016, 0x0017, 0x0018,
|
||||
0x0019, 0x001A, 0x001B, 0x001C,
|
||||
0x001D, 0x001E, 0x001F, 0x0020
|
||||
};
|
||||
/* ========================================================================= */
|
||||
|
||||
/* --- Internal helpers ---------------------------------------------------- */
|
||||
|
||||
static uint16_t EE_GetPageStatus(uint32_t pageBase)
|
||||
{
|
||||
return *(__IO uint16_t *)pageBase;
|
||||
}
|
||||
|
||||
static HAL_StatusTypeDef EE_FlashProgramHalfWord(uint32_t Address, uint16_t Data)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, Data);
|
||||
HAL_FLASH_Lock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static HAL_StatusTypeDef EE_FlashErasePage(uint32_t PageAddress)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
FLASH_EraseInitTypeDef EraseInit;
|
||||
uint32_t PageError = 0;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
|
||||
EraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
EraseInit.PageAddress = PageAddress;
|
||||
EraseInit.NbPages = 1;
|
||||
|
||||
status = HAL_FLASHEx_Erase(&EraseInit, &PageError);
|
||||
|
||||
HAL_FLASH_Lock();
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Find first free record address in given page (returns 0 if full) */
|
||||
static uint32_t EE_FindFreeAddress(uint32_t pageBase)
|
||||
{
|
||||
uint32_t addr = pageBase + 2U; /* Skip status word */
|
||||
uint32_t pageEnd = pageBase + EE_PAGE_SIZE;
|
||||
|
||||
while (addr < (pageEnd - sizeof(EE_Record_t) + 1U))
|
||||
{
|
||||
uint16_t vaddr = *(__IO uint16_t *)addr;
|
||||
|
||||
if (vaddr == 0xFFFFU)
|
||||
{
|
||||
/* Empty slot */
|
||||
return addr;
|
||||
}
|
||||
addr += sizeof(EE_Record_t);
|
||||
}
|
||||
|
||||
return 0U; /* No space */
|
||||
}
|
||||
|
||||
/* Find latest value of VirtAddress in a specific page (internal, uses EE_Status) */
|
||||
/* Find latest value of VirtAddress in a specific page (scan forward) */
|
||||
static EE_Status EE_FindInPage(uint32_t pageBase, uint16_t VirtAddress, uint16_t *Data)
|
||||
{
|
||||
uint32_t addr = pageBase + 2U; // skip status halfword
|
||||
uint32_t pageEnd = pageBase + EE_PAGE_SIZE;
|
||||
EE_Status result = EE_NOT_FOUND;
|
||||
uint16_t lastVal = 0;
|
||||
|
||||
if (Data == NULL)
|
||||
return EE_ERROR;
|
||||
|
||||
while (addr <= (pageEnd - sizeof(EE_Record_t)))
|
||||
{
|
||||
uint16_t vaddr = *(__IO uint16_t *)addr;
|
||||
|
||||
if (vaddr == 0xFFFFU)
|
||||
{
|
||||
// First empty slot => no more records in this page
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t value = *(__IO uint16_t *)(addr + 2U);
|
||||
|
||||
if (vaddr == VirtAddress)
|
||||
{
|
||||
lastVal = value; // keep most recent
|
||||
result = EE_OK;
|
||||
}
|
||||
|
||||
addr += sizeof(EE_Record_t); // move 4 bytes forward
|
||||
}
|
||||
|
||||
if (result == EE_OK)
|
||||
*Data = lastVal;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Format both pages: erase and set PAGE0 as VALID */
|
||||
static EE_Status EE_Format(void)
|
||||
{
|
||||
if (EE_FlashErasePage(EE_PAGE0_BASE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
if (EE_FlashErasePage(EE_PAGE1_BASE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
if (EE_FlashProgramHalfWord(EE_PAGE0_BASE, EE_PAGE_STATUS_VALID) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* PAGE1 will remain erased (status = 0xFFFF) */
|
||||
EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
|
||||
return EE_STATUS_OK;
|
||||
}
|
||||
|
||||
/* Get the base of the other page */
|
||||
static uint32_t EE_GetOtherPageBase(uint32_t pageBase)
|
||||
{
|
||||
return (pageBase == EE_PAGE0_BASE) ? EE_PAGE1_BASE : EE_PAGE0_BASE;
|
||||
}
|
||||
|
||||
/* Page transfer (garbage collection + new write) */
|
||||
static EE_Status EE_PageTransfer(uint16_t VirtAddress, uint16_t Data)
|
||||
{
|
||||
uint32_t oldBase = EE_ActivePageBase;
|
||||
uint32_t newBase = EE_GetOtherPageBase(oldBase);
|
||||
uint32_t addr;
|
||||
uint16_t value;
|
||||
EE_Status st;
|
||||
|
||||
/* Erase new page */
|
||||
if (EE_FlashErasePage(newBase) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Mark new page as RECEIVE */
|
||||
if (EE_FlashProgramHalfWord(newBase, EE_PAGE_STATUS_RECEIVE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Start writing records just after status */
|
||||
addr = newBase + 2U;
|
||||
|
||||
/* For each known virtual variable */
|
||||
for (uint16_t i = 0; i < EE_NUM_VIRTUAL_ADDR; i++)
|
||||
{
|
||||
uint16_t vaddr = EE_VirtAddrs[i];
|
||||
|
||||
if (vaddr == VirtAddress)
|
||||
{
|
||||
/* Use the new data passed into PageTransfer */
|
||||
value = Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read latest value from old active page */
|
||||
st = EE_FindInPage(oldBase, vaddr, &value);
|
||||
if (st != EE_STATUS_OK)
|
||||
{
|
||||
/* Variable never written -> skip */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write record to new page */
|
||||
if (EE_FlashProgramHalfWord(addr, vaddr) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
if (EE_FlashProgramHalfWord(addr + 2U, value) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
addr += sizeof(EE_Record_t);
|
||||
if (addr >= (newBase + EE_PAGE_SIZE))
|
||||
return EE_STATUS_NO_SPACE;
|
||||
}
|
||||
|
||||
/* Erase old page */
|
||||
if (EE_FlashErasePage(oldBase) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Mark new page as VALID */
|
||||
if (EE_FlashProgramHalfWord(newBase, EE_PAGE_STATUS_VALID) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Update active page */
|
||||
EE_ActivePageBase = newBase;
|
||||
|
||||
return EE_STATUS_OK;
|
||||
}
|
||||
|
||||
/* --- Public API ----------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Initialize the EEPROM emulation.
|
||||
* - Checks page statuses and chooses the active page.
|
||||
* - If inconsistent or blank, formats pages.
|
||||
* PUBLIC RETURN TYPE: uint16_t (EE_OK / EE_ERROR / ...)
|
||||
*/
|
||||
uint16_t EE_Init(void)
|
||||
{
|
||||
uint16_t status0 = EE_GetPageStatus(EE_PAGE0_BASE);
|
||||
uint16_t status1 = EE_GetPageStatus(EE_PAGE1_BASE);
|
||||
|
||||
if ((status0 == EE_PAGE_STATUS_ERASED) && (status1 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
/* Fresh device -> format */
|
||||
return (uint16_t)EE_Format();
|
||||
}
|
||||
else if ((status0 == EE_PAGE_STATUS_VALID) && (status1 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
return EE_OK;
|
||||
}
|
||||
else if ((status1 == EE_PAGE_STATUS_VALID) && (status0 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
EE_ActivePageBase = EE_PAGE1_BASE;
|
||||
return EE_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Any weird or inconsistent state -> reformat */
|
||||
return (uint16_t)EE_Format();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a 16-bit variable by its virtual address.
|
||||
* PUBLIC RETURN: EE_OK / EE_NOT_FOUND / EE_ERROR (as uint16_t)
|
||||
*/
|
||||
uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t *Data)
|
||||
{
|
||||
EE_Status st;
|
||||
|
||||
if (Data == NULL)
|
||||
return EE_ERROR;
|
||||
|
||||
st = EE_FindInPage(EE_ActivePageBase, VirtAddress, Data);
|
||||
return (uint16_t)st;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write (append) a 16-bit variable.
|
||||
* - Writes a new record in the active page.
|
||||
* - If the page is full, triggers a page transfer (GC).
|
||||
* PUBLIC RETURN: EE_OK / EE_ERROR / EE_NO_SPACE (as uint16_t)
|
||||
*/
|
||||
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
|
||||
{
|
||||
uint32_t freeAddr;
|
||||
EE_Status st;
|
||||
|
||||
/* Find free space in active page */
|
||||
freeAddr = EE_FindFreeAddress(EE_ActivePageBase);
|
||||
if (freeAddr != 0U)
|
||||
{
|
||||
/* Write new record */
|
||||
if (EE_FlashProgramHalfWord(freeAddr, VirtAddress) != HAL_OK)
|
||||
return EE_ERROR;
|
||||
if (EE_FlashProgramHalfWord(freeAddr + 2U, Data) != HAL_OK)
|
||||
return EE_ERROR;
|
||||
|
||||
return EE_OK;
|
||||
}
|
||||
|
||||
/* No space -> page transfer */
|
||||
st = EE_PageTransfer(VirtAddress, Data);
|
||||
return (uint16_t)st;
|
||||
}
|
||||
|
||||
void loadEE(void){
|
||||
EEW_Read(M1PWMAP, &m1pwmap);
|
||||
EEW_Read(M1PWMCH, &m1pwmch);
|
||||
EEW_Read(M2PWMAP, &m2pwmap);
|
||||
EEW_Read(M2PWMCH, &m2pwmch);
|
||||
EEW_Read(M3PWMAP, &m3pwmap);
|
||||
EEW_Read(M3PWMCH, &m3pwmch);
|
||||
EEW_Read(M4PWMAP, &m4pwmap);
|
||||
EEW_Read(M4PWMCH, &m4pwmch);
|
||||
EEW_Read(T1AP, &t1ap);
|
||||
EEW_Read(T2AP, &t2ap);
|
||||
EEW_Read(T3AP, &t3ap);
|
||||
EEW_Read(T4AP, &t4ap);
|
||||
EEW_Read(TWAP, &twap);
|
||||
EEW_Read(T1CH, &t1ch);
|
||||
EEW_Read(T2CH, &t2ch);
|
||||
EEW_Read(T3CH, &t3ch);
|
||||
EEW_Read(T4CH, &t4ch);
|
||||
EEW_Read(TWCH, &twch);
|
||||
EEW_Read(TRAMP1, &tramp1);
|
||||
EEW_Read(M1PWMMAN, &m1pwmMan);
|
||||
EEW_Read(M2PWMMAN, &m2pwmMan);
|
||||
EEW_Read(M3PWMMAN, &m3pwmMan);
|
||||
EEW_Read(M4PWMMAN, &m4pwmMan);
|
||||
EEW_Read(TRAMPMAN, &trampman);
|
||||
EEW_Read(TRAMP, &tramp);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
/*
|
||||
* debug.c
|
||||
*
|
||||
* Created on: Apr 20, 2026
|
||||
* Author: user
|
||||
*/
|
||||
|
||||
|
||||
void debug(void){
|
||||
|
||||
HAL_UART_Transmit(&huart1, &b, 1, HAL_MAX_DELAY);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* debug.c
|
||||
*
|
||||
* Created on: Apr 20, 2026
|
||||
* Author: user
|
||||
*/
|
||||
#include "main.h"
|
||||
|
||||
extern UART_HandleTypeDef huart1;
|
||||
|
||||
void debug(void){
|
||||
|
||||
HAL_UART_Transmit(&huart1, &b, 1, HAL_MAX_DELAY);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* debug.h
|
||||
*
|
||||
* Created on: Apr 20, 2026
|
||||
* Author: user
|
||||
*/
|
||||
|
||||
#ifndef SRC_DEBUG_H_
|
||||
#define SRC_DEBUG_H_
|
||||
|
||||
|
||||
|
||||
#endif /* SRC_DEBUG_H_ */
|
||||
@@ -38,6 +38,23 @@ extern "C" {
|
||||
/* USER CODE BEGIN ET */
|
||||
typedef enum{
|
||||
omchiuso,
|
||||
omM1fw1,
|
||||
omM1fw2,
|
||||
omM1bw1,
|
||||
omM1bw2,
|
||||
omM2fw1,
|
||||
omM2fw2,
|
||||
omM2bw1,
|
||||
omM2bw2,
|
||||
omM3fw1,
|
||||
omM3fw2,
|
||||
omM3bw1,
|
||||
omM3bw2,
|
||||
omM4fw1,
|
||||
omM4fw2,
|
||||
omM4bw1,
|
||||
omM4bw2,
|
||||
omStopMan,
|
||||
omapertura1,
|
||||
omapertura2,
|
||||
omapertura3,
|
||||
@@ -0,0 +1,388 @@
|
||||
#include "eeprom.h"
|
||||
|
||||
/*
|
||||
* Record format (4 bytes):
|
||||
* [0] VirtAddress (uint16_t)
|
||||
* [2] Data (uint16_t)
|
||||
*
|
||||
* Page layout:
|
||||
* [0] PageStatus (uint16_t)
|
||||
* [2..] Records...
|
||||
*/
|
||||
|
||||
extern uint16_t m1pwmap;
|
||||
extern uint16_t m1pwmch;
|
||||
extern uint16_t m2pwmap;
|
||||
extern uint16_t m2pwmch;
|
||||
extern uint16_t m3pwmap;
|
||||
extern uint16_t m3pwmch;
|
||||
extern uint16_t m4pwmap;
|
||||
extern uint16_t m4pwmch;
|
||||
extern uint16_t t1ap;
|
||||
extern uint16_t t2ap;
|
||||
extern uint16_t t3ap;
|
||||
extern uint16_t t4ap;
|
||||
extern uint16_t twap;
|
||||
extern uint16_t tramp;
|
||||
extern uint16_t t1ch;
|
||||
extern uint16_t t2ch;
|
||||
extern uint16_t t3ch;
|
||||
extern uint16_t t4ch;
|
||||
extern uint16_t twch;
|
||||
extern uint16_t trampman;
|
||||
extern uint16_t m1pwmMan;
|
||||
extern uint16_t m2pwmMan;
|
||||
extern uint16_t m3pwmMan;
|
||||
extern uint16_t m4pwmMan;
|
||||
|
||||
const uint8_t deftab[32]={
|
||||
40, //m1pwmap
|
||||
60, //m1pwmch
|
||||
70, //m2pwmap
|
||||
70, //m2pwmch
|
||||
35, //m3pwmap
|
||||
40, //m3pwmch
|
||||
40, //m4pwmap
|
||||
40, //m4pwmch
|
||||
20, //m1rampstart
|
||||
20, //m2rampstart
|
||||
20, //m3rampstart
|
||||
20, //m4rampstart
|
||||
28, //t1ap
|
||||
4, //t2ap
|
||||
10, //t3ap
|
||||
40, //t4ap
|
||||
1, //twap
|
||||
20, //t1ch
|
||||
10, //t2ch
|
||||
30, //t3ch
|
||||
1, //t4ch
|
||||
1, //twch
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
60, //m1pwmMan
|
||||
70, //m2pwmMan
|
||||
40, //m3pwmMan
|
||||
40, //m4pwmMan
|
||||
50, //trampman
|
||||
10, //tramp
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t VirtAddress;
|
||||
uint16_t Data;
|
||||
} EE_Record_t;
|
||||
|
||||
/* Active page base address (runtime selected in EE_Init) */
|
||||
static uint32_t EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
|
||||
/* 32 sequential virtual addresses */
|
||||
const uint16_t EE_VirtAddrs[EE_NUM_VIRTUAL_ADDR] =
|
||||
{
|
||||
0x0001, 0x0002, 0x0003, 0x0004,
|
||||
0x0005, 0x0006, 0x0007, 0x0008,
|
||||
0x0009, 0x000A, 0x000B, 0x000C,
|
||||
0x000D, 0x000E, 0x000F, 0x0010,
|
||||
0x0011, 0x0012, 0x0013, 0x0014,
|
||||
0x0015, 0x0016, 0x0017, 0x0018,
|
||||
0x0019, 0x001A, 0x001B, 0x001C,
|
||||
0x001D, 0x001E, 0x001F, 0x0020
|
||||
};
|
||||
/* ========================================================================= */
|
||||
|
||||
/* --- Internal helpers ---------------------------------------------------- */
|
||||
|
||||
static uint16_t EE_GetPageStatus(uint32_t pageBase)
|
||||
{
|
||||
return *(__IO uint16_t *)pageBase;
|
||||
}
|
||||
|
||||
static HAL_StatusTypeDef EE_FlashProgramHalfWord(uint32_t Address, uint16_t Data)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, Address, Data);
|
||||
HAL_FLASH_Lock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static HAL_StatusTypeDef EE_FlashErasePage(uint32_t PageAddress)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
FLASH_EraseInitTypeDef EraseInit;
|
||||
uint32_t PageError = 0;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
|
||||
EraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
|
||||
EraseInit.PageAddress = PageAddress;
|
||||
EraseInit.NbPages = 1;
|
||||
|
||||
status = HAL_FLASHEx_Erase(&EraseInit, &PageError);
|
||||
|
||||
HAL_FLASH_Lock();
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Find first free record address in given page (returns 0 if full) */
|
||||
static uint32_t EE_FindFreeAddress(uint32_t pageBase)
|
||||
{
|
||||
uint32_t addr = pageBase + 2U; /* Skip status word */
|
||||
uint32_t pageEnd = pageBase + EE_PAGE_SIZE;
|
||||
|
||||
while (addr < (pageEnd - sizeof(EE_Record_t) + 1U))
|
||||
{
|
||||
uint16_t vaddr = *(__IO uint16_t *)addr;
|
||||
|
||||
if (vaddr == 0xFFFFU)
|
||||
{
|
||||
/* Empty slot */
|
||||
return addr;
|
||||
}
|
||||
addr += sizeof(EE_Record_t);
|
||||
}
|
||||
|
||||
return 0U; /* No space */
|
||||
}
|
||||
|
||||
/* Find latest value of VirtAddress in a specific page (internal, uses EE_Status) */
|
||||
/* Find latest value of VirtAddress in a specific page (scan forward) */
|
||||
static EE_Status EE_FindInPage(uint32_t pageBase, uint16_t VirtAddress, uint16_t *Data)
|
||||
{
|
||||
uint32_t addr = pageBase + 2U; // skip status halfword
|
||||
uint32_t pageEnd = pageBase + EE_PAGE_SIZE;
|
||||
EE_Status result = EE_NOT_FOUND;
|
||||
uint16_t lastVal = 0;
|
||||
|
||||
if (Data == NULL)
|
||||
return EE_ERROR;
|
||||
|
||||
while (addr <= (pageEnd - sizeof(EE_Record_t)))
|
||||
{
|
||||
uint16_t vaddr = *(__IO uint16_t *)addr;
|
||||
|
||||
if (vaddr == 0xFFFFU)
|
||||
{
|
||||
// First empty slot => no more records in this page
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t value = *(__IO uint16_t *)(addr + 2U);
|
||||
|
||||
if (vaddr == VirtAddress)
|
||||
{
|
||||
lastVal = value; // keep most recent
|
||||
result = EE_OK;
|
||||
}
|
||||
|
||||
addr += sizeof(EE_Record_t); // move 4 bytes forward
|
||||
}
|
||||
|
||||
if (result == EE_OK)
|
||||
*Data = lastVal;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Format both pages: erase and set PAGE0 as VALID */
|
||||
static EE_Status EE_Format(void)
|
||||
{
|
||||
if (EE_FlashErasePage(EE_PAGE0_BASE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
if (EE_FlashErasePage(EE_PAGE1_BASE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
if (EE_FlashProgramHalfWord(EE_PAGE0_BASE, EE_PAGE_STATUS_VALID) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* PAGE1 will remain erased (status = 0xFFFF) */
|
||||
EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
|
||||
return EE_STATUS_OK;
|
||||
}
|
||||
|
||||
/* Get the base of the other page */
|
||||
static uint32_t EE_GetOtherPageBase(uint32_t pageBase)
|
||||
{
|
||||
return (pageBase == EE_PAGE0_BASE) ? EE_PAGE1_BASE : EE_PAGE0_BASE;
|
||||
}
|
||||
|
||||
/* Page transfer (garbage collection + new write) */
|
||||
static EE_Status EE_PageTransfer(uint16_t VirtAddress, uint16_t Data)
|
||||
{
|
||||
uint32_t oldBase = EE_ActivePageBase;
|
||||
uint32_t newBase = EE_GetOtherPageBase(oldBase);
|
||||
uint32_t addr;
|
||||
uint16_t value;
|
||||
EE_Status st;
|
||||
|
||||
/* Erase new page */
|
||||
if (EE_FlashErasePage(newBase) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Mark new page as RECEIVE */
|
||||
if (EE_FlashProgramHalfWord(newBase, EE_PAGE_STATUS_RECEIVE) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Start writing records just after status */
|
||||
addr = newBase + 2U;
|
||||
|
||||
/* For each known virtual variable */
|
||||
for (uint16_t i = 0; i < EE_NUM_VIRTUAL_ADDR; i++)
|
||||
{
|
||||
uint16_t vaddr = EE_VirtAddrs[i];
|
||||
|
||||
if (vaddr == VirtAddress)
|
||||
{
|
||||
/* Use the new data passed into PageTransfer */
|
||||
value = Data;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read latest value from old active page */
|
||||
st = EE_FindInPage(oldBase, vaddr, &value);
|
||||
if (st != EE_STATUS_OK)
|
||||
{
|
||||
/* Variable never written -> skip */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write record to new page */
|
||||
if (EE_FlashProgramHalfWord(addr, vaddr) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
if (EE_FlashProgramHalfWord(addr + 2U, value) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
addr += sizeof(EE_Record_t);
|
||||
if (addr >= (newBase + EE_PAGE_SIZE))
|
||||
return EE_STATUS_NO_SPACE;
|
||||
}
|
||||
|
||||
/* Erase old page */
|
||||
if (EE_FlashErasePage(oldBase) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Mark new page as VALID */
|
||||
if (EE_FlashProgramHalfWord(newBase, EE_PAGE_STATUS_VALID) != HAL_OK)
|
||||
return EE_STATUS_ERROR;
|
||||
|
||||
/* Update active page */
|
||||
EE_ActivePageBase = newBase;
|
||||
|
||||
return EE_STATUS_OK;
|
||||
}
|
||||
|
||||
/* --- Public API ----------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Initialize the EEPROM emulation.
|
||||
* - Checks page statuses and chooses the active page.
|
||||
* - If inconsistent or blank, formats pages.
|
||||
* PUBLIC RETURN TYPE: uint16_t (EE_OK / EE_ERROR / ...)
|
||||
*/
|
||||
uint16_t EE_Init(void)
|
||||
{
|
||||
uint16_t status0 = EE_GetPageStatus(EE_PAGE0_BASE);
|
||||
uint16_t status1 = EE_GetPageStatus(EE_PAGE1_BASE);
|
||||
|
||||
if ((status0 == EE_PAGE_STATUS_ERASED) && (status1 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
/* Fresh device -> format */
|
||||
return (uint16_t)EE_Format();
|
||||
}
|
||||
else if ((status0 == EE_PAGE_STATUS_VALID) && (status1 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
EE_ActivePageBase = EE_PAGE0_BASE;
|
||||
return EE_OK;
|
||||
}
|
||||
else if ((status1 == EE_PAGE_STATUS_VALID) && (status0 == EE_PAGE_STATUS_ERASED))
|
||||
{
|
||||
EE_ActivePageBase = EE_PAGE1_BASE;
|
||||
return EE_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Any weird or inconsistent state -> reformat */
|
||||
return (uint16_t)EE_Format();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a 16-bit variable by its virtual address.
|
||||
* PUBLIC RETURN: EE_OK / EE_NOT_FOUND / EE_ERROR (as uint16_t)
|
||||
*/
|
||||
uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t *Data)
|
||||
{
|
||||
EE_Status st;
|
||||
|
||||
if (Data == NULL)
|
||||
return EE_ERROR;
|
||||
|
||||
st = EE_FindInPage(EE_ActivePageBase, VirtAddress, Data);
|
||||
return (uint16_t)st;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write (append) a 16-bit variable.
|
||||
* - Writes a new record in the active page.
|
||||
* - If the page is full, triggers a page transfer (GC).
|
||||
* PUBLIC RETURN: EE_OK / EE_ERROR / EE_NO_SPACE (as uint16_t)
|
||||
*/
|
||||
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
|
||||
{
|
||||
uint32_t freeAddr;
|
||||
EE_Status st;
|
||||
|
||||
/* Find free space in active page */
|
||||
freeAddr = EE_FindFreeAddress(EE_ActivePageBase);
|
||||
if (freeAddr != 0U)
|
||||
{
|
||||
/* Write new record */
|
||||
if (EE_FlashProgramHalfWord(freeAddr, VirtAddress) != HAL_OK)
|
||||
return EE_ERROR;
|
||||
if (EE_FlashProgramHalfWord(freeAddr + 2U, Data) != HAL_OK)
|
||||
return EE_ERROR;
|
||||
|
||||
return EE_OK;
|
||||
}
|
||||
|
||||
/* No space -> page transfer */
|
||||
st = EE_PageTransfer(VirtAddress, Data);
|
||||
return (uint16_t)st;
|
||||
}
|
||||
|
||||
void loadEE(void){
|
||||
EEW_Read(M1PWMAP, &m1pwmap);
|
||||
EEW_Read(M1PWMCH, &m1pwmch);
|
||||
EEW_Read(M2PWMAP, &m2pwmap);
|
||||
EEW_Read(M2PWMCH, &m2pwmch);
|
||||
EEW_Read(M3PWMAP, &m3pwmap);
|
||||
EEW_Read(M3PWMCH, &m3pwmch);
|
||||
EEW_Read(M4PWMAP, &m4pwmap);
|
||||
EEW_Read(M4PWMCH, &m4pwmch);
|
||||
EEW_Read(T1AP, &t1ap);
|
||||
EEW_Read(T2AP, &t2ap);
|
||||
EEW_Read(T3AP, &t3ap);
|
||||
EEW_Read(T4AP, &t4ap);
|
||||
EEW_Read(TWAP, &twap);
|
||||
EEW_Read(T1CH, &t1ch);
|
||||
EEW_Read(T2CH, &t2ch);
|
||||
EEW_Read(T3CH, &t3ch);
|
||||
EEW_Read(T4CH, &t4ch);
|
||||
EEW_Read(TWCH, &twch);
|
||||
EEW_Read(M1PWMMAN, &m1pwmMan);
|
||||
EEW_Read(M2PWMMAN, &m2pwmMan);
|
||||
EEW_Read(M3PWMMAN, &m3pwmMan);
|
||||
EEW_Read(M4PWMMAN, &m4pwmMan);
|
||||
EEW_Read(TRAMPMAN, &trampman);
|
||||
EEW_Read(TRAMP, &tramp);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user