Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вышла TNKernel 2.7
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы
yuri_t

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

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

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 и каждый творит что хочет.
Но если посчитаете перечисленные хотелки приемлимыми и адекватными, то не плохо чтобы это все появилось в оффициальной версии
Grape
Спасибо!

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

Код
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

megajohn
небольшие рекомендации от меня:
не использовать printf и прочие тяжелые функции в tn_app_init, так как исполнение этой функции выполняется в контексе сервисной задачи tn_timer_task, у которой стек не большой и по дефолту 64 слова.
В результате выхода за пределы стека, портится список tn_ready_list (который как раз находится перед tn_timer_task_stack )
в итоге, получаете удивительные но нерадостные сюрпризы от операционки.




megajohn
a вce-тaки пoлeзнaя фичa peaлизoвaнa idle_user_cb вepcии 2.5 для PIC24.
Может сделать стандартым для всех портов ?
megajohn
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 разместить в начале структур, чтобы проще выявлять виновников портящих память
Almaz_emb
Добрый день!
Сразу же прошу прощения если мой ламерский вопрос не в тему.
Встала задача запустить 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".
Как быть?
A. Fig Lee
Кстати, а есть сравнение TNkernel с Coocox?
dimonomid
Всем привет.

Сразу перейду к делу, после чего изложу лирику, если она кому-то интересна. Итак: в 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; Не знаю, заинтересует ли кого-то этот мой проект, но на всякий случай я написал.

Спасибо за внимание.
Valentine Loginov
Очень интересно, спасибо! А то сейчас на pic'ах грустно с качественными ОСРВ, а в своё время tn_kernel очень нравился sm.gif
Хотелось бы узнать: есть ли возможность посмотреть проекты с unit-test'ами? Тесты очень часто помогают понять логику API больше, чем документация. Да и вообще интересно на какой платформе тестируется: x86, pic-mips или совместно?
dimonomid
Цитата(Valentine Loginov @ Sep 18 2014, 12:16) *
Очень интересно, спасибо! А то сейчас на pic'ах грустно с качественными ОСРВ, а в своё время tn_kernel очень нравился sm.gif
Хотелось бы узнать: есть ли возможность посмотреть проекты с 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

Вот таким образом. Уже много раз эти тесты сразу указывали мне, когда я где-то что-то ломал sm.gif
megajohn
прикрутил к 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 );
        }
    }
}
Intel4004
А порт для Cortex-M0(M0+) существует?
megajohn
Цитата(Intel4004 @ Oct 30 2015, 03:40) *
А порт для Cortex-M0(M0+) существует?


где-то на просторах электроникса лежит tn_port_cm0 ( но не нашел )
но вот давненько выкладывал готовый проект, можете оттуда выдрать
Intel4004
Цитата(megajohn @ Oct 30 2015, 12:49) *
где-то на просторах электроникса лежит tn_port_cm0 ( но не нашел )
но вот давненько выкладывал готовый проект, можете оттуда выдрать


Спасибо, выдрал.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.