Professional Documents
Culture Documents
Counters and timers are two entities that we must encounter in a μcontroller.
They both do exactly the same thing. Indeed they correspond to registers that count
up or down and have rising or descending fronts, or both. The difference between
the two names is that, in the case of timers, the front sequence that supplies the unit
is periodic and has a known period (which is often adjustable). This implies that the
value contained within the register corresponds to a time measurement, hence its
name.
The main event that occurs in the process of incrementation (or decrementation,
respectively) is the overflow (or underflow) of the capacity of the register. Many
things can intervene in this event but the main two programmable actions on
overflow (underflow) are sending an interrupt request and reloading a given value in
the counting register, causing a sample call to a specific routine. This functionality is
necessary for the development of a real-time kernel whose main role is sharing
central processing unit (CPU) time between different tasks running on the processor.
The motivation for the Advanced RISC Machine’s (ARM’s) choice to provide a
timer inside the core was to be free from the specificities of the μcontrollers (and so
to be free from the choice of developers) so that a real-time kernel base could be
developed for all of the circuits based on Cortex-M3. On its website, ARM lists the
partners proposing such a real-time kernels (Real-Time Operating Systems) – there
are over 20, and the list is subject to frequent change.
210 Assembly Language Programming
Request IT n°15
Maximum Value: 0x00FFFFFF
Current Value
N
Reload Value
Start
Overflow cycle: (N+1)*h
Clcck
h: Clock period
B.2. SysTick
The SysTick timer is a 24-bit decrementation timer. Unlike the complex timer
units that we can find in a μcontroller, it has no functioning modes other than a
24-bit decrementation. Its overall operation is summarized in Figure B.1.
One subtlety is in how to avoid mistakes in the programming of this timer. The
interrupt request takes place when the current value switches from 1 to 0, but
reloading only takes place at the next rising edge of the clock. This obviously means
that in the case of periodic functioning (which is a priori the classic functioning) the
interrupt call has a periodicity of N + 1 clock cycles, with N being the value stored in
the reload register. In the example presented (Example B.1), this reload value is first
calculated as the ratio (integer division) between the frequency of the internal clock
(Freq_Quartz) and the request frequency (Freq_Request). This ratio is then
Appendix B 211
decremented by one to take into account the interval between interrupt and reload.
Finally, note that in such a calculation the request frequency does not necessarily
match up to the real frequency of functioning. In fact, as this calculation rests on an
integer division, there is no guarantee that the remainder from this division will be
zero. Another, more atypical, function is possible and involves modification of the
load value every time the handler is activated. By definition, it is no longer a
periodic function but an alarm clock function reprogrammed each time, we assume
being calculated to correspond with N cycles of the clock. As direct “by hand”
reload by assignment of the current value is not possible, we can carry out this
reprogramming by affecting the reload value, but with N instead of N – 1. In fact, we
could consider that the starting of the timer corresponds to the next interruption and
as the activation will take place as the current value switches from 1 to 0, it is
normal to start with the calculated value.
When SysTick is active, the value of this register decreases with each rising front
of the clock. As this timer is coded in 24 bits, the eight most significant bits in this
register are always at 0. It is possible to get read access to find out the current value.
However write access, if permitted, is limited: whatever value you want to write,
such access would result in deletion of the contents. It is therefore not possible to
write a value to this register – you can only erase one.
This register (see Figure B.2) has only four significant bits:
– COUNTFLAG: switches to 1 if the counting register (Current Value) has
switched to 0. It is reset either when the processor reads the register containing this
bit (Control and Status), or when the processor writes a value in the Current Value
register. This bit allows the use of the timer without using interrupts, simply by
scanning the state of this bit. Obviously this is not as effective as the interrupt
because the scan uses CPU time. What is more, the detection is not concurrent with
the event, so the precision of time measurement is not assured.
– CLKSOURCE: there are two clock sources that supply the timer. The first,
which is standard and corresponds to the bit being set to 1, consists of using the
internal clock of Cortex-M3. It is, however, possible (with the bit set to 0) to specify
an external clock. This clock is only external to Cortex-M3 and not the μcontroller
that integrates it and must be a fraction (at least 2.5 times smaller) of the internal
212 Assembly Language Programming
– TICKINT: when this is set to 1, it enables the launch of the SYSTICK exception
(fifteenth entry in the table of interrupt vectors) when the decrementation of the
timer gives 0.
– ENABLE: this is the bit that starts (bit at 1)/stops (bit at 0) the timer. As soon as
this bit is activated, each rising front of the chosen clock causes the decrementation
of the Current Value register. At the moment when it is switched to 1, the Current
Value register is loaded with the value contained in the Reload register.
This register, insofar as it serves as a reset value for the Current Value register,
can only receive a value between 1 and 0x00FFFFFF. It is possible to give it a
value of 0, but this would inhibit the functioning of SysTick. After a Reset, the value
of this register is unpredictable.
documentation. The main datum, TENMS (10 milliseconds) (the 24 least significant
bits) is therefore a value set by the circuit designer. If we later want another
sampling period, proportional to 10 ms, we just need to read this register, add 1 to
get the number of cycles corresponding to these 10 ms, apply the necessary
proportionality ratio (multiplication or division), subtract 1 and modify the reload
value with this value.
In this example, three generic procedures have been written. The first two
(Start_SysTick and Stop_SysTick) allow us to start/stop the timer. The third
(SysStickSetPeriod) is called by Start_SysTick to calculate the reload value needed
to operate the SysTick periodicity at a chosen value (Freq_Request). We assume that
the SysTick clock has a frequency of 8 MHz.
variable (Time_Val) is decremented, allowing the main program to start the timer
until the variable is cancelled.
;*************************************************************
; DATA SECTION
;*************************************************************
AREA MyData, DATA, ALIGN=0
;*************************************************************
Freq_Quartz EQU 8000000
Freq_Request EQU 100
SysTick_CTRL EQU 0xe000e010
SysTick_LOAD EQU 0xe000e014
SysTick_VAL EQU 0xe000e018
SysTick_CALIB EQU 0xe000e01C
Time_Val DCW 123
;*************************************************************
; PROGRAM SECTION
;*************************************************************
AREA MyCode, CODE, readonly, ALIGN=2
Appendix B 215
;*************************************************************
;– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
SystickSetPeriod PROC
LDR R1,=Freq_Quartz ; Read clock frequency
SDIV R2,R1,R0 ; Calculation of number N of
; cycles for desired freq.
SUBS R2,R2,#1 ; Modification of value N – 1
LDR R3,=Systick_LOAD ; of reload register
STR R2,[R3]
BX LR
ENDP
;– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
Start_SysTick PROC
PUSH LR
LDR R0,=Freq_Request ; Load value of requested period
LDR R1,=SysTick_VAL
STR R0,[R1]
BL SystickSetPeriod ; Initialization of reload
LDR R0,=Systick_CTRL
LDR R1,[R0]
ORR R1,R1,#4 ; Choice of clock
ORR R1,R1,#2 ; Authorization of interrupt
ORR R1,R1,#1 ; Timer launch
STR R1,[R0]
POP PC
ENDP
;– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
Stop_Systick PROC
LDR R0,=Systick_CTRL
LDR R1,[R0]
BIC R1,R1,#2 ; Deactivates systick interrupt
BIC R1,R1,#1 ; Stops the timer
STR R1,[R0]
BX LR
ENDP
;– – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – – –
216 Assembly Language Programming
SysTick_Handler PROC
EXPORT SysTick_Handler
LDR R0,= Time_Val ; Loading of global variable
LDRH R1,[R0]
SUB R1,#1 ; Decrementation
STRH R1,[R0] ; and storage
BX LR
ENDP
;*************************************************************
; PROGRAM SECTION
;*************************************************************
;*************************************************************
main PROC
LDR R5,=Time_Val
BL Start_Systick
CMP R0,#0
BNE Unfinished
BL Stop_Systick
ENDP