cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G4: Dual bank Page Erase blocking interrupts from bank 2 to 1 (but not 1 to 2)

pikachu
Associate II

Hello,

We've developing an application where interruptions are a bit critical, we can't stop the IRQ for even short times, or the control gets crazy.

We update the device via MODBUS and we use the dual bank for the updates. Initially we had a problem with the ERASE of the bank during runtime, during the erase of the data section the flash the interruptions would stop for a while and we will lose control.

In order to fix that, we decided to move the data to the opposite bank of the active bank. And this actually worked a solution (BUT ONLY IN BANK 1), when we're in the first bank, everything works perfectly, but from Bank 2, the problem still persists and it's even worst now, because we're now erasing page by page instead of the full bank, so erase is slower.

Any idea on why this is only happening in Bank 2? Any way of fixing this for both banks without having to add an external flash?

We also tried to move interruptions, control, and a lot of functions to RAM, but we weren't able to fix the issue, this way.

This is the code we're using right now to erase before and update. The first lines are a workaround we've managed to implement to avoid problems with the control during an update. 

static bool bank_boot_erase(void)
{
    //Stop Converter and turn on battery relay to avoid problem with flash erase during updates
    request_update_stop();
    vTaskDelay(100);
    
    //ERASE CODE
    bool retval                  = false;
    FLASH_EraseInitTypeDef erase = { 0 };
    HAL_StatusTypeDef status     = HAL_OK;

    erase.Banks = active_bank == 1 ? FLASH_BANK_2 : FLASH_BANK_1;

    /* Erase the pages for the application only */
    erase.TypeErase = FLASH_TYPEERASE_PAGES;
    erase.NbPages =
        (FLASH_MAXIMUM_VALID_ADDRESS - BANK_BOOT_START_MAIN) / FLASH_PAGE_SIZE;
    erase.Page           = 0;
    pages_erased         = 0;
    pages_erase_expected = erase.NbPages;
    LOG_WARNING("App erase %lu %lu %lu", erase.Banks, erase.NbPages,
                erase.Page);

    // Call Erase
    operation_requested = FLASH_ERASE;
    HAL_FLASH_Unlock();
    status = HAL_FLASHEx_Erase_IT(&erase);

    if (status != HAL_OK) {
        retval = false;
        LOG_ERROR("%d", status);
        operation_requested = FLASH_NONE;
    } else {
        while (operation_requested == FLASH_ERASE) {
        }
        retval = true;
    }

    /* Erase Counter & Recovery Flags */
    FLASH_EraseInitTypeDef erase2 = { 0 };
    status                        = HAL_OK;

    erase2.Banks = active_bank == 1 ? FLASH_BANK_2 : FLASH_BANK_1;

    erase2.TypeErase = FLASH_TYPEERASE_PAGES;
    erase2.NbPages   = 1;
    erase2.Page      = (APP_COUNTER - BANK_BOOT_START_MAIN) / FLASH_PAGE_SIZE;
    pages_erased     = 0;
    pages_erase_expected = erase2.NbPages;
    LOG_WARNING("Recovery flags erase %lu %lu %lu", erase2.Banks,
                erase2.NbPages, erase2.Page);

    // Call Erase
    operation_requested = FLASH_ERASE;
    HAL_FLASH_Unlock();
    status = HAL_FLASHEx_Erase_IT(&erase2);

    if (status != HAL_OK) {
        retval = false;
        LOG_ERROR("%d", status);
        operation_requested = FLASH_NONE;
    } else {
        while (operation_requested == FLASH_ERASE) {
        }
        retval = true;
    }

    return retval;
}

This second code is used to erase a single page with some data in it, this happens every time we write this data via modbus.

static void erase_page(void)
{
    LOG_DEBUG("Erase page factory");
    uint8_t active_bank = READ_BIT(SYSCFG->MEMRMP, 0x1 <<  == 0 ? 2 : 1;
    FLASH_EraseInitTypeDef erase_init = { .TypeErase = FLASH_TYPEERASE_PAGES,
                                          .Banks     = active_bank,
                                          .Page      = 120,
                                          .NbPages   = 1 };

    uint32_t page_error = 0;
    HAL_FLASH_Unlock();
    HAL_StatusTypeDef retval = HAL_FLASHEx_Erase(&erase_init, &page_error);
    HAL_FLASH_Lock();
    if (retval != HAL_OK) {
        LOG_CRITICAL("Error erase %lu", page_error);
    }
}

I'm running out of ideas, any feedback will be appreciated.

2 REPLIES 2
KDJEM.1
ST Employee

Hello @pikachu and welcome to the community;

 

The erase/programming of other bank while code execution from concurrent bank is the main feature of the dual bank architecture. 

The architecture is symmetric, so the code executed from bank 2 should not be stopped by programming bank 1.

I think that the problem is the location of the interrupt vector table (and all the interrupt service routines).

Please make sure that the interrupt vector table (SCB->VTOR) must be also moved to Bank2 ( and all interrupt service routines). 

 

Thank you.

Kaouthar

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Ozone
Principal

> We've developing an application where interruptions are a bit critical, we can't stop the IRQ for even short times, or the control gets crazy.

> We update the device via MODBUS and we use the dual bank for the updates.

I would say, trying firmware updates while running realtime operations is a very bad idea - kind of begging for trouble.

Have a look at the datasheets, and check the worst-case times for Flash erase/program operations. Higher temperatures, which will inevitably occur during operation on customers' sites, will move you close to these limits.