LPC11xx and Timer16 - example problems

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC11xx and Timer16 - example problems

1,471 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by robert.palmer on Thu Jun 14 14:27:30 MST 2012
I am trying to use the 16bit timer to generate a delay.  I started out using the driver code provided by NXP (timer16.c/.h) but since I was having problems, I reduced to the minimum code that will generate the issue. 

I'm using the timer to generate pulses on I/O pins.  I have a scope on the pins and can see them toggling, but my delay is not working, the pulses are always about 5uS long (they SHOULD be 5msec long).

It seems that no matter what value I write into the LPC_TMR16B0->PR and ->MR0 register, the loop seems to exit immediately.

Also, when I step through the register setup and use the peripheral display, the values in the register always show zero.  They never seem to update.  I've done the same thing with the SSP and I2C peripherals in other projects and had not problems.

I thought it might be optimization issues, so I ensured that I have optimization off.

Here is my code:  I used the project wizard to create a CMSIS 2.0 empty project and added the delay function based on what was originally in the timer16.c file.  I have read through the LPC11xx UserManual and cannot see anything obvious that I am doing wrong in setting up the timer.


void delay(uint32_t time)
{
    LPC_TMR16B0->TCR = 0x02;        /* reset timer */
    LPC_TMR16B0->PR  = 48; /* set prescaler to get 1 M counts/sec */
    LPC_TMR16B0->MR0 = time * 1000;
    LPC_TMR16B0->IR  = 0xff;        /* reset all interrrupts */
    LPC_TMR16B0->MCR = 0x04;        /* stop timer on match */
    LPC_TMR16B0->TCR = 0x01;        /* start timer */
    /* wait until delay time has elapsed */
    while (LPC_TMR16B0->TCR & 0x01);
}

int main(void) {

    /* Initialize GPIO (sets up clock) */
    GPIOInit();

    volatile static int i = 0 ;
    GPIOSetDir( 3, 1, 1 );
    for(i=10; i>0; i--)
    {
        GPIOSetValue( 3, 1, 0 );
        delay(5);
        GPIOSetValue( 3, 1, 1 );
        delay(10);
    }
// Enter an infinite loop, just incrementing a counter

while(1) {
i++ ;
}
return 0 ;
}
0 Kudos
Reply
7 Replies

1,385 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Genesy on Wed Nov 14 08:27:28 MST 2012
[FONT=Times New Roman][SIZE=4]I found a difference between timer32.h and timer16.h. In particular timer16 doesn't work because it doesn't properly initialize the MR0 register in the delayMs function:[/SIZE][/FONT][SIZE=4]
[FONT=Courier New]-timer32.c:
LPC_TMR32B0->MR0 = delayInMs * ((SystemCoreClock/(LPC_TMR32B0->PR+1)) / 1000);

  -timer16.c:
#define [FONT=Courier New]TIME_INTERVALmS 1000
...
[/FONT][/FONT][FONT=Courier New]LPC_TMR16B0->MR0 = delayInMs * TIME_INTERVALmS;
[/FONT]Same problem in the function[/SIZE] [FONT=Courier New][SIZE=4][FONT=Times New Roman] init_timer16.[/FONT][/SIZE][/FONT][SIZE=4]      
[FONT=Courier New][FONT=Times New Roman]I don't know why it was written so this driver![/FONT][/FONT][/SIZE]
0 Kudos
Reply

1,385 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by robert.palmer on Sat Jun 16 06:16:24 MST 2012

Quote: Rob65

"we sell chips, not software" was what I have heard a lot of times working at NXP (for another team though).
This makes it even stranger to see that there is such a broad range of examples programs that seem to diverge over the processors instead of converse...

Regards,[INDENT]Rob
[/INDENT]



I completely agree with you on this.  But some companies, and NXP is learning this, use the software as the hook to get you to use their chips.  It speeds the learning curve, and IF the software IS "production ready" can cut development times for project significantly.  Look at Microchip (they're not the only ones) - they have a very clear and consistent library of software and examples.  Even to experienced developers this can be a huge time savings and benefit to the overall project.  The sample code/driver software can mean the difference between using chip from company A or company B.  I've been there, I've made the decision, for me and for my customers. 

I do get a bit frustrated at how divergent the sample code is from NXP, as you move from one family of chips to another (not just micros either).  No consistency, even if they are both micros and they both support CMSIS.  I'm working on an LPC11xx project AND a different LPC17xx project, both have CMSIS, both have CMSIS examples, but the projects aren't arranged the same way, the files aren't packaged the same way online (17xx has a CMSIS drivers download, 11xx doesn't, 11xx has an examples download that includes the drivers).  It makes switching families MUCH slower, you have to relearn where everything is, where the config files are, etc. 

I think it's funny (in a sad way) that even the debug frameworks code is completely different between the 11xx samples and the 17xx samples - obviously the development decisions are left up to the individual developer and they were not the same person.  I had already expanded on the 17xx debug_frmwrk approach while working on one project and then loaded the 11xx project only to find a completely different way of handling debug print statements.  One of my first changes was to replace the 11xx debug_printf files with my modified debug_frmwrk.

Oh well, such are the challenges of an embedded developer. That's what keeps us on our toes and makes it interesting.
0 Kudos
Reply

1,385 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Fri Jun 15 23:08:14 MST 2012

Quote: robert.palmer
On the other hand, what is the point of sample code if it doesn't work at all?  I would expect a basic use of the sample code to work - in this case it didn't and by using the manual.  I do have it next to me and I DID go through it



We are two minds alike
Most of the examples I tried at least worked (somehow...). But it is indeed strange if the comment states that a clock is initialized at 400 kHz where I measure 300-something kHz ...

And what about that one line of code with strange comment:
while (!(LPC_SC->PLL0STAT & ((1<<25) | (1<<24))));/* Wait for PLLC0_STAT & PLLE0_STAT */
Any of us should be able to see that this is clearly wrong - yet noone ever noticed (or most likely: bothered to check). And why did NXP provide this silly comment but there are hardly any usable comments to clarify what functions do...

And yes - you already wrote in your first posting that you checked the user manual. If it helps; first time I read the manual I skimmed the initialization sections and immediately skipped over to the register defines :rolleyes:

Unfortunately the NXP team creating the examples hardly gets any time to create those examples "we sell chips, not software" was what I have heard a lot of times working at NXP (for another team though).
This makes it even stranger to see that there is such a broad range of examples programs that seem to diverge over the processors instead of converse...

Regards,[INDENT]Rob
[/INDENT]
0 Kudos
Reply

1,385 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by robert.palmer on Fri Jun 15 06:17:35 MST 2012
I understand about initializing in the main loop.  However, there is no general Timer16 module init.  The only init in the sample code actually sets up and starts a timer, not just initializing the module (guess it depends on your definition of initializing).

I have fixed it in my own copy of the Driver samples.

Looking at the peripheral registers and them not changing.  Chalk that one up to lack of experience with ARM.  I couldn't figure out what was causing that, until I found the problem.  Now I know and that will be a BIG clue in the future.

As for the warning about sample code - completely understand that it should not be regarded as tried and true, fully tested software.  On the other hand, what is the point of sample code if it doesn't work at all?  I would expect a basic use of the sample code to work - in this case it didn't and by using the manual.  I do have it next to me and I DID go through it, unfortunately, I skimmed right over section 18.2 and dug into the registers. Between looking at the manual and looking at other parts of the sample code, I was able to figure out the issue.
0 Kudos
Reply

1,385 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Rob65 on Thu Jun 14 23:52:06 MST 2012

Quote: robert.palmer
After even more digging, I discovered that the SYSAHBCLKCTRL bit for the TMR16B0 was not set.



A few of peripherals are clocked after boot, the others are not.
Luckily the user manual contains some hints on how to set up each peripheral.
Chapter 18 describes the 16 bits timer and 18.2  shows the basic configuration. If you follow the link to table 21, you might notice that bits 7 and 8 (clock enable bits for both 16 bits timers) are 0 (clock disabled).

SSP is one of the peripherals that is clocked after boot. I2C is not but most likely you used just enough of the original driver to enable clocking :)

If you debug your code, you can view the peripheral registers (somewhere in the left pane in the IDE) and there you might notice that the registers are not enabled because they are not clocked. This has hinted me a few times about forgetting to enable the clock to a peripheral ...

One warning: don't trust any code that comes as free 'example' or 'driver library' with the LPCXpresso IDE or on any of the websites. As I've mentioned a number of times in other threads; these examples are untested and may contain bugs or even be completely wrong.
The I2C 'driver'  that is (or at least was) delivered does not handle any error situations and may result in a non responsive I2C bus, it also produced clock frequencies that did not match the comments in the code.
And just this week we even discovered a redundant line of code in the PLL startup code (thanks to Brutte). This was one line of code that I missed when I created my own PLL routines. :eek:

So always have the user manual at hand and check everything that you copy from existing (example) code.

Rob
0 Kudos
Reply

1,385 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by creafyumi on Thu Jun 14 20:32:42 MST 2012

Quote: robert.palmer
After even more digging, I discovered that the SYSAHBCLKCTRL bit for the TMR16B0 was not set.  Once I set this, it began to work as expected.

In the NXP driver code, they set this if you are start a timer, if you start PWM, but NOT if you just use the delay.



In your main(), you should initialize your timer16. How could we use timer without initializing(setting it correctly) it. Timer has so many functions, use it according to what we need.
0 Kudos
Reply

1,385 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by robert.palmer on Thu Jun 14 15:09:27 MST 2012
After even more digging, I discovered that the SYSAHBCLKCTRL bit for the TMR16B0 was not set.  Once I set this, it began to work as expected.

In the NXP driver code, they set this if you are start a timer, if you start PWM, but NOT if you just use the delay.
0 Kudos
Reply