проект выходного дня....вроде заработало! свежак KGP для
riscv32-kgp-elf с поддержкой CH32Vxxx (QingKeV4, QingKeV4B,
QingKeV4C, QingKeV4F) с подачи VladislavS, я возбудился на "поднять" код из транка c добавкой поддержки ядер bamblebee N200, QingKeV4, QingKeV4B, QingKeV4C, QingKeV4F
тестирование сборки тулсов из пакета MounRiver обнаружило злобный косячищще - при включении оптимизации LTO почему то линкер нах выпиливает код обработчиков прерываний, атрибут used не спасает ситуацию, также не помогло притягиванияе моего свежего линкера из бинутилса. из этого я делаю вывод что что то еще до линковки пошло не так в компиллере. непонятно - это только мой сценарий или всегда так, мне не интересна сборка китайцев.... но тем не менее как бэ намекаэээ.
в код из транка я добавил следующие моменты для обработчиков прерываний
1. для таргета riscv*-*-* добавлено поведение кодогенератора прологов/'эпилогов :
__attribute__((interrupt)) - генерится запись/сохраниене контекста в стек (в случаее QingKeV4F сохранябтся также регисты fpu)
__attribute__((interrupt("hpe"))) - hpe сокращенно от Hardware prolog/epilog, аппаратное сохранение регистров CPU и FPU в теневые регистровые файлы
__attribute__((interrupt("hpei"))) - hpei сокращенно от Hardware prolog/epilog integer regs, аппаратное сохранение регистров только CPU, для регистов FPU генерятся прологи и эпилоги.
таким образом покрываются ситуации когда есть аппаратная поддержка сохранения контекcта или нет , когда она только для целочисленных регистров или нет.... и никакой жесткой привязки к кастомным расширениям вендора процессоров
далее примеры компилялись с ключиами
-march=rv32imafc_zicsr -mabi=ilp32f -mcmodel=medlow -mtune=qkv4f
случай обычной функции - характерно для сценария GD32VF103
код
void TIM8_IRQHandler(void) { TIM_ClearITPendingBit(TIM7, TIM_IT_Update); GPIO_WriteBit(GPIOA, GPIO_Pin_0, GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET ? Bit_SET : Bit_RESET ); }
выход кодогенератора
0000038a <TIM7_IRQHandler>:
void TIM7_IRQHandler(void) { TIM_ClearITPendingBit(TIM7, TIM_IT_Update); GPIO_WriteBit(GPIOA, GPIO_Pin_0, GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET ? Bit_SET : Bit_RESET ); }
38a: 40001537 lui a0,0x40001
38e: 1141 add sp,sp,-16
390: 4585 li a1,1
392: 40050513 add a0,a0,1024 # 40001400 <_eusrstack+0x1fff1400>
396: c606 sw ra,12(sp)
398: 359000ef jal ef0 <TIM_ClearITPendingBit>
39c: 400112b7 lui t0,0x40011
3a0: 4585 li a1,1
3a2: 80028513 add a0,t0,-2048 # 40010800 <_eusrstack+0x20000800>
3a6: 2f89 jal af8 <GPIO_ReadInputDataBit>
3a8: 40b2 lw ra,12(sp)
3aa: 40011337 lui t1,0x40011
3ae: 00153613 seqz a2,a0
3b2: 4585 li a1,1
3b4: 80030513 add a0,t1,-2048 # 40010800 <_eusrstack+0x20000800>
3b8: 0141 add sp,sp,16
3ba: a7a9 j b04 <GPIO_WriteBit>+0x104>
случай обработчика прерывания - характерно для сценария СH32V3xx ( fpu используется)
код
__attribute__((interrupt)) void TIM7_IRQHandler(void) { TIM_ClearITPendingBit(TIM7, TIM_IT_Update); GPIO_WriteBit(GPIOA, GPIO_Pin_0, GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET ? Bit_SET : Bit_RESET ); }
выход кодогенератора
0000038a <TIM7_IRQHandler>:
__attribute__((interrupt)) void TIM7_IRQHandler(void) { TIM_ClearITPendingBit(TIM7, TIM_IT_Update); GPIO_WriteBit(GPIOA, GPIO_Pin_0, GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET ? Bit_SET : Bit_RESET ); }
38a: 7175 add sp,sp,-144
38c: deaa sw a0,124(sp)
38e: 40001537 lui a0,0x40001
392: c706 sw ra,140(sp)
394: c31a sw t1,132(sp)
396: c11e sw t2,128(sp)
398: dab2 sw a2,116(sp)
39a: d8b6 sw a3,112(sp)
39c: d6ba sw a4,108(sp)
39e: d4be sw a5,104(sp)
3a0: d2c2 sw a6,100(sp)
3a2: d0c6 sw a7,96(sp)
3a4: cef2 sw t3,92(sp)
3a6: ccf6 sw t4,88(sp)
3a8: cafa sw t5,84(sp)
3aa: c8fe sw t6,80(sp)
3ac: e682 fsw ft0,76(sp)
3ae: e486 fsw ft1,72(sp)
3b0: e28a fsw ft2,68(sp)
3b2: e08e fsw ft3,64(sp)
3b4: fe12 fsw ft4,60(sp)
3b6: fc16 fsw ft5,56(sp)
3b8: fa1a fsw ft6,52(sp)
3ba: f81e fsw ft7,48(sp)
3bc: f62a fsw fa0,44(sp)
3be: f42e fsw fa1,40(sp)
3c0: f232 fsw fa2,36(sp)
3c2: f036 fsw fa3,32(sp)
3c4: ee3a fsw fa4,28(sp)
3c6: ec3e fsw fa5,24(sp)
3c8: ea42 fsw fa6,20(sp)
3ca: e846 fsw fa7,16(sp)
3cc: c516 sw t0,136(sp)
3ce: dcae sw a1,120(sp)
3d0: 40050513 add a0,a0,1024 # 40001400 <_eusrstack+0x1fff1400>
3d4: 4585 li a1,1
3d6: e672 fsw ft8,12(sp)
3d8: e476 fsw ft9,8(sp)
3da: e27a fsw ft10,4(sp)
3dc: e07e fsw ft11,0(sp)
3de: 3a3000ef jal f80 <TIM_ClearITPendingBit>
3e2: 400112b7 lui t0,0x40011
3e6: 80028513 add a0,t0,-2048 # 40010800 <_eusrstack+0x20000800>
3ea: 4585 li a1,1
3ec: 2f71 jal b88 <GPIO_ReadInputDataBit>
3ee: 40011337 lui t1,0x40011
3f2: 00153613 seqz a2,a0
3f6: 4585 li a1,1
3f8: 80030513 add a0,t1,-2048 # 40010800 <_eusrstack+0x20000800>
3fc: 2f61 jal b94 <GPIO_WriteBit>
3fe: 40ba lw ra,140(sp)
400: 42aa lw t0,136(sp)
402: 431a lw t1,132(sp)
404: 438a lw t2,128(sp)
406: 5576 lw a0,124(sp)
408: 55e6 lw a1,120(sp)
40a: 5656 lw a2,116(sp)
40c: 56c6 lw a3,112(sp)
40e: 5736 lw a4,108(sp)
410: 57a6 lw a5,104(sp)
412: 5816 lw a6,100(sp)
414: 5886 lw a7,96(sp)
416: 4e76 lw t3,92(sp)
418: 4ee6 lw t4,88(sp)
41a: 4f56 lw t5,84(sp)
41c: 4fc6 lw t6,80(sp)
41e: 6036 flw ft0,76(sp)
420: 60a6 flw ft1,72(sp)
422: 6116 flw ft2,68(sp)
424: 6186 flw ft3,64(sp)
426: 7272 flw ft4,60(sp)
428: 72e2 flw ft5,56(sp)
42a: 7352 flw ft6,52(sp)
42c: 73c2 flw ft7,48(sp)
42e: 7532 flw fa0,44(sp)
430: 75a2 flw fa1,40(sp)
432: 7612 flw fa2,36(sp)
434: 7682 flw fa3,32(sp)
436: 6772 flw fa4,28(sp)
438: 67e2 flw fa5,24(sp)
43a: 6852 flw fa6,20(sp)
43c: 68c2 flw fa7,16(sp)
43e: 6e32 flw ft8,12(sp)
440: 6ea2 flw ft9,8(sp)
442: 6f12 flw ft10,4(sp)
444: 6f82 flw ft11,0(sp)
446: 6149 add sp,sp,144
448: 30200073 mret
случай обработчика прерывания c аппаратным сохранением целочисленных регистров - характерно для сценария СH32V3xx ( fpu используется)
код
__attribute__((interrupt("hpei"))) void TIM8_IRQHandler(void) { asm volatile ("nop") ; }
выход кодогенератора
0000038a <TIM7_IRQHandler>:
__attribute__((interrupt("hpei"))) void TIM7_IRQHandler(void) { TIM_ClearITPendingBit(TIM7, TIM_IT_Update); GPIO_WriteBit(GPIOA, GPIO_Pin_0, GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET ? Bit_SET : Bit_RESET ); }
38a: 40001537 lui a0,0x40001
38e: 715d add sp,sp,-80
390: 4585 li a1,1
392: 40050513 add a0,a0,1024 # 40001400 <_eusrstack+0x1fff1400>
396: e682 fsw ft0,76(sp)
398: e486 fsw ft1,72(sp)
39a: e28a fsw ft2,68(sp)
39c: e08e fsw ft3,64(sp)
39e: fe12 fsw ft4,60(sp)
3a0: fc16 fsw ft5,56(sp)
3a2: fa1a fsw ft6,52(sp)
3a4: f81e fsw ft7,48(sp)
3a6: f62a fsw fa0,44(sp)
3a8: f42e fsw fa1,40(sp)
3aa: f232 fsw fa2,36(sp)
3ac: f036 fsw fa3,32(sp)
3ae: ee3a fsw fa4,28(sp)
3b0: ec3e fsw fa5,24(sp)
3b2: ea42 fsw fa6,20(sp)
3b4: e846 fsw fa7,16(sp)
3b6: e672 fsw ft8,12(sp)
3b8: e476 fsw ft9,8(sp)
3ba: e27a fsw ft10,4(sp)
3bc: e07e fsw ft11,0(sp)
3be: 383000ef jal f40 <TIM_ClearITPendingBit>
3c2: 400112b7 lui t0,0x40011
3c6: 4585 li a1,1
3c8: 80028513 add a0,t0,-2048 # 40010800 <_eusrstack+0x20000800>
3cc: 2fb5 jal b48 <GPIO_ReadInputDataBit>
3ce: 40011337 lui t1,0x40011
3d2: 00153613 seqz a2,a0
3d6: 4585 li a1,1
3d8: 80030513 add a0,t1,-2048 # 40010800 <_eusrstack+0x20000800>
3dc: 2fa5 jal b54 <GPIO_WriteBit>
3de: 6036 flw ft0,76(sp)
3e0: 60a6 flw ft1,72(sp)
3e2: 6116 flw ft2,68(sp)
3e4: 6186 flw ft3,64(sp)
3e6: 7272 flw ft4,60(sp)
3e8: 72e2 flw ft5,56(sp)
3ea: 7352 flw ft6,52(sp)
3ec: 73c2 flw ft7,48(sp)
3ee: 7532 flw fa0,44(sp)
3f0: 75a2 flw fa1,40(sp)
3f2: 7612 flw fa2,36(sp)
3f4: 7682 flw fa3,32(sp)
3f6: 6772 flw fa4,28(sp)
3f8: 67e2 flw fa5,24(sp)
3fa: 6852 flw fa6,20(sp)
3fc: 68c2 flw fa7,16(sp)
3fe: 6e32 flw ft8,12(sp)
400: 6ea2 flw ft9,8(sp)
402: 6f12 flw ft10,4(sp)
404: 6f82 flw ft11,0(sp)
406: 6161 add sp,sp,80
408: 30200073 mret
случай обработчика прерывания c аппаратным сохранением всех регистров - пока такого процессора мы не знаем :)
код
__attribute__((interrupt("hpe"))) void TIM8_IRQHandler(void) { asm volatile ("nop") ; }
выход кодогенератора
0000038a <TIM7_IRQHandler>:
__attribute__((interrupt("hpe"))) void TIM7_IRQHandler(void) { TIM_ClearITPendingBit(TIM7, TIM_IT_Update); GPIO_WriteBit(GPIOA, GPIO_Pin_0, GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET ? Bit_SET : Bit_RESET ); }
38a: 40001537 lui a0,0x40001
38e: 4585 li a1,1
390: 40050513 add a0,a0,1024 # 40001400 <_eusrstack+0x1fff1400>
394: 359000ef jal eec <TIM_ClearITPendingBit>
398: 400112b7 lui t0,0x40011
39c: 4585 li a1,1
39e: 80028513 add a0,t0,-2048 # 40010800 <_eusrstack+0x20000800>
3a2: 2f89 jal af4 <GPIO_ReadInputDataBit>
3a4: 40011337 lui t1,0x40011
3a8: 00153613 seqz a2,a0
3ac: 4585 li a1,1
3ae: 80030513 add a0,t1,-2048 # 40010800 <_eusrstack+0x20000800>
3b2: 27b9 jal b00 <GPIO_WriteBit>
3b4: 30200073 mret
2. добалена протяжка по реализациям микроарихитектур и соответствующая оптимизация
-mtune=bamblebee
-mtune=qkv4a
-mtune=qkv4b
-mtune=qkv4c
-mtune=qkv4f
3. добален биндинг -mcu -> -tune/-arch
-mcu=gd32vf103
-mcu=ch32v103
-mcu=ch32v203
-mcu=ch32v208
-mcu=ch32v30x
вроде бы все работает - потестил примерчик с вложенными + цепочными прерываниями на gd32vf103 и ch32v307. ничего не разваливается. но нада тестить.
в связи с тем что кроме общего описания ядер bamblebee N200 и QingKeV4 я не имею ничего детального - параметры оптимизации выставлены примерно как у похожих sifive.
нужны данные по затратам тактов для выполнения операций (стоймость операции)
fp_add
fp_mul
fp_div
int_mul
int_div
issue_rate
branch
memory
fmv
unaligned_access
если кто найдет доки - всуну чтоб все было красиво.
в принципе из данного положения на спортивном снаряде можно попробывать протянуть в GCC поддержку миландровских riscv микроконтроллеров .... но я их в природе не наблюдал печалька
архив тулсов host x86_64-kgp-linux-gnu_znver3-avx2 :
http://www.klen.org/Files/DevTools/x86_64-kgp-linux-gnu_znver3-avx2/riscv32imac-kgp-elf/riscv32imac-kgp-elf_@_x86_64-kgp-linux-gnu_znver3-avx2_20230410_BISTORTA.tar.7z
выходные полностью всрались.. в субботу проснулся, встал - сел в трусах за комп.... воскресение 18:00 в том же положении в трусах... бутыль кинзмараули.... доза не сработала - неотпускает...