Ethernut 5 Timer/Counter
Note: Until version 4.10.2, Nut/OS uses timer/counter 0 as the system timer. From release version 4.10.3, timer 0 is available for applications as the Periodic Interval Timer is now used as a system timer.
Unlike many other peripheral devices, Nut/OS does not provide a specific API interface for the timer/counter. The necessary hardware access must therefore be implemented as part of the application. Nut/OS does offer a few basic functions based upon the system clock - See Sleep and Delay in Nutwiki.
The AT91SAM9XE CPU has a total of 6 timer/counters, which are divided into two groups. Details can be found in this Datasheet.
These blocks can be used very flexibly, which makes dealing with them quite complicated, especially for newcomers.
Register access
While Nut/OS does not offer a portable API, it does have all the necessary hardware register definitions. This allows the application code within the AT91 family to be reasonably portable. It should be noted that there are some differences within that CPU family, so the data sheet of the specific chip must be followed precisely.
The hardware register definitions are located within the header file arch/arm/atmel/at91_tc.h. This header must not be explicitly inserted in your program code itself. The header files are likely to include compiler.h at some point, which subsequently includes the at91_tc.h file. If this is not the case, for instance if you do not use any other Nut/OS headers/features, then include arch/arm.h or compiler.h at the start of your own source code instead:
#include <compiler.h> ...or... #include <arch/arm.h>
For clarity, C register names in Nut/OS are consistent with those used in the datasheet.
Nut/OS uses the somewhat old-fashioned-looking features out () and in() to write and read values to/from registers. Refer to Low Level Port I/O in the Nutwiki, specifically the sections entitled "Nut/OS port access macros" and "Using Digital I/O on AT91 ARM".
It should be noted that the compiler can only perform limited checks on the variable types used with macros. If you are programming for Nut/OS version 5, you should consider using the newer inline functions or mem_wr mem_rd, which are also available from the file arch/arm.h
To save power, the timer/counter is not supplied with a clock automatically after reset. The clock signal is mandatory and must be enabled by the application code . This is done by setting the corresponding bit in register PMC_PCER. For example for the timer 1:
outr(PMC_PCER, _BV(TC1_ID));
This step is easily forgotten, and causes a lot of frustrating problems early in development because nothing works!
The interval timer is activated with
outr(TC1_CCR, TC_CLKEN);
Now you need only set the TC_CMR register correctly and possibly start the timer with
outr(TC1_CCR, TC_SWTRG);
In fact, the configuration can be complicated, depending upon what you would like to achieve as other timer registers are involved. Hint: If you want to control digital outputs with a timer, you have to activate the corresponding peripheral function of the GPIO ports. For this purpose, it is recommended that the pin definitions in arch/arm/atmel/at91sam9xe.h are used. This will ensure that these pins actually exist - If the code is later translated to another CPU, the compiler will complain immediately and you do not run the risk of damage due to wrong pin configuration your hardware. For example:
/* Enable TIOA peripheral function. */ outr(PIOA_ASR, _BV(PA27_TIOA1_A)); outr(PIOA_PDR, _BV(PA27_TIOA1_A));