реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Embedded TDD (Test Driven Development): отладка реентерабельных модулей, похоже, это можно делать и в простых системах.
Evgeny_CD
сообщение Aug 22 2006, 16:06
Сообщение #1


Гуру
******

Группа: СуперМодераторы
Сообщений: 2 065
Регистрация: 11-01-05
Из: Москва
Пользователь №: 1 892



========== Предыдущие посты по теме ==========

TDD (Test-driven Development) применительно к embedded системам: похоже, я догнал, как это должно быть устроено.
http://www.caxapa.ru/echo/arm.html?id=63285
http://electronix.ru/forum/index.php?showtopic=18859

Развитие идей по упрощенной отладке.
http://www.caxapa.ru/echo/arm.html?id=63474
http://electronix.ru/forum/index.php?s=&showtopic=18859

Дальнейшее развитие идей по Embedded TDD (test driven development). Самый экономичный вариант по памяти и процу.
http://www.caxapa.ru/echo/arm.html?id=65892
http://electronix.ru/forum/index.php?showtopic=20099

========== COG ==========
http://www.nedbatchelder.com/code/cog/index_ru.html
http://www.onembedding.com/articles/cog-n-make/
http://www.onembedding.com/articles/cog-n-make/examples.htm

========== Суть ==========

Есть некий модуль. Надо оттестировать. Он реентерабелен, и его юзают все, кому не лень.

Мы построили test framework (по одной изобсужденных или иной технологии) и вкомпилли его в реальное приложение. Запустили.

При помощи __FILE__, __LINE__ (большой респект Алексей Мусин:: Caxapa - до меня только сейчас дошла вся красота использования этих классических "шняг" !!!) мы идентифицировали, кому принадлежит отладочный вывод. Но остается вопрос - а какому инстансу нашей функции принадлежит этот вывод? Как это отловить? Как там насчет PID в простых осях?

Нда, это уже "GDB вручную" получается....

С другой стороны, я просто чую, что вырисовывается совершенно фантастическая картина. Если не заморачиваться на JTAG и специфические отладочные функции среды (например, CrossWorks умеет программно из программы на таргете открывать файлы на хосте по JTAG!), то пожно построить полностью портабильную систему тестирования софта. JTAG пусть остается для начальной "заводки" незнакомой платформы да для отладки дров.

А грамотное использование COG (или другой подобной кодогенерации) позволит свести ручную работу к минимуму.

========== Отладка с минимальным уровнем вмешательства в отлаживаемую программу ==========

При использовании prinf и других "стандартых отладочных шняг" есть опасность внести сильные изменения в работу многозадачной системы. Ибо шняги не просто жрут память, они еще и стек жрут. И может полчить так, что их работа со стеком внесет существенное "возмущение" в систему (отлаживать с большим стеком на задачу, а затем при переходе в release стек уменьшать просто глупо, ибо отлов ошибок по стеку и есть одна из целей отладки).

Есть идея!

Резервируем некую область памяти для отладки. Делаем из нее систему кольцевых буферов с дескрипторами.

Есть прерывание - "выводилка" - читает эти буфера и загоняет их в отладочный интерфес - COM, Ethernet,...

module_under_test();
// задать список переменных для отладочного вывода
// комананда для COG - сгенерировать отладочный кусок для переменных их списка
// COG генерирует кусок кода, который без вызовов чего бы то ни было заталкивает необходимую информацию в буфер
// __FILE__, __LINE__ используются для идентификации места, откуда прошел вывод
// PID тоже как-то надо учитывать

В результате:
* мы не нагружаем стеки задач - у нас не происходит вызовов функций
* мы не делаем "лишних" вызовов malloc, и, таким образом, ничего не нарушаем в системе
* мы только немного увеличиваем размера кода
* "отладочный" кусок памяти живет сам по себе, и на систему влияния не оказывает
* затраты процессорного времени на обработчик прерывания будут небольшими при грамотном подходе. Поскольу обработчик работает только с дебуг интерфейсом и свой областью памяти, то он тоже ничего не сможет нарушить.
* переход debug -> release:
-- ставим флаг запрете генерации отладочного кода
* организация файлов проекта
-- my_file_proto.c - тут живут исходники верхнего увровня - с командами для COG
-- my_file.c - это получается после обработки proto COG. Именно эти файлы идут на компиляцию.

COG позволит вставлять достаточно большие "параметризированные" куски кода, задав всего лишь несколько параметров. Такой кусок кода один раз отлаживается - и все, на все случаи жизни.

С реентерабельностью вроде как тоже все получется - просто памяти поболее в дебуг область.

YES!!!
Go to the top of the page
 
+Quote Post
klen
сообщение Aug 22 2006, 17:04
Сообщение #2


бессмертным стать можно тремя способами
*****

Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912



Идея насчет узнавания кто реентвбельную функцию заюзал:
1. Эсли это нормальная ОС - читаем PID, HANDLE, ID и так далее и выводим в отлаочный интерфейс.
2. Если это нормальный шедуллер smile.gif типа FreeRTOS то в момент запуска системы скидываем указатели на вершины стеков задач (держим их в уме), а в месте отладочного вывода суем из реентабельного модуля текущий указатель стека - таким образом на основании таблицы вершин узнаем кто заюзал его. Естественно это работает если стеки не глючат, если так то можно еще чтонит засунуть, всегда есть атрибуты уникальные.
Go to the top of the page
 
+Quote Post
Evgeny_CD
сообщение Aug 22 2006, 18:29
Сообщение #3


Гуру
******

Группа: СуперМодераторы
Сообщений: 2 065
Регистрация: 11-01-05
Из: Москва
Пользователь №: 1 892



Цитата(klen @ Aug 22 2006, 21:04) *
1. Эсли это нормальная ОС - читаем PID, HANDLE, ID и так далее и выводим в отлаочный интерфейс.
Для нормальых осей все понятно. Нам надо lite.
Цитата(klen @ Aug 22 2006, 21:04) *
2. Если это нормальный шедуллер smile.gif типа FreeRTOS то в момент запуска системы скидываем указатели на вершины стеков задач (держим их в уме), а в месте отладочного вывода суем из реентабельного модуля текущий указатель стека - таким образом на основании таблицы вершин узнаем кто заюзал его. Естественно это работает если стеки не глючат, если так то можно еще чтонит засунуть, всегда есть атрибуты уникальные.
a14.gif за идею!!!
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 22 2006, 18:58
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(klen @ Aug 22 2006, 20:04) *
Если это нормальный шедуллер smile.gif типа FreeRTOS то в момент запуска системы скидываем указатели на вершины стеков задач (держим их в уме)

??? что значит "скидываем"? Указатель на начало стека pxStack штатно хранится в TCB FreeRTOS.
Размер стека usStackDepth - хранится тоже, но это лишнее - я выбросил нафиг, ибо у менеджера памяти спросить можно при необходимости.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Evgeny_CD
сообщение Aug 22 2006, 19:18
Сообщение #5


Гуру
******

Группа: СуперМодераторы
Сообщений: 2 065
Регистрация: 11-01-05
Из: Москва
Пользователь №: 1 892



Цитата(zltigo @ Aug 22 2006, 22:58) *
??? что значит "скидываем"? Указатель на начало стека pxStack штатно хранится в TCB FreeRTOS.
Размер стека usStackDepth - хранится тоже, но это лишнее - я выбросил нафиг, ибо у менеджера памяти спросить можно при необходимости.
А там случайно в TCB какой-нибудь идентификатор процесса не хранится? Чтобы поменьше возни было...
Go to the top of the page
 
+Quote Post
klen
сообщение Aug 22 2006, 19:22
Сообщение #6


бессмертным стать можно тремя способами
*****

Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912



Цитата(zltigo @ Aug 22 2006, 22:58) *
...ибо у менеджера памяти спросить можно при необходимости.

У меня суперлайт! никакого менеджера памяти нет, спрашивать некого. Поэтому и предложил запоминать границы стеков при их выделении(они то конечно хранятся в TCB), но в момент глюка эту TCB можно и потерять, а указатель стека вот он родимый в регистре.
Хотя в момент глюка все можно потерять.. и начения регистров и содержимое памяти, тогда ваще нихрена не узнаеш откуда трасса пришла.

Сообщение отредактировал klen - Aug 22 2006, 19:23
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 22 2006, 19:29
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Evgeny_CD @ Aug 22 2006, 22:18) *
А там случайно в TCB какой-нибудь идентификатор процесса не хранится? Чтобы поменьше возни было...

Хранится :-) pcTaskName - ASCII символы ( до 8 штук это у меня, конфигурабельно) в качестве имени задачи.
В менеджер памяти собираюсь дополнительно засунуть адрес TCB 'владельца' - в своих системках так всегда делал - задача и все порожденные ей буфера как на ладошке...


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Evgeny_CD
сообщение Aug 22 2006, 19:35
Сообщение #8


Гуру
******

Группа: СуперМодераторы
Сообщений: 2 065
Регистрация: 11-01-05
Из: Москва
Пользователь №: 1 892



Цитата(klen @ Aug 22 2006, 23:22) *
У меня суперлайт! никакого менеджера памяти нет, спрашивать некого. Поэтому и предложил запоминать границы стеков при их выделении(они то конечно хранятся в TCB), но в момент глюка эту TCB можно и потерять, а указатель стека вот он родимый в регистре.
Хотя в момент глюка все можно потерять.. и начения регистров и содержимое памяти, тогда ваще нихрена не узнаеш откуда трасса пришла.
Идея с суперглюкоустойчивостью понятна. Сразу виден опыт суровой борьбы с глюками при минимальных ресурсах железа. biggrin.gif Спасибо!

Но с другой стороны, если накопить весь массив трасс перед этим, то можно, постепенно вставляя новые check points, найти место, после которого труба наступает smile.gif


Цитата(zltigo @ Aug 22 2006, 23:29) *
Хранится :-) pcTaskName - ASCII символы ( до 8 штук это у меня, конфигурабельно) в качестве имени задачи.
В менеджер памяти собираюсь дополнительно засунуть адрес TCB 'владельца' - в своих системках так всегда делал - задача и все порожденные ей буфера как на ладошке...
Да, чувствуется на FreeRTOS Вы целую стаю собак съели! А в том коде, что на сайте лежит, что там насчет pcTaskName?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 22 2006, 19:37
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(klen @ Aug 22 2006, 22:22) *
тогда ваще нихрена не узнаеш откуда трасса пришла.

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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
klen
сообщение Aug 22 2006, 19:43
Сообщение #10


бессмертным стать можно тремя способами
*****

Группа: Свой
Сообщений: 1 405
Регистрация: 9-05-06
Из: Москва
Пользователь №: 16 912



Цитата(Evgeny_CD @ Aug 22 2006, 23:35) *
Цитата(klen @ Aug 22 2006, 23:22) *
У меня суперлайт! никакого менеджера памяти нет, спрашивать некого. Поэтому и предложил запоминать границы стеков при их выделении(они то конечно хранятся в TCB), но в момент глюка эту TCB можно и потерять, а указатель стека вот он родимый в регистре.
Хотя в момент глюка все можно потерять.. и начения регистров и содержимое памяти, тогда ваще нихрена не узнаеш откуда трасса пришла.
Идея с суперглюкоустойчивостью понятна. Сразу виден опыт суровой борьбы с глюками при минимальных ресурсах железа. biggrin.gif Спасибо!

Но с другой стороны, если накопить весь массив трасс перед этим, то можно, постепенно вставляя новые check points, найти место, после которого труба наступает smile.gif


Цитата(zltigo @ Aug 22 2006, 23:29) *
Хранится :-) pcTaskName - ASCII символы ( до 8 штук это у меня, конфигурабельно) в качестве имени задачи.
В менеджер памяти собираюсь дополнительно засунуть адрес TCB 'владельца' - в своих системках так всегда делал - задача и все порожденные ей буфера как на ладошке...
Да, чувствуется на FreeRTOS Вы целую стаю собак съели! А в том коде, что на сайте лежит, что там насчет pcTaskName?


Зачем таскать имя задачки? это лишнее
Вот TCB
Код
/*
* Task control block.  A task control block (TCB) is allocated to each task,
* and stores the context of the task.
*/
typedef struct tskTaskControlBlock
{
    volatile portSTACK_TYPE    *pxTopOfStack;        /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE STRUCT. */
    xListItem                xGenericListItem;    /*< List item used to place the TCB in ready and blocked queues. */
    xListItem                xEventListItem;        /*< List item used to place the TCB in event lists. */
    unsigned portBASE_TYPE    uxPriority;            /*< The priority of the task where 0 is the lowest priority. */
    portSTACK_TYPE            *pxStack;            /*< Points to the start of the stack. */
    unsigned portBASE_TYPE    uxTCBNumber;        /*< This is used for tracing the scheduler and making debugging easier only. */
    signed portCHAR            pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */
    unsigned portSHORT        usStackDepth;        /*< Total depth of the stack (when empty).  This is defined as the number of variables the stack can hold, not the number of bytes. */
} tskTCB;


Тут есть типа "PID" - uxTCBNumber , тоесть просто уникальный номер задачи. Тут и написано "ДЛЯ ТРАССИРОВКИ", те для отладки.
С эти все и так понятно.

Не понятно вот что. Кто ?? будет ставит check-point до наступления "трубы". Если это буду делать я а не автомат то я тогда не догнал тему топика. Я и так руками отлаживаю. К чему стремимся?

Сообщение отредактировал klen - Aug 22 2006, 19:44
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 22 2006, 19:45
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Evgeny_CD @ Aug 22 2006, 22:35) *
Да, чувствуется на FreeRTOS Вы целую стаю собак съели!

Выбирал опираясь на свой предыдущий опыт собственного системописательства. Теперь пользуюсь, смотрю, обдумываю, правлю под себя.
Цитата
А в том коде, что на сайте лежит, что там насчет pcTaskName?

Это штатная фича, просто по умолчанию, там кажется 16 сиволов заложено - меня жаба задушила :-)


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Evgeny_CD
сообщение Aug 22 2006, 19:58
Сообщение #12


Гуру
******

Группа: СуперМодераторы
Сообщений: 2 065
Регистрация: 11-01-05
Из: Москва
Пользователь №: 1 892



Цитата(klen @ Aug 22 2006, 23:43) *
Тут есть типа "PID" - uxTCBNumber , тоесть просто уникальный номер задачи. Тут и написано "ДЛЯ ТРАССИРОВКИ", те для отладки.
С эти все и так понятно.
Спасибо! Все действительно стало понятно. Вероятно, не одни мы такие изыскания проводили smile.gif
Цитата(klen @ Aug 22 2006, 23:43) *
Не понятно вот что. Кто ?? будет ставит check-point до наступления "трубы". Если это буду делать я а не автомат то я тогда не догнал тему топика. Я и так руками отлаживаю. К чему стремимся?
Естественно, речь идет об автомате. Я себе так мыслю.

* есть комплект макросов для редактора. Типа по курсору вставить специальный коммент для COG

* есть все необходимые модули для COG

* есть отладочный фрейвмворк на питоне, который автоматизирует всю рутинную работу. Например, он сканирует proto файлы и строить в памяти таблицу - что Вы там на отладку поставили. Затем принимает отладочный поток и расладывает его по этой таблице

* есть небольшой модуль, test unit, специально написанный Вами для теста. Он оперирует высокоуровнеыми понятиями (созданными внутри фреймфорка): задает тестовое воздействие и смотрит результат.

* все это хозяйство управляется из интерактивной консоли типа
http://ipython.scipy.org/ - супер весчь!!!

Кайф в том, что вместо "парсинга глазами" можно в пару строк написать нормальный парсер (на пЫтоне это просто идеально пишется), который из отладочного вывода выловит то, что надо.

Т.е. фактически при возникновени непоняток Вы насыщаете код COG макросами для отладки, затем играетесь с фильтром, чтобы отловить интересующий момент.

По моему мнению это должно дать нехилую экономию времени.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Aug 22 2006, 21:28
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(klen @ Aug 22 2006, 22:43) *
Зачем таскать имя задачки? это лишнее

Затем, дабы не вспоминать, что такое задача номер 9 для какой-то конкретной сборки спустя некоторе время. Кроме того, политика назначения во FreeRTOS этого числа абсолютно отфонарна - просто порядковый номер вызова xTaskCreate(), что при использовании механизма прибития задач приводит
к появлению хоть и уникального (и то при условии не переполнения), но абсолютно произвольного и не индифицирующего задачу числа :-(.
Автором используется исключительно для того, чтобы макрос vWriteTraceToBuffer() был потупее и сохранял поменьше информации. Бесполезный параметр - у меня он под
#if ( configUSE_TRACE_FACILITY == 1 )
стоит :-)
Еще некоторое время тому назад использовался в качестве параметра для прибития задачи из командной строки консоли, потом на имя перешел и прибил номер задачи.
При этом оставив:
Код
typedef struct tskTaskControlBlock
{
....
    signed portCHAR            pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */
.....
} tskTCB;


Цитата
Тут есть типа "PID" - uxTCBNumber , тоесть просто уникальный номер задачи. Тут и написано "ДЛЯ ТРАССИРОВКИ", те для отладки.

Трассировка это tracecon.exe :-) не пользовался и не буду этой внешней приблудой пользоватся,
а нежели внутреннюю буду делать - воспользуюсь для аналогичной цели просто адресом TCB.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 17:58
Рейтинг@Mail.ru


Страница сгенерированна за 0.01564 секунд с 7
ELECTRONIX ©2004-2016