How properly, under RTOS, to set up the highest priority non-maskable interrupt vector?

djixon
Posts: 113
Joined: Sun Oct 01, 2023 7:48 pm

How properly, under RTOS, to set up the highest priority non-maskable interrupt vector?

Postby djixon » Fri Apr 19, 2024 8:56 pm

For example, in XTENSA ISA architecture there are several CCOMPARE registers, capable to generete an interrupt once CCOUNT (32bits hardware clock counter) matches the value in any CCOMPARE register. Since setup of an interrupt also requires interrupt priority level, the my goal is to set up that interupt with highest priority, so it can not be masked (disabled) or interrupted by any other interrrupt, because only one assembler instruction will be executed in that ISR handler and that should not impact on any other high priority interrupts. (actually 2 istructions, because, according to documentation, writting value back to CCOMPARE is required to clear that interrupt bit):
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;
   
Snap variable will contain proper 64 bit snapshot clock value, just the same as it would be captured by the first instruction of your code by some hidden hardware mechanism. So "the first instruction of your code" executes at snapshot as there was no any function call before it. Offcorse, the real ticks are spent in that function but snap variable contains value as they are not. So you can add another snap1 varibale after your code and difference of those two will exact matches the ticks spent by your code only. Sure, that is just an illustrative example, becuse in RTOS environment you have to take into account possible switching contexts, interrupts happened during your code execution and so on.

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?

ESP_Sprite
Posts: 9729
Joined: Thu Nov 26, 2015 4:08 am

Re: How properly, under RTOS, to set up the highest priority non-maskable interrupt vector?

Postby ESP_Sprite » Sat Apr 20, 2024 12:51 am

You can. I attached an example on how to do that here. Note that this code is ancient, it e.g. still uses the old make build system, so you may need to tweak it a bit, but the details should be there. In general, this is not implemented in esp-idf because 1. that clock stops in any sleep mode (and may even not run if freertos is idle, I can't recall) and 2. is affected by frequency scaling. That means it's only useful to do performance measurement, and those events generally don't last anything near 17 seconds, so 32 bit is more than enough. For anything else, we have the GPTimers, which are 64 or 56 bit.
Attachments
asm_int_example.zip
(1.81 KiB) Downloaded 144 times

MicroController
Posts: 1706
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: How properly, under RTOS, to set up the highest priority non-maskable interrupt vector?

Postby MicroController » Sat Apr 20, 2024 6:44 pm

Are you sure you need a CPU cycle accurate time counter which can span more than 2000 years? - I'm talking about 'resolution' here. E.g. if some code would take 10 seconds to run, i.e. 2'400'000'000 clock cycles... realistically, who would care if it took 240 clocks more or less? Counting microseconds instead, you'd risk an inaccuracy of 1 part in 10 million.

IIRC, on the RISC-V's, by default, the CPU clock performance counter is halted while Waiting For Interrupt (i.e. OS is idling); the Xtensas' keep ticking.

Btw, lock-free code to read a multi-word counter can look like this:

Code: Select all

uint32_t cnt_lo1;
uint32_t cnt_lo2;
uint32_t cnt_hi;
do {
  cnt_lo1 = CCOUNT;
  cnt_hi = ccount_overflows;
  cnt_lo2 = CCOUNT;
} while (cnt_lo2 < cnt_lo1);
return (((uint64_t)cnt_hi)<<32) | cnt_lo2;
Last edited by MicroController on Sun Apr 21, 2024 8:57 am, edited 1 time in total.

djixon
Posts: 113
Joined: Sun Oct 01, 2023 7:48 pm

Re: How properly, under RTOS, to set up the highest priority non-maskable interrupt vector?

Postby djixon » Sat Apr 20, 2024 9:36 pm

@MicroController It is not about time! Forget a time as a frame of reference. It is about exact amount of instructions executed after some amount of clock cycles. So doesnt matter if one ESP runs at 80MHz another on 160 and third on 240, after N amount of ticks they have to execute the same amount of instructions (doesnt matter if fastest completes it in shorter time interval) with assumption that they execute the same code without asynchronic events, after N amount of cycles they all have to be at the same instruction. For proper measurement of efficiency of some process with respect to lets say consumed energy (and not measurement of time used) more efficient chip is one which get some job done by utilizing smaller amount of instructions (clocks). So if you have identical algorithm (which "talks" to some asynchronic process, lets say some communication with some third party) running on lets say two ESP chips where one runs at 240MHz and another at 160MHz both will complete the job (probably in different times but not necessary). However, if you measure the amount of ticks on both ESP, the efficient chip (with respect to power consumption) is one which achieved smaller amount of ticks during that execution of job. It completed the job utilizing smaller amount of instructions, so also less memory utilization, less cache invalidation and flushing, less DMA utilization and so on. So it spent less energy. In such a context, a 17.8 seconds window is too small for accurate measurements which could take hours esspecially if "whole job done" depends on that asynchronic events (in this primer, the comunication with third party) Etc.

@ESP-Sprite: Thanks for posted code. Here in attachment (link at bottom) is modified version which compiles succesfuly under latest ESP-IDF 5.2. A CPUticker64 is made as a component included within an example project. I also modified assembly code and made all necessary comments for testing. However, with all posible combinations of cpu timers, CCOMPARE(N) registers and all possible combinations for ESP_INTR_FLAG_LEVEL(N), RTOS can not find any free available resource for interrupt allocation. I've made comments inside the code how to properly TURN ON trace of allocation process during powering up chip. It looks that RTOS preallocates and reserves all possible resources on chip which is conceptual mistake. There must be left some free resources for custom user purpose. So I guess, that "user" custom ISR should be allocated before a RTOS allocate and reserve all available interrupts. Maybe I am wrong. You can check it. The assembler routine should be fine, but I couldn't test it because at first place allocation of interrupt has to pass properly. I do not understand why on RTOS allocating is so complicated. On any other platform it is simple as: 1. Write your own ISR routine 2.Store its address in interrupt vector address table 3. Set the priority and masks for it 4. Enable interrupt

Offcourse it is usually done at very first moment during cpu initialization sequence, but you could also made declaration of some pre-kernel functions for custom ISRs so when kernel reach allocation process, it sees that some of interrupts are already reserved and allocated by the user (or call it by user privileged drivers) so it skips messing with them and treats them as already reserved and unusable.

(this is the first time I am attaching a file link on this forum. I tested the link before attachment and it works fine. However if it is not visible on this forum, notify me and I will try to post it on another server)


https://easyupload.io/1ic44c
Last edited by djixon on Sun Apr 21, 2024 1:25 am, edited 1 time in total.

ESP_Sprite
Posts: 9729
Joined: Thu Nov 26, 2015 4:08 am

Re: How properly, under RTOS, to set up the highest priority non-maskable interrupt vector?

Postby ESP_Sprite » Sun Apr 21, 2024 1:00 am

The issue with interrupts in Xtensa CPUs at least is that you don't have a list of vectors, one per interrupt; instead you have a vector per interrupt *level* and there are only a fairly limited amount of them (5 or so iirc). For the C interrupts, we have a bit of code that multiplexes them but for the higher levels, we can't do that. Could be that by now some ESP-IDF features use these higher levels. Just to check: what chip are you trying this out on?

djixon
Posts: 113
Joined: Sun Oct 01, 2023 7:48 pm

Re: How properly, under RTOS, to set up the highest priority non-maskable interrupt vector?

Postby djixon » Sun Apr 21, 2024 1:27 am

ESP32-wroom-32E

If you tried that project, in sdkconfig you can see that I turned all watchdog timers off. I thought that RTOS utilize those timers for them. But even with turned them all off, simply that allocation routine pass through all 32 (priority levels) and can not find any available for allocation. All are reported as reserved although most of them don't even have any ISR assigned at all.

User avatar
ok-home
Posts: 78
Joined: Sun May 02, 2021 7:23 pm
Location: Russia Novosibirsk
Contact:

Re: How properly, under RTOS, to set up the highest priority non-maskable interrupt vector?

Postby ok-home » Sun Apr 21, 2024 3:45 am

use of nmi(level7) via esp_intr_alloc is prohibited during system initialization
https://github.com/espressif/esp-idf/ ... u.c#L241
https://github.com/espressif/esp-idf/b ... c.h#L294

ESP_Sprite
Posts: 9729
Joined: Thu Nov 26, 2015 4:08 am

Re: How properly, under RTOS, to set up the highest priority non-maskable interrupt vector?

Postby ESP_Sprite » Sun Apr 21, 2024 5:58 am

djixon wrote:
Sun Apr 21, 2024 1:27 am
ESP32-wroom-32E

If you tried that project, in sdkconfig you can see that I turned all watchdog timers off. I thought that RTOS utilize those timers for them. But even with turned them all off, simply that allocation routine pass through all 32 (priority levels) and can not find any available for allocation. All are reported as reserved although most of them don't even have any ISR assigned at all.
Your code is buggy. I can't be arsed to look at the rest of the code, but interrupt allocation works fine (with interrupt level 5, like my example code shows) if you make sure the int_CPUticker64_setup code is called *once* per cpu rather than *twice* per CPU, like your code does.

djixon
Posts: 113
Joined: Sun Oct 01, 2023 7:48 pm

Re: How properly, under RTOS, to set up the highest priority non-maskable interrupt vector?

Postby djixon » Sun Apr 21, 2024 8:41 am

Code: Select all

void app_main(void)
{
 int_CPUticker64_init();

   while(true){
//    uint32_t l=xthal_get_ccount();
//    ESP_LOGI("xtal", "%"PRIu32, l);

// here we expect to see that
// higher_CCOUNT increases by 1 after every 17.8 seconds 
// (that is approx if chip runs at 240MHz, wrap-arround 2^32 boundary is after 17.8 seconds)

    uint32_t h = higher_CCOUNT;
    ESP_LOGI("higher", "%"PRIu32, h);
     
    vTaskDelay(1000 / portTICK_PERIOD_MS); 
   } 


}
There is only one call to int_CPUticker64_init() in the app_main() so I do not know where did you found another one?

As I already told I tried all posible combinations and always get the same problem. Here is the exact version you posted which uses int5. Absolutelly the same thing.
  • rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff0030,len:7152
    load:0x40078000,len:14460
    load:0x40080400,len:4
    0x40080400: _init at ??:?

    load:0x40080404,len:3736
    entry 0x40080638
    I (29) boot: ESP-IDF v5.2-dirty 2nd stage bootloader
    I (29) boot: compile time Apr 21 2024 09:14:36
    I (29) boot: Multicore bootloader
    I (34) boot: chip revision: v3.0
    I (38) boot.esp32: SPI Speed : 80MHz
    I (42) boot.esp32: SPI Mode : DIO
    I (47) boot.esp32: SPI Flash Size : 4MB
    I (51) boot: Enabling RNG early entropy source...
    I (57) boot: Partition Table:
    I (60) boot: ## Label Usage Type ST Offset Length
    I (68) boot: 0 nvs WiFi data 01 02 00009000 00006000
    I (75) boot: 1 phy_init RF data 01 01 0000f000 00001000
    I (83) boot: 2 factory factory app 00 00 00010000 00100000
    I (90) boot: End of partition table
    I (94) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=09130h ( 37168) map
    I (113) esp_image: segment 1: paddr=00019158 vaddr=3ffb0000 size=02aach ( 10924) load
    I (117) esp_image: segment 2: paddr=0001bc0c vaddr=40080000 size=0440ch ( 17420) load
    I (125) esp_image: segment 3: paddr=00020020 vaddr=400d0020 size=12510h ( 75024) map
    I (149) esp_image: segment 4: paddr=00032538 vaddr=4008440c size=08c0ch ( 35852) load
    I (168) boot: Loaded app from partition at offset 0x10000
    I (168) boot: Disabling RNG early entropy source...
    I (180) cpu_start: Multicore app
    D (180) cpu_start: Pro cpu up
    D (180) cpu_start: Starting app cpu, entry point is 0x4008111c
    0x4008111c: call_start_cpu1 at D:/Espressif/esp-idf/components/esp_system/port/cpu_start.c:183

    D (0) cpu_start: App cpu up
    D (190) clk: RTC_SLOW_CLK calibration value: 3786842
    I (201) cpu_start: Pro cpu start user code
    I (201) cpu_start: cpu freq: 240000000 Hz
    I (201) cpu_start: Application information:
    I (206) cpu_start: Project name: CPU_ticker64
    I (211) cpu_start: App version: 1
    I (216) cpu_start: Compile time: Apr 21 2024 09:14:27
    I (222) cpu_start: ELF file SHA256: 7b820b5cd...
    I (227) cpu_start: ESP-IDF: v5.2-dirty
    I (232) cpu_start: Min chip rev: v0.0
    I (237) cpu_start: Max chip rev: v3.99
    I (242) cpu_start: Chip rev: v3.0
    D (247) memory_layout: Checking 9 reserved memory ranges:
    D (252) memory_layout: Reserved memory range 0x3ff82000 - 0x3ff82000
    D (258) memory_layout: Reserved memory range 0x3ffae000 - 0x3ffae6e0
    D (265) memory_layout: Reserved memory range 0x3ffb0000 - 0x3ffb3350
    D (271) memory_layout: Reserved memory range 0x3ffe0000 - 0x3ffe0440
    D (278) memory_layout: Reserved memory range 0x3ffe3f20 - 0x3ffe4350
    D (284) memory_layout: Reserved memory range 0x40070000 - 0x40078000
    D (291) memory_layout: Reserved memory range 0x40078000 - 0x40080000
    0x40080000: _WindowOverflow4 at D:/Espressif/esp-idf/components/xtensa/xtensa_vectors.S:2027

    D (297) memory_layout: Reserved memory range 0x40080000 - 0x4008d018
    0x40080000: _WindowOverflow4 at D:/Espressif/esp-idf/components/xtensa/xtensa_vectors.S:2027

    D (303) memory_layout: Reserved memory range 0x50001fe8 - 0x50002000
    D (310) memory_layout: Building list of available memory regions:
    D (316) memory_layout: Available memory region 0x3ffae6e0 - 0x3ffb0000
    D (323) memory_layout: Available memory region 0x3ffb3350 - 0x3ffb8000
    D (329) memory_layout: Available memory region 0x3ffb8000 - 0x3ffc0000
    D (336) memory_layout: Available memory region 0x3ffc0000 - 0x3ffc2000
    D (342) memory_layout: Available memory region 0x3ffc2000 - 0x3ffc4000
    D (349) memory_layout: Available memory region 0x3ffc4000 - 0x3ffc6000
    D (356) memory_layout: Available memory region 0x3ffc6000 - 0x3ffc8000
    D (362) memory_layout: Available memory region 0x3ffc8000 - 0x3ffca000
    D (369) memory_layout: Available memory region 0x3ffca000 - 0x3ffcc000
    D (375) memory_layout: Available memory region 0x3ffcc000 - 0x3ffce000
    D (382) memory_layout: Available memory region 0x3ffce000 - 0x3ffd0000
    D (389) memory_layout: Available memory region 0x3ffd0000 - 0x3ffd2000
    D (395) memory_layout: Available memory region 0x3ffd2000 - 0x3ffd4000
    D (402) memory_layout: Available memory region 0x3ffd4000 - 0x3ffd6000
    D (408) memory_layout: Available memory region 0x3ffd6000 - 0x3ffd8000
    D (415) memory_layout: Available memory region 0x3ffd8000 - 0x3ffda000
    D (422) memory_layout: Available memory region 0x3ffda000 - 0x3ffdc000
    D (428) memory_layout: Available memory region 0x3ffdc000 - 0x3ffde000
    D (435) memory_layout: Available memory region 0x3ffde000 - 0x3ffe0000
    D (441) memory_layout: Available memory region 0x3ffe0440 - 0x3ffe3f20
    D (448) memory_layout: Available memory region 0x3ffe4350 - 0x3ffe8000
    D (455) memory_layout: Available memory region 0x3ffe8000 - 0x3fff0000
    D (461) memory_layout: Available memory region 0x3fff0000 - 0x3fff8000
    D (468) memory_layout: Available memory region 0x3fff8000 - 0x3fffc000
    D (474) memory_layout: Available memory region 0x3fffc000 - 0x40000000
    0x40000000: _WindowOverflow4 in ROM

    D (481) memory_layout: Available memory region 0x4008d018 - 0x4008e000
    D (488) memory_layout: Available memory region 0x4008e000 - 0x40090000
    D (494) memory_layout: Available memory region 0x40090000 - 0x40092000
    D (501) memory_layout: Available memory region 0x40092000 - 0x40094000
    D (507) memory_layout: Available memory region 0x40094000 - 0x40096000
    D (514) memory_layout: Available memory region 0x40096000 - 0x40098000
    D (521) memory_layout: Available memory region 0x40098000 - 0x4009a000
    D (527) memory_layout: Available memory region 0x4009a000 - 0x4009c000
    D (534) memory_layout: Available memory region 0x4009c000 - 0x4009e000
    D (540) memory_layout: Available memory region 0x4009e000 - 0x400a0000
    I (547) heap_init: Initializing. RAM available for dynamic allocation:
    D (554) heap_init: New heap initialised at 0x3ffae6e0
    I (559) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
    D (565) heap_init: New heap initialised at 0x3ffb3350
    I (570) heap_init: At 3FFB3350 len 0002CCB0 (179 KiB): DRAM
    I (577) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
    I (583) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
    D (589) heap_init: New heap initialised at 0x4008d018
    I (595) heap_init: At 4008D018 len 00012FE8 (75 KiB): IRAM
    D (601) intr_alloc: get_available_int: try to find existing. Cpu: 0, Source: 46
    D (608) intr_alloc: get_free_int: start looking. Current cpu: 0
    D (614) intr_alloc: Int 0 reserved 2 priority 1 LEVEL hasIsr 0
    D (620) intr_alloc: ....Unusable: reserved
    D (624) intr_alloc: Int 1 reserved 2 priority 1 LEVEL hasIsr 0
    D (630) intr_alloc: ....Unusable: reserved
    D (634) intr_alloc: Int 2 reserved 0 priority 1 LEVEL hasIsr 0
    D (640) intr_alloc: Int 3 reserved 0 priority 1 LEVEL hasIsr 0
    D (646) intr_alloc: ...worse than int 2
    D (650) intr_alloc: Int 4 reserved 2 priority 1 LEVEL hasIsr 0
    D (656) intr_alloc: ....Unusable: reserved
    D (660) intr_alloc: Int 5 reserved 2 priority 1 LEVEL hasIsr 0
    D (666) intr_alloc: ....Unusable: reserved
    D (670) intr_alloc: Int 6 reserved 2 priority 1 EDGE hasIsr 0
    D (676) intr_alloc: ....Unusable: reserved
    D (680) intr_alloc: Int 7 reserved 0 priority 1 EDGE hasIsr 0
    D (686) intr_alloc: ....Unusable: special-purpose int
    D (691) intr_alloc: Int 8 reserved 2 priority 1 LEVEL hasIsr 0
    D (697) intr_alloc: ....Unusable: reserved
    D (701) intr_alloc: Int 9 reserved 0 priority 1 LEVEL hasIsr 0
    D (707) intr_alloc: ...worse than int 2
    D (711) intr_alloc: Int 10 reserved 0 priority 1 EDGE hasIsr 0
    D (717) intr_alloc: ....Unusable: incompatible trigger type
    D (722) intr_alloc: Int 11 reserved 0 priority 3 EDGE hasIsr 0
    D (728) intr_alloc: ....Unusable: special-purpose int
    D (733) intr_alloc: Int 12 reserved 0 priority 1 LEVEL hasIsr 0
    D (739) intr_alloc: ...worse than int 2
    D (743) intr_alloc: Int 13 reserved 0 priority 1 LEVEL hasIsr 0
    D (749) intr_alloc: ...worse than int 2
    D (753) intr_alloc: Int 14 reserved 2 priority 7 LEVEL hasIsr 0
    D (759) intr_alloc: ....Unusable: reserved
    D (763) intr_alloc: Int 15 reserved 0 priority 3 EDGE hasIsr 0
    D (769) intr_alloc: ....Unusable: special-purpose int
    D (774) intr_alloc: Int 16 reserved 0 priority 5 EDGE hasIsr 0
    D (780) intr_alloc: ....Unusable: special-purpose int
    D (785) intr_alloc: Int 17 reserved 0 priority 1 LEVEL hasIsr 0
    D (791) intr_alloc: ...worse than int 2
    D (795) intr_alloc: Int 18 reserved 0 priority 1 LEVEL hasIsr 0
    D (801) intr_alloc: ...worse than int 2
    D (805) intr_alloc: Int 19 reserved 0 priority 2 LEVEL hasIsr 0
    D (811) intr_alloc: ...worse than int 2
    D (815) intr_alloc: Int 20 reserved 0 priority 2 LEVEL hasIsr 0
    D (821) intr_alloc: ...worse than int 2
    D (825) intr_alloc: Int 21 reserved 0 priority 2 LEVEL hasIsr 0
    D (831) intr_alloc: ...worse than int 2
    D (835) intr_alloc: Int 22 reserved 2 priority 3 EDGE hasIsr 0
    D (841) intr_alloc: ....Unusable: reserved
    D (845) intr_alloc: Int 23 reserved 0 priority 3 LEVEL hasIsr 0
    D (851) intr_alloc: ...worse than int 2
    D (855) intr_alloc: Int 24 reserved 2 priority 4 LEVEL hasIsr 0
    D (861) intr_alloc: ....Unusable: reserved
    D (865) intr_alloc: Int 25 reserved 2 priority 4 LEVEL hasIsr 0
    D (871) intr_alloc: ....Unusable: reserved
    D (875) intr_alloc: Int 26 reserved 0 priority 5 LEVEL hasIsr 0
    D (881) intr_alloc: ....Unusable: incompatible priority
    D (887) intr_alloc: Int 27 reserved 2 priority 3 LEVEL hasIsr 0
    D (892) intr_alloc: ....Unusable: reserved
    D (897) intr_alloc: Int 28 reserved 0 priority 4 EDGE hasIsr 0
    D (903) intr_alloc: ....Unusable: incompatible priority
    D (908) intr_alloc: Int 29 reserved 0 priority 3 EDGE hasIsr 0
    D (914) intr_alloc: ....Unusable: special-purpose int
    D (919) intr_alloc: Int 30 reserved 2 priority 4 EDGE hasIsr 0
    D (925) intr_alloc: ....Unusable: reserved
    D (929) intr_alloc: Int 31 reserved 2 priority 5 LEVEL hasIsr 0
    D (935) intr_alloc: ....Unusable: reserved
    D (939) intr_alloc: get_available_int: using int 2
    D (944) intr_alloc: Connected src 46 to int 2 (cpu 0)
    D (950) spi_flash: trying chip: issi
    D (953) spi_flash: trying chip: gd
    D (956) spi_flash: trying chip: mxic
    D (960) spi_flash: trying chip: winbond
    D (964) spi_flash: trying chip: generic
    I (968) spi_flash: detected chip: generic
    I (972) spi_flash: flash io: dio
    D (976) cpu_start: calling init function: 0x400d6034
    0x400d6034: esp_ipc_init at D:/Espressif/esp-idf/components/esp_system/esp_ipc.c:114

    D (981) cpu_start: calling init function: 0x400d4af4
    0x400d4af4: int_CPUticker64_init at D:/BLEprojects/CPU_ticker64/components/CPUticker64/CPUticker64.c:47

    I (986) CPUticker64: Setting up CPUticker64...
    D (992) cpu_start: calling init function: 0x40085424
    0x40085424: enable_timer_group0_for_calibration at D:/Espressif/esp-idf/components/esp_hw_support/port/esp32/rtc_time.c:197

    D (997) cpu_start: calling init function: 0x400d0be4
    0x400d0be4: esp_app_format_init_elf_sha256 at D:/Espressif/esp-idf/components/esp_app_format/esp_app_desc.c:68

    D (1002) cpu_start: calling init function: 0x400d2ee8 on core: 0
    0x400d2ee8: __esp_system_init_fn_esp_timer_startup_init at D:/Espressif/esp-idf/components/esp_timer/src/esp_timer.c:578

    D (1008) intr_alloc: get_available_int: try to find existing. Cpu: 0, Source: 17
    D (1015) intr_alloc: get_free_int: start looking. Current cpu: 0
    D (1021) intr_alloc: Int 0 reserved 2 priority 1 LEVEL hasIsr 0
    D (1027) intr_alloc: ....Unusable: reserved
    D (1031) intr_alloc: Int 1 reserved 2 priority 1 LEVEL hasIsr 0
    D (1037) intr_alloc: ....Unusable: reserved
    D (1042) intr_alloc: Int 2 reserved 0 priority 1 LEVEL hasIsr 1
    D (1048) intr_alloc: ....Unusable: already in (non-shared) use.
    D (1054) intr_alloc: Int 3 reserved 0 priority 1 LEVEL hasIsr 0
    D (1060) intr_alloc: Int 4 reserved 2 priority 1 LEVEL hasIsr 0
    D (1066) intr_alloc: ....Unusable: reserved
    D (1070) intr_alloc: Int 5 reserved 2 priority 1 LEVEL hasIsr 0
    D (1076) intr_alloc: ....Unusable: reserved
    D (1080) intr_alloc: Int 6 reserved 2 priority 1 EDGE hasIsr 0
    D (1086) intr_alloc: ....Unusable: reserved
    D (1090) intr_alloc: Int 7 reserved 0 priority 1 EDGE hasIsr 0
    D (1096) intr_alloc: ....Unusable: special-purpose int
    D (1101) intr_alloc: Int 8 reserved 2 priority 1 LEVEL hasIsr 0
    D (1107) intr_alloc: ....Unusable: reserved
    D (1112) intr_alloc: Int 9 reserved 0 priority 1 LEVEL hasIsr 0
    D (1118) intr_alloc: ...worse than int 3
    D (1122) intr_alloc: Int 10 reserved 0 priority 1 EDGE hasIsr 0
    D (1128) intr_alloc: ....Unusable: incompatible trigger type
    D (1133) intr_alloc: Int 11 reserved 0 priority 3 EDGE hasIsr 0
    D (1139) intr_alloc: ....Unusable: special-purpose int
    D (1144) intr_alloc: Int 12 reserved 0 priority 1 LEVEL hasIsr 0
    D (1151) intr_alloc: ...worse than int 3
    D (1155) intr_alloc: Int 13 reserved 0 priority 1 LEVEL hasIsr 0
    D (1161) intr_alloc: ...worse than int 3
    D (1165) intr_alloc: Int 14 reserved 2 priority 7 LEVEL hasIsr 0
    D (1171) intr_alloc: ....Unusable: reserved
    D (1175) intr_alloc: Int 15 reserved 0 priority 3 EDGE hasIsr 0
    D (1181) intr_alloc: ....Unusable: special-purpose int
    D (1186) intr_alloc: Int 16 reserved 0 priority 5 EDGE hasIsr 0
    D (1192) intr_alloc: ....Unusable: special-purpose int
    D (1197) intr_alloc: Int 17 reserved 0 priority 1 LEVEL hasIsr 0
    D (1203) intr_alloc: ...worse than int 3
    D (1207) intr_alloc: Int 18 reserved 0 priority 1 LEVEL hasIsr 0
    D (1213) intr_alloc: ...worse than int 3
    D (1217) intr_alloc: Int 19 reserved 0 priority 2 LEVEL hasIsr 0
    D (1224) intr_alloc: ....Unusable: incompatible priority
    D (1229) intr_alloc: Int 20 reserved 0 priority 2 LEVEL hasIsr 0
    D (1235) intr_alloc: ....Unusable: incompatible priority
    D (1240) intr_alloc: Int 21 reserved 0 priority 2 LEVEL hasIsr 0
    D (1246) intr_alloc: ....Unusable: incompatible priority
    D (1252) intr_alloc: Int 22 reserved 2 priority 3 EDGE hasIsr 0
    D (1258) intr_alloc: ....Unusable: reserved
    D (1262) intr_alloc: Int 23 reserved 0 priority 3 LEVEL hasIsr 0
    D (1268) intr_alloc: ....Unusable: incompatible priority
    D (1274) intr_alloc: Int 24 reserved 2 priority 4 LEVEL hasIsr 0
    D (1280) intr_alloc: ....Unusable: reserved
    D (1284) intr_alloc: Int 25 reserved 2 priority 4 LEVEL hasIsr 0
    D (1290) intr_alloc: ....Unusable: reserved
    D (1294) intr_alloc: Int 26 reserved 0 priority 5 LEVEL hasIsr 0
    D (1300) intr_alloc: ....Unusable: incompatible priority
    D (1306) intr_alloc: Int 27 reserved 2 priority 3 LEVEL hasIsr 0
    D (1312) intr_alloc: ....Unusable: reserved
    D (1316) intr_alloc: Int 28 reserved 0 priority 4 EDGE hasIsr 0
    D (1322) intr_alloc: ....Unusable: incompatible priority
    D (1327) intr_alloc: Int 29 reserved 0 priority 3 EDGE hasIsr 0
    D (1333) intr_alloc: ....Unusable: special-purpose int
    D (1339) intr_alloc: Int 30 reserved 2 priority 4 EDGE hasIsr 0
    D (1345) intr_alloc: ....Unusable: reserved
    D (1349) intr_alloc: Int 31 reserved 2 priority 5 LEVEL hasIsr 0
    D (1355) intr_alloc: ....Unusable: reserved
    D (1359) intr_alloc: get_available_int: using int 3
    D (1364) intr_alloc: Connected src 17 to int 3 (cpu 0)
    D (1369) cpu_start: calling init function: 0x400e0f78 on core: 0
    0x400e0f78: __esp_system_init_fn_init_components0 at D:/Espressif/esp-idf/components/esp_system/startup.c:480

    D (1376) intr_alloc: get_available_int: try to find existing. Cpu: 0, Source: 24
    D (1383) intr_alloc: get_free_int: start looking. Current cpu: 0
    D (1389) intr_alloc: Int 0 reserved 2 priority 1 LEVEL hasIsr 0
    D (1395) intr_alloc: ....Unusable: reserved
    D (1399) intr_alloc: Int 1 reserved 2 priority 1 LEVEL hasIsr 0
    D (1405) intr_alloc: ....Unusable: reserved
    D (1409) intr_alloc: Int 2 reserved 0 priority 1 LEVEL hasIsr 1
    D (1415) intr_alloc: ....Unusable: already in (non-shared) use.
    D (1421) intr_alloc: Int 3 reserved 0 priority 1 LEVEL hasIsr 1
    D (1427) intr_alloc: ....Unusable: already in (non-shared) use.
    D (1433) intr_alloc: Int 4 reserved 2 priority 1 LEVEL hasIsr 0
    D (1439) intr_alloc: ....Unusable: reserved
    D (1444) intr_alloc: Int 5 reserved 2 priority 1 LEVEL hasIsr 0
    D (1450) intr_alloc: ....Unusable: reserved
    D (1454) intr_alloc: Int 6 reserved 2 priority 1 EDGE hasIsr 0
    D (1460) intr_alloc: ....Unusable: reserved
    D (1464) intr_alloc: Int 7 reserved 0 priority 1 EDGE hasIsr 0
    D (1470) intr_alloc: ....Unusable: special-purpose int
    D (1475) intr_alloc: Int 8 reserved 2 priority 1 LEVEL hasIsr 0
    D (1481) intr_alloc: ....Unusable: reserved
    D (1485) intr_alloc: Int 9 reserved 0 priority 1 LEVEL hasIsr 0
    D (1491) intr_alloc: Int 10 reserved 0 priority 1 EDGE hasIsr 0
    D (1497) intr_alloc: ....Unusable: incompatible trigger type
    D (1503) intr_alloc: Int 11 reserved 0 priority 3 EDGE hasIsr 0
    D (1509) intr_alloc: ....Unusable: special-purpose int
    D (1514) intr_alloc: Int 12 reserved 0 priority 1 LEVEL hasIsr 0
    D (1520) intr_alloc: ...worse than int 9
    D (1524) intr_alloc: Int 13 reserved 0 priority 1 LEVEL hasIsr 0
    D (1530) intr_alloc: ...worse than int 9
    D (1534) intr_alloc: Int 14 reserved 2 priority 7 LEVEL hasIsr 0
    D (1540) intr_alloc: ....Unusable: reserved
    D (1545) intr_alloc: Int 15 reserved 0 priority 3 EDGE hasIsr 0
    D (1551) intr_alloc: ....Unusable: special-purpose int
    D (1556) intr_alloc: Int 16 reserved 0 priority 5 EDGE hasIsr 0
    D (1562) intr_alloc: ....Unusable: special-purpose int
    D (1567) intr_alloc: Int 17 reserved 0 priority 1 LEVEL hasIsr 0
    D (1573) intr_alloc: ...worse than int 9
    D (1577) intr_alloc: Int 18 reserved 0 priority 1 LEVEL hasIsr 0
    D (1583) intr_alloc: ...worse than int 9
    D (1587) intr_alloc: Int 19 reserved 0 priority 2 LEVEL hasIsr 0
    D (1593) intr_alloc: ...worse than int 9
    D (1597) intr_alloc: Int 20 reserved 0 priority 2 LEVEL hasIsr 0
    D (1603) intr_alloc: ...worse than int 9
    D (1607) intr_alloc: Int 21 reserved 0 priority 2 LEVEL hasIsr 0
    D (1613) intr_alloc: ...worse than int 9
    D (1617) intr_alloc: Int 22 reserved 2 priority 3 EDGE hasIsr 0
    D (1623) intr_alloc: ....Unusable: reserved
    D (1628) intr_alloc: Int 23 reserved 0 priority 3 LEVEL hasIsr 0
    D (1634) intr_alloc: ...worse than int 9
    D (1638) intr_alloc: Int 24 reserved 2 priority 4 LEVEL hasIsr 0
    D (1644) intr_alloc: ....Unusable: reserved
    D (1648) intr_alloc: Int 25 reserved 2 priority 4 LEVEL hasIsr 0
    D (1654) intr_alloc: ....Unusable: reserved
    D (1658) intr_alloc: Int 26 reserved 0 priority 5 LEVEL hasIsr 0
    D (1665) intr_alloc: ....Unusable: incompatible priority
    D (1670) intr_alloc: Int 27 reserved 2 priority 3 LEVEL hasIsr 0
    D (1676) intr_alloc: ....Unusable: reserved
    D (1680) intr_alloc: Int 28 reserved 0 priority 4 EDGE hasIsr 0
    D (1686) intr_alloc: ....Unusable: incompatible priority
    D (1692) intr_alloc: Int 29 reserved 0 priority 3 EDGE hasIsr 0
    D (1698) intr_alloc: ....Unusable: special-purpose int
    D (1703) intr_alloc: Int 30 reserved 2 priority 4 EDGE hasIsr 0
    D (1709) intr_alloc: ....Unusable: reserved
    D (1713) intr_alloc: Int 31 reserved 2 priority 5 LEVEL hasIsr 0
    D (1719) intr_alloc: ....Unusable: reserved
    D (1723) intr_alloc: get_available_int: using int 9
    D (1728) intr_alloc: Connected src 24 to int 9 (cpu 0)
    D (1734) app_start: Starting scheduler on CPU0
    D (1738) intr_alloc: get_available_int: try to find existing. Cpu: 0, Source: -3
    D (1738) intr_alloc: get_available_int: try to find force. Cpu: 0, Source: -3, Force: 16
    D (1748) intr_alloc: gennectelable_-3 to iy t16 ind ex0sting.
    Cpu: 1, Source: 25
    D (1758) intr_alloc: get_free_int: start looking. Current cpu: 1
    D (1758) intr_alloc: Int 0 reserved 2 priority 1 LEVEL hasIsr 0
    D (1768) intr_alloc: ....Unusable: reserved
    D (1768) intr_alloc: Int 1 reserved 2 priority 1 LEVEL hasIsr 0
    D (1778) intr_alloc: ....Unusable: reserved
    D (1778) intr_alloc: Int 2 reserved 0 priority 1 LEVEL hasIsr 0
    D (1788) intr_alloc: Int 3 reserved 0 priority 1 LEVEL hasIsr 0
    D (1798) intr_alloc: ...worse than int 2
    D (1798) intr_alloc: Int 4 reserved 0 priority 1 LEVEL hasIsr 0
    D (1808) intr_alloc: ...worse than int 2
    D (1808) intr_alloc: Int 5 reserved 2 priority 1 LEVEL hasIsr 0
    D (1818) intr_alloc: ....Unusable: reserved
    D (1818) intr_alloc: Int 6 reserved 2 priority 1 EDGE hasIsr 0
    D (1828) intr_alloc: ....Unusable: reserved
    D (1828) intr_alloc: Int 7 reserved 0 priority 1 EDGE hasIsr 0
    D (1838) intr_alloc: ....Unusable: special-purpose int
    D (1838) intr_alloc: Int 8 reserved 2 priority 1 LEVEL hasIsr 0
    D (1848) intr_alloc: ....Unusable: reserved
    D (1848) intr_alloc: Int 9 reserved 0 priority 1 LEVEL hasIsr 0
    D (1858) intr_alloc: ...worse than int 2
    D (1858) intr_alloc: Int 10 reserved 0 priority 1 EDGE hasIsr 0
    D (1868) intr_alloc: ....Unusable: incompatible trigger type
    D (1868) intr_alloc: Int 11 reserved 0 priority 3 EDGE hasIsr 0
    D (1878) intr_alloc: ....Unusable: special-purpose int
    D (1888) intr_alloc: Int 12 reserved 0 priority 1 LEVEL hasIsr 0
    D (1888) intr_alloc: ...worse than int 2
    D (1898) intr_alloc: Int 13 reserved 0 priority 1 LEVEL hasIsr 0
    D (1898) intr_alloc: ...worse than int 2
    D (1908) intr_alloc: Int 14 reserved 2 priority 7 LEVEL hasIsr 0
    D (1908) intr_alloc: ....Unusable: reserved
    D (1918) intr_alloc: Int 15 reserved 0 priority 3 EDGE hasIsr 0
    D (1918) intr_alloc: ....Unusable: special-purpose int
    D (1928) intr_alloc: Int 16 reserved 0 priority 5 EDGE hasIsr 0
    D (1928) intr_alloc: ....Unusable: special-purpose int
    D (1938) intr_alloc: Int 17 reserved 0 priority 1 LEVEL hasIsr 0
    D (1938) intr_alloc: ...worse than int 2
    D (1948) intr_alloc: Int 18 reserved 0 priority 1 LEVEL hasIsr 0
    D (1948) intr_alloc: ...worse than int 2
    D (1958) intr_alloc: Int 19 reserved 0 priority 2 LEVEL hasIsr 0
    D (1958) intr_alloc: ...worse than int 2
    D (1968) intr_alloc: Int 20 reserved 0 priority 2 LEVEL hasIsr 0
    D (1968) intr_alloc: ...worse than int 2
    D (1978) intr_alloc: Int 21 reserved 0 priority 2 LEVEL hasIsr 0
    D (1978) intr_alloc: ...worse than int 2
    D (1988) intr_alloc: Int 22 reserved 0 priority 3 EDGE hasIsr 0
    D (1988) intr_alloc: ....Unusable: incompatible trigger type
    D (1998) intr_alloc: Int 23 reserved 0 priority 3 LEVEL hasIsr 0
    D (2008) intr_alloc: ...worse than int 2
    D (2008) intr_alloc: Int 24 reserved 0 priority 4 LEVEL hasIsr 0
    D (2018) intr_alloc: ....Unusable: incompatible priority
    D (2018) intr_alloc: Int 25 reserved 2 priority 4 LEVEL hasIsr 0
    D (2028) intr_alloc: ....Unusable: reserved
    D (2028) intr_alloc: Int 26 reserved 2 priority 5 LEVEL hasIsr 0
    D (2038) intr_alloc: ....Unusable: reserved
    D (2038) intr_alloc: Int 27 reserved 2 priority 3 LEVEL hasIsr 0
    D (2048) intr_alloc: ....Unusable: reserved
    D (2048) intr_alloc: Int 28 reserved 0 priority 4 EDGE hasIsr 0
    D (2058) intr_alloc: ....Unusable: incompatible priority
    D (2058) intr_alloc: Int 29 reserved 0 priority 3 EDGE hasIsr 0
    D (2068) intr_alloc: ....Unusable: special-purpose int
    D (2078) intr_alloc: Int 30 reserved 2 priority 4 EDGE hasIsr 0
    D (2078) intr_alloc: ....Unusable: reserved
    D (2088) intr_alloc: Int 31 reserved 2 priority 5 LEVEL hasIsr 0
    D (2088) intr_alloc: ....Unusable: reserved
    D (2098) intr_alloc: get_available_int: using int 2
    D (2098) intr_alloc: Connected src 25 to int 2 (cpu 1)
    D (2108) app_start: Starting scheduler on CPU1
    D (2108) intr_alloc: get_available_int: try to find existing. Cpu: 1, Source: -3
    D (2118) intr_alloc: get_available_int: try to find force. Cpu: 1, Source: -3, Force: 16
    D (2128) intr_alloc: Connected src -3 to int 16 (cpu 1)
    I (1758) main_task: Started on CPU0
    D (2138) heap_init: New heap initialised at 0x3ffe0440
    D (2138) heap_init: New heap initialised at 0x3ffe4350
    I (2148) main_task: Calling app_main()
    I (2148) CPUticker64: Setting up CPUticker64...
    D (2158) intr_alloc: get_available_int: try to find existing. Cpu: 0, Source: -3
    D (2158) intr_alloc: get_available_int: existing vd found. intno: 16
    D (2158) intr_alloc: ....Unusable: already in (non-shared) use.
    D (2158) intr_alloc: get_available_int: existing vd invalid.
    E (2178) intr_alloc: No free interrupt inputs for interrupt (flags 0x420)

    assert failed: int_CPUticker64_setup CPUticker64.c:43 (err==ESP_OK)


    Backtrace: 0x400816c6:0x3ffb4c60 0x40085921:0x3ffb4c80 0x4008baad:0x3ffb4ca0 0x400d4aea:0x3ffb4dc0 0x400889b5:0x3ffb4de0
    0x400816c6: panic_abort at D:/Espressif/esp-idf/components/esp_system/panic.c:472
    0x40085921: esp_system_abort at D:/Espressif/esp-idf/components/esp_system/port/esp_system_chip.c:93
    0x4008baad: __assert_func at D:/Espressif/esp-idf/components/newlib/assert.c:81
    0x400d4aea: int_CPUticker64_setup at D:/BLEprojects/CPU_ticker64/components/CPUticker64/CPUticker64.c:43 (discriminator 1)
    0x400889b5: vPortTaskWrapper at D:/Espressif/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:134





    ELF file SHA256: 7b820b5cd

    CPU halted.
You can see in that debug trace list that asking Source is -3 (which coresponds to timer2) passed only on Core1 (forced as 16) however it doesnt pass on Core0. Could it be related to that small programming board which uses FTDI chip to program the ESP32 to allocates an additional resource for UART so no more left for Core0? How did you test that example? And how did you detect two calls when only one exists?
And also a code which matches to your template settings (uses int5, timer2, and CCOMPARE2 register):

https://uploadnow.io/f/hBtgXWG

djixon
Posts: 113
Joined: Sun Oct 01, 2023 7:48 pm

Re: How properly, under RTOS, to set up the highest priority non-maskable interrupt vector?

Postby djixon » Sun Apr 21, 2024 9:09 am

Voilla !!!! I figured it out. I have to guard that call from app_main and be sure it is called just on single core!!!! It works, and it works as expected, since both Cores are calling that ISR incremen is properly done by 2 !!!! Indicating that it works perfectly on both cores

I will reshape the code and post that final working version here in hour or two.

Who is online

Users browsing this forum: Majestic-12 [Bot] and 79 guests