Hi,
Can I get an example of reading the CNTFRQ register in cortex-a9 using assembly inline of arm compiler 5 (DS built in) ?
I didn't find anywhere...
If you just need to read the CNTFRQ register, defining a named register is probably the easiest way of doing this:
https://developer.arm.com/documentation/dui0472/m/Compiler-specific-Features/Named-register-variables?lang=en
The manual (above link) gives an example based on PMCR:
You'd just need to replace ("cp15:0:c9:c12:0") with the correct value for CNTFRQ.
Thank you very much for your reply.
I saw this page but I didn't find the CNTFRQ register name (I'm new to assembly). Is there a chance you can guide me with this? why I can't find this register name in these pages, maybe I'm looking wrong? from my understanding this register exists in all ARM architectures.
I started replying about named registers and then remembered...
CNTFRQ is a Generic Timer register, which is an architectural extension to Armv7-A. The Cortex-A9 doesn't support that extension, so the CNTFRQ register won't exist on a Cortex-A9.
The Cortex-A9 does have integrated timers, but they're memory mapped:
https://developer.arm.com/documentation/ddi0407/i/global-timer--private-timers--and-watchdog-registers?lang=en
So to access the timer registers you just need to know the virtual address they are mapped to.
-------
In Armv7/AArch32, the CP15 system registers have a name (e.g. PMCR) and an encoding (PMCR = "cp15:0:c9:c12:0"). In assembly you refer to register by its encoding.
What the "register unsigned int PMCR __asm("cp15:0:c9:c12:0")" means is "treat the variable PMCR as the system register with the encoding cp15:0:c9:c12:0".
So what you need to do is provide the equivalent for CNTFRQ.
The encodings for system registers are given in the Arm Architecture Reference Manual, but it's often easier to use the online XML descriptions. Starting with PMCR:
https://developer.arm.com/documentation/ddi0601/2022-12/AArch32-Registers/PMCR--Performance-Monitors-Control-Register?lang=en
PMCR => coproc=cp15 opc1=0 CRn=c9 CRm=c12 opc2=0
Comparing that with CNTFRQ:
https://developer.arm.com/documentation/ddi0601/2022-12/AArch32-Registers/CNTFRQ--Counter-timer-Frequency-register
CNTFRQ => coprocessor=cp15 opc1=0 CRn=c14 CRm=c0 opc=0
Which would give something like:
register unsigned int CNTFRQ __asm("cp15:0:c14:c0:0")
Note: In AArch64 things are a little different.
Thank you for your detailed reply.
I have 2 followups , by your permission:
1. I read below that cortex-a9 is armv7-a architecture. so why it lacks this register?
https://developer.arm.com/Processors/Cortex-A9
2. Do you know which register I need in order to get the cpu frequency in case cntfrq doesn't exists? (baremetal app)
Thanks again
bsp_user said:1. I read below that cortex-a9 is armv7-a architecture. so why it lacks this register?
Armv7-A supports a number of optional extensions (e.g. Virtualisation, Generic Timer, Large Physical Addresses...). Not all Armv7-A processors will support all of the extensions.
You can check a processor's TRM to see which extensions are implemented, and the information is also reported via feature registers in the processor.
Thank you for your help. Do you have any Idea how I can read the frequency in another way (since this register doesn't exists)
I think Ronan answered on the other thread. But one comment, for processors that support the Generic Timer, CNTFRQ reports the frequency of the timers - not of the core. The timer frequency is fixed and typically slower than the core's frequency (which might be subject to DVFS).