Hi guys...I'm a newbie in ARM7 programming.I have a readymade hardware board of LPC2148.I'm doing a simple blinking action on it.I'm supplying the processor with 12MHz frequency as its processor clock.And i hve read in net somewhere tht each for loop [for(x=0;x<1;x++)] takes 12-13 cycles to execute.So by rough calculation the value of the delay counter should be 1000000 for 1sec delay.But my delay turns out to be 4-5sec. I have deactivated the MAM block and also PLL0 i.e., I'm using the external supplied oscillator as the clock source for the processor. I havn't used the timer module to get the desired delay till now..as i need to brush up the theories behind it first.But whether it is absolutely necessary to use the timer block to produce the 1sec delay?? plz answer my post some one..thanks in advance.My code is given below --
#include "LPC214x.H" /* Fosc = external supplied crystal frequency Fcclk = Processor clock or o/p of PLL0 Pclk = The VPB clock frquency.The o/p of the VPB driver Fcco = the frequency of the PLL current controlled oscillator */ void init_clock() { /* PLL0CON = 0x03; // PLL0 is enabled & connected as the clock source of the microcontroller PLL0CFG = 0x24; // The i/p crystal oscillator frequency is multiplied in the PLL0 block by a fator of 5(=4+1) PLL0FEED == 0xAA; // 0xAA and 0x55 should be feed into this register for the PLL0FEED == 0x55; // changes in PLL0CON and PLL0CFG to take place actively VPBDIV = 0x01; // The Pclk frequency = Fcclk frequecy..not necessary. // by default the GPIO are selacted as legacy ports */ PLL0CON=0x0; // these 4 lins are as given by blink.c.Though the result is nt coming as expected.the above commented out result are my first try to supply the processor with 60MHz clock supply // the PLL is nt connected as the clock source for the processor PLL0FEED=0xAA; PLL0FEED=0x55; VPBDIV=0x00; MAMCR = 0x00; // Any MAM function is disabled..i.e } void delay() { unsigned long int i; for(i=0;i<250000;i++); } // with 12MHZ clock supply the time delay is cmng as 1sec if the delay value is 250000 but it should be 1000000 according to my calculation // in this void main(void) { unsigned long dword=0x00000000; unsigned char min_hand=0; init_clock(); PINSEL1 &= 0x00000000; // all the pins of port1 are selected as GPIO IODIR1 = 0x00FF0000; // the pin 16 to 23 are configuered as the o/p pins. IOCLR1 = 0xFFFFFFFF; while(1) { min_hand++; dword = dword>>16; dword++; dword = dword <<16; IOSET1 |= dword; // IOPIN1 = IOSET1; delay(); if(min_hand /60 == 0) { min_hand=0; delay(); } IOCLR1 = 0xFFFFFFFF; delay(); } }
the program---
/* Clock cycle timing as described in the Datasheet is 40-100ns */ /* My primary aim is to blink the LEDs connected to pin1.16-pin1.23 in a pattern 00000000,00000001,00000010... and so on with an interval of 1sec between each blinking.Thus measuring 60seconds i.e, 1min.*/ #include "LPC214x.H" /* Fosc = external supplied crystal frequency Fcclk = Processor clock or o/p of PLL0 Pclk = The VPB clock frquency.The o/p of the VPB driver Fcco = the frequency of the PLL current controlled oscillator */ void init_clock() { PLL0CON=0x0; // the PLL is nt connected as the clock source for the processor PLL0FEED=0xAA; PLL0FEED=0x55; VPBDIV=0x01; // the VPB clock is same as that of the processor clock. MAMCR = 0x00; // Any MAM function is disabled..i.e } /* This is the delay block where the timer0 register are configuered to count upto a certain value so that 1sec delay is produced.After each such case the timer block is deactivated and agin when the delay() function will be called it will be activated and configuered to produce 1sec delay. the prescaler register is set to have the value 9999(=0x270F),so that the TC register is increased after every 10000 clock cycles.So it should count upto 1200(=0x4B0) for 1sec delay since the supply is 12MHz i.e., 12,000,000 clocks per second.Hence I have put the value 0x04B0 in MR0,which is compared with the TC and as soon as the match happens the Timer counter is being reset..and along with the timer block is deactivated. */ void delay() { T0PR = 0x0000270F; T0MR0 = 0x000004B0 ; T0TCR = 0x01; // the timer0 is activated while(T0TC != T0MR0); T0MCR = 0x00000002; // Timer Counter will be in reset condition if the match between the MR0 and TC happens. T0TCR = 0x02; /* when the match happens the Timer0 is resetted and deactivated and it is again activated while the next delay is called */ } void main(void) { unsigned long dword=0x00000000; unsigned char min_hand=0; init_clock(); PINSEL1 &= 0x00000000; // all the pins of port1 are selected as GPIO IODIR1 = 0x00FF0000; // the pin 16 to 23 are configuered as the output pins. IOCLR1 = 0xFFFFFFFF; while(1) { min_hand++; dword = dword>>16; dword++; dword = dword <<16; IOSET1 |= dword; // IOPIN1 = IOSET1; delay(); if(min_hand /60 == 0) { min_hand=0; delay(); } IOCLR1 = 0xFFFFFFFF; delay(); } }
Simulator? Remember that the simulator may not run at 100% speed of the real hardware.
its ok...but in the hardware also its nt cmng 1sec delay as expected by me..its cmng much greater than 1sec..and onr thing that i forgot to mention in the last post is that i havn't incorporated any interrupt system here as i dont want the interrupt handling to run for creating a delay of 1sec...
VPBDIV or APBDIV
Please check the address of APB Divider
My LPC214x.h header file doesnt cntain APBDIV but it contains the VPBDIV and its defined in the header file as #define VPBDIV (*((volatile unsigned char *) 0xE01FC100))
I checked two user manuals, one for LPC21xx/22xx, one for LPC214x; the address for your VLSI Peripheral Bus Divider should be correct.
But I think that, you didn't properly configure your CCLK and PCLK.
Don't know what your startup code does, but the several versions of the void init_clock() you provided, look strange to me.
Please use the [Peripherals] menu of the KEIL IDE to confirm your CCLK/PCLK settings first.
i dont know why the void init_clock() is looking strange to you.I have disabled the PLL0 and have used the external 12MHz supplied frequency as the processor clock source i.e., the Fcclk.VPB clock(Pclk) is also adjusted to be equal to that of Fcclk.At the same time the MAM functional block is disabled...as I dont want the MAM action to be taken here.I'm more worried about producing a 1sec delay using the timer0 block.Plz check it and let me know the error as the time delay is coming much greater than 1sec..I'm cant post my start-up code here as the size is too long..but i assure u its the standard starp-up code that is available for ARM processors in keil.
You need to check your startup code to make sure how it configures your PLL0, FCCLK, CCLK, PCLK.
Your LPC2148 has two PLL.
Proper PLL handle procedure should look like the below:
void TargetResetInit(void) { #ifdef __DEBUG_RAM MEMMAP = 0x2; /* set remap register */ #endif #ifdef __DEBUG_FLASH MEMMAP = 0x1; /* set remap register */ #endif #ifdef __IN_CHIP MEMMAP = 0x1; /* set remap register */ #endif /* Set system timers for each component */ PLLCON = 1; #if (Fpclk / (Fcclk / 4)) == 1 VPBDIV = 0; #endif #if (Fpclk / (Fcclk / 4)) == 2 VPBDIV = 2; #endif #if (Fpclk / (Fcclk / 4)) == 4 VPBDIV = 1; #endif #if (Fcco / Fcclk) == 2 PLLCFG = ((Fcclk / Fosc) - 1) | (0 << 5); #endif #if (Fcco / Fcclk) == 4 PLLCFG = ((Fcclk / Fosc) - 1) | (1 << 5); #endif #if (Fcco / Fcclk) == 8 PLLCFG = ((Fcclk / Fosc) - 1) | (2 << 5); #endif #if (Fcco / Fcclk) == 16 PLLCFG = ((Fcclk / Fosc) - 1) | (3 << 5); #endif PLLFEED = 0xaa; PLLFEED = 0x55; while((PLLSTAT & (1 << 10)) == 0); PLLCON = 3; PLLFEED = 0xaa; PLLFEED = 0x55; /* Set memory accelerater module*/ MAMCR = 0; #if Fcclk < 20000000 MAMTIM = 1; #else #if Fcclk < 40000000 MAMTIM = 2; #else MAMTIM = 3; #endif #endif MAMCR = 2; /* Add your codes here */ return; }
thanks to ur sir....I dont want to activate the PLL0 block as i want to use the frquency of the external crystal oscillator so i dont find any justification for all those calculation involving the Fcclk.Moreover I want to equate the processor clock and the VPB clock hence i have set VPBDIV =1. I have checked the PLL0 system block while simulating the code...and its coming as i have configuered.The PLL0 block gets deactivated and the processor clock is 12MHz just as the external crystal frequency.
Next thing is that i dont find any justification to activate the MAM block so i deactivate it and that is also evident during the simulator that it is deactivated..I'm facing problem mainly i the timer0 block..as its nt giving a 1sec delay..but what it should give according to the value loaded to PR,TC and MR0 registers by me....plz comment on this..
Could you also confirm the PCLK of your Timer0?
void delay() { T0PR = 0x0000270F; T0MR0 = 0x000004B0 ; T0TCR = 0x01; // the timer0 is activated while(T0TC != T0MR0); T0MCR = 0x00000002; // Timer Counter will be in reset condition if the match between the MR0 and TC happens. T0TCR = 0x02; /* when the match happens the Timer0 is resetted and deactivated and it is again activated while the next delay is called */ }
This is incorrect! You need to re-write it.
or remove the line in red, and see what will happen.
Sorry. -> or remove the line in red, and see what will happen. <- It is my mistake.
It should be: remove the line of
T0MCR = 0x00000002;
and see what will happen.
External frequency->Fosc -> 12MHZ Processor clock->Fcclk -> 12Mhz VPB clock -> Pclk -> 12MHz
And one more thing if the line T0MCR = 0x00000002; is not there then TC will never be resetted until and unless it reaches the value 0xFFFFFFFF.But thats not at all required..so the line must be there...
I haven't had time to check through your individual configuration bits. But resetting the timer is something you do when running the timer continuously. You let the timer tick until it reaches the match, and then restart from zero again for the next cycle. But you are calling delay() as a one-off call so why bother about the timer resetting for a next delay cycle?
That was one of the things I discussed in my first post - that you try to do a 1s delay in your loop, instead of trying to synchronize your loop with a 1s timer. The two concepts may sound similar but one of them will result in 1s+delta repeat time for the loop, and one will result in 1s repeat time.
When using timers in polling mode, the timer is normally just compared with the planned stop value. Most people runs the timer free-running, where it uses the full 32-bit span and then restarts the next turn. Such a delay would then capture the timer value on entry to the delay. Then it would continuously poll the timer value and compute t1-t0 using unsigned integers. If the difference between the two values is >= the number of ticks to wait, then the delay function can return. Such code will not suffer from the timer counter wrapping as long as you don't try to have delays longer than the number size that fits in the counter. And such code can use the same timer for many different timing issues.
The normal use for the auto-reset is with an interrupt handler. Each time the timer counter gets reset, you let the timer create an interrupt. This interrupt may count uptimes or perform other quick things, but long before the interrupt handler ended (or even was entered) the timer would already be busy counting the next period.
Please replace your delay() with the below code, and give it a try.
void delay() { T0PR = 0x0000270F; // Prescale Register = 9999 T0MR0 = 0x000004B0; // Match Register = 1200 T0MCR = 0x00000004; // Stop on MR0: the TC and PC will be stopped // and TCR[0] will be set to 0 if MR0 matches the TC. T0TCR = 0x02; // Counter Reset T0TCR = 0x01; // Counter Enable while(T0TC != T0MR0); }
I am not good at explanation due to my limited English ability and technical ability. If my code works (please give it a try.), I will try to explain my perspective.