This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RM48L952: Unable to write to flash sectors 0 through 4 on flash bank 0

Part Number: RM48L952
Other Parts Discussed in Thread: SEGGER

Hello,

I am attempting to create an application that alters a bootloader, which is stored in flash sectors 0 through 4 of flash bank 0 (address starts at 0x00000000).
I am currently unable to consistently write bytes to flash sectors 0 through 4 in flash bank 0 of the RM48L952 chip.
I have made test code that writes to sectors 5,6, and 7 with no issues, but while writing to sectors 0 through 4 I my program hangs up intermittently, especially at the start of sector 4.
Currently, this code will just clear sector 0 but not write anything. When I added the xTaskDelay(1) at the end of my while loop (delays the thread for 1 ms) things started writing in sectors 0 through 3 but would still hang up at the beginning of sector 4.
Also I occasionally get an Fapi_status of 0x10, which doesn't make sense since there isn't a corresponding value in the status enum.
I know that there are several annoying infinite for loops, but I keep break points in them while I debug and they are only cause hang ups when Fapi_status is 0x10. I think I am causing an error in Fapi_issueProgrammingCommand, but I am not sure what.
Is there anything special about sectors 0 through 4?
I was told I may have an issue with improperly embedded code, so a TI helpdesk person will be appending my snippet to this post.
  • Code from Matt:

    while (bytes_left > 0) {

     

                    if (isSectorStart((uint32_t) flash_address))

                    {

     

                        taskENTER_CRITICAL();

                        // make sure the FSM isn't busy before issuing erase command.

                        while (FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy);

     

                        //Data at start of a bank1 erase it first

                        Fapi_status = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (uint32_t *) flash_address);

                        while (FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy);

                        Fapi_status = (Fapi_StatusType) FAPI_GET_FSM_STATUS;

                        if (Fapi_status != Fapi_Status_Success) {

                            //HealthMonitor::SetFault(FLASH_PROGRAMMING_FAILURE);

                            BootMonitor::set_download_state(FLASH_FAILURE);

                            for (;;);

                        }

                        taskEXIT_CRITICAL();

                    }

     

                    /* If you want to use Fapi_AutoEccGeneration option, the data size to be programmed has to be

                     * either 8 or 16 bytes because ECC is calculated on 64bit (8 bytes) basis. */

                    uint32_t write_bytes = (bytes_left > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE : bytes_left);

     

                    taskENTER_CRITICAL();

     

                    Fapi_status = Fapi_issueProgrammingCommand((uint32_t *) flash_address,

                            source_ptr,

                            write_bytes,

                            0,

                            0,

                            Fapi_AutoEccGeneration);

                    flashLoader.num_bytes_written += write_bytes;

     

                    while (FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmBusy);

                    Fapi_status = (Fapi_StatusType) FAPI_GET_FSM_STATUS;

     

                    if (Fapi_status != Fapi_Status_Success) {

                        //HealthMonitor::SetFault(FLASH_PROGRAMMING_FAILURE);

                        BootMonitor::set_download_state(FLASH_FAILURE);

                        for (;;);

                    }

     

                    taskEXIT_CRITICAL();

     

                    bytes_left -= FLASH_PAGE_SIZE;

                    flash_address += FLASH_PAGE_SIZE;

                    source_ptr += FLASH_PAGE_SIZE;

                    

                    if(bytes_left <= (byte_printout_count - (16 * 1024)))

                    {

                      _DEBUG.Syslog(LOG_INFO, "Flashed %d bytes at address %d. %d bytes left", write_bytes, flash_address, bytes_left);

                      xTaskDelay(10);

                      byte_printout_count = bytes_left;

                    }       

                    //xTaskDelay(1);

     

                }

     

     

    bool FlashLoader::isSectorStart(uint32_t address)

    {

      uint32_t sec_size = 0x020000;

      uint32_t small_sec_size = 0x08000;

     

      if(address > 0x0001FFFF)

      {

          if(address % sec_size == 0)

          {

            return true;

          }

      }

      else

      {

          if(address % small_sec_size == 0)

          {

            return true;

          }

      }

     

      return false;

    }


    Thanks,

    Gabe Garza

    TI Support

  • Hello,

    Where is your code which performs the flash operation (erase/program)? If the code (text) is located in sector0~4, you can not erase this area.
  • Hello,

    The code I am executing is out of Bank 1, so I don't think there is a conflict.

    I have attached an image from my map file to show you the location of the Fapi code.

  • I played with Fapi a little more and I am able to erase every relevant sector where the bootloader exists (I have verified this with Segger JFlash). It seems that the act of writing the first line of bytes causes the issue.
  • Hello Matthew,

    The interrupt vector is located at from 0x00 to 0x20. If the sector 0 is erased, any exception (data abort, prefetch, etc) will cause problem. Did you try to erase sector 4 only, and leave content of the sector 0 there? I never tried to update the bootloader from the application.
  • I have just attempted to write data starting at sector 4 (address 0x20000). I was able to erase the sector, but not program it. The program just began executing something from the bootloader and hung up since it was partially erased. I have break points at the sections of code that handle aborts, so to my knowledge no exceptions occurred.

    Immediately after this I attempted the same test starting at sector 5 (address 0x40000) and had no issues. All information was flashed correctly.

    I am not sure what could be different about these addresses.
  • I thought that only the application code in bank1 is executed, and only code in bank0 used is the interrupt vector (0x0~0x20). If the code in bank0 is running, it will cause problem when you try to erase this area.

    Do you configure the MPU to protect sectors of flash from erasing?
  • There are occasions in my code where a failure condition will cause the board to reboot and enter the bootloader code (which is being overwritten). If a hang up persists for too long the board reboots. Basically by the time my program starts executing out of Bank0 something has gone horribly wrong and the board has reset.

    So, in normal conditions this code (the bootloader) will not execute from Bank0 until everything has been flashed successfully and the board is power cycled.

    I'm sorry that this is vague, I am working on a legacy project with fairly little background knowledge.
  • Hello Again,

    I have spoken with some of my co-workers and reviewed your answers as well as other users' post. I believe my issue is that I have not disabled interrupts.

    Could this be a possible source of my problems (it seems that way since I am erasing 0x00 to 0x20)?

    I have looked through some documentation, but I am not sure how to disable interrupts? Can you show me an example or relevant document to help with this?

    Thanks,

    Matt

  • Hello Matt,

    You can disable IRQ and FIQ by setting I bit and F bit of CPSR register. The two functions in sys_core,asm can be used to disable IRQ and FIQ.

    ;-------------------------------------------------------------------------------
    ; Disable FIQ interrupt
    .def _disable_FIQ_interrupt_
    .asmfunc
    _disable_FIQ_interrupt_
    cpsid f
    bx lr
    .endasmfunc

    ;-------------------------------------------------------------------------------
    ; Disable FIQ interrupt
    .def _disable_IRQ_interrupt_
    .asmfunc
    _disable_IRQ_interrupt_
    cpsid i
    bx lr
    .endasmfunc

    Other exceptions (undef, prefetch, data abort) can not be disabled.

  • At this point I am using your example code from bl_flash.c with no modifications, so I am pretty confident the flash code is fine (it still works at other addresses that don't include my bootloader).

    I have attempted to disable interrupts, but have run into a roadblock

    I noticed that despite calling _disable_FIQ_interrupt_ the associated bit in CPSR was not changing. I did some digging and it looks like it cannot be changed from software due to the NMFI bit being set in the SCTLR register. It appears that this bit is set via hardware and cannot be changed simply via code.

    Do you know of any other way to disable Fast Interrupts? Do timer interrupts count as fast interrupts?

    Also, I put break points in the exception vector to see what type of exceptions I was getting (this is after they were erased, so it would continually fail here).

    It was stopping at 0x0C, which is the prefetch abort address. I attempted to disable aborts just to see what happens, but I also cannot change the abort bit in CPSR just like the FIQ bit.

    Is it possible disabling aborts will work? How should I go about that?

  • Hello Matthew,

    There is a fault address register, called prefetch aborts (IFAR). This indicate the address of the memory access that caused the fault. The IFAR register is listed in registers view window.

    When NMFI is set in system control register, the FIQ can not be masked by software.