STM32F745 - HAL_FLASH_Программа не записывает в fla sh постоянно - PullRequest
1 голос
/ 29 апреля 2020

Я использую HAL_FLASH_Program () для программирования uuid в указанный c адрес. Я могу проверить это успешно написать, прочитав с адреса. Однако, если я включаю и снова включаю MCU, память по этому адресу возвращается к исходному значению. Если я пишу это напрямую через ST-Link, то оно остается навсегда. Кто-нибудь знает, почему это? Нужно ли стирать ячейку памяти перед записью в нее с помощью HAL_FLASH_Program ()? Я использую STM32F745.

Мой код очень прост:

#define UUID_ADDR      (0x080FFFFB)
uint16_t uuid 0x1234
HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, UUID_ADDR, uuid);

Спасибо

Ответы [ 2 ]

0 голосов
/ 05 мая 2020

Я сделал тест с Stm32F417. Я посмотрел справочное руководство для STM32F6xx. Это похоже на

Erase Fla sh Память

void eraseFlash()
{
    //  Disable prefetch memory
    __HAL_FLASH_PREFETCH_BUFFER_DISABLE();

    //  Flash 5 wait state.
    //  Check the Number of wait states according to CPU clock
    //  In my case, HCLK = 168MHz, Need FLASH_LATENCY_5
    if (FLASH_LATENCY_5 == __HAL_FLASH_GET_LATENCY())
        __HAL_FLASH_SET_LATENCY( FLASH_LATENCY_5 );

    //  Lock the memory to make sure to write the FLASH_OPT_KEYn in OPTKEYR
    HAL_FLASH_Lock();

    //  Clean all flags except FLASH_FLAG_BSY
    __HAL_FLASH_CLEAR_FLAG( FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR );

    //  Write the FLASH_OPT_KEYn in OPTKEYR to access the memory
  HAL_FLASH_Unlock();

  //    Timeout of 500ms for the operation. Check if the FLASH_FLAG_BSY.
  FLASH_WaitForLastOperation( 500 );

  //    Write the Sector.
  //    STM32F40/41 have 11 sectors. 5 sectors of 16K, 1 x 64K, 7 x 128K
  //    Each STM32 has a different memory organisation
  //    The voltage range will selection the type to erase the memory
  //    FLASH_VOLTAGE_RANGE_3 erases by WORD
  FLASH_Erase_Sector(  FLASH_SECTOR_1,  FLASH_VOLTAGE_RANGE_3);

  FLASH_WaitForLastOperation( 500 );

    HAL_FLASH_Lock();
    //  The memory is erased from that point
}

Запись данных в fla sh

uint32_t writeFlashData()
{
    __HAL_FLASH_PREFETCH_BUFFER_ENABLE();

    // Flash 5 wait state
    if (FLASH_LATENCY_5 == __HAL_FLASH_GET_LATENCY())
        __HAL_FLASH_SET_LATENCY( FLASH_LATENCY_5 );

    HAL_FLASH_Lock();
  HAL_FLASH_Unlock();

    //  Clean all flags except FLASH_FLAG_BSY
    __HAL_FLASH_CLEAR_FLAG( FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR );

  /* Wait for last operation to be completed */
  FLASH_WaitForLastOperation((uint32_t)500);
  //    To check the state of this operation, we must declare
  //    extern FLASH_ProcessTypeDef pFlash;
  if (pFlash.ErrorCode != 0)
    return pFlash.ErrorCode;
  // Make sure the address match the FLASH_SECTOR_1.
  // The Memroy Organisation gives the address of each sector of memory
  HAL_FLASH_Program( FLASH_TYPEPROGRAM_WORD, 0x8004000, 0xAC1234AC );
  HAL_FLASH_Program( FLASH_TYPEPROGRAM_WORD, 0x8004004, 0xCA1234CA );
  // The return code must be 0, otherwise, there is an error
  return pFlash.ErrorCode;
}

Fla sh можно использовать с ПРЕРЫВАНИЕ. Прерывание должно быть установлено перед стиранием или записью данных.

HAL_NVIC_SetPriority(FLASH_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(FLASH_IRQn);

Затем FLASH_CR_EOP IE должно быть установлено так

  FLASH->CR |=  FLASH_CR_EOPIE;
  HAL_FLASH_Program( FLASH_TYPEPROGRAM_WORD, 0x8004000, 0xAC1234AC );

Внутри подпрограммы прерывания должен быть установлен какой-либо флаг сброс

void FLASH_IRQHandler(void)
{
  FLASH->CR &= ~FLASH_CR_PG;
  FLASH->CR &= ~FLASH_CR_EOPIE;
  FLASH->CR |= FLASH_CR_LOCK;
  FLASH->SR = (FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR);
}
0 голосов
/ 03 мая 2020

Fla sh память требует, чтобы сектор, в который вы хотите записать, должен быть в состоянии стирания, прежде чем вы сможете записать в него.

Для этого вам нужно выполнить некоторые дополнительные шаги, прежде чем вы сможете выполнить запись persistent.

Ниже приведен пример того, как это сделать, но убедитесь, что адреса соответствуют вашей цели, вот только общий код c:

HAL_StatusTypeDef write_halfword_to_flash(uint32_t sector, uint32_t addr, void *data) {
    HAL_StatusTypeDef status = HAL_FLASH_Unlock();
    uint32_t error = 0;

    // make sure that this structure matches the datasheet of your chip
    FLASH_EraseInitTypedef FLASH_EraseInitStruct = {
        .TypeErase = FLASH_TYPEERASE_SECTORS,
        .Sector = sector,
        .NbSectors = 1,
        .VoltageRange = FLASH_VOLTAGE_RANGE_3
    };

    // clear all flags before you write it to flash
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR |
                FLASH_FLAG_WRPERR | FLASH_FLAGH_PGAERR | FLAG_PGSERR);

    if (status != HAL_OK)
        return status;

    // perform the erase first
    HAL_FLASHEx_Erase(&FLASH_EraseInitStruct, &error);

    if (error)
        return -1;

    // now that the sector is erased, we can write to it
    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, addr, data);
    if (status != HAL_OK)
        return status;

    HAL_FLASH_Unlock();

    return status;
}

...