Перейти к содержанию
    

Вышла TNKernel 2.7

 

Эта версия посвящена ,в основном, устранению накопившихся багов.

 

Огромное спасибо всем участникам проекта TNKernel !!!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

благодарю, но хочу высказать свои хотелки, в целях повышения юзабельности

 

1. добавить контроль стека в tn_port_cm3_iar.s. Хотя бы закоменченным блоком. Кому надо разкоментят на этапе отладки.

2. вынести TN_CHECK_PARAM, TN_MEAS_PERFORMANCE, USE_MUTEXES, USE_EVENTS из tn.h в tn_config.h. Как это реализовано в прочих ОС

3. добавить mailbox. Повышает функциональность за счет увеличенного трансфера данных между задачами

4. сделать TN_FILL_STACK_VAL оффициальным 0xDEADBEEF

5. в tn_event_wait сделать p_flags_pattern необязательным

6. в TN_TCB опциональные поля под дефайнами USE_MUTEXES и USE_EVENTS перенести в хвост структуры. Это для унификации пункта 1 и будущих асмовских проверок

 

P.S. это я всё у себя реализовал. И понимаю что TNKernel is free и каждый творит что хочет.

Но если посчитаете перечисленные хотелки приемлимыми и адекватными, то не плохо чтобы это все появилось в оффициальной версии

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо!

 

немножко дополнений...

 

diff -urN 2.7/TNKernel/tn.c 2.7_mod/TNKernel/tn.c
--- 2.7/TNKernel/tn.c    2013-07-01 10:29:34.000000000 +0400
+++ 2.7_mod/TNKernel/tn.c    2013-07-16 12:42:45.687500000 +0400
@@ -238,12 +238,12 @@

    TN_CHECK_NON_INT_CONTEXT

-   tn_disable_interrupt();
-
    if(priority <= 0 || priority >= TN_NUM_PRIORITY-1 ||
                                 value < 0 || value > MAX_TIME_SLICE)
       return TERR_WRONG_PARAM;

+   tn_disable_interrupt();
+
    tn_tslice_ticks[priority] = value;

    tn_enable_interrupt();
diff -urN 2.7/TNKernel/tn_event.c 2.7_mod/TNKernel/tn_event.c
--- 2.7/TNKernel/tn_event.c    2013-07-01 10:30:42.000000000 +0400
+++ 2.7_mod/TNKernel/tn_event.c    2013-07-16 12:43:43.015625000 +0400
@@ -349,10 +349,12 @@
{
    TN_INTSAVE_DATA

+#if TN_CHECK_PARAM
    if(evf == NULL || pattern == TN_INVALID_VAL)
       return TERR_WRONG_PARAM;
    if(evf->id_event != TN_ID_EVENT)
       return TERR_NOEXS;
+#endif

    TN_CHECK_NON_INT_CONTEXT

diff -urN 2.7/TNKernel/tn_mutex.c 2.7_mod/TNKernel/tn_mutex.c
--- 2.7/TNKernel/tn_mutex.c    2013-07-01 10:31:54.000000000 +0400
+++ 2.7_mod/TNKernel/tn_mutex.c    2013-07-16 12:44:39.609375000 +0400
@@ -93,7 +93,7 @@

    TN_CHECK_NON_INT_CONTEXT
     
-   if(tn_curr_run_task != mutex->holder)
+   if(mutex->holder && (tn_curr_run_task != mutex->holder))
       return TERR_ILUSE;

    //-- Remove all tasks(if any) from mutex's wait queue

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

небольшие рекомендации от меня:

не использовать printf и прочие тяжелые функции в tn_app_init, так как исполнение этой функции выполняется в контексе сервисной задачи tn_timer_task, у которой стек не большой и по дефолту 64 слова.

В результате выхода за пределы стека, портится список tn_ready_list (который как раз находится перед tn_timer_task_stack )

в итоге, получаете удивительные но нерадостные сюрпризы от операционки.

 

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

a вce-тaки пoлeзнaя фичa peaлизoвaнa idle_user_cb вepcии 2.5 для PIC24.

Может сделать стандартым для всех портов ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9. в фyнкциях tn_event_clear и tn_task_create проверка параметров без условной компиляции

10. при компиляции без TN_CHECK_PARAM поля id_task, id_mutex и прочие id излишны, и только зря "поедают" RAM

11. не плохо бы разместить поля id_task, id_mutex и прочие в режиме TN_CHECK_PARAM разместить в начале структур, чтобы проще выявлять виновников портящих память

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добрый день!

Сразу же прошу прощения если мой ламерский вопрос не в тему.

Встала задача запустить TNKernel на STM32F401VC.

Порядок действий:

Скачал порт для Cortex M4 на офф сайте: http://www.tnkernel.com/tn_port_CortexM4.html

Из скачанного архива перенес папку "TNKernel" в свой проект. Добавил в проект все исходники, прописал пути к заголовочным файлам, выставил необходимые макроопределения.

Теперь пытаюсь написать простейшую программу:

#include <tn.h>

#define  TASK_1_PRIORITY   5   

#define  TASK_1_STK_SIZE     128   

unsigned int task_1_stack[TASK_1_STK_SIZE];   

TN_TCB  task_1;   

void task_1_func(void * par);   
void tn_app_init(void)
{
}

int main( void )
{
    tn_start_system();
    while(1)
    {
    }
}

 

И тут я получаю сообщения об ошибках:

compiling main.c...
C:\Keil_v5\ARM\PACK\ARM\CMSIS\4.1.0\CMSIS\Include\core_cmFunc.h(181): error:  #247: function "__get_PRIMASK" has already been defined
  __STATIC_INLINE uint32_t __get_PRIMASK(void)
C:\Keil_v5\ARM\PACK\ARM\CMSIS\4.1.0\CMSIS\Include\core_cmFunc.h(194): error:  #247: function "__set_PRIMASK" has already been defined
  __STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
src\main.c: 0 warnings, 2 errors
".\output\stm32.axf" - 2 Error(s), 0 Warning(s).

Функции __get_PRIMASK() и __set_PRIMASK() в файле "tn_port_cmf4.h" совпадают с одноименными функциями из файла "core_cmFunc.h".

Как быть?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всем привет.

 

Сразу перейду к делу, после чего изложу лирику, если она кому-то интересна. Итак: в TNKernel все еще есть достаточно неприятные баги, и в течении последнего месяца я интенсивно переписываю TNKernel, исправляя найденные ошибки. Ошибки обнаруживаются с помощью подробных unit-тестов (которые я тоже аккуратно пишу), благодаря чему стабильность системы реально повышается, а вероятность добавления впоследствии новых ошибок снижается. Судя по найденным багам, оригинальная TNKernel тестировалась только "вручную", без формализованных тестов, что печально.

 

Текущий список найденных и исправленных багов:

 

* если в tn_sys_tclice_ticks() переданы неверные параметры, то возвращается TERR_WRONG_PARAM и прерывания остаются запрещенными

* есть три задачи: две низкоприоритетные с одинаковым приоритетом task_low1 и task_low2; и одна высокоприоритетная task_high. Теперь: task_low1 блокирует мютекс М1 (с алгоритмом повышения наследования приоритета), потом task_low2 пытается тоже его заблокировать и уходит в ожидание, потом task_high тоже пытается его заблокировать и тоже уходит в ожидание -> приоритет task_low1 повышается до приоритета task_high. Теперь task_low1 разблокирует мютекс, следующая задача в очереди - task_low2, она его блокирует, и ее приоритет должен быть повышен до приоритета task_high (т.к. она все еще его ждет), но этого не происходит: высокоприоритетная task_high продолжает ждать задачу task_low2, приоритет которой низкий.

* низкоприоритетная задача task_low блокирует мютекс М1 (с алгоритмом повышения наследования приоритета), высокоприоритетная задача task_high тоже пытается его заблокировать и уходит в ожидание -> приоритет task_low повышается до приоритета task_high; теперь task_high выходит из ожидания по таймауту -> приоритет task_low остается повышенным. То же самое происходит, если task_high была остановлена с помощью tn_task_terminate.

* tn_mutex_delete() - если мютекс не заблокирован, то возвращается TERR_ILUSE. То есть, чтобы удалить мютекс, нужно сначала его заблокировать. Это неправильно.

 

Проект размещен на bitbucket: ссылка.

 

Как получилось, что я вообще занялся этим: сначала я долгое время пользовался портом Alex.B для PIC32, не особо вникая в то, как работает это ядро; потом в какой-то момент меня очень расстроил тот факт, что в нормальном режиме работы контекст может быть сохранен в стек задачи два и более раз. Плюс к этому, мне уже давно надоели проблемы, связанные с тем, что для прерываний используется стек задачи, которую оно прервало (вместо отдельного стека для прерываний) - на это тратится куча RAM, которой и так вечно не хватает, и я начал искать другой порт. Нашел: это порт от Anders Montonen, в котором для прерываний используется отдельный стек, поддерживаются вложенные прерывания и shadow register set.

 

Но в этом порте отсутствовали некоторые вкусности, которые есть в порте Alex.B: как минимум, там не было удобных Сишных макросов для определения прерываний, и еще сам TNKernel должен быть собран в составе проекта, без возможности выделить его в отдельную либу. Таким образом, я решил допилить его для себя. Anders Montonen хочет оставить свой порт настолько близко к апстриму, насколько возможно, поэтому мне оставалось только форкнуть его.

 

Далее, чем больше я вникал в TNKernel, тем меньше мне нравился ее код. Подробно см. на страничке моего проекта Why refactor?, все переписывать сюда не буду, изложу кратко: очень много дублирования кода, нет централизованных методов чтобы делать многие вещи, таким образом, одно и то же реализовано в куче мест просто копи-пастом (именно это является причиной изложенных выше багов с мютексами). Почти в каждой функции есть много точек выхода, почти перед каждым оператором return - разрешение прерываний. Это нарушение очень хорошего правила: "одна точка входа - одна точка выхода". Если бы это правило соблюдалось, то ошибка в tn_sys_tclice_ticks() никогда не появилась бы.

 

Должен сказать, что в своих "текущих" проектах я иногда позволяю себе вольности (хоть и знаю, что могу навлечь на себя беду), и далеко не всегда у меня получается код, который мне очень нравится. Но ядро - особый проект; и я хочу чтобы код ядра был как можно более близок к идеальному. Поэтому я решил заняться этим, хотя это отнимает сейчас все мое свободное время: работы очень много.

 

В данный момент большинство кода уже переписано таким образом, чтобы код дублировался как можно меньше. Если есть два похожих сервиса (например, tn_fmem_release() и tn_fmem_irelease()), то основная работа производится в одном месте, а вышеуказанные сервисы являются только обертками, совершающими соответствующие вступительные и заключительные действия.

 

И так во всем остальном. Больше всего путаницы с мютексами и их алгоритмами управления приоритетами задач; tn_mutex.c и tn_tasks.c переписаны, наверное, процентов на 70%.

 

Насчет тестов: на данный момент написаны очень подробные тесты для мютексов, чуть менее подробные тесты для управления задачами. Остальное - в скором (надеюсь) будущем.

 

О некоторых проблемах (например, про баг в tn_sys_tclice_ticks и про путаницу с макросом MAKE_ALIG) я писал Юрию на почту, он ничего не ответил: видимо, потерял интерес.

 

Некоторые детали API были изменены, т.к. они мне не нравятся; конкретно об изменениях тут: Differences from original TNKernel. Скорее всего, впоследствии API будет еще изменяться (т.к. я еще не все поправил, что мне не нравится), но по возможности оставлю слой совместимости с оригинальным TNKernel.

 

Вообще, изменений уже очень много (например, нет timer task - подробнее об этом по ссылке выше, хотя на API это не влияет), и будет еще больше, так что совместимость с оригинальной TNKernel будет, конечно, не абсолютная. Чтобы не вводить в заблуждение, возможно, придется выбрать новое название. Возможно, это будет TNeoKernel - и безусловная причастность к TNKernel указана (Юрий, большое спасибо вам за этот проект), и добавлена частичка Neo, которая указывает на некую новизну =)

 

В настоящий момент существует только порт для PIC32; Не знаю, заинтересует ли кого-то этот мой проект, но на всякий случай я написал.

 

Спасибо за внимание.

Изменено пользователем dimonomid

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Очень интересно, спасибо! А то сейчас на pic'ах грустно с качественными ОСРВ, а в своё время tn_kernel очень нравился :)

Хотелось бы узнать: есть ли возможность посмотреть проекты с unit-test'ами? Тесты очень часто помогают понять логику API больше, чем документация. Да и вообще интересно на какой платформе тестируется: x86, pic-mips или совместно?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Очень интересно, спасибо! А то сейчас на pic'ах грустно с качественными ОСРВ, а в своё время tn_kernel очень нравился :)

Хотелось бы узнать: есть ли возможность посмотреть проекты с unit-test'ами? Тесты очень часто помогают понять логику API больше, чем документация. Да и вообще интересно на какой платформе тестируется: x86, pic-mips или совместно?

 

Спасибо за интерес =)

 

Проект с юнит-тестами пока один, гоняю в железе на своем PIC32MX440F512H (камень, использующийся в текущем проекте на моей работе), вывожу лог в UART.

 

Конечно я покажу его, но сразу предупрежу: его код пока не такой вылизанный: к сожалению, мое open-source время ограничено и на все не хватает, но когда я смогу найти время и причесать его, то размещу ссылку на странице самого ядра.

 

Как в целом работают тесты: есть задача с самым высоким приоритетом (типа test_director), она создает себе рабочие задачи(A, B, C, ...), создает объекты (например, мютексы: M1, M2, ...), говорит задачам что делать, и проверяет, что после этого получилось.

 

Вкратце, код тестов выглядят примерно так:

 

   TNT_TEST_COMMENT("A locks M1");
   TNT_ITEM__SEND_CMD_MUTEX(TNT_TASK__A, MUTEX_LOCK, TNT_MUTEX__1);
   TNT_ITEM__WAIT_AND_CHECK_DIFF(
         TNT_CHECK__MUTEX(TNT_MUTEX__1, HOLDER, TNT_TASK__A);
         TNT_CHECK__MUTEX(TNT_MUTEX__1, LOCK_CNT, 1);

         TNT_CHECK__TASK(TNT_TASK__A, LAST_RETVAL, TERR_NO_ERR);
         );

   TNT_TEST_COMMENT("B tries to lock M1 -> B blocks, A has priority of B");
   TNT_ITEM__SEND_CMD_MUTEX(TNT_TASK__B, MUTEX_LOCK, TNT_MUTEX__1);
   TNT_ITEM__WAIT_AND_CHECK_DIFF(
         TNT_CHECK__TASK(TNT_TASK__B, LAST_RETVAL, TWORKER_MAN__LAST_RETVAL__UNKNOWN);
         TNT_CHECK__TASK(TNT_TASK__B, WAIT_REASON, TSK_WAIT_REASON_MUTEX_I);

         TNT_CHECK__TASK(TNT_TASK__A, PRIORITY, priority_task_b);
         );

   TNT_TEST_COMMENT("A deletes M1");
   TNT_ITEM__SEND_CMD_MUTEX(TNT_TASK__A, MUTEX_DELETE, TNT_MUTEX__1);
   TNT_ITEM__WAIT_AND_CHECK_DIFF(
         TNT_CHECK__MUTEX(TNT_MUTEX__1, HOLDER, TNT_TASK__NONE);
         TNT_CHECK__MUTEX(TNT_MUTEX__1, LOCK_CNT, 0);
         TNT_CHECK__MUTEX(TNT_MUTEX__1, EXISTS, 0);

         TNT_CHECK__TASK(TNT_TASK__A, LAST_RETVAL, TERR_NO_ERR);
         TNT_CHECK__TASK(TNT_TASK__A, PRIORITY, TNT_BASE_PRIORITY);
         TNT_CHECK__TASK(TNT_TASK__B, LAST_RETVAL, TERR_DLT);
         TNT_CHECK__TASK(TNT_TASK__B, WAIT_REASON, TSK_WAIT_REASON_DQUE_WRECEIVE);
         );

Здесь мы сначала выводим в лог дословный коммент "A locks M1", потом отправляем команду задаче A, чтобы она заблокировала мютекс 1. После чего ждем некоторое время, и проверяем: владелез мютекса 1 должна быть задача А, кол-во блокировок должно быть 1, последнее возвращенное значение - TERR_NO_ERR. Ну и так далее, код тестов должен быть понятен без лишних комментариев (я надеюсь).

 

В лог при этом выводится следующее:

 

[18.09 14:04:03] [I]: tnt_item_proceed():0910: ----- Command to task A: lock mutex M1 (0xa0006f14) 
[18.09 14:04:03] [I]: tnt_item_proceed():0937: Wait 80 ticks 
[18.09 14:04:03] [I]: _task_worker():0199: [Task A]: locking mutex (0xa0006f14).. 
[18.09 14:04:03] [I]: _task_worker():0206: [Task A]: mutex (0xa0006f14) locked 
[18.09 14:04:03] [I]: _task_worker():0160: [Task A]: waiting for command.. 
[18.09 14:04:03] [I]: tnt_item_proceed():0955: Checking: 
[18.09 14:04:03] [I]: * Task A: priority=6 (as expected), wait_reason=DQUE_WRECEIVE (as expected), last_retval=TERR_NO_ERR (as expected), state=WAIT (as expected) 
[18.09 14:04:03] [I]: * Task B: priority=5 (as expected), wait_reason=DQUE_WRECEIVE (as expected), last_retval=NOT-YET-RECEIVED (as expected), state=WAIT (as expected) 
[18.09 14:04:03] [I]: * Mutex M1: holder=A (as expected), lock_cnt=1 (as expected), exists=yes (as expected) 
[18.09 14:04:03] //-- B tries to lock M1 -> B blocks, A has priority of B (line 90 in ../source/appl/appl_tntest/appl_tntest_mutex.c) 
[18.09 14:04:03] [I]: tnt_item_proceed():0910: ----- Command to task B: lock mutex M1 (0xa0006f14) 
[18.09 14:04:03] [I]: tnt_item_proceed():0937: Wait 80 ticks 
[18.09 14:04:03] [I]: _task_worker():0199: [Task B]: locking mutex (0xa0006f14).. 
[18.09 14:04:03] [I]: tnt_item_proceed():0955: Checking: 
[18.09 14:04:03] [I]: * Task A: priority=5 (as expected), wait_reason=DQUE_WRECEIVE (as expected), last_retval=TERR_NO_ERR (as expected), state=WAIT (as expected) 
[18.09 14:04:03] [I]: * Task B: priority=5 (as expected), wait_reason=MUTEX_I (as expected), last_retval=NOT-YET-RECEIVED (as expected), state=WAIT (as expected) 
[18.09 14:04:03] [I]: * Mutex M1: holder=A (as expected), lock_cnt=1 (as expected), exists=yes (as expected) 
[18.09 14:04:03] //-- A deletes M1 (line 99 in ../source/appl/appl_tntest/appl_tntest_mutex.c) 
[18.09 14:04:03] [I]: tnt_item_proceed():0910: ----- Command to task A: delete mutex M1 (0xa0006f14) 
[18.09 14:04:03] [I]: tnt_item_proceed():0937: Wait 80 ticks 
[18.09 14:04:03] [I]: _task_worker():0227: [Task A]: deleting mutex (0xa0006f14).. 
[18.09 14:04:03] [I]: _task_worker():0208: [Task B]: mutex (0xa0006f14) locking failed with err=-10 
[18.09 14:04:03] [I]: _task_worker():0160: [Task B]: waiting for command.. 
[18.09 14:04:03] [I]: _task_worker():0234: [Task A]: mutex (0xa0006f14) deleted 
[18.09 14:04:03] [I]: _task_worker():0160: [Task A]: waiting for command.. 
[18.09 14:04:03] [I]: tnt_item_proceed():0955: Checking: 
[18.09 14:04:03] [I]: * Task A: priority=6 (as expected), wait_reason=DQUE_WRECEIVE (as expected), last_retval=TERR_NO_ERR (as expected), state=WAIT (as expected) 
[18.09 14:04:03] [I]: * Task B: priority=5 (as expected), wait_reason=DQUE_WRECEIVE (as expected), last_retval=TERR_DLT (as expected), state=WAIT (as expected) 
[18.09 14:04:03] [I]: * Mutex M1: holder=NONE (as expected), lock_cnt=0 (as expected), exists=no (as expected)

 

Если что-то пойдет не так, то будет не "as expected", а подробности, что именно ожидалось и что получилось, и тесты останавливаются.

 

Репозиторий можно получить так (будет скачан "environment" репозиторий с несколькими подрепами, одна из подреп - собственно, сам проект с тестами, остальные - либы, их немного) :

 

hg clone http://hg.dfrank.ru/rtos_check/_env rtos_check

 

Файл со всеми тестами мютексов: hg.dfrank.ru/rtos_check/project_common/files/tip/fw_tmp_bk16/appl/source/appl/appl_tntest/appl_tntest_mutex.c

Файл со всеми тестами задач (пока их немного) : hg.dfrank.ru/rtos_check/project_common/files/tip/fw_tmp_bk16/appl/source/appl/appl_tntest/appl_tntest_tasks.c

 

Лог всех тестов: http://vpaste.net/gsfGv

 

Вот таким образом. Уже много раз эти тесты сразу указывали мне, когда я где-то что-то ломал :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

прикрутил к TnKernel систему runtime контроля стеков задач, и текущего состояния задач. Кому интересно делюсь

 

пример

19:40:53                    priorty stkuse% cpu 
19:40:53  tskname state     bse/cur cur/max use% ProgCntr   pwait_que  mut...
19:40:53   tn_tmr wait slep   0/  0  28/ 35   0  0x0000ECCE 0x00000000 
19:40:53  tn_idle runnable   31/ 31  38/ 38  99  0x0001CB8E 0x00000000 
19:40:53     init dormant     2/  2   8/ 60   0  0x0001452D 0x00000000 
19:40:53  dprintf runnable   18/ 18  37/ 55   0  0x0000DDC4 0x00000000 
19:40:53      sdc wait queR   5/  5   9/ 29   0  0x0000DDC4 0x1000C674 
19:40:53     algo wait slep  16/ 16   8/ 42   0  0x00005A84 0x00000000 
19:40:53   sysobs runnable    8/  8  17/ 69   0  0x00005A84 0x00000000 
19:40:53      led runnable   19/ 19  23/ 23   0  0x00005A84 0x00000000 
19:40:53  calldir runnable   11/ 11  17/ 42   0  0x00005A84 0x00000000 
19:40:53   sysmon runnable    1/  1  32/ 35   0  0x0001FC2F 0x00000000 
19:40:53     v2sd wait queR  20/ 20  20/ 26   0  0x0000DDC4 0x1000C5F4 
19:40:53  collect wait queR  21/ 21   8/ 25   0  0x0000ACF0 0x1000C304 
19:40:53      sys wait slep  15/ 15  44/ 86   0  0x00005A84 0x00000000 
19:40:53      mdm runnable    7/  7  13/ 64   0  0x0000DDC4 0x00000000 
19:40:53  srvconn wait evnt  17/ 17  23/ 43   0  0x0000877A 0x100019C0 
19:40:53      sys wait slep  15/ 15  44/ 81   0  0x00005A84 0x00000000 
19:40:53      ftp wait queR  14/ 14  15/ 45   0  0x0000DDC4 0x1000C374 
19:40:53      mdm wait queR   7/  7  13/ 62   0  0x0000DDC4 0x10003594 
19:40:53   ssp_tx wait queR   4/  4  26/ 33   0  0x0000DDC4 0x100088A8 
19:40:53   ssp_rx wait evnt   3/  3  25/ 48   0  0x0000877A 0x10008C10 
19:40:53   ssp_tx wait queR   4/  4  26/ 34   0  0x0000DDC4 0x100081F4 
19:40:53   ssp_rx wait evnt   3/  3  24/ 48   0  0x0000877A 0x1000855C

 

реализация

//------------------------------------------------------------------------------
char const* tn_tsk_state_and_wait_rsn2str( int task_state, int task_wait_reason )
{
    switch( task_state )
    {
    default:                 return "?????????";
    case TSK_STATE_RUNNABLE: return "runnable ";
    case TSK_STATE_SUSPEND:  return "suspend  ";
    case TSK_STATE_WAITSUSP: return "wait sspd";
    case TSK_STATE_DORMANT:  return "dormant  ";
    case TSK_STATE_WAIT:
        switch( task_wait_reason )
        {
        case TSK_WAIT_REASON_SLEEP:          return "wait slep";
        case TSK_WAIT_REASON_SEM:            return "wait sem ";
        case TSK_WAIT_REASON_EVENT:          return "wait evnt";
        case TSK_WAIT_REASON_DQUE_WSEND:     return "wait queS";
        case TSK_WAIT_REASON_DQUE_WRECEIVE:  return "wait queR";
        case TSK_WAIT_REASON_MUTEX_C:        return "wait mtxc";
        case TSK_WAIT_REASON_MUTEX_C_BLK:    return "wait mtxb";
        case TSK_WAIT_REASON_MUTEX_I:        return "wait mtxi";
        case TSK_WAIT_REASON_MUTEX_H:        return "wait mtxh";
        case TSK_WAIT_REASON_RENDEZVOUS:     return "wait rnvs";
        case TSK_WAIT_REASON_WFIXMEM:        return "wait wfim";
        default:                             return "wait ????";
        }
    }
}

//------------------------------------------------------------------------------
void tcb2stack_usage( TN_TCB* tcb, unsigned int* curr_prcn_p, unsigned int* max_prcn_p )
{
    unsigned int* stk_head = tcb->stk_start - tcb->stk_size + 1;
    unsigned int* stk_p = stk_head;

    for(; *stk_p == TN_FILL_STACK_VAL; stk_p++ )
    {
        if( stk_p == tcb->stk_start )
            break;
    }

    unsigned int curr_prcn = 100 - ( tcb->task_stk - stk_head ) * 100 / tcb->stk_size;
    unsigned int max_prcn  = 100 - ( stk_p         - stk_head ) * 100 / tcb->stk_size;
    *curr_prcn_p = curr_prcn;
    *max_prcn_p  = max_prcn;
}

//------------------------------------------------------------------------------
void task_sysmon_func( void * par )
{
#ifndef DEBUG
    #define SYSMON_PERIOD ( 60 * 1000 )
#else
    #define SYSMON_PERIOD ( 15 * 1000 )
#endif

    while( 1 )
    {
        SLEEP( SYSMON_PERIOD );

        dprintf( "         " "          " "priorty " "stkuse%% " "cpu " );
        dprintf( " tskname " "state     " "bse/cur " "cur/max "  "use%% " "ProgCntr   " "pwait_que  " "mutex_que  " "ev_pattern" );
        //        11111111 " "???? ???? " "000/000 " "000/000 "  "000  "  "0x01234567 " "0x01234567 " "0x01234567 " "0x01234567"

        for( CDLL_QUEUE* p = &tn_create_queue; p->next != &tn_create_queue; p = p->next )
        {
            TN_TCB* tcb = (TN_TCB*)( (u8*)p->next - offsetof( TN_TCB, create_queue ) );

            unsigned int curr_prcn, max_prcn;
            tcb2stack_usage( tcb, &curr_prcn, &max_prcn );

            unsigned int curr_cpu = tcb->on_time_count * 100 / SYSMON_PERIOD;
            tcb->on_time_count = 0;
            Stn_stack_port_cm3* regs_stk = (Stn_stack_port_cm3*)tcb->task_stk;

            dprintf( "% 8s " "%s " "% 3d/% 3d " "% 3d/% 3d " "% 3d  " "0x%08X " "0x%08X " ,
                    tcb->name, tn_tsk_state_and_wait_rsn2str( tcb->task_state, tcb->task_wait_reason ),
                    tcb->base_priority, tcb->priority, curr_prcn, max_prcn, curr_cpu, regs_stk->psr, tcb->pwait_queue, tcb->mutex_queue, tcb->ewait_pattern );
        }
    }
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А порт для Cortex-M0(M0+) существует?

 

где-то на просторах электроникса лежит tn_port_cm0 ( но не нашел )

но вот давненько выкладывал готовый проект, можете оттуда выдрать

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

где-то на просторах электроникса лежит tn_port_cm0 ( но не нашел )

но вот давненько выкладывал готовый проект, можете оттуда выдрать

 

Спасибо, выдрал.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...