cembeddedstm32

stm32l072kz - write firmware in flash bank2 and jump to bank2


I am writing a new firmware received by UART. I use DMA with Interrupt and my new firmware is in .HEX format, I receive it in blocks of 1500 in 1500 bytes, and I have a case that performs the processing of extracting the addresses, crc, cheksum, and the real data and after that calls the businessRules_update_firmware function. I want to write the firmware using the application code itself. However, I have a problem writing after 0x08018000. My microcontroller is category 5, with 192KB and dual-bank. And my application code is running on bank1 and I want to write the new firmware on bank2. I always record correctly from 0x08018000 to 0x080180F0, but I can never record after 0x08018100, what could this be?

The businessRules_updateFirmware function is called within a loop after the data from the .HEX file has been processed.

uint32_t flashAddress = 0x08018000;

void businessRules_updateFirmware(void)
{
  uint8_t buffer[FIRMWARE_PACKAGE_SIZE];
  uint32_t pageError;

  if (protocol_feedFirmwareBuffer(buffer))
  {
    HAL_FLASH_Unlock();
    HAL_FLASH_OB_Unlock();

    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_BSY);
    FLASH_EraseInitTypeDef eraseInitStruct;
    eraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
    eraseInitStruct.PageAddress = flashAddress;
    eraseInitStruct.NbPages = 1;

    if (HAL_FLASHEx_Erase(&eraseInitStruct, &pageError) != HAL_OK)
    {
      HAL_FLASH_Lock();
      HAL_FLASH_OB_Lock();
      return;
    }

    uint8_t binaryData[FIRMWARE_PACKAGE_SIZE / 2];

    hexStringToBytes((const char*)buffer, binaryData, FIRMWARE_PACKAGE_SIZE);

    for (uint32_t i = 0; i < FIRMWARE_PACKAGE_SIZE / 2; i += 4)
    {
      uint32_t data = *(uint32_t*)&binaryData[i];

      if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, flashAddress , data) != HAL_OK)
      {
        HAL_FLASH_Lock();
        HAL_FLASH_OB_Lock();
        return;
      }

      flashAddress += 4;
    }

    HAL_FLASH_Lock();
    HAL_FLASH_OB_Lock();
  }
}


uint8_t hexCharToValue(char hexChar)
{
  if (isdigit(hexChar))
    return hexChar - '0';
  else
    return tolower(hexChar) - 'a' + 10;
}

void hexStringToBytes(const char *hexString, uint8_t *byteArray, size_t byteArraySize)
{
  for (size_t i = 0; i < byteArraySize / 2; ++i)
  {
    if (2 * i + 1 >= strlen(hexString))
    {
      byteArray[i] = 0x00;
      break;
    }

    byteArray[i] = (hexCharToValue(hexString[2 * i]) << 4) | hexCharToValue(hexString[2 * i + 1]);
  }
}

I tried some variations of this function, but without success so far.

void businessRules_updateFirmware(void)
{

    uint32_t pageAddress;
    uint32_t pageError;
    uint8_t buffer[FIRMWARE_PACKAGE_SIZE];

    bool dataIsReady = false;
    dataIsReady = protocol_feedFirmwareBuffer(buffer);

    if (dataIsReady)
    {
        uint8_t binaryData[FIRMWARE_PACKAGE_SIZE / 2];
        hexStringToBytes((char *)buffer, binaryData, FIRMWARE_PACKAGE_SIZE / 2);

        pageAddress = protocol_getAddressToFirmware();

        HAL_FLASH_Unlock();
        HAL_FLASH_OB_Unlock();


        FLASH_EraseInitTypeDef eraseInitStruct;
        eraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
        eraseInitStruct.PageAddress = pageAddress;
        eraseInitStruct.NbPages = 1;

        if(HAL_FLASHEx_Erase(&eraseInitStruct, &pageError) != HAL_OK){
            HAL_FLASH_Lock();
            HAL_FLASH_OB_Lock();
            return;
        }

        for(uint32_t i = 0; i < FIRMWARE_PACKAGE_SIZE / 2; i += 4){

            uint32_t data = (binaryData[i] << 0) | (binaryData[i + 1] << 8) | (binaryData[i + 2] << 16) | (binaryData[i + 3] << 24);

            if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, pageAddress + i , data) != HAL_OK){
                HAL_FLASH_Lock();
                HAL_FLASH_OB_Lock();
                return;
            }

        }

        pageAddress += FIRMWARE_PACKAGE_SIZE / 2;
        protocol_setAddressToFirmware(pageAddress);

        HAL_FLASH_OB_Lock();
        HAL_FLASH_Lock();
    }

}

uint8_t hexCharToValue(char hexChar) {
    if (isdigit(hexChar))
        return hexChar - '0';
    else
        return tolower(hexChar) - 'a' + 10;
}

void hexStringToBytes(const char *hexString, uint8_t *byteArray, size_t byteArraySize) {
    for (size_t i = 0; i < byteArraySize; ++i) {
        byteArray[i] = (hexCharToValue(hexString[2 * i]) << 4) | hexCharToValue(hexString[2 * i + 1]);
    }
}

Solution

  • I solved the problem, as I was using DMA, I was having a problem with my circular buffer that was filling up and was unable to process the rest of the data received. Then I adjusted the pointer and counter and also the HAL_UARTEx_RxEventCallback function