Skip to main content
Associate II
November 11, 2024
Solved

Problem writing string to emulated Eeprom

  • November 11, 2024
  • 7 replies
  • 2903 views

Can anyone explain to me what is wrong in my code?

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);
 }

}



 

 



Best answer by Andrew Neil

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 ... ?

7 replies

Tesla DeLorean
Guru
November 11, 2024

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.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Associate II
November 12, 2024

Thank you friend, I already made the changes

Andrew Neil
Andrew NeilBest answer
Super User
November 12, 2024

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 ... ?

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
Associate II
November 12, 2024

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);
 }
}

 

LCE
Principal II
November 12, 2024

Check the reference manual, but I'm pretty sure that the flash must be erased before each writing.

No "real" EEPROM on the C0 ?

 

Andrew Neil
Super User
November 12, 2024

That'd be a bit of a blow!

@jlourencao maybe take a look at how X-CUBE-EEPROM does it:

https://www.st.com/en/embedded-software/x-cube-eeprom.html

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
LCE
Principal II
November 13, 2024

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

Associate II
November 13, 2024

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.

Andrew Neil
Super User
November 13, 2024

Part of the job of the emulation is to get around that - again, you could see how X-CUBE-EEPROM does it...

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
LCE
Principal II
November 13, 2024

It was actually @Andrew Neil who said first that flash must be erased before writing, so maybe mark his answer as solution.

Although I guess "in the end it doesn't really matter", as who sang? ;)

Associate III
November 16, 2024

hello iam using srm32f429i-disc1 microcontroller and i want refrence code for emulated eeprom 

Andrew Neil
Super User
November 16, 2024

@syedhashmiraza you already have your own thread on this:

https://community.st.com/t5/stm32-mcus-products/use-stm32f4-flash-for-non-volatile-data-storage-eeprom/td-p/743291

This thread is about a different, much newer chip - not relevant to yours.

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.