┬ÁTasker Forum > FreescaleTM MC9S12NE64

Global Hardware Timer

(1/2) > >>

Hi Mark,

I am trying to set up the global hardware timers for a 10ms timeout.

After playing around a bit, and checking the docs I notice that the define for MILLISEC doesn't appear to exist in the NE64 project.

When I try to set the timeout using:


The timer triggers only once - the delay value ends up being set to 0. ( The uTasker tick is set to the default of 34ms.)

I suspect that a correct define for the MILLISEC would fix the problem - has this value been determined for the NE64?



Hi Jamie

I didn't realise that the NE64 project SP1 was missing Global HW timer support but it really is not completely configured.

There are a few things to note:
1. The original method used a define for the resolution but was subsequently adapted to work with MILLISEC (according to present documentation) but the NE64 project not completely.
2. The MILLISEC method (as also the previous one) suffers from rounding errors with larger values and the development version is now using a macro which allows better accuracy.
3. The original support (corresponding to NE64 SP1) has a couple of bugs, including not always retriggering properly and also some cases of multiple timers being stopped not being handled correctly.
This means that sometimes it works fine but can suffer from problems in certain cases. I suggest generally avoiding Global HW timer support in preference of HW timer interrupts. This is generally not a problem as long as the number of timers needed is not more that the available 16 bit timers in the chip and is also more accurate (direct interrupt handler rather than via global task distibuting events).

Here are my proposals.

1. Quick correction to use a 10ms timer (no problems should be encountered if using it as only timer in Global HW Timer system).
- define macro: #define HW_TIMEOUT_MS(x) (CLOCK_LIMIT)((x * (BUS_CLOCK / 128))/1000)
- start the timer as follows: uTaskerGlobalMonoTimer( (UTASK_TASK)(OWN_TASK | HARDWARE_TIMER), HW_TIMEOUT_MS(10),  E_TIMER_TEST_10MS ); // start a 10ms timer
The macro ensures optimum accuracy without any accumulative rounding errors. It can be used with constant values as in the example or with variables. Fixed values resolve the value at compiler time so are optimally efficient.
- In ne64.c change one line in fnSetHardwareTimer() as follows
OLD: CLOCK_LIMIT NewDelay = (CLOCK_LIMIT)(*hw_delay * ((BUS_CLOCK / 128 / 1000) * HW_TIM_RES));
NEW: CLOCK_LIMIT NewDelay = *hw_delay;

2. I will add the HW timer interrupt interface as is now standard in newer versions. This allows defining timers with interrupt handers via a standard interface. I'll send this to you via email so that you can then see whether it is more suitable for your project.



PS. A revised version of the global hardware timers is planned to address some weaknesses which have been experienced...

Hi Mark,

I tried your quick fix for a 10ms Global HW timer - it does work (though it was running at 20ms with the values you gave but I think it was probably something I was doing wrong)

Does the HW timer interrupt interface support other timers?  The Global HW timer is set up by default to use timer 7 but our hardware uses PT7 to generate a waveform using output compare.  I am not sure yet but I would expect a conflict. 

So it might be easier to set up a different timer for my 10ms timeout using the HW timer interrupt interface.




I looked again in more detail but think that there is a problem here due to the fact that the NE64 is quite limited in timer support. It has one PIT (Periodic Interrupt Timer), which is used by the OS Tick. It then has one 4-channel 16 bit timer module.

The restriction in the timer module is that it has only one 16-bit counter. The 4 channels (4,5,6,7) are all based on the single counter and can thus generate interrupts and waveforms, but only channel 7 has the capability to reset the counter and thus control the basic rate of a periodic interrupts or frequencies - the other outputs can do things like pulsing an output at a fraction of the period - useful for PWM etc. but are not independant.

Therefore, if channel 7 is used for another application, the timer module can not be used to generate other delays (unless they are somehow synchronised to the other use, which is probably not the case). I am presently working much more with the M5223X Coldfire which has this module (or at least very similar), 2 PITs and additional 4 x 32-bit timers which are totally independent, so I seemed to have forgotten how much more restrictive the NE64 is.

I am wondering whether a suitable solution for your use would be to set the TICK to 10ms and then use a simple SW timer?

There are some other workarounds however if a HW interrupt is absolutely needed, even when no timer if free to deliver it:
If you have a free UART or SPI it can be programmed to transmit a byte with a transmission rate corresponding to the delay that you require (depending on prescalers available, the resolution may not be perfect, but you could be lucky). Once the transmission has freed the output buffer it will generate an interrupt (probably after a few bit transmission times which can be easily determined by experimentation or studying the data sheet and will be fixed according to teh baud rate set up). I have used this method to run the TICK from in order to free up the PIT in another processor. The TICK is running continuously from a UART interrupt, which is sending each time a dummy byte of data (the port pin doesn't need to be set to UART so the data goes no where) and the character time is set to generate the basic TICK rate required. The PIT can then be used for additional hardware periodic or single-shot interrupts. Note however that the resolution of the PIT in the NE64 is not that high so again only approximate delays may be possible (eg. instead of 10.0000ms one may have to settle for 10.05ms since the clock and dividers doen't allow higher resolution - this is not a calculation but fictional example...)

Which solution looks most practical for you?



Hi Mark

I think for me the easiest thing to do is try the regular SW timer.  I changed the tick to 10ms and used uTaskerMonoTimer.

This seems to work ok. 




[0] Message Index

[#] Next page

Go to full version