Изтриването на страница на stm32 е неуспешно с FLASH_ERROR_WRP

Опитвам се да изтрия една страница във флаш на STM32F103RB така:

FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR | FLASH_FLAG_OPTERR);
FLASHStatus = FLASH_ErasePage(Page);

FLASH_ErasePage обаче не успява да генерира FLASH_ERROR_WRP

Ръчното активиране/деактивиране на защитата срещу запис в инструмента за stm32-linker не решава проблема.


person user2830438    schedule 23.10.2013    source източник


Отговори (3)


По принцип FLASH_ErasePage се проваля с WRP грешка, без да се опитва да направи нищо, ако има предишна WRP грешка в регистъра на състоянието.

Това, което идва при вашето извикване на FLASH_ClearFlag, поне FLASH_FLAG_BSY ще предизвика assert_param(IS_FLASH_CLEAR_FLAG(FLASH_FLAG)); да се провали (въпреки че не съм много сигурен какво се случва в този случай).

#define IS_FLASH_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFFFFC0FD) == 0x00000000) && ((FLAG) != 0x00000000))
person d'-'b    schedule 02.04.2014

Какъв е адресът на вашата страница? До кой адрес се опитвате да получите достъп? Например, този пример е тестван на STM32F100C8 по отношение не само на изтриване, но и на правилно записване на данни. http://www.ozturkibrahim.com/TR/eeprom-emulation-on-stm32/

person ozturkib    schedule 04.04.2014

Ако използвате HAL драйвера, вашият код може да изглежда така (изрязано и поставено от реален проект)

static HAL_StatusTypeDef Erase_Main_Program ()
{
    FLASH_EraseInitTypeDef ins;
    uint32_t sectorerror;

    ins.TypeErase = FLASH_TYPEERASE_SECTORS;
    ins.Banks = FLASH_BANK_1; /* Do not care, used for mass-erase */
#warning We currently erase from sector 2 (only keep 64KB of flash for boot))
    ins.Sector = FLASH_SECTOR_4;
    ins.NbSectors = 4;
    ins.VoltageRange = FLASH_VOLTAGE_RANGE_3; /* voltage-range defines how big blocks can be erased at the same time */
    return HAL_FLASHEx_Erase (&ins, &sectorerror);
}

Вътрешната функция в HAL драйвера, която всъщност върши работата

void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange)
{
  uint32_t tmp_psize = 0U;

  /* Check the parameters */
  assert_param(IS_FLASH_SECTOR(Sector));
  assert_param(IS_VOLTAGERANGE(VoltageRange));

  if(VoltageRange == FLASH_VOLTAGE_RANGE_1)
  {
     tmp_psize = FLASH_PSIZE_BYTE;
  }
  else if(VoltageRange == FLASH_VOLTAGE_RANGE_2)
  {
    tmp_psize = FLASH_PSIZE_HALF_WORD;
  }
  else if(VoltageRange == FLASH_VOLTAGE_RANGE_3)
  {
    tmp_psize = FLASH_PSIZE_WORD;
  }
  else
  {
    tmp_psize = FLASH_PSIZE_DOUBLE_WORD;
  }

  /* If the previous operation is completed, proceed to erase the sector */
  CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
  FLASH->CR |= tmp_psize;
  CLEAR_BIT(FLASH->CR, FLASH_CR_SNB);
  FLASH->CR |= FLASH_CR_SER | (Sector << POSITION_VAL(FLASH_CR_SNB));
  FLASH->CR |= FLASH_CR_STRT;
}

Второ нещо, което трябва да проверите. Разрешени ли са прекъсванията и има ли хардуерен достъп между повикването за отключване и повикването за изтриване?

Надявам се това да помогне

person Stian Skjelstad    schedule 14.05.2018