In-Application Programming Erase Sector Works Initially But Fails After Reboot (LPC1313)

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

In-Application Programming Erase Sector Works Initially But Fails After Reboot (LPC1313)

1,077 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mroe on Mon Aug 04 18:31:10 MST 2014
Hello,

I am trying to use IAP to store a variable in NV Flash RAM that will retain its state after reboot.
I am using my own linker script and storing the variable at location 0x6000 far away from anything else.
This the memory is being properly written to when I initially debug the application, but not after reboot.  After rebooting, the code crashes when I try to erase the iap sector before writing to it.

Here is the relevant portion of my iap code:
int iap_erase_sector(unsigned int sector_start, unsigned int sector_end)
{
    unsigned int command[5];
    unsigned int result[4];

    command[0] = ERASE_SECTOR; // 52
    command[1] = (unsigned int)sector_start;
    command[2] = (unsigned int)sector_end;
    command[3] = SystemCoreClock / 1000;
    iap_entry(command, result);

    return result[0];
}

int iap_prepare_sector(unsigned int sector_start, unsigned int sector_end)
{
    unsigned int command[5];
    unsigned int result[4];

    command[0] = PREPARE_SECTOR; // 50
    command[1] = (unsigned int) sector_start;
    command[2] = (unsigned int) sector_end;
    iap_entry(command, result);

    return result[0];
}

int iap_copy_ram_to_flash(void* ram_address, void* flash_address, unsigned int count)
{
    unsigned int command[5];
    unsigned int result[4];

    command[0] = COPY_RAM_TO_FLASH; // 51
    command[1] = (unsigned int)flash_address;
    command[2] = (unsigned int)ram_address;
    command[3] = count;
    command[4] = SystemCoreClock / 1000;
    iap_entry(command, result);

    return result[0];
}

int iap_write(void *ram_address, void *flash_address, unsigned int count, unsigned int sector, unsigned int sector_size)
{
   int iap_status = 0; // CMD_SUCCESS

    SystemCoreClockUpdate();

    iap_status = iap_prepare_sector(sector, sector_size);
    if (iap_status != 0) return iap_status;

    // after reboot, this crashes when I try to erase the sector
    iap_status = iap_erase_sector(sector, sector_size);
    if (iap_status != 0) return iap_status;

    iap_status = iap_prepare_sector(sector, sector_size);
    if (iap_status != 0) return iap_status;

    iap_status = iap_copy_ram_to_flash(ram_address, flash_address, count);
    if (iap_status != 0) return iap_status;

    return iap_status;
}

Here is the relevant section of my linker script:
    .var (0x6000) :
    {
        KEEP(*(.var*))
    } > MFlash32

Here is the relevant section of my calling code:

__CRP const unsigned int CRP_WORD = CRP_NO_CRP;

static unsigned char var_temp[] = {0, 1, 1, 1, 1, 1, 1, 1, 1};

__attribute__ ((section(".var"))) unsigned char var[256];

int main()
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 16);

if (var[0] == 0)
{
                // after reboot, this crashes when I try to erase the sector
                // iap_write(ram_address, flash_address, count, sector, sector_size)
iap_write(&var_temp, (void *)0x6000, 256, 6, 7);
}

while (1)
{
}

return 0;
}

Thanks in advance for your help.
标签 (1)
0 项奖励
12 回复数

939 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mroe on Tue Aug 12 14:33:36 MST 2014
Now my ADC is returning incorrect values after an iap erase sector and reboot - the exact same issue as with the uart.

(1) Does anybody know why I had to call SystemCoreClockUpdate() and re-init the uart module after an iap_write?
(2) Why would an iap erase affect the ADC as well? 
(3) Does an iap erase sector change the peripheral clock when the system reboots?
0 项奖励

939 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mroe on Thu Aug 07 15:25:56 MST 2014
Yeah I am using the sample UART. 
I've got this working now by updating the system clock before and after UARTInit, which I now re-call after every iap write. 

I guess that erasing the sector was modifying the system clock and throwing off the uart timing?

iap_write(...);
SystemCoreClockUpdate();
UARTInit(...);
SystemCoreClockUpdate();
0 项奖励

939 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LabRat on Thu Aug 07 14:49:33 MST 2014
I'm not sure which ISR we are talking about...

Are you using a sample ISR?

Something like:

/*****************************************************************************
** Function name:UART_IRQHandler
**
** Descriptions:UART interrupt handler
**
** parameters:None
** Returned value:None
** 
*****************************************************************************/
void UART_IRQHandler(void)
{
  uint8_t IIRValue, LSRValue;
  uint8_t Dummy = Dummy;

  IIRValue = LPC_UART->IIR;
    
  IIRValue >>= 1;/* skip pending bit in IIR */
  IIRValue &= 0x07;/* check bit 1~3, interrupt identification */
  if (IIRValue == IIR_RLS)/* Receive Line Status */
  {
    LSRValue = LPC_UART->LSR;
    /* Receive Line Status */
    if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI))
    {
      /* There are errors or break interrupt */
      /* Read LSR will clear the interrupt */
      UARTStatus = LSRValue;
      Dummy = LPC_UART->RBR;/* Dummy read on RX to clear 
interrupt, then bail out */
      return;
    }
    if (LSRValue & LSR_RDR)/* Receive Data Ready */
    {
      /* If no error on RLS, normal ready, save into the data buffer. */
      /* Note: read RBR will clear the interrupt */
      UARTBuffer[UARTCount++] = LPC_UART->RBR;
      if (UARTCount == BUFSIZE)
      {
        UARTCount = 0;/* buffer overflow */
      }
    }
  }
  else if (IIRValue == IIR_RDA)/* Receive Data Available */
  {
    /* Receive Data Available */
    UARTBuffer[UARTCount++] = LPC_UART->RBR;
    if (UARTCount == BUFSIZE)
    {
      UARTCount = 0;/* buffer overflow */
    }
  }
  else if (IIRValue == IIR_CTI)/* Character timeout indicator */
  {
    /* Character Time-out indicator */
    UARTStatus |= 0x100;/* Bit 9 as the CTI error */
  }
  else if (IIRValue == IIR_THRE)/* THRE, transmit holding register empty */
  {
    /* THRE interrupt */
    LSRValue = LPC_UART->LSR;/* Check status in the LSR to see if
valid data in U0THR or not */
    if (LSRValue & LSR_THRE)
    {
      UARTTxEmpty = 1;
    }
    else
    {
      UARTTxEmpty = 0;
    }
  }
  return;
}
0 项奖励

939 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mroe on Thu Aug 07 14:21:32 MST 2014
Yeah, tried the global disable and re-enable interrupt but to no avail.
I even took the interrupt handler out of my code completely, and instead I just poll the line status register.

// this condition is never evaluates to true after reboot if i've erased the sector when first debugging the application
// however, this condition does fire if I haven't erased the sector when first debugging
if (LPC_UART->LSR & 0x01)
{
// read from uart FIFO
}
0 项奖励

939 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LabRat on Thu Aug 07 13:53:13 MST 2014

Quote: mroe
Can anyone recommend how to properly disable and re-enable my interrupt?

Here is what I am currently doing:

  NVIC_DisableIRQ(UART_IRQn);
iap_write(&var_temp, (void *)0x6000, 256, 6, 7);
  NVIC_EnableIRQ(UART_IRQn);



Would suggest to use:

 __disable_irq();
...iap_
 __enable_irq();
0 项奖励

939 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mroe on Thu Aug 07 11:53:50 MST 2014
Hi LabRat,

Thanks for your suggestion.  I have moved the stack offset to reserve space for the IAP command set using my linker script.

MEMORY
{
  /* Define each memory region */
  MFlash32 (rx) : ORIGIN = 0x0, LENGTH = 0x8000 /* 32k */
  RamLoc8 (rwx) : ORIGIN = 0x10000000, LENGTH = 0x2000 /* 8k */
}
  /* Define a symbol for the top of each memory region */
  __top_MFlash32 = 0x0 + 0x8000;
  __top_RamLoc8 = 0x10000000 + 0x2000;

_vRamTop = __top_RamLoc8 ;
_vStackTop = _vRamTop - 32; /* offset 32 for iap command set */

It seems to be an issue with the UART line status not firing (i.e. LPC_UART->LSR is never getting set.)
I've taken out the UART interrupt and instead I just poll the line status (I know - not the best asynchronous design, but for debugging...), but it is not getting setting when I send a UART command after reboot.
As before, the UART commands go through after reboot when I comment out the erase sector portion of the iap write.



0 项奖励

939 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by LabRat on Wed Aug 06 23:42:07 MST 2014
RAM problems?

http://www.lpcware.com/content/faq/lpcxpresso/reserving-ram-iap
0 项奖励

939 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mroe on Wed Aug 06 21:42:01 MST 2014
This may be an issue with my UART interrupt handler.  I've tried disabling and re-enabling before and after writing to flash, but to no avail.  Can anyone recommend how to properly disable and re-enable my interrupt?

Here is what I am currently doing:

  NVIC_DisableIRQ(UART_IRQn);
iap_write(&var_temp, (void *)0x6000, 256, 6, 7);
  NVIC_EnableIRQ(UART_IRQn);


0 项奖励

939 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mroe on Wed Aug 06 17:25:09 MST 2014
Any ideas as to why this would only work when I first debug, and not after I reboot and stop debugging?
Is there any more relevant information I can provide?
0 项奖励

939 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mroe on Tue Aug 05 09:31:44 MST 2014
The program goes into an unexpected state after reboot if I erase the sector.
I try communicating with the MCU over UART after reboot, but this fails.
I am able to communicate with the MCU over UART after reboot if I comment out the erase sector function in the iap write command.

Please let me know what other information I can provide.

0 项奖励

939 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mroe on Tue Aug 05 09:25:56 MST 2014
I'm not sure how to tell if I get a fault because it only happens after I stop the debugging process - after I reboot.
Hence the vague term 'crashes'.

0 项奖励

939 次查看
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by TheFallGuy on Tue Aug 05 01:01:34 MST 2014
What do you mean by 'crashes'? Do you get a fault? If you want help, please describe what actually happens rather than using vague terms.
0 项奖励