Forum : ST7/STM8
Post Information | Post |
---|---|
April 27, 2009 - 2:08pm
|
Hello, I have got the following problem. I am using a ST7FLIT19B microcontroller. I would like to use the lite timer of the controller for a system clock. To do this I defined a time structure similar to the timeval structure: typedef struct stTimeSpec { UINT32 tv_sec; // seconds since last reboot UINT16 tv_msec; // milliseconds since last reboot } stTimeSpec_t; I then defined a global variable To guarantee the consistency of the time structure for any given access, I would like to restrict access by any function other than the timer interrupt through a time_get function. This time_get function copies the value of the global structure to an address supplied and protects this memcopy by disabling the timer interrupt before starting the copy and enabling it again after the copy is done. void get_time(stTimeSpec_t *currentSystemTimePtr) { TB1IE = 0; // Disable Timebase interrupt memcpy(currentSystemTimePtr, &systemTimeGlob, sizeof(systemTimeGlob)); TB1IE = 1; // Enable Timebase interrupt } In order to do this, I would like to selectively disable the timer interrupt for the Lite Timer by clearing the TB1IE bit in the LTCSR1 register of the controller and then enable it again by setting the bit after the memcopy is done. When I try this approach however, I am losing a millisecond from time to time. My first approach was to clear and set the bit by accessing the byte-address of the register and just using a bitmask for the TB1IE bit. This made me lose lots of timer interrupts, often several in a row. After reading the documentation a second time, I guess this was due to the fact, that accessing the LTCSR1 register this way cleared the TB1F flag and therefore a timer counter overflow occurring during the memcopy would get lost. The second approach now is to directly address the bit in the register, using the directive The only way I was able to lock the interrupts for the memcopy and not lose any timer interrupts at all was to use the _rim_(); and _sim_(); instructions, therefore locking all interrupts for the time of the copy operation (which is not a good idea and which I would like to avoid). Can you explain to me, why this is happening and if there is any way to prevent this while still being able to deactivate the timer interrupt during the memcopy? Do you have any suggestions how I could accomplish what I have in mind, or is it just not possible with the controller I am using? Thanks for your help, |
Hi Stephan,
From your example I think you have an invalid bit address for TB1IE. It should be:
at 0x5C hbit TB1IE; // NOT 0x5B!
I tried to compile your code and it should work fine now:
The initial code you posted was not devalidating the interrupts, hence some registers accesses could be done in non-atomic (destructive) ways.
Let us know if you still have some issues.
Regards
Hi Bruno,
thanks for the fast answer.
I followed the example given in the hbit keyword description of the RCST7 compiler manual for determining the TB1IE bit address.
From this I deducted that the TB1IE bit (bit 4 of the LTCSR1 register) should have the address (0x0B * 8) + 3 which equals 0x5B. After your answer I checked the compiler manual again and found another description for the at keyword.
Following this description the address would be (0x0B * 8) + 4 which equals 0x5C (as you pointed out to me). So I was mislead by the example for the hbit keyword in the compiler manual which seems a bit confusing to me in regard to the numbering of the bits.
Unfortunately even with the correction you posted I am still losing timer interrupts (and hence milliseconds) when disabling timer interrupts. The reason for this seems to be, that I am using the time struct to implement a wait_ms function. In this function I am spending a lot of time with the locked timer interrupt. Now I seem to lose an interrupt every time the timer counter overflows while the interrupt is locked. I was expecting that the TB1F flag would be set when an overflow occurs, regardless if the timer interrupt is enabled or disabled. I was further expecting, that after enabling the timer interrupt again by doing a direct bit access I would immediately get the timer interrupt, since the TB1F bit should indicate that a counter overflow has occured. But it seems to me that this is not happening.
I could supply you with a stripped down sample project which shows how I am using the global timestruct and might better explain my problem if you could supply me with an email address where I can send it to.
Regards,
Stephan
Hi Stephan,
You are right about hbit, this is a compiler documentation bug! The "hbit" examples are invalid. We will correct this in the documentation for the next release. Thanks for the bird's eye!
Concerning your millisecond loss, I am surprised by this behavior, and I do not have much idea how to proceed. Can you simulate the overflow interrupt (using Ride7) and retrieve the cycle time required by the whole increment? The operations should not be more than few tens of cycles, which obviously fit within a millisecond.
Do you loose _all_ the overflowed milliseconds, or only some of them?
Also can you try to slow down the speed of the interrupt and check if the problem still happens?
Also did you activate the SPEED optimization mode (at least for the interrupt handler and get_time)? This could make the execution faster and keep you safe of the problem.
Regards,