|
|
  |
RTOS, тупые вопросы |
|
|
|
Jun 7 2016, 07:03
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(AHTOXA @ Jun 7 2016, 09:59)  Всё понятно, "Пастернака не читал, но осуждаю". К вашему сведению, scmRTOS издавна поставляется с отличной документацией. ЗЫ. Вам хоть приплачивают за рекламу MQX? Или это вы добровольно?  А вы сколько на scmRTOS зарабатываете?  Цитата(dxp @ Jun 7 2016, 09:51)  Вау! Есть оказывается. Правда объемом со статью на гиктаймсе. Неудивительно что не заметил.
|
|
|
|
|
Jun 7 2016, 07:12
|
Гуру
     
Группа: Свой
Сообщений: 2 198
Регистрация: 23-12-04
Пользователь №: 1 640

|
Цитата(AlexandrY @ Jun 6 2016, 15:38)  К линуксу никакого отношения не имеет. Если не думать что родство с линуксом определяется по наличию функций read и write в структурах драйверов.
Путаница с линуксом может возникнуть от того, что в MQX есть стек межзадачного взаимодействия портированный в частности и на линукс. Поэтому MQX очень легко связать с линуксом в мультикристальных SoC-ах POSIX это не линукс. Линукс - это полноценная ось, в которой не только posix, но и куча всякого разного. то есть то, что сейчас модно называть экосистемой (+ куча народа, который знает эту экосистему). опять же синтетический таргет - то есть перенос кода с ПК. насколько я понимаю, в том же MQX TCP-шный стек уже за деньги? то есть, я хотел сказать, что если i.mx6, то смысл ставить на него переключалку задач имеет только для каких-то специфических приложений
|
|
|
|
|
Jun 7 2016, 09:14
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(dxp @ Jun 7 2016, 10:18)  Покажите статью на гиктаймсе объёмом в 140 страниц А4?
Раньше думал, вы хоть смотрели доку, раз такие смелые выводы делаете. Оказывается, вам это не надо - вам фантазии для этого достаточно. При этом открывшемся обстоятельстве остальные ваши выводы на любые темы вы обесценили сами. Ой извиняюсь. Не заметил кнопку "More Pages". Да и на кой читать всю эту доку. Грамматические ошибки исправлять? Или рецензировать? Со многим согласен, но многое ужасно запутано. Скажем слово 'порт' в разных смыслах без понятного контекста. Или слово 'объект', ну просто не перевариваемое. Причем тоже где-то 'объект', где-то 'элемент', где-то 'совокупность', где-то 'часть'. Нет строгости соблюдения терминологии. У неопытного крыша съедет. Нет, это я бы не рекомендовал.
|
|
|
|
|
Jun 7 2016, 09:30
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
QUOTE (AlexandrY @ Jun 7 2016, 15:14)  Да и на кой читать всю эту доку. Грамматические ошибки исправлять? Найдите хотя бы одну? QUOTE (AlexandrY @ Jun 7 2016, 15:14)  Скажем слово 'порт' в разных смыслах без понятного контекста. Или слово 'объект', ну просто не перевариваемое. Причем тоже где-то 'объект', где-то 'элемент', где-то 'совокупность', где-то 'часть'. Нет строгости соблюдения терминологии. "Порт" употребляется в обычном смысле для ПО и в контексте RTOS, тут всё однозначно. "Объект" употребляется преимущественно в контексте используемого ЯП С++, что тоже даёт однозначность. В остальном обычный русский язык, с терминологией обращение аккуратное. В начале даже приведён список используемых терминов и сокращений, дабы свести к минимуму непонятности. QUOTE (AlexandrY @ Jun 7 2016, 15:14)  У неопытного крыша съедет. Похоже, это и наблюдаем. QUOTE (AlexandrY @ Jun 7 2016, 15:14)  Нет, это я бы не рекомендовал. Как обычно в своём репертуаре: не читал, но не рекомендую. Не знакомы с вопросом - проходите мимо, не нужно шум поднимать по теме, о которой вы ничего не знаете, т.к. не дали себе труда хотя бы бегло ознакомиться с ней. Офтопить прекращаю. Замечу напоследок, что изучать новую тему как правило всегда легче на небольших и неперегруженных примерах и особенно когда имеется подробная документация.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Jun 7 2016, 12:45
|
Знающий
   
Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842

|
Цитата(Valentine Loginov @ Jun 7 2016, 09:43)  ... и полистать чужие реализации (замечательная статья про TNeo). А вы в своих проектах используете Тнео?
|
|
|
|
|
Jun 8 2016, 10:53
|

Местный
  
Группа: Свой
Сообщений: 285
Регистрация: 10-12-04
Из: Earth
Пользователь №: 1 437

|
Еще вопросы. Значит, написал вот такой код: main.c:Код #define TASK_STK_SIZE 2048 uint32_t task1_stk[TASK_STK_SIZE];
void task1(void* x) { while(1) { led_toggle(led); //printf("@ task1\n"); } }
int main(void) { configure_clocks(); led = led_create(GPIOE, 6); os_add_task("task1", task1, (void*) 0x555, task1_stk, TASK_STK_SIZE); os_start(); while(1); } scheduler.c:Код typedef struct task_descriptor { uint32_t* stk_ptr; uint16_t stk_size; task_handler handler; void* args; task_state state; char* name; } task_descriptor;
static uint8_t tasks_used = 0; static task_descriptor* tasks[MAX_TASKS];
__asm void _run_process(uint32_t* stk_ptr) { LDR R4, [R0, #(4*14)] ADD R0, R0, #(4*16) MSR PSP, R0 MOV R0, #2 MSR CONTROL, R0 CPSIE I BX R4 }
void os_add_task(char* name, task_handler task, void *args, uint32_t* stk_ptr, uint32_t stk_size) { tasks[tasks_used]->name = name; tasks[tasks_used]->handler = task; tasks[tasks_used]->args = args; tasks[tasks_used]->stk_size = stk_size; tasks[tasks_used]->state = RUN; tasks[tasks_used]->stk_ptr = (uint32_t*) ((uintptr_t) stk_ptr & 0xFFFFFFF8); *(--tasks[tasks_used]->stk_ptr) = 0x01000000L; *(--tasks[tasks_used]->stk_ptr) = (uint32_t)(task); tasks[tasks_used]->stk_ptr -= 14; //init_stack(task, &stk_ptr[stk_size-1]); if(tasks_used < MAX_TASKS) tasks_used++; printf("# created task: %s\n", name); }
void os_start(void) { printf("# starting OS...\n"); _run_process(tasks[0]->stk_ptr); } Инициализацию стека задачи и ассемблерный код пока взял из scmrtos (спасибо за наводку!). Мои вопросы вот в чем: 1. Правильно ли я понимаю: стек задачи - это просто область памяти (в моем случае task1_stk), конец которой заполняется таким образом, чтобы получить в ней значения регистров процессора как при переключении контекста (среди прочего там сидит и указатель на задачу). А далее асмовым (как правило) кодом из этого куска памяти значения тупо переписываются в регистры, после чего все как бы указывает на нужную нам задачу. 2. Приведенный выше код вроде как работает - в задачу task1 входит и крутится в ней. Но если раскомментировать printf в задаче task1, то проц уходит в MemFault (MemManage_Handler) сразу же в самой первой команде printf'а (судя по дизассемблеру). Почему так? 3. Не очень понятна запись tasks[tasks_used]->stk_ptr = (uint32_t*) ((uintptr_t) stk_ptr & 0xFFFFFFF8);. Для чего нужно выравнивание по 8 байтам?
|
|
|
|
|
Jun 8 2016, 13:48
|

Местный
  
Группа: Свой
Сообщений: 285
Регистрация: 10-12-04
Из: Earth
Пользователь №: 1 437

|
Цитата(AlexandrY @ Jun 8 2016, 15:34)  Говорю же читайте описание от микриума на uC/OS, это первоисточник. Действительно, в микриуме формирование стека расписано гораздо понятнее: Код CPU_STK *OSTaskStkInit (OS_TASK_PTR p_task, void *p_arg, CPU_STK *p_stk_base, CPU_STK *p_stk_limit, CPU_STK_SIZE stk_size, OS_OPT opt) { CPU_STK *p_stk;
(void)opt; /* Prevent compiler warning */
p_stk = &p_stk_base[stk_size]; /* Load stack pointer */ /* Align the stack to 8-bytes. */ p_stk = (CPU_STK *)((CPU_STK)(p_stk) & 0xFFFFFFF8); /* Registers stacked as if auto-saved on exception */ *--p_stk = (CPU_STK)0x01000000u; /* xPSR */ *--p_stk = (CPU_STK)p_task; /* Entry Point */ *--p_stk = (CPU_STK)OS_TaskReturn; /* R14 (LR) */ *--p_stk = (CPU_STK)0x12121212u; /* R12 */ *--p_stk = (CPU_STK)0x03030303u; /* R3 */ *--p_stk = (CPU_STK)0x02020202u; /* R2 */ *--p_stk = (CPU_STK)p_stk_limit; /* R1 */ *--p_stk = (CPU_STK)p_arg; /* R0 : argument */ /* Remaining registers saved on process stack */ *--p_stk = (CPU_STK)0x11111111u; /* R11 */ *--p_stk = (CPU_STK)0x10101010u; /* R10 */ *--p_stk = (CPU_STK)0x09090909u; /* R9 */ *--p_stk = (CPU_STK)0x08080808u; /* R8 */ *--p_stk = (CPU_STK)0x07070707u; /* R7 */ *--p_stk = (CPU_STK)0x06060606u; /* R6 */ *--p_stk = (CPU_STK)0x05050505u; /* R5 */ *--p_stk = (CPU_STK)0x04040404u; /* R4 */
return (p_stk); } И, что интересно, с таким кодом инициализации стека printf из задачи - заработал  UPD: собственно говоря, printf заработал и с кодом от scmRTOS. Ошибка была в строке Код tasks[tasks_used]->stk_ptr = (uint32_t*) ((uintptr_t) stk_ptr & 0xFFFFFFF8); Я неправильно брал вершину стека. Надо так: Код tasks[tasks_used]->stk_ptr = (uint32_t*) ((uintptr_t) &stk_ptr[stk_size] & 0xFFFFFFF8);
|
|
|
|
|
Jun 10 2016, 12:38
|

Местный
  
Группа: Свой
Сообщений: 285
Регистрация: 10-12-04
Из: Earth
Пользователь №: 1 437

|
Правильно ли я понимаю, что PendSV используется так: Ему выставляется нижайший приоритет. Если в данный момент есть что делать - делаем (ну, цикл какой или работа с периферией). Если делать нечего или мы сидим в прерывании и нам нельзя там долго находиться, то что-то делаем по-быстрому и взводим флажок-запрос на PendSV. Как только все остальные работающие в данный момент прерывания завершатся, проц, видя флажок-запрос, автоматом уходит в PendSV, т.к. теперь ему теперь совсем нечем заняться и можно спокойно уйти на обработку самого низкоприоритетного PendSV. В планировщике, если есть живые задачи, также взводится этот флаг, чтобы по наступлению таймаута процессор ушел в PendSV и таким образом выполнил переключение. Либо в коде самой задачи, в ее самом конце (когда она завершила свою работу согласно алгоритму), делается принудительная установка флажка-запроса на PendSV. Все так? Цитата(AlexandrY @ Jun 10 2016, 15:16)  Странно почему вы не видите, во всех вызовах стоят _set_pend_sv Спасибо, рассмотрел.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|