The CCOUNT register increments on every processor-clock cycle. When CCOUNT =
CCOMPARE, a TIMERINT interrupt request is generated. Although CCOUNT continues to increment and thus matches for only one cycle, the interrupt request is remembered until the interrupt is taken. In spite of this, timer interrupts are cleared by writing
CCOMPARE, not by writing INTCLEAR. Interrupt configuration determines the interrupt number and level. It is automatically an Internal interrupt type (the INTTYPE
configuration parameter, Table 4–70).
Is it possible to setup suc interrupt under RTOS application layer, or it requires RTOS kernel modification? Which of those CCOMPARE registers are reserved for RTOS (if any)?
I just want to extend that 32bit CCOUNT value to 64 bits. So value in CCOMPARE[1] (or any other available index not used by RTOS) would be 0, with meaning to generate a non-maskable interrupt when wrap-arround 32 bit boundary happens. In ISR it only needs to increment a value in some 32 bit variable in RAM which would be set up to 0 once chip is powered up. As such interrupt can occur only once in 17.89 seconds (it is approximatelly, for chip running at 240MHz) so its impact on the rest of any critical time routines can be ignored and it can be set up as non-maskable interrupt of the highest priority.
I am aware that reading of such "quasi" 64 bit value on 32 bit cores must be performed with two 32bit readings in assembly code, so some, let's say function GetCCount64 written in assembly, with intention to get that composed 64bit snapshot as accurate as possible and as sooner as possible, and still properly handle that wrap-arround problem could look like this:
(this is just pseudo code with crucial comments and timing examples of each assembler instruction)
Code: Select all
call to this function (lets say 3 clocks)
and assignment the result value to some 64bit variable (4 clocks)
uint64_t GetSnapshotCCount64(void){
1. DiasableInterrupts (lets say 10 clocks)
2. FlushTheCacheLines (lets say 5 clocks) // we do not want cache impacts on execution time
3. read HigherPart of CCOUNT in lets say R1 register //stored in our memory location and handled by our ISR (lets say 1 clock)
4. rsr.CCOUNT in some register lets say R0 // read the value of lower 32bit part (CCOUNT is special register so rsr instruction is required for reading of its content (lets say 2 clocks)
5. compare that value in R0 with 32 bit constant 0x00000003 // that is the amount of clock cycles spent from reading of higher part to reading of lower part. If value in R0 is less than that (means value in R0 is 0,1 or 2), we know a wrap-arround has just happened and read value in R1 belongs to previous wrap so we have to increase it by 1
6. Now we have 64 bit value in register pair R1 and R0 which represents proper 64 bit snapshot at the moment after execution of assembler instruction in step 4 and we want to compensate all clocks spent
in calling of our function and clocks of steps 1, 2, 3 and 4 so we will subtract 25 clocks from that 64 bit snapshot like uint64_t result = R1:R0 - 25 (because all clocks till step 5 sums to 25)
7. EnableInterrupts
8. return compensated 64 bit result
}
With proper execution times of each instruction, we should be able to anulate all the clocks spent by calling this function and have exact snapshot of 64bit clock counter just right before the function is called. So you can write something like:
Code: Select all
uint64_t snap = GetSnapshotCCount64();
the first instruction of your code
the second instruction of your code
....
uint64_t ticks_spent = GetSnapshotCCount64() - snap;
However that same the function can be used to virtualy compensate ticks spent in any function (system or ISR routine(s) doesn't matter), but that is an another topic.
I also do not know why such a function is not already implemented although all XTENSA cores contain at least one (most of them contain 4) of CCOMPARE register. Such a function can be handy in many other cases (from debuging and fine-tuning, synchronizing of different ESPs, measuring performances and so on). Anyway, I can handle that assembler part for proper compensation, but can someone help in activating that hardware capability implemented in XTENSA cores in RTOS environment?