STM32F0 WriteToFlash แล้วใช้ได้รอบเดียว

  • 3 Replies
  • 1368 Views
ผมลองหาวิธีเม็มค่าลงในชิพ stm32F072 Nucleo ไปเจอจากในเน็ตมากปรับๆดู  ผมสร้างฟังชั่นกดปุ่มให้มันเขียนค่าลงไป แล้วผมลอง กดรีเซ็ตที่บอร์ดเพื่อเริ่มการทำงานใหม่ มันก็จะสามารถอ่านค่าได้ตรงกับที่เม็มไว้ แต่ถ้าผมกดรีเซ็ตอีกรอบ มันก็ไม่สามารถอ่านค่าได้แล้ว  ต้องกดปุ่มให้เขียนค่าอีกที ถึงจะเรียกอ่านได้อีกรอบ เพิ่งเคยลองเล่นการflash ครั้งแรก ยังไม่มีประสบการณ์เท่าไหร่  ขอคำแนะนำหน่อยครับ

Quote
void WriteToFlash(uint16_t MemA1){
        //Declare and initialize variables
            
                   //Unlock Flash
        while ((FLASH->SR & FLASH_SR_BSY) != 0); //Wait until flash not busy
        if ((FLASH->CR & FLASH_CR_LOCK) != 0){    //If flash is locked, do unlk seq.
                FLASH->KEYR = FLASH_KEY1;    //Unlock code 1
                FLASH->KEYR = FLASH_KEY2;    //Unlock code 2
        }

        //Clear Flags
        FLASH->SR |= FLASH_SR_EOP;   //Clear end of operation flag
        FLASH->SR |= FLASH_SR_WRPRTERR;      //Clear write protect error flag
        FLASH->SR |= FLASH_SR_PGERR; //Clear programming error

 

        //Erase Page before writing
        FLASH->CR |= FLASH_CR_PER;           //Enable flash page erase
        FLASH->AR = FLASH_PAGE;              //Set page to erase
        FLASH->CR |= FLASH_CR_STRT;          //Start erase
            
        while ((FLASH->SR & FLASH_SR_BSY) != 0);//Wait until flash no busy
        if ((FLASH->SR & FLASH_SR_EOP) != 0){    //If flash finished operation
                FLASH->SR |= FLASH_SR_EOP;   //Clear flag
        }
        FLASH->CR &= ~FLASH_CR_PER;              //Disable page erase

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //Write to Page
        FLASH->CR |= FLASH_CR_PG;            //Write 1 to PG (programming bit)
        //*pPage = Temperature;                 //Write to flash page
         *(__IO uint16_t*)(FLASH_PAGE) = MemA1; //GET HARDFAULT HERE. CODE FROM ST
            
            
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////            
            
        while ((FLASH->SR & FLASH_SR_BSY) != 0);      //Wait until bus is not busy
        if ((FLASH->SR & FLASH_SR_EOP) != 0){          //Check if flash is completed
                FLASH->SR |= FLASH_SR_EOP;            //Clear flag is flash is complete
        }
        FLASH->CR &= ~FLASH_CR_PG;               //Clear prog bit to disable write to flash

            HAL_Delay(10);
}

ผมจะอ่านค่าด้วยฟังก์ชั่นนี้
Quote
uint16_t ReadFromFlash(uint16_t memAdd){
uint16_t InitTemp;

     
        //Read value in flash
        InitTemp = *((uint16_t *) (FLASH_PAGE));  //GET HARDFAULT HERE. CODE FROM ST

            HAL_Delay(10);
        return InitTemp;
            
}

*

Offline dec

  • **
  • 67
    • View Profile
เท่าที่ดู Sequence การโปรแกรม Flash ก็ถูกหมดนะครับ ขาดแค่ Lock Flash หลังจากเขียนเสร็จเอง ไม่รู้เกี่ยวรึเปล่า

หลังจากเขียน Flash เสร็จลอง Lock flash เหมือนเดิมด้วยดูครับ
Quote
FLASH->CR |= FLASH_CR_LOCK;

ปกติผมจะแยก Function เขียนกับลบออกจากกัน
Quote
#define FLASH_PAGE_START_ADDRESS    0x0803F800
#define FLASH_PAGE_END_ADDRESS      0x0803FFFF
#define FLASH_PAGE_SIZE             2048

uint8_t FlashErase(void)
{
  uint8_t ret = 1;
  uint32_t Address;
 
  /* Unlock the Flash to enable the flash control register access *************/
  if((FLASH->CR & FLASH_CR_LOCK) != RESET)
  {
    /* Unlocking the program memory access */
    FLASH->KEYR = FLASH_FKEY1;
    FLASH->KEYR = FLASH_FKEY2;
  }
 
  /* Erase the user Flash area ***********/

  /* Clear pending flags (if any) */ 
  FLASH->SR = (FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
 
  for(Address = FLASH_PAGE_START_ADDRESS; Address < FLASH_PAGE_END_ADDRESS; Address += FLASH_PAGE_SIZE)
  {
    /* Wait for last operation to be completed */
    while((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY);
   
    if((FLASH->SR & (uint32_t)FLASH_FLAG_WRPERR)!= (uint32_t)0x00)
    {
      /* Write protected error */
      ret = 0;
      break;
    }
   
    if((FLASH->SR & (uint32_t)(FLASH_SR_PGERR)) != (uint32_t)0x00)
    {
      /* Programming error */
      ret = 0;
      break;
    }
   
    /* If the previous operation is completed, proceed to erase the page */
    FLASH->CR |= FLASH_CR_PER;
    FLASH->AR  = Address;
    FLASH->CR |= FLASH_CR_STRT;
     
    /* Wait for last operation to be completed */
    while((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY);
   
    if((FLASH->SR & (uint32_t)FLASH_FLAG_WRPERR)!= (uint32_t)0x00)
    {
      /* Write protected error */
      ret = 0;
      break;
    }
   
    if((FLASH->SR & (uint32_t)(FLASH_SR_PGERR)) != (uint32_t)0x00)
    {
      /* Programming error */
      ret = 0;
      break;
    }
     
    /* Disable the PER Bit */
    FLASH->CR &= ~FLASH_CR_PER;
  }
 
  /* Lock the Flash to disable the flash control register access (recommended
  to protect the FLASH memory against possible unwanted operation) *********/
  /* Set the LOCK Bit to lock the FLASH control register and program memory access */
  FLASH->CR |= FLASH_CR_LOCK;
 
  return ret;
}

Quote
uint8_t FlashWrite(uint32_t Address, uint8_t *Data, uint32_t Length)
{
  uint8_t ret = 1;
  uint16_t TmpData;
 
  if(Address >= FLASH_PAGE_START_ADDRESS && Address <= FLASH_PAGE_END_ADDRESS)
  {
    /* Unlock the Flash to enable the flash control register access *************/
    if((FLASH->CR & FLASH_CR_LOCK) != RESET)
    {
      /* Unlocking the program memory access */
      FLASH->KEYR = FLASH_FKEY1;
      FLASH->KEYR = FLASH_FKEY2;
    }
   
    /* Clear pending flags (if any) */ 
    FLASH->SR = (FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR);
   
    while(Length > 0)
    {
      if(Length == 1)
      {
        TmpData = Data[0] | (0x00 << 8 );
        Data = Data + 1;
        Length = Length - 1;
      }
      else
      {
        TmpData = Data[0] | (Data[1] << 8 );
        Data = Data + 2;
        Length = Length - 2;
      }
     
      /* Wait for last operation to be completed */
      while((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY);
     
      if((FLASH->SR & (uint32_t)FLASH_FLAG_WRPERR)!= (uint32_t)0x00)
      {
        /* Write protected error */
        ret = 0;
        break;
      }
     
      if((FLASH->SR & (uint32_t)(FLASH_SR_PGERR)) != (uint32_t)0x00)
      {
        /* Programming error */
        ret = 0;
        break;
      }
     
      /* If the previous operation is completed, proceed to program the new data */
      FLASH->CR |= FLASH_CR_PG;
     
      *(__IO uint16_t*)Address = TmpData;
     
      /* Wait for last operation to be completed */
      while((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY);
     
      if((FLASH->SR & (uint32_t)FLASH_FLAG_WRPERR)!= (uint32_t)0x00)
      {
        /* Write protected error */
        ret = 0;
        break;
      }
     
      if((FLASH->SR & (uint32_t)(FLASH_SR_PGERR)) != (uint32_t)0x00)
      {
        /* Programming error */
        ret = 0;
        break;
      }
     
      /* Disable the PG Bit */
      FLASH->CR &= ~FLASH_CR_PG;
     
      /* Next address */
      Address = Address + 2;
    }
   
    /* Lock the Flash to disable the flash control register access (recommended
    to protect the FLASH memory against possible unwanted operation) *********/
    /* Set the LOCK Bit to lock the FLASH control register and program memory access */
    FLASH->CR |= FLASH_CR_LOCK;
  }
  else
    ret = 0;
 
  return ret;
}

*

Offline TaoTao

  • ***
  • 231
    • View Profile
อืม ถ้ามัน Flash สำเร็จแล้ว
อ่านหลังจากนั้น มันก็ต้องได้ค่านั้นนะ

เข้ามา งง @_@! เหมือนกัน
ผมใช้ HAL Library ที่มากับ CubeMX
โค้ดสั้นดี แต่ก็ read-write flash ได้ปกติครับ

แต่ เวลาผมอ่าน ผมใช้ pointer
ชี้ไปที่ addredd นั้นๆ เลย
และเวลา DBG ก็ดู Memory เอาอ่ะ
ไม่ก็ สร้างตัวแปร มารับ pointer ของ address นั้นๆ

ค่อยๆ วิเคราะห์ครับ เดี๋ยวก็คงหาเจอ
อ้อ ผมใช้ 32F051 กับ 32F103 อ่ะ คนละตัวกันกับ จขกท
^_^!

ลองใช้ HAL library ไหมครับ สะดวกดีนะครับ มี Reference manual มาให้ด้วยจาก st ครับ