zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.44k stars 6.4k forks source link

mcuboot not upgrade for stm32l1 series #39423

Closed LQchengdu closed 2 years ago

LQchengdu commented 2 years ago

Describe the bug

To Reproduce Steps to reproduce the behavior:

  1. Program bootloader and first slot to borad stm32l151
  2. Program the second slot
  3. Reboot,but bootloader can not find second slot

Expected behavior

  1. Copy the second slot to first slot.
  2. Upgrade normally

Impact Can't upgrade by bootloader

Logs and console output

I: Starting bootloader
I: Swap type: none
I: Bootloader chainload address offset: 0xa000
I: Jumping to the first image slot

Environment (please complete the following information):

Additional context I debugged mcuboot code. In function bootutil_buffer_is_erased on file bootutil_public.c

bool bootutil_buffer_is_erased(const struct flash_area *area,
                               const void *buffer, size_t len)
{
    size_t i;
    uint8_t *u8b;
    uint8_t erased_val;

    if (buffer == NULL || len == 0) {
        return false;
    }

    erased_val = flash_area_erased_val(area);
    for (i = 0, u8b = (uint8_t *)buffer; i < len; i++) {
        if (u8b[i] != erased_val) {
            return false;
        }
    }

    return true;
}

The value returned by flash_area_erased_val is 0 but actually is 0xff. then I step in flash_area_erased_val on file flash_stm32.c

static const struct flash_parameters flash_stm32_parameters = {
    .write_block_size = FLASH_STM32_WRITE_BLOCK_SIZE,
    /* Some SoCs (L0/L1) use an EEPROM under the hood. Distinguish
     * between them based on the presence of the PECR register. */
#if defined(FLASH_PECR_ERASE)
    .erase_value = 0x0,
#else
    .erase_value = 0xff,
#endif
};

If defined FLASH_PECR_ERASE macro, the erase_value will always zero. That is correct for EEROM, not for FLASH. EEROM and FLASH exist at the same time on stm32l151. I comment the zero value, then the problem solved. So I wonder there is another smart way to fix it?

erwango commented 2 years ago

Can you provide the exact reference of the chip you're using ?

FYI, this was discussed here and here. And thanks to https://github.com/zephyrproject-rtos/zephyr/pull/25947, there should be a way to sort this out. We just need to understand the exact chip memory techno/mapping.

erwango commented 2 years ago

Can you provide the exact reference of the chip you're using ?

LQchengdu commented 2 years ago

stm32l151cba

erwango commented 2 years ago

@LQchengdu According to RM manual, as implemented erase value is 0x00, even on the flash (program memory). cf RM0038.pdf (Unfortunately, there is no explicitly information about this)

**3.4.2 Erasing memory**
[...]
*Program memory page erase*
This operation is used to erase a page in program memory (64 words). To do so:
[...]
• Write 0x0000 0000 to the first word of the program page to erase
[...]

I've been able to verify this on a nucleo_l152re, using STM32CubeProgrammer: Perform a full chip erase, then read flash memory, erased bytes are 0x00. In Zephyr, same behavior could be observed using samples/drivers/flash_shell. If you confirm that the changing erase_value from 0x00 to 0xFF, then I'd suspect that this confusion is coming from another component of the chain. In call to bootutil_buffer_is_erased, can you check where buffer is coming from ?

LQchengdu commented 2 years ago

@erwango After I testing, the erased value is indeed 0,This issue should be caused by other reasons.

LQchengdu commented 2 years ago

@erwango When using imgtool.py in mcuboot, I did not use the option --erased-val to set the erased value, and its default value is 0xff, which is wrong for the L0/L1 series.

  -R, --erased-val [0|0xff]       The value that is read back from erased
                                  flash.

thank you very much for your help.

erwango commented 2 years ago

When using imgtool.py in mcuboot, I did not use the option --erased-val to set the erased value, and its default value is 0xff, which is wrong for the L0/L1 series.

Ok, great I wasn't aware of this option, but this explains the issue you were seeing. Thanks for the heads up. I'm closing this issue for now, don't hesitate to re open or open a new one if needed.