ASF 4 Flashdriver Callback causes infinite loop

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am using the ASF 4 EFC driver routines to write to internal flash on a SAMv71.  I registered a callback so that I can tell when the Flash is ready to accept a new command. Before a flash_write I set m_bReady to false (busy). The callback routine sets m_bReady to true.

 

The problem is that as soon as I do a flash_register_callback(),  the flash FRDY bit is already set (since the flash is ready) and this generates an immediate interrupt.  EFC_Handler() (in hap_efc.c) then calls the callback.  Once the callback is executed, the FRDY bit is still true, so it keeps calling the callback routine continuously and the program is hung.

 

Am I doing this wrong or is this just an ASF driver bug?

 

void flash_callback(struct flash_descriptor *const descr);

bool     m_bReady;

InternalFlashDriver::InternalFlashDriver()
{
    m_ui32PageSize = flash_get_page_size(&FLASH_0);
    flash_register_callback(&FLASH_0, FLASH_CB_READY, flash_callback);
    m_bReady = true;
}


void InternalFlashDriver::flash_callback(struct flash_descriptor *const descr)
{
   m_bReady = true;
}

bool InternalFlashDriver::WritePage(uint8_t * pData, uint32_t ui32Address)
{
    bool bFlag = false;

    if (m_bReady == true)
    {
        m_bReady = false;                                       // Set flash busy
        if (flash_write(&FLASH_0, ui32Address, pData, m_ui32PageSize) != ERR_NONE)
        {
            bFlag = true;                                       // Error
        }
    }
    else
    {
        bFlag = true;                                           // Flash not ready
    }

    return(bFlag);
}

----------------------------

In hpl_efc.c

void EFC_Handler(void)
{
	void *const hw = _efc_dev->hw;

	if (hri_efc_get_EEFC_FSR_FRDY_bit(hw)) {
		if (NULL != _efc_dev->flash_cb.ready_cb) {
			_efc_dev->flash_cb.ready_cb(_efc_dev);
		}
	}
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@awneil:

 

Thanks for your reply.  You are correct that I forgot to put the volatile qualifier on the m_bReady flag when I posted the example code. However, that change does not fix the problem.

 

The problem is that the  FRDY bit in the ECF Status Register stays set as long as the EFC is ready, which it normally is.  It does not reset when the register is read. So when  the EFC_Handler calls the flash_callback routine, that bit stays set.  When the callback is done, the FRDY bit is still set. That will cause an immediate interrupt, which will again call the flash_callback routine.

 

The FRDY bit only goes low while the EFC is busy writing to flash. So it seems that the way to make this work would be for the EFC Handler to keep track of low to high transitions of FRDY and then call the callback routine.  The way the ASF code is written, I don't see how it can work.