2024-11-11 12:23 PM - edited 2024-11-12 04:16 AM
Microcontroller: STM32C031K6T6
I'm trying to make an interface so that the user can change the name of their environment in real time, my idea and what I tried to write is something that holds the previous strings (which may already be edited) in RAM, makes the modifications and then then write in flash again. Currently my code is like this, it shows the environments ("AMBIENTE 01...24"), I can edit the name of the string, it "saves" when i call Grava();, but when I turn my board off and on the changes do not continue...
I tried to copy the txtL strings to b_txtL using memcpy, and strncpy at the beginning of main();, but when i do this my my display goes "crazy" showing the strings "AMBIENTE ..." all broken in line 1 and 2
Note: I can't debug and at the same time see the changes that happen on the display because the SWCLK pin was used for a display pin, I had to implement a code that erased the memory after holding down some buttons to be able to record another code, workaround ...
const char txtL[][17] = {
" AMBIENTE L01 ", " AMBIENTE L02 ", " AMBIENTE L03 ",
" AMBIENTE L04 ", " AMBIENTE L05 ", " AMBIENTE L06 ",
" AMBIENTE L07 ", " AMBIENTE L08 ", " AMBIENTE L09 ",
" AMBIENTE L10 ", " AMBIENTE L11 ", " AMBIENTE L12 ",
" AMBIENTE L13 ", " AMBIENTE L14 ", " AMBIENTE L15 ",
" AMBIENTE L16 ", " AMBIENTE L17 ", " AMBIENTE L18 ",
" AMBIENTE L19 ", " AMBIENTE L20 ", " AMBIENTE L21 ",
" AMBIENTE L22 ", " AMBIENTE L23 ", " AMBIENTE L24 ",
" ENGFOX 24L "
}; // default flash text
char b_txtL[26][17]; //BUFFER
int main{
//lcd and gpios inits
EEPROM_INIT();
lerEeprom();
//button config and enters the prog
Prog();
//test to see if saved something
lcd_set_cursor(0, 0);
lcd_write_string2((const char*)txtL[0]);
lcd_set_cursor(0, 1);
lcd_write_string2((const char*)b_txtL[15]);
// Prog func
/* I'm using a eeprom_write function to write flags of 0 or 1, due to the limitation of my microcontroller I can only use DOUBLEWORD, which ends up recording a flag in 32 bits, and the next 32 bits are empty */
while (loop < 26) {
DisplayLaco(loop);
HAL_Delay(60);
if (HAL_GPIO_ReadPin(GPIOA, SW1_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(200);
// Verifica o estado atual dos bits
int re_bit = (ure.re_all[loop / 8] & (1 << (loop % 8))) ? 1 : 0;
int rfl_bit = (urfl.rfl_all[loop / 8] & (1 << (loop % 8))) ? 1 : 0;
// Alterna entre as combinações S N, N S, N N, S S
if (re_bit && !rfl_bit)
{
// Caso atual seja S N -> Muda para N S
ure.re_all[loop / 8] &= ~(1 << (loop % 8)); // Desativa o bit em re_all
urfl.rfl_all[loop / 8] |= (1 << (loop % 8)); // Ativa o bit em rfl_all
}
else if (!re_bit && rfl_bit)
{
// Caso atual seja N S -> Muda para N N
ure.re_all[loop / 8] &= ~(1 << (loop % 8)); // Desativa o bit em re_all
urfl.rfl_all[loop / 8] &= ~(1 << (loop % 8)); // Desativa o bit em rfl_all
}
else if (!re_bit && !rfl_bit)
{
// Caso atual seja N N -> Muda para S S
ure.re_all[loop / 8] |= (1 << (loop % 8)); // Ativa o bit em re_all
urfl.rfl_all[loop / 8] |= (1 << (loop % 8)); // Ativa o bit em rfl_all
}
else
{
// Caso atual seja S S -> Muda para S N
ure.re_all[loop / 8] |= (1 << (loop % 8)); // Ativa o bit em re_all
urfl.rfl_all[loop / 8] &= ~(1 << (loop % 8)); // Desativa o bit em rfl_all
}
DisplayLaco(loop); // Atualiza o display
}
if (HAL_GPIO_ReadPin(GPIOA, SW2_Pin) == GPIO_PIN_RESET) {
HAL_Delay(200);
uoff.off_all[loop / 8] ^= (1 << (loop % 8));
DisplayLaco(loop);
}
if (HAL_GPIO_ReadPin(GPIOA, SW3_Pin) == GPIO_PIN_RESET) {
HAL_Delay(200);
Conf_txt(loop);
lcd_display_control(true, false, false);
DisplayLaco(loop);
loop++;
}
}
dcBKL_ch2(200);
}
//Display func (Maybe the trouble is here, idk)
void DisplayLaco(int loop)
{
// Exibe informações sobre o laço atual e o nome correspondente
char nomeL[20];
snprintf(nomeL, sizeof(nomeL), "L%02d:", loop + 1);
lcd_set_cursor(0, 0);
lcd_write_string(nomeL);
lcd_write_string((uoff.off_all[loop / 8] & (1 << (loop % 8))) ? "S " : "N ");
lcd_write_string((ure.re_all[loop / 8] & (1 << (loop % 8))) ? "RE:S " : "RE:N ");
lcd_write_string((urfl.rfl_all[loop / 8] & (1 << (loop % 8))) ? "RFL:S" : "RFL:N");
// Exibe o nome do ambiente correspondente (da RAM)
lcd_set_cursor(0, 1);
// Copiar as strings de b_txtL para txtL (presumindo que b_txtL foi modificado)
lcd_write_string(b_txtL[loop]); // `b_txtL[loop]` já deve estar em `char[]`
}
// Conf_txt func, it's a bit buggy, I'm trying to solve it...
void Conf_txt(uint16_t loop)
{
// Permite a edição em tempo real do nome selecionado em b_txtL
bool edit = true;
// Posição do caractere dentro do nome
uint8_t pressCounter = 0;
uint8_t col = 0;
// Exibe o nome inicial na LCD
lcd_write_string2((const char*)b_txtL[loop]);
lcd_set_cursor(col, 1); // Coloca o cursor na posição inicial
while (edit)
{
lcd_display_control(true, true, true);
lcd_set_cursor(col, 1); // Atualiza a posição do cursor
bool SW3 = (HAL_GPIO_ReadPin(GPIOA, SW3_Pin) == GPIO_PIN_RESET);
// Pressão longa do SW3 para sair do modo de edição
if (SW3)
{
pressCounter++; // Incrementa o contador
if (pressCounter >= 15) // 3 segundos (ajuste conforme necessário)
{
edit = false;
lcd_display_control(true, false, false);
Grava();
return;
}
}
else
{
pressCounter = 0; // Resetando o contador após uma ação
col++; // Avança para a próxima coluna
lcd_set_cursor(col, 1);
if (col >= 16)
{
col = 0;
}
}
// Controle de incremento e decremento do caractere na posição atual
if (HAL_GPIO_ReadPin(GPIOA, SW1_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(200);
b_txtL[loop][col]++;
if (b_txtL[loop][col] > 0x5A) b_txtL[loop][col] = 0x30; // "Z" -> "0"
else if (b_txtL[loop][col] < 0x30) b_txtL[loop][col] = 0x41; // " " -> "A"
else if (b_txtL[loop][col] > 0x39 && b_txtL[loop][col] < 0x41) b_txtL[loop][col] = 0x20; // "9" -> " "
lcd_write_string2((const char*)b_txtL[loop]); // Atualiza o caractere na posição do cursor
}
if (HAL_GPIO_ReadPin(GPIOA, SW2_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(200);
b_txtL[loop][col]--;
if (b_txtL[loop][col] < 0x20) b_txtL[loop][col] = 0x39; // " " -> "9"
else if (b_txtL[loop][col] < 0x30) b_txtL[loop][col] = 0x5A; // "0" -> "Z"
else if (b_txtL[loop][col] > 0x39 && b_txtL[loop][col] < 0x41) b_txtL[loop][col] = 0x20; // "A" -> " "
lcd_write_string2((const char*)b_txtL[loop]); // Atualiza o caractere na posição do cursor
}
HAL_Delay(200);
}
}
// Then, after i call grava(); function to write the changes in the eeprom
for (int i = 0; i < 26; i++) // i is my ID
{
EEPROM_WRITE_STRING(i, b_txtL[i]);
}
// EEPROM write stirng.
void EEPROM_WRITE_STRING(uint16_t id, const char* c)
{
HAL_Delay(10); // Pode ser ajustado conforme necessário
HAL_FLASH_Unlock(); // Desbloqueia a memória FLASH para gravação
uint32_t address = ACTIVE_PAGE; // Começa no endereço da última gravação
// Verifica o comprimento da string
int str_len = strlen(c);
if (str_len > 17) str_len = 17; // Limita o comprimento a 17 caracteres (tamanho máximo da string)
// Garantir que o endereço está alinhado a 8 bytes
if (address % 8 != 0)
{
address += 8 - (address % 8); // Ajuste de alinhamento
}
// Grava a string na Flash em blocos de 8 bytes
for (int offset = 0; offset < str_len; offset += 8)
{
uint64_t data_to_write = 0;
// Preenche os próximos 8 bytes (ou menos, se a string terminar antes)
for (int i = 0; i < 8; i++)
{
if (offset + i < str_len) {
data_to_write |= ((uint64_t)c[offset + i]) << (i * 8);
}
}
// Grava os dados na memória FLASH
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data_to_write);
address += 8; // Avança para o próximo endereço
}
if (address >= (ACTIVE_PAGE + PAGE_SIZE - sizeof(EEPROM)))
{EEPROM_SWAP();}
HAL_FLASH_Lock(); // Bloqueia a memória FLASH após a gravação
}
void EEPROM_READ_STRING(uint16_t id, char* c)
{
uint32_t address = ACTIVE_PAGE + (id * sizeof(EEPROM)); // Endereço baseado no ID
uint64_t data_read = 0;
// Lê os dados da memória FLASH em blocos de 8 bytes
while (address < (ACTIVE_PAGE + PAGE_SIZE))
{
EEPROM* entry = (EEPROM*)address;
if (entry->id == id)
{
for (int offset = 0; offset < 17; offset += 16)
{
data_read = *(volatile uint64_t*)address;
// Copia os dados lidos de volta para a string
memcpy(&c[offset], &data_read, (offset + 8 <= 17) ? 8 : (17 - offset));
address += 8; // Avança para o próximo endereço
}
}
address += sizeof(EEPROM);
}
}
Solved! Go to Solution.
2024-11-12 04:23 AM
Flash needs to be erased before you can write to it.
Where does that happen in your code?
You don't check return values from the HAL_ functions - maybe they are telling you something ... ?
2024-11-11 12:40 PM
Use the Code pasting tool </> so it's readable. See Icon Bar immediately about editing window. Edit your top-post
State which model of STM32 you're talking about.
Show what is and is not happening. Perhaps but dumping the memory content to establish what exactly is going on, and what exactly is failing, or not working as you expected.
2024-11-12 04:18 AM
Thank you friend, I already made the changes
2024-11-12 04:23 AM
Flash needs to be erased before you can write to it.
Where does that happen in your code?
You don't check return values from the HAL_ functions - maybe they are telling you something ... ?
2024-11-12 05:10 AM
In the eeprom init i think
void EEPROM_INIT(void) {
uint32_t address = ACTIVE_PAGE;
uint8_t format_ = 1;
while (address < (ACTIVE_PAGE + PAGE_SIZE))
{
EEPROM* entry = (EEPROM*)address;
if (entry->id != 0xFFFF || entry->data != 0xFFFF)
{
format_ = 0;
break;
}
address += sizeof(EEPROM);
}
if (format_)
{
EEPROM_ERASE(ACTIVE_PAGE);
EEPROM_ERASE(BACKUP_PAGE);
}
}
2024-11-12 06:30 AM
Check the reference manual, but I'm pretty sure that the flash must be erased before each writing.
No "real" EEPROM on the C0 ?
2024-11-12 06:39 AM
That'd be a bit of a blow!
@jlourencao maybe take a look at how X-CUBE-EEPROM does it:
2024-11-13 12:16 AM
I was curious and just checked the website's shot description of that C0: there's no EEPROM.
So you have to use the eeprom emulation by writing to flash, what you are already doing by using the HAL_FLASH_* functions.
So, as Andrew said before, flash must be erased before each writing (unless you only want to change bits from 1 to 0 :D ).
-> check if HAL_FLASH_Program() does the erasing for you
2024-11-13 05:48 AM - edited 2024-11-13 05:49 AM
I thought that when using emulated eeprom it would not be necessary to erase it to be able to write later, I was very silly haha xD. Thank you guys.
2024-11-13 06:02 AM
Part of the job of the emulation is to get around that - again, you could see how X-CUBE-EEPROM does it...