вот Вам мое видение порта freertos для QingKeV4 V4F (микросхемы аля
ch32v307) пока портировал писал для себя камменты в голове фалов порта.
сегодня почистил и дооформил.
c портом прилагаю в архиве наисвежайшее ядро freertos "сегодняшнее и3 remotes/origin/HEAD "
freertos_kgp_qkv4f.tar.xz
ниже содержание камментов - "что? зачем? почему?"
/*
FreeRTOS Kernel V11.0.1+ kgp/klibc
куда пойдете - copy направо или на лево - это ваше личное решение!
я иду вверх! присоеденяйтесь...
Чернов Сергей aka Klen Santakheza
klen_s@mail.ru
*/
/*
* Порт построен на базе кода FreeRTOS\Source\portable\GCC\RISC-V-RV32 и кода
* порта из MounRiver_Studio как результат изучения riscv и размышлений как бы
* сделать все половчее чем "лишь бы как то заработало".
* Первый из них является линшь заготовкой и не может работать, второй работает
* из коробки но сделан с ошибками в стиле "хуяк-хуяк в продакшэн" - например у
* "узкоглазых братьев" напрочь не предусмотрено переключение режимов процессора,
* и потоки РАБОТАЮТ В РЕЖИМЕ machine, а не как полагается в режиме user!!!
* это говнокод и трэш, друзья мои. Но их понть можно - "кейтайские пейсайтели из
* MounRiver" кажется не умеют читать "кейтайские доки" на процессор - они уперлись
* в то что mstatus традиционно в riscv доступен ТОЛЬКО в режиме machine :)
* .... нешмагла... а мы сделали!
*
* в связи с тем что данный порт целевой - для ядера QingKeV4 микросхем ch32v307
* файл freertos_risc_v_chip_specific_extensions.h исключен, работа с регистрами
* сопроцессора внесена в port_asm.s
* макросы portasmSAVE_ADDITIONAL_REGISTERS и portasmRESTORE_ADDITIONAL_REGISTER
* внесены под дефайн portasmADDITIONAL_CONTEXT_SIZE по этому порт должен
* без проблем заработать на всех вариантах ядра QingKeV4 - V4A, V4B, V4C и V4F
* посредством настройки portasmADDITIONAL_CONTEXT_SIZE.
*
*
* отличия от потрта MounRiver_Studio
*
* 0. порт строился на связке с исходниками freertos kernel из main - ветки
* https://github.com/FreeRTOS/FreeRTOS-Kernel.git
* соответсвенно он является "наисвежайшим" :) версии V11.0.1+
* само ядро в моем случае тоже доработано (отдельная тема), в частности на предмет реентерабельности,
* использования ситемного таймера ядра процессора и тд....
* но работа порта от этого не зависит. ядро отдельно - порт отдельно!
*
* 1. freertos_port_machine_mode_init()
* данная функция добалена в порт и должна быть вызвана в reset/crt коде в машинном режиме до выхода в режим пользователя.
* данная мера необходима в связи с тем что необходимо протестировать регистр mtvec на валидность адреса в нем и выполнить
* сохранение указателя вершины стека обработчиков в регистре mscratch, эти регистры доступны только в машинном режиме.
*
* 2. проблема uxCriticalNesting - невозможно использовать статические объекты freertos.
* изначально в обоих исходных портах uxCriticalNesting инициализируется в 0xaaaaaaaa, что бы пометить сотояние до запуска планировщика.
* однако это имее негативный побочный эффект. практически любой api freertos (например размещение статических мьютексов)
* сбросит прерывания и не включит их!! это ломает логику работы системы до старта планировщика, на которую в таком
* случае ложатся ограничения по использованию статического размещения объектов freertos. для исключения данной проблемы
* выполняется сброс uxCriticalNesting в исходное соcтояние, необходимый для устранения проблем при вызове функций работы с объектами
* freertos до старта шедуллера. имеем результат: в freertos_port_machine_mode_init() выполняется uxCriticalNesting = 0 ;
*
* 3 xPortStartFirstTask
*
*
* 4. xPortSetInterruptMask/vPortClearInterruptMask
* нехуй писать в mstatus 0x7800 и засирать состояние fpu по каждому прерыванию. решаем проблему так - выполняем csrrci -
* чтение регистра и ТОЛЬКО сброс!!! бита глобального прерывания при выходе взад записываем исходное сотояние,
* также получаем бонус! исключаем четыре иструкции загрузки регистров так как используем indirect варианты команд доступа к mstatus !
* имеем результат:
* portUBASE_TYPE xPortSetInterruptMask(void) { portUBASE_TYPE uvalue=0; __asm volatile("csrrci %0, mstatus, %1":"=r"(uvalue):"i"(0x8)); return uvalue; }
* void vPortClearInterruptMask(portUBASE_TYPE uvalue) { __asm volatile("csrw mstatus, %0"::"r"(uvalue)); }
*
* 5. TODO #0: выполнив пункт 2 открывается возможность сделать "ленивое" сохранение/востановление регистров сопроцессора.
* на данный момент все гоняется "туда-сюда по полной" при смене контекста - и целочисленные регистры и регистры fpu.
* однако наличие флагов
* src::mstatus [14:13] Floating-point unit status
* позволяют выполнять отслеживание изменения состояния fpu за время кванта времени выполненя потока(task) выполнять сохранение/востановление
* только в случае необходимости, что сущенственно снизить время на переключение контектов потоков которые редко или вообще не не исполняют код,
* использующий fpu
* как результат приведенных рассуждений, планируется в ближайшее время это реализовать в шедуллере и посмотерь каков выйгрыш по времени и при
* каких условиях, выработать методику разработки и проектирования кода с эффективным использованием этой фичи.
*
* 6. TODO #1: порт назван как qkv4 - то есть для всех вариантов: V4A, V4B, V4C и V4F. но по факту данный код для V4F у которого есть fpu.
* я решил поступить как делает японский автопром - сначала ебалайка на колесиках в ПОЛНОЙ КОМПЛЕКТАЦИИ, а уж потом что то отключать дефайнами,
* а не как у гейропейцев и у нас - сделать полуфабрикат, а потом прикручивать скотчем костыли. расширяющие фцнкционал...
*/