Here's the complete function:
#define PREVENT_IRQS { \
reenable_irq = !(__get_PRIMASK()); \
__disable_irq(); \
}
#define RESTORE_IRQS { \
if( reenable_irq ) \
__enable_irq(); \
}
#define SYSTEM_CLOCK_SPEED_UPON_RESET 12000000
uint32_t ReadEEPROM( bool pre_clock_config, uint32_t eeprom_start_address, uint32_t *dst_ptr, uint32_t byte_count )
{
uint32_t iap_command[6], iap_result[6], clock_speed_kHz;
volatile uint8_t *byte_ptr, reenable_irq, retry = 50;
byte_ptr = (uint8_t *)dst_ptr;
if( pre_clock_config )
clock_speed_kHz = SYSTEM_CLOCK_SPEED_UPON_RESET / 1000;
else
clock_speed_kHz = SystemCoreClock / 1000;
PREVENT_IRQS;
try_again:
// Load IAP Command Buffer
iap_command[0] = IAP_EEPROM_READ;
iap_command[1] = eeprom_start_address;
iap_command[2] = (uint32_t) byte_ptr;
iap_command[3] = byte_count;
iap_command[4] = clock_speed_kHz;
iap_entry( iap_command, iap_result );
if( (iap_result[0] != IAP_CMD_SUCCESS) && retry-- )
goto try_again;
RESTORE_IRQS;
return( iap_result[0] );
}
The above code seems to work just fine. But if I don't do the "divide by 1000" in the upper code and instead try to do it right there at the iap_entry[4] assignment (as in my prior email) I crash upon entering iap_entry(). I set up my LPCXpresso11U68 board as a debug interface to my target and single stepped the code using the LPCXpresso IDE. I confirmed the value of the variable used at the [4] assignment - it is correct immediately prior to calling iap_entry(). When I set a breakpoint immediately after the call to iap_entry() and run the code, I immediately trap to the HardFault ISR.
If I put all constants at the [4] assignment (i.e. 12000000 / 1000) it works. If I assign the single (predivided) value at the [4] assignment it works. But if I use:
iap_command[4] = clock_speed / 1000; (Where clock_speed is confirmed to have a value of 12000000 as observed in the debugger) I crash.
As you can see in the above code, I am disabling interrupts and my "clock_speed" variable is an automatic/local variable on the stack, so it shouldn't be getting overwritten.
I am doing this function right after reset, before calling the ResetISR() initialization function. Are there any resources that I need to have configured or enabled (e.g. clocking) in order to use the IAP call? The Stack Pointer would have been initialized via the Vector Table as specified in the Linker Script: PROVIDE(_vStackTop = __top_Ram0_32 - 64);
As you can see, I am leaving the uppermost 32 bytes of the Stack free for the IAP resource (as required) and an additional 32 Bytes as well...
Now that you can see the whole code and you know that I'm calling this function right after reset, does anything come to mind explaining why:
iap_command[4] = clock_speed_full / 1000; // FAILS (clock_speed_full = 12000000)
iap_command[4] = clock_speed_alone; // WORKS (clock_speed_alone = 12000)
iap_command[4] = 12000000 / 1000; // WORKS
My concern is that if I don't understand what's happening, there could be an issue which might manifest elsewhere, so it's important to understand what's happening here - it could be pointing to a bigger problem that needs to be addressed.
Thanks for your help with this.
Matt