Hi all,
I've just started using an MC13213 mcu and am struggling setting up interrupts. I am trying to set up timer 0 channel 0 as an output compare to generate an interrupt to be used for a simple delay. I feel like I've set up all of the control registers properly, but once the program is running in the debugger (hiwave w/ P&E micro USB), the free running counter does not appear to be counting which in turn means an interrupt is never generated. Here is my initialization code:
TPM1SC_CPWMS = 0; //set pwm for output compare
TPM1SC_CLKSA = 0; //A:B -> 0:1 == System clock
TPM1SC_CLKSB = 1;
TPM1C0SC_MS0A = 1; //MS0A:MS0B -> 1:0 == outputcompare
TPM1C0SC_MS0B = 0;
TPM1C0SC_ELS0A = 0; //ELS0A:ELS0B -> 0:0 == software compare
TPM1C0SC_ELS0B = 0;
TPM1C0SC_CH0IE = 1;
TPM1C0SC_CH0F = 0;
TPM1C0V=TPM1CNT+E_PER_MS; //set value register for compare
E_PER_MS is equal to the number of clock cycles per ms, so this interrupts once per ms.
Here is my interrupt code:
interrupt 5 void OC0Isr(){
TPM1C0SC_CH0F; //Read Flag
TPM1C0SC_CH0F = 0; //Clear Flag
TPM1C0V=TPM1CNT+E_PER_MS;
OCmSCnt++; /* Increment counter */
}
My Delay function (delays a passed number of ms):
void OCDelay(INT16U ms){
INT16U start_cnt;
start_cnt = OCmSCnt;
while((OCmSCnt - start_cnt) < ms){} /* wait for ms to pass */
}
My main function (just to blink an led every .5 seconds:
void main(void) {
PTCDD = 0x10; // initialize PTC4 as output
PTCD = 0; // initialize PTC to 0
OCDlyInit();
ENABLE_INT();
for(; {
OCDelay(500);
PTCD_PTCD4 = ~PTCD_PTCD4; // invert the output
} /* loop forever */
/* please make sure that you never leave main */
}
Any ideas on what is going on here? I am using the default start08.c startup code, except I disabled the COP timer. Thanks for any suggestions,
Dan
Added p/n to subject.
Denn*** wrote:And its a better, safe practice to read Interrupt event flag CHOF when it is set and then clear the flag in the ISR as menitioned in the HCS08 datasheet. But it also works without the initial dummy read of this flag/corresponding register!!!
bigmac wrote:
Now consider the action of the statement to clear a single bit -TPM1C0SC_CH0F = 0;When this is executed, the value within TPM1C0 will first be read. Then the bit corresponding with CH0F will be set to zero, and the whole byte then written back to the TPM1C0 register. This what is meant by a "read-modify-write" sequence, and is precisely the action required to clear the flag bit.In practice, the compiler may utilize a single BCLR instruction, which obeys the sequence described above.The dummy read is therfore never necessary (but should do no harm).
They mention that it must be read first because not every write to the register will create a read first. Writing a whole byte to the register will not read the register first and if the bit is cleared this way a dummy read is needed before this.
Denn*** wrote:I think the "read-modify-write" sequence what you are referring to is the one that is( I'm not sure about this ) happening within the controller.And if BCLR instruction obeys the sequence described above why should Freescale HCS08 datasheet menition about the initial dummy read of "event flag register" TPMxCnSC and then the bit clear of event flag CHnF.
one can go to the type we follow(just an example nothing to do with above code),which generates less code & executes in less time.Also more clear than the above one.
TPM2SC = 0x0B;// 0b00001011 // |||||||| // |||||||*--- PS0 : Timer Prescaler 0 // ||||||*---- PS1 : Timer Prescaler 1 // |||||*----- PS2 : Timer Prescaler 2 // ||||*------ CLKS3 :Clock Source Select // |||*------- CLKS4 : Clock Source Select // ||*-------- CPWMS: Center-Aligned PWM Select // |*--------- TOIE : Timer Overflow Interrupt Enable // *---------- TOF : Timer Overflow Flag
Again in mass production kind of projects (productions in millions.I really mean it) say automotive or telcom, customers normally prefer cheaper (in price) MCUs. Each cent they save will make a huge difference at the end .Here cost reduction will be the mantra.They want to eliminate all those things that are unnecessary.As you know the cheaper MCUs come with slight pinch like less featureslike say 32k flash MCUs will always be less costlier than say 60k variant of the same MCU.In a such case one has to code efficiently as much as possible. I would say better code is the one which executes in less time takes less memory.Also there could be some contraints from customers saying there should be atleast 10% free space in flash say for future bug fix before release into the market from the time of delivery of code.
In these scenarios one cannot lavishly spend program memory. Try to reduce code,Speedy execution will be the goal.
"Software Engineering principles" like documentation/related quality process will always be followed in large scale production.These days one can even find in the ordinary medium scale productions unless product is produced in lesser quntities.
Anyway my concern had nothing to do with the above sample code.I understand Dan had written a sample pgm to test interrupt.It was with the clearing process of event flagCHnF inside the ISR.Was dummy read really reqd to clear event flag(also in this case ISR)???
Regards,
Denn
JimDon wrote:
On the other hand, a bedside alarm clock that fails to go off on February 29th, while not desirable, is no big deal. Chances are the user may not even notice. And if you are going to make 50 million of them, it makes sense to spend a considerable amount of time squeezing the code down to the cheapest part. If it saves 5 cents per unit to not go off on on February 29th, that's 500K of savings. I'm not saying that would 100% be the right choice, but it might be.
An algorithm in computer science is robust if it continues to operate despite abnormalities in input, calculations, etc.
JimDon wrote:
I still don't think my advice was biased and can only be applied to a project with less memory.So, my point is you can't just make sweeping rules that cover all situations, and quite often "advise" is biased one way or the other.
Denn*** wrote:
There they mention about a 2 step procedure. 1)==> Read then 2)==>write 0 to flagbit(BCLR used by compiler)
Denn*** wrote:Why would FSL ask for a dummy read if BCLR was sufficient as justified by Mac and Allawtterb. (Also Refer section Clearing Timer Interrupt Flags)
interrupt 5 void OC0Isr(){ TPM1C0SC = 0x48; // Clears the CH0F flag, but doesn't read first! // Do something}
Denn*** wrote:Aren't we giving a chance for a bug ? Even I've observed just bitclearing is sufficient to clear event flag.But sometime later who knows event flag may not be cleared by just BCLR.How can one always ensure it always works in our favor.Safe practice is to follow what data sheet says rather than to experiment to save maybe 1 byte (possibly just LDA ) in program memory.
Denn*** wrote:So you think dummy read is not necessary.
No I did not say this, I don't have a problem with someone doing it either way. When I have a flag that reqiures a reading before writing to clear it I have always explicitly read it for the reasons I stated above, being clear about the operations needed to clear the flag.
This is what my first response was about, writing to a single bit isn't the only way to clear the flag. You can write to the whole byte. If you do it this way a dummy read is always needed to clear the flag properly.
Denn*** wrote:If then why would FSL datasheet mention about dummy read as the first step in clearing event flag.
DSweet wrote:
the free running counter does not appear to be counting