This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Problem with IAP on LPC2138

The IAP is driving me crazy. When I single step my code using ulink it works, but when I just let it run the micro reboots itself and the IAP hasn't worked. I've read the manual, AN10256, searched the forums and looked at the sample code.

Here's my code:

ErrorCode_t writeBufToOneFlashSector(uint8_t secNum)
{
    BOOL good = TRUE;
    ErrorCode_t retCode = ERR_NO_ERROR;
        unsigned int enables;
    BOOL pllStat;

    // Disable interrupts during erase and write operations
    // Keep a copy of what was enabled
    enables = VICIntEnable;
    command[0] = IAP_PrepareSectors;
    command[1] = (uint32_t)secNum;
    command[2] = (uint32_t)secNum;
    waitTXComplete();
    pauseTX(TRUE);
    pllStat = usePLL(FALSE);
    iap_entry(command, result);
    good = (BOOL)(IAP_CMD_SUCCESS == result[0]);
    if(!good)
    {
        usePLL(pllStat);
        retCode = ERR_IAP_ERASE_PREPARE | ERR_NUM_USED;
        errVal = (ParamType)result[0];
    }
    else
    {
        command[0] = IAP_EraseSectors;
        command[1] = (uint32_t)secNum;
        command[2] = (uint32_t)secNum;
        command[3] = XTAL_OSC_KHZ;
        // Disable interrupts during erase
        VICIntEnable = 0;
        iap_entry(command, result);
        VICIntEnable = enables;
        good = (BOOL)(IAP_CMD_SUCCESS == result[0]);
        if(!good)
        {
            usePLL(pllStat);
            retCode = ERR_IAP_ERASE | ERR_NUM_USED;
            errVal = (ParamType)result[0];
        }
    }

    // See about doing the write
    if(good)
    {
        command[0] = IAP_PrepareSectors;
        command[1] = (uint32_t)secNum;
        command[2] = (uint32_t)secNum;
        iap_entry(command, result);
        good = (BOOL)(IAP_CMD_SUCCESS == result[0]);
        if(!good)
        {
            usePLL(pllStat);
            retCode = ERR_IAP_WRITE_PREPARE | ERR_NUM_USED;
            errVal = (ParamType)result[0];
        }
    }

    // Ready to write at last
    if(good)
    {
        command[0] = IAP_CopyRAMtoFlash;
        command[1] = SectorStartAddr[secNum];
        command[2] = (unsigned int)nvBuf;
        command[3] = FLASH_NV_PAGE_SIZE8;
        command[4] = XTAL_OSC_KHZ;
        // Disable interrupts during erase
        VICIntEnable = 0;
        iap_entry(command, result);
        usePLL(pllStat);
        VICIntEnable = enables;
        good = (BOOL)(IAP_CMD_SUCCESS == result[0]);
        if(!good)
        {
            retCode = ERR_IAP_WRITE | ERR_NUM_USED;
            errVal = (ParamType)result[0];
        }
    }
    pauseTX(FALSE);
    return retCode;
}

Parents
  • That bit was lifted out of the published code snippet. It looks like this:

    BOOL usePLL (BOOL useIt)
    {
        BOOL pllConStat;
    
        // PLL must be enabled AND connected
        pllConStat = (BOOL)((PLL_STAT & PLLSTAT_PLLE_MASK) == PLLSTAT_PLLE_MASK);
        // Start the PLL if it's stopped
        if(useIt && !pllConStat)
        {
            start_pll();
        }
        pllConStat = pllConStat && (BOOL)((PLL_STAT & PLLSTAT_PLLC_MASK) == PLLSTAT_PLLC_MASK);
        // Connect or disconnect as required
        if(useIt)
        {
            connect_pll();
        }
        else
        {
            disconnect_pll();
        }
        return pllConStat;
    }
    
    void connect_pll (void)  {
      __asm  {
            LDR     R0, =PLL_BASE
            MOV     R1, #0xAA
            MOV     R2, #0x55
    
            // Switch to PLL Clock
            MOV     R2, #0x55
            MOV     R3, #(PLLCON_PLLE_ENA + PLLCON_PLLC_ENA)
            STR     R3, [R0, #PLLCON_OFS]
            STR     R1, [R0, #PLLFEED_OFS]
            STR     R2, [R0, #PLLFEED_OFS]
      }
    }
    
    void start_pll (void)  {
      __asm  {
            LDR     R0, =PLL_BASE
            MOV     R1, #0xAA
            MOV     R2, #0x55
    
            // Enable PLL
            MOV     R3, #(PLLCON_PLLE_ENA + PLLCON_PLLC_DIS)
            STR     R3, [R0, #PLLCON_OFS]
            STR     R1, [R0, #PLLFEED_OFS]
            STR     R2, [R0, #PLLFEED_OFS]
    
            // Wait until PLL Locked
            LDR     R2, =PLLSTAT_PLOCK
        PLL_Loop:
            LDR     R3, [R0, #PLLSTAT_OFS]
            CMP     R3, R2
            BEQ     PLL_Loop
      }
    }
    
    
    /*
     * Switch CPU to standard XTAL but leave PLL enabled
     */
    void disconnect_pll(void) __arm  {
      __asm  {
            LDR     R0, =PLL_BASE
            MOV     R1, #0xAA
            MOV     R2, #0x55
    
            // Disconnect PLL but leave it enabled
            MOV     R3, #(PLLCON_PLLE_ENA + PLLCON_PLLC_DIS)
            STR     R3, [R0, #PLLCON_OFS]
            STR     R1, [R0, #PLLFEED_OFS]
            STR     R2, [R0, #PLLFEED_OFS]
      }
    }
    
    /*
     * Switch CPU to standard XTAL and disable PLL
     */
    void stop_pll(void) __arm  {
      __asm  {
            LDR     R0, =PLL_BASE
            MOV     R1, #0xAA
            MOV     R2, #0x55
    
            // Disable PLL
            MOV     R3, #(PLLCON_PLLE_DIS + PLLCON_PLLC_DIS)
            STR     R3, [R0, #PLLCON_OFS]
            STR     R1, [R0, #PLLFEED_OFS]
            STR     R2, [R0, #PLLFEED_OFS]
      }
    }
    

Reply
  • That bit was lifted out of the published code snippet. It looks like this:

    BOOL usePLL (BOOL useIt)
    {
        BOOL pllConStat;
    
        // PLL must be enabled AND connected
        pllConStat = (BOOL)((PLL_STAT & PLLSTAT_PLLE_MASK) == PLLSTAT_PLLE_MASK);
        // Start the PLL if it's stopped
        if(useIt && !pllConStat)
        {
            start_pll();
        }
        pllConStat = pllConStat && (BOOL)((PLL_STAT & PLLSTAT_PLLC_MASK) == PLLSTAT_PLLC_MASK);
        // Connect or disconnect as required
        if(useIt)
        {
            connect_pll();
        }
        else
        {
            disconnect_pll();
        }
        return pllConStat;
    }
    
    void connect_pll (void)  {
      __asm  {
            LDR     R0, =PLL_BASE
            MOV     R1, #0xAA
            MOV     R2, #0x55
    
            // Switch to PLL Clock
            MOV     R2, #0x55
            MOV     R3, #(PLLCON_PLLE_ENA + PLLCON_PLLC_ENA)
            STR     R3, [R0, #PLLCON_OFS]
            STR     R1, [R0, #PLLFEED_OFS]
            STR     R2, [R0, #PLLFEED_OFS]
      }
    }
    
    void start_pll (void)  {
      __asm  {
            LDR     R0, =PLL_BASE
            MOV     R1, #0xAA
            MOV     R2, #0x55
    
            // Enable PLL
            MOV     R3, #(PLLCON_PLLE_ENA + PLLCON_PLLC_DIS)
            STR     R3, [R0, #PLLCON_OFS]
            STR     R1, [R0, #PLLFEED_OFS]
            STR     R2, [R0, #PLLFEED_OFS]
    
            // Wait until PLL Locked
            LDR     R2, =PLLSTAT_PLOCK
        PLL_Loop:
            LDR     R3, [R0, #PLLSTAT_OFS]
            CMP     R3, R2
            BEQ     PLL_Loop
      }
    }
    
    
    /*
     * Switch CPU to standard XTAL but leave PLL enabled
     */
    void disconnect_pll(void) __arm  {
      __asm  {
            LDR     R0, =PLL_BASE
            MOV     R1, #0xAA
            MOV     R2, #0x55
    
            // Disconnect PLL but leave it enabled
            MOV     R3, #(PLLCON_PLLE_ENA + PLLCON_PLLC_DIS)
            STR     R3, [R0, #PLLCON_OFS]
            STR     R1, [R0, #PLLFEED_OFS]
            STR     R2, [R0, #PLLFEED_OFS]
      }
    }
    
    /*
     * Switch CPU to standard XTAL and disable PLL
     */
    void stop_pll(void) __arm  {
      __asm  {
            LDR     R0, =PLL_BASE
            MOV     R1, #0xAA
            MOV     R2, #0x55
    
            // Disable PLL
            MOV     R3, #(PLLCON_PLLE_DIS + PLLCON_PLLC_DIS)
            STR     R3, [R0, #PLLCON_OFS]
            STR     R1, [R0, #PLLFEED_OFS]
            STR     R2, [R0, #PLLFEED_OFS]
      }
    }
    

Children