EmbeddedRelated.com
Forums

LPC2106 - Problem with accuracy of timer

Started by voltz56 April 13, 2010
--- In l..., "voltz56" wrote:
>
> > I do not see any code turning on the power for the timers.
> >
> > regards,
> > Charles
> > Your joking right?
>
> I think the problem is with my startup file, -there doesnt appear to
be
> any code to enable/config interrupts, but Im unsure how to do this.
>
> http://pastebin.com/cDB2j3Sb Regards,
> J
>

Hi

All peripherals default to powered up on the LPC2106 so, as long as they
haven't been disabled to save power, a power up is not necessary.

The peripheral code looks OK so I would agree that the interrupt hasn't
been enabled to the core. This can be done in the code as follows,
depending on compiler:

__enable_interrupt() - IAR intrinsic
__enable_irq() - Keil intrinsic

for GCC the following assembler can be called (extern void
__irq_en(void) from C)
.code 32
.global __irq_en
__irq_en:
mrs r12, CPSR
/* get present SR value */
bic r12, r12, #0xC0
/* remove IRQ and FIQ mask bits */
msr CPSR_c, r12
/* set new value to SR */
bx lr
/* return with interrupts enabled */
Regards

Mark

www.uTasker.com

An Engineer's Guide to the LPC2100 Series

--- In l..., "Mark" wrote:
>
> --- In l..., "voltz56" wrote:
> >
> > > I do not see any code turning on the power for the timers.
> > >
> > > regards,
> > > Charles
> > >
> >
> > Your joking right?
> >
> > I think the problem is with my startup file, -there doesnt appear to
> be
> > any code to enable/config interrupts, but Im unsure how to do this.
> >
> > http://pastebin.com/cDB2j3Sb
> >
> > Regards,
> > J
> > Hi
>
> All peripherals default to powered up on the LPC2106 so, as long as they
> haven't been disabled to save power, a power up is not necessary.
>
> The peripheral code looks OK so I would agree that the interrupt hasn't
> been enabled to the core. This can be done in the code as follows,
> depending on compiler:
>
> __enable_interrupt() - IAR intrinsic
> __enable_irq() - Keil intrinsic
>
> for GCC the following assembler can be called (extern void
> __irq_en(void) from C)
> .code 32
> .global __irq_en
> __irq_en:
> mrs r12, CPSR
> /* get present SR value */
> bic r12, r12, #0xC0
> /* remove IRQ and FIQ mask bits */
> msr CPSR_c, r12
> /* set new value to SR */
> bx lr
> /* return with interrupts enabled */
> Regards
>
> Mark
>
> www.uTasker.com
Im using keil with the codesourcery GNU tool chain, I downloaded an example project for this setup from keil and after a few hours of playing around with compiler and linker settings and changing the startup and linker files I got it working.

Thanks,
J

--- In l..., "Mark" wrote:
>
> --- In l..., "voltz56" vltzzzzzzz@ wrote:
> >
> > > I do not see any code turning on the power for the timers.
> > >
> > > regards,
> > > Charles
> > >
> >
> > Your joking right?
> >
> > I think the problem is with my startup file, -there doesnt appear to
> be
> > any code to enable/config interrupts, but Im unsure how to do this.
> >
> > http://pastebin.com/cDB2j3Sb
> >
> > Regards,
> > J
> > Hi
>
> All peripherals default to powered up on the LPC2106 so, as long as
they
> haven't been disabled to save power, a power up is not necessary.
>
> The peripheral code looks OK so I would agree that the interrupt
hasn't
> been enabled to the core. This can be done in the code as follows,
> depending on compiler:
>
> __enable_interrupt() - IAR intrinsic
> __enable_irq() - Keil intrinsic
>
> for GCC the following assembler can be called (extern void
> __irq_en(void) from C)
> .code 32
> .global __irq_en
> __irq_en:
> mrs r12, CPSR
> /* get present SR value */
> bic r12, r12, #0xC0
> /* remove IRQ and FIQ mask bits */
> msr CPSR_c, r12
> /* set new value to SR */
> bx lr
> /* return with interrupts enabled */
> Regards
>
> Mark
>
> www.uTasker.com
Well I think I spoke too soon. The interrupt is firing, but Im still
having trouble with the interval accuracy. When configured for 1us the
interval measured in keil debugger is 190ns.

http://pastebin.com/LneyYUq5

Regards,
V
> Well I think I spoke too soon. The interrupt is firing, but Im still
> having trouble with the interval accuracy. When configured for 1us the
> interval measured in keil debugger is 190ns.
>
> http://pastebin.com/LneyYUq5 Regards,
> V
>

The value you are setting to T0_MCR seems a little odd.

Richard

--- In l..., "rtstofer" wrote:
> > Well I think I spoke too soon. The interrupt is firing, but Im still
> > having trouble with the interval accuracy. When configured for 1us the
> > interval measured in keil debugger is 190ns.
> >
> > http://pastebin.com/LneyYUq5
> >
> > Regards,
> > V
> > The value you are setting to T0_MCR seems a little odd.
>
> Richard
>

Ya just noticed that, think I accidentally assigned that to MCR instead of MR0 at some point when testing. That is not my problem though as I have just checked.

Regards,
J

--- In l..., "voltz56" wrote:
>
> When I configure the prescaler for a 1ms tick, it is off by 84ns
when
> checked in the keil debugger, this much inaccuracy I can live with.
> , but when I have it configured for 1us it is off by approximately
> 940ns, this is a major problem for me.
>
> Regards,
> J
> //delay = us * no_loops
> void delay_us(unsigned int no_loops)
> {
> unsigned int i;
> for(i = 0; i < no_loops; i++)
> {
> //pclk = cclk = 48MHz
>
> T0_PR = 0x30; //Load Prescaler register
for
> usec tick, formula --> toHex(interval/(1/pclk))
> T0_TCR = 0x00000003; //Reset counter and
prescaler
> T0_TCR = 0x00000001; //enable timer
> while ( T0_TC < 1);
> T0_TCR &= ~(1<<0); // Stop timer
> }/*end for*/
>
> }/*end delay*/
>

Still no joy with this, anyone, any ideas or suggestions?

http://pastebin.com/1j2b9G62

Regards,
J

Hi

I would try setting the pre-scaler to 0 and setting the match value to the number of clocks that you require (0x30).

Regards

Mark
http://www.uTasker.com
--- In l..., "voltz56" wrote:
> --- In l..., "voltz56" wrote:
> >
> > When I configure the prescaler for a 1ms tick, it is off by 84ns
> when
> > checked in the keil debugger, this much inaccuracy I can live with.
> > , but when I have it configured for 1us it is off by approximately
> > 940ns, this is a major problem for me.
> >
> > Regards,
> > J
> >
> >
> > //delay = us * no_loops
> > void delay_us(unsigned int no_loops)
> > {
> > unsigned int i;
> > for(i = 0; i < no_loops; i++)
> > {
> > //pclk = cclk = 48MHz
> >
> > T0_PR = 0x30; //Load Prescaler register
> for
> > usec tick, formula --> toHex(interval/(1/pclk))
> > T0_TCR = 0x00000003; //Reset counter and
> prescaler
> > T0_TCR = 0x00000001; //enable timer
> > while ( T0_TC < 1);
> > T0_TCR &= ~(1<<0); // Stop timer
> > }/*end for*/
> >
> > }/*end delay*/
> > Still no joy with this, anyone, any ideas or suggestions?
>
> http://pastebin.com/1j2b9G62
>
> Regards,
> J
>

Excellent that seems to have worked, thanks. Although every 3th interrupt is off by +60 to 70ns, is that normal?

Regards,
J

--- In l..., "Mark" wrote:
>
> Hi
>
> I would try setting the pre-scaler to 0 and setting the match value to the number of clocks that you require (0x30).
>
> Regards
>
> Mark
> http://www.uTasker.com
> --- In l..., "voltz56" wrote:
> >
> >
> > --- In l..., "voltz56" wrote:
> > >
> > > When I configure the prescaler for a 1ms tick, it is off by 84ns
> > when
> > > checked in the keil debugger, this much inaccuracy I can live with.
> > > , but when I have it configured for 1us it is off by approximately
> > > 940ns, this is a major problem for me.
> > >
> > > Regards,
> > > J
> > >
> > >
> > > //delay = us * no_loops
> > > void delay_us(unsigned int no_loops)
> > > {
> > > unsigned int i;
> > > for(i = 0; i < no_loops; i++)
> > > {
> > > //pclk = cclk = 48MHz
> > >
> > > T0_PR = 0x30; //Load Prescaler register
> > for
> > > usec tick, formula --> toHex(interval/(1/pclk))
> > > T0_TCR = 0x00000003; //Reset counter and
> > prescaler
> > > T0_TCR = 0x00000001; //enable timer
> > > while ( T0_TC < 1);
> > > T0_TCR &= ~(1<<0); // Stop timer
> > > }/*end for*/
> > >
> > > }/*end delay*/
> > >
> >
> > Still no joy with this, anyone, any ideas or suggestions?
> >
> > http://pastebin.com/1j2b9G62
> >
> > Regards,
> > J
>

Hi

At 48MHz there would be an increment once every 20ns.
I don't know how well this clock is synchronised to the clock being used for instruction execution - 20ns jitter is probably to be expected but I can't explain +60..70ns every three interrupts. Maybe it is an accumulation of the 20ns each time (?)

Regards

Mark

--- In l..., "voltz56" wrote:
>
> Excellent that seems to have worked, thanks. Although every 3th interrupt is off by +60 to 70ns, is that normal?
>
> Regards,
> J
>
> --- In l..., "Mark" wrote:
> >
> > Hi
> >
> > I would try setting the pre-scaler to 0 and setting the match value to the number of clocks that you require (0x30).
> >
> > Regards
> >
> > Mark
> >
> >
> > http://www.uTasker.com
> >
> >
> > --- In l..., "voltz56" wrote:
> > >
> > >
> > > --- In l..., "voltz56" wrote:
> > > >
> > > > When I configure the prescaler for a 1ms tick, it is off by 84ns
> > > when
> > > > checked in the keil debugger, this much inaccuracy I can live with.
> > > > , but when I have it configured for 1us it is off by approximately
> > > > 940ns, this is a major problem for me.
> > > >
> > > > Regards,
> > > > J
> > > >
> > > >
> > > > //delay = us * no_loops
> > > > void delay_us(unsigned int no_loops)
> > > > {
> > > > unsigned int i;
> > > > for(i = 0; i < no_loops; i++)
> > > > {
> > > > //pclk = cclk = 48MHz
> > > >
> > > > T0_PR = 0x30; //Load Prescaler register
> > > for
> > > > usec tick, formula --> toHex(interval/(1/pclk))
> > > > T0_TCR = 0x00000003; //Reset counter and
> > > prescaler
> > > > T0_TCR = 0x00000001; //enable timer
> > > > while ( T0_TC < 1);
> > > > T0_TCR &= ~(1<<0); // Stop timer
> > > > }/*end for*/
> > > >
> > > > }/*end delay*/
> > > >
> > >
> > > Still no joy with this, anyone, any ideas or suggestions?
> > >
> > > http://pastebin.com/1j2b9G62
> > >
> > > Regards,
> > > J
> > >
>

I'm beginning to think the keil software has a mind of its own. I just tested again and now Im getting +20ns "every time". This I can live with. Thanks for all your help.

Regards,
J
--- In l..., "Mark" wrote:
>
> Hi
>
> At 48MHz there would be an increment once every 20ns.
> I don't know how well this clock is synchronised to the clock being used for instruction execution - 20ns jitter is probably to be expected but I can't explain +60..70ns every three interrupts. Maybe it is an accumulation of the 20ns each time (?)
>
> Regards
>
> Mark
> --- In l..., "voltz56" wrote:
> >
> > Excellent that seems to have worked, thanks. Although every 3th interrupt is off by +60 to 70ns, is that normal?
> >
> > Regards,
> > J
> >
> > --- In l..., "Mark" wrote:
> > >
> > > Hi
> > >
> > > I would try setting the pre-scaler to 0 and setting the match value to the number of clocks that you require (0x30).
> > >
> > > Regards
> > >
> > > Mark
> > >
> > >
> > > http://www.uTasker.com
> > >
> > >
> > > --- In l..., "voltz56" wrote:
> > > >
> > > >
> > > > --- In l..., "voltz56" wrote:
> > > > >
> > > > > When I configure the prescaler for a 1ms tick, it is off by 84ns
> > > > when
> > > > > checked in the keil debugger, this much inaccuracy I can live with.
> > > > > , but when I have it configured for 1us it is off by approximately
> > > > > 940ns, this is a major problem for me.
> > > > >
> > > > > Regards,
> > > > > J
> > > > >
> > > > >
> > > > > //delay = us * no_loops
> > > > > void delay_us(unsigned int no_loops)
> > > > > {
> > > > > unsigned int i;
> > > > > for(i = 0; i < no_loops; i++)
> > > > > {
> > > > > //pclk = cclk = 48MHz
> > > > >
> > > > > T0_PR = 0x30; //Load Prescaler register
> > > > for
> > > > > usec tick, formula --> toHex(interval/(1/pclk))
> > > > > T0_TCR = 0x00000003; //Reset counter and
> > > > prescaler
> > > > > T0_TCR = 0x00000001; //enable timer
> > > > > while ( T0_TC < 1);
> > > > > T0_TCR &= ~(1<<0); // Stop timer
> > > > > }/*end for*/
> > > > >
> > > > > }/*end delay*/
> > > > >
> > > >
> > > > Still no joy with this, anyone, any ideas or suggestions?
> > > >
> > > > http://pastebin.com/1j2b9G62
> > > >
> > > > Regards,
> > > > J
> > > >
> > >
>