2022-02-17 05:49 AM
Hi everyone, i`ve got trouble with InApp flash programming on STM32G474RE. While i`am trying to load some data to address higher than 0x08040000 (Bank 2) in dual bank mode by the internal bootloader (placed on address range from 0x08000000 to 0x08005000 and it takes data from external QSPI flash memory chip), the data in bank 2 is stay clear (Look at Image1).
But flash programming by internal InApp bootloader is always sucsessful (and Bank 2 too), when memory was erased before device powering up. Unfortunately application does`t allow to turn device off, so it`s necessary to find out another solution for this problem.And that is really strange, cause all pages in addr range from 0x08005000 to 0x0807FFFF have been erased previosly. Memory protection is off and no Option Bytes checked, which may affect on memory programming processes.
The programming function:
while(!ready());//waiting for BSY flag is cleared
FLASH->CR |= FLASH_CR_PG; //PG bit on
*(volatile uint32_t*)address = (uint32_t)(word1);//uploading first word
*(volatile uint32_t*)(address + 4) = (uint32_t)(word2);//uploading second word
while(!ready()); // waiting for BSY flag is cleared
FLASH->CR &= ~(FLASH_CR_PG); //Set PG bit off
Erase function follows:
void Erase(uint8_t start, uint8_t stop)
{
while (FLASH->SR & FLASH_SR_BSY);
if (stop <= 128) {
for (page_index = start; page_index < (stop); page_index++)
{
MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((page_index & 0xFFU) << FLASH_CR_PNB_Pos));
SET_BIT(FLASH->CR, FLASH_CR_PER);
SET_BIT(FLASH->CR, FLASH_CR_STRT);
while (FLASH->SR & FLASH_SR_BSY);
CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
}
}
else {
for (page_index = start; page_index < (127); page_index++)
{
MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((page_index & 0xFFU) << FLASH_CR_PNB_Pos));
SET_BIT(FLASH->CR, FLASH_CR_PER);
SET_BIT(FLASH->CR, FLASH_CR_STRT);
while (FLASH->SR & FLASH_SR_BSY);
CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
}
SET_BIT (FLASH->CR, FLASH_CR_BKER);
for (page_index = 128; page_index < (stop); page_index++)
{
MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((page_index & 0xFFU) << FLASH_CR_PNB_Pos));
SET_BIT(FLASH->CR, FLASH_CR_PER);
SET_BIT(FLASH->CR, FLASH_CR_STRT);
while (FLASH->SR & FLASH_SR_BSY);
CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
}
CLEAR_BIT (FLASH->CR, FLASH_CR_BKER);
}
}
Does anyone faced with such problem?
2022-02-17 06:28 AM
Maybe your uint8_t's are overflowing and causing issues. Would be helpful to see the full code, with calls to the given functions.
2022-02-17 06:56 AM
Thansk for your answer.
Sending the full code bellow:
#define MAIN_ADDRESS 0x08005000
void delay (unsigned long time);
void unlock (void);
void Erase_main(uint8_t start, uint8_t stop);
_Bool Program(uint32_t address, uint32_t data1,uint32_t data2);
_Bool EOP(void);
_Bool ready(void);
void teleport(uint32_t addr);
uint8_t buff[256];
uint64_t z, byte_inc;
uint8_t key[0x100], loh;
uint32_t page_index;
unsigned long addr =0x100000, flash_addr = MAIN_ADDRESS, heh, it;
uint32_t word1,word2;
int main(void)
{
SCB->VTOR = 0x08000000;
SystemInit();
QuadSpi1Init();
if (TIM2->ARR == 162) { // That is a reference point from main program, which telling us about necessary of software updating
PWR->CR1 = 1<<PWR_CR1_VOS_Pos;
unlock();
FLASH->SR |= FLASH_SR_EOP | FLASH_SR_PGAERR | FLASH_SR_WRPERR|FLASH_SR_OPTVERR;
Erase_main(10, 255);
while (1) {
delay (10);
QSPI_read_page (1, addr, &buff[0], 0x100);
addr+= 0x100;
byte_inc = 0;
word1 = 0;
word2 = 0;
if (it > 0) {
if ((buff[0] == 0xFF) && (buff[2] == 0xFF) && (buff[3] == 0xFF) && (buff[8] == 0xFF) && (buff[43] == 0xFF) && (buff[45] == 0xFF) && (buff[112] == 0xFF)) {
break;
}
while (byte_inc < 0x100) {
word1 = buff[byte_inc]|buff[byte_inc + 1]<<8|buff[byte_inc + 2]<<16|buff[byte_inc + 3]<<24;
word2 = buff[byte_inc+4]|buff[byte_inc + 5]<<8|buff[byte_inc + 6]<<16|buff[byte_inc + 7]<<24;
Program (flash_addr,word1,word2);
flash_addr +=8;
byte_inc += 8;
}
}
it = it + 1;
}
TIM2->ARR = 66; // This point tells main program that software has been updated
teleport(MAIN_ADDRESS);
}
else {
teleport(MAIN_ADDRESS);
}
}
void teleport(uint32_t addr)
{
uint32_t jump;
typedef void(*pFunction)(void);
pFunction Jump;
__disable_irq();
jump = *( uint32_t*) (addr + 4);
Jump = (pFunction)jump;
__set_MSP(*(__IO uint32_t*) addr);
Jump();
}
void unlock (void) {
FLASH->KEYR = 0x45670123;
FLASH->KEYR = 0xCDEF89AB;
}
_Bool ready(void)
{
return !(FLASH->SR & FLASH_SR_BSY);
}
_Bool EOP(void)
{
if(FLASH->SR & FLASH_SR_EOP)
{
FLASH->SR |= FLASH_SR_EOP;
return 1;
}
return 0;
}
void Erase_main(uint8_t start, uint8_t stop)
{
while (FLASH->SR & FLASH_SR_BSY);
if (stop <= 128) {
for (page_index = start; page_index < (stop); page_index++)
{
MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((page_index & 0xFFU) << FLASH_CR_PNB_Pos));
SET_BIT(FLASH->CR, FLASH_CR_PER);
SET_BIT(FLASH->CR, FLASH_CR_STRT);
while (FLASH->SR & FLASH_SR_BSY);
CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
}
}
else {
for (page_index = start; page_index < (127); page_index++)
{
MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((page_index & 0xFFU) << FLASH_CR_PNB_Pos));
SET_BIT(FLASH->CR, FLASH_CR_PER);
SET_BIT(FLASH->CR, FLASH_CR_STRT);
while (FLASH->SR & FLASH_SR_BSY);
CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
}
SET_BIT (FLASH->CR, FLASH_CR_BKER);
for (page_index = 128; page_index < (stop); page_index++)
{
MODIFY_REG(FLASH->CR, FLASH_CR_PNB, ((page_index & 0xFFU) << FLASH_CR_PNB_Pos));
SET_BIT(FLASH->CR, FLASH_CR_PER);
SET_BIT(FLASH->CR, FLASH_CR_STRT);
while (FLASH->SR & FLASH_SR_BSY);
CLEAR_BIT(FLASH->CR, (FLASH_CR_PER | FLASH_CR_PNB));
}
CLEAR_BIT (FLASH->CR, FLASH_CR_BKER);
}
}
_Bool Program(uint32_t address, uint32_t data1,uint32_t data2)
{
while(!ready());
FLASH->CR |= FLASH_CR_PG;
*(volatile uint32_t*)address = (uint32_t)data1;
*(volatile uint32_t*)(address + 4U) = (uint32_t)(data2);
while(!ready());
FLASH->CR &= ~(FLASH_CR_PG);
if(!EOP())return 0;
return EOP();
}
void delay (unsigned long time) {
for (heh = 0; heh <= time*170; heh ++) {
__NOP();
}
}