I am developing an application based on an LPC1754 that requires the use of a timer and have found a problem that seems to be an issue with the way the libc.a library is linked into the project.
When calling the function to initialise the timer, a hard fault exception occurs, which I have traced to a call to the __aeabi_uldivmod function in libc.a. This is invoked in the TIM_ConverUSecToVal function in lpc17xx_timer.c, shown below:
uint32_t TIM_ConverUSecToVal (uint32_t timernum, uint32_t usec)
{
uint64_t clkdlycnt;
// Get Pclock of timer
clkdlycnt = (uint64_t) TIM_GetPClock (timernum);
clkdlycnt = (clkdlycnt * usec) / 1000000; //<-- call to __aeabi_uldivmod to perform long division
return (uint32_t) clkdlycnt;
}
The assembler output shows where the problem comes from, as shown in this extract:
2fce: f249 4cb4 movw ip, #38068 ; 0x94b4 <-- address for the call, LSB = '0' !!!
2fd2: f2c0 0c00 movt ip, #0
2fd6: 4610 mov r0, r2
2fd8: 4619 mov r1, r3
2fda: f44f 2274 mov.w r2, #999424 ; 0xf4000
2fde: f502 7210 add.w r2, r2, #576 ; 0x240
2fe2: f04f 0300 mov.w r3, #0
2fe6: 47e0 blx ip ; <-- call to function causes exception
The blx instruction above causes a hard fault exception since, with the LSB of the address in ip set to '0', the CPU attempts to change to ARM mode from thumb2 mode, which is illegal for allcortex processors.
In all other instances where the blx instruction is used to call a function the address has been correctly formed with the LSB = '1'. This is the only time it gets it wrong but I can't find any way to make it work properly.
To test if it is consistent I made up a simple project with the following main.c source code:
#include "lpc_types.h"
int main(void)
{
while(1)
{
uint64_t clkdlycnt;
uint32_t usec;
usec = 100;
// Get Pclock of timer
clkdlycnt = (uint64_t) 24000000;
clkdlycnt = (clkdlycnt * usec) / 1000000;
return (uint32_t) clkdlycnt;
}
}
The same problem is encountered in this simple case.
I am using CoBuilder V 0.16 and have Sourcery G++ Lite 2009q3-68 installed. Whether this is a bug in your code or in the GNU tools I can't say but I'm fairly sure it's not in my code. Please can you help.