ViKo 1 6 января, 2014 Опубликовано 6 января, 2014 · Жалоба В Keil CMSIS-RTOS RTX в параметрах задач указано: void job1 (void const *arg) Что это, зачем? Писал, не задумываясь. Теперь хочу просветиться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
megajohn 7 6 января, 2014 Опубликовано 6 января, 2014 · Жалоба ну к примеру у вас на контроллере два UART и в одном проекте на modbus реализован на UART0 9600 а на UART1 модем AT 115200 а в другом проекте modbus реализован на UART1 19200 а на UART0 модем AT 36000 а задачи одинаковые. тогда для проекта 1 typedef struct{ int port; int speed; }Suart_init; const Suart_init mb_cfg = { 0, 9600 }; task_start( mb_task, ..., (void*)mb_cfg ); где void mb_task( void const* arg ) { Suart_init* arg_p = (Suart_init*)arg; uart_open( arg_p->port, arg_p->speed ); ... } то есть как реально в RTX синтаксис вызова не в курсе, но суть передал - вызов задач с конкретными параметрами. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kosyak© 0 6 января, 2014 Опубликовано 6 января, 2014 · Жалоба Вот зачем оно конст...? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
megajohn 7 6 января, 2014 Опубликовано 6 января, 2014 · Жалоба если оно будет на стеке, то по моменту запуска самой задачи естветсвено всё уплывет. то есть так нельзя Suart_init mb_cfg = { 0, 9600 }; task_start( mb_task, ..., (void*)mb_cfg ); а так можно const Suart_init mb_cfg = { 0, 9600 }; task_start( mb_task, ..., (void*)mb_cfg ); или так static Suart_init mb_cfg = { 0, 9600 }; task_start( mb_task, ..., (void*)mb_cfg ); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 6 января, 2014 Опубликовано 6 января, 2014 · Жалоба то есть как реально в RTX синтаксис вызова не в курсе, но суть передал - вызов задач с конкретными параметрами. Спасибо! Понял. Проверил в действии. Работает. Нужно поправить - брать адрес структуры. task_start( mb_task, ..., (void*)&mb_cfg ); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kosyak© 0 6 января, 2014 Опубликовано 6 января, 2014 · Жалоба тогда уж task_start( mb_task, ..., (void const*)&mb_cfg ); :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 6 января, 2014 Опубликовано 6 января, 2014 (изменено) · Жалоба Вообще-то компилятор должен "съедать" этот параметр при вызове функции и без явного преобразования. Как и для параметра "void *" компилятор должен принимать указатель на любой неконстантный объект из соответствующего адресного пространства. Если отказывается, то это наверное плохой компилятор. Без явного преобразования очевидно, что безопаснее. Нужно поправить - брать адрес структуры. Какая разница в данном случае, с амперсандом или без? В случае когда голый идентификатор структуры без указания поля. Однозначнее, конечно, было бы с амперсандом, но на данный момент в Си оба варианта вроде бы одинаковые. если оно будет на стеке, то по моменту запуска самой задачи естветсвено всё уплывет. Квалификатор const не запретит передачу локальной переменной. Не встать на грабли - забота программиста. const в параметре "проявит себя" только внутри тела функции, когда этот указатель без явного преобразования будет передан параметром или присвоен другому типизированному указателю на константу. то есть так нельзя Suart_init mb_cfg = { 0, 9600 }; task_start( mb_task, ..., (void*)mb_cfg ); а так можно const Suart_init mb_cfg = { 0, 9600 }; task_start( mb_task, ..., (void*)mb_cfg ); Второй вариант тоже будет на стеке. Просто менять его значения нельзя будет. Изменено 7 января, 2014 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 января, 2014 Опубликовано 7 января, 2014 · Жалоба Какая разница в данном случае, с амперсандом или без? В случае когда голый идентификатор структуры без указания поля. Однозначнее, конечно, было бы с амперсандом, но на данный момент в Си оба варианта вроде бы одинаковые. Возможно, в других языках варианты одинаковые. Но не в С. В C можно структуру передавать в функцию, именно, по значению, а не по ссылке. Т.е., имя структуры не есть ее адрес. В отличие от массива. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 7 января, 2014 Опубликовано 7 января, 2014 (изменено) · Жалоба Возможно, в других языках варианты одинаковые. Но не в С. Чем отличается результат двух вариантов выражений со структурами ниже? (void*)&mb_cfg и (void*)mb_cfg Если отличаются, то в каких компиляторах. Идентификатор/имя массива тоже не является адресом его первого элемента. Иначе выражение &mass было бы аналогом &(&mass[0]). Взятие адреса от адреса в Си допустимо? Изменено 7 января, 2014 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 января, 2014 Опубликовано 7 января, 2014 · Жалоба Чем отличается результат двух вариантов выражений со структурами ниже? (void*)&mb_cfg и (void*)mb_cfg Если отличаются, то в каких компиляторах. Тем, что второй вариант не компилируется. Keil V5.1.0 source\exsUSB.c(164): error: #171: invalid type conversion Led9_id = osThreadCreate(osThread(Led_thread), (void *)led9); А в каком компиляторе работают оба? :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
megajohn 7 7 января, 2014 Опубликовано 7 января, 2014 · Жалоба Квалификатор const не запретит передачу локальной переменной. Не встать на грабли - забота программиста. const в параметре "проявит себя" только внутри тела функции, когда этот указатель без явного преобразования будет передан параметром или присвоен другому типизированному указателю на константу. не знаю как в высших материях, но в дизамсе передается просто адрес. Задача компилятора - ругатся при попытке записи по const* Второй вариант тоже будет на стеке. Просто менять его значения нельзя будет. если это AVR то будет во флеше, если ARM то как указано в линкере ROM_region. А в других архитектурах как решит компиляторы, но размещать const на стеке вызывающей задачи - сомнительно. Нужно поправить - брать адрес структуры. task_start( mb_task, ..., (void*)&mb_cfg ); да, мой косяк. Вместо компилятора под руками была текила, и это зло вчера меня победило Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 7 января, 2014 Опубликовано 7 января, 2014 (изменено) · Жалоба Led9_id = osThreadCreate(osThread(Led_thread), (void *)led9); А в каком компиляторе работают оба? :rolleyes: Предъявите объявление led9. Проверьте для корректности все предыдущие версии Кейла. Если раньше оба варианта допускались, то как разработчики это обосновали и обосновали ли? если это AVR то будет во флеше, То есть от компилятора не зависит? не знаю как в высших материях, но в дизамсе передается просто адрес. Задача компилятора - ругатся при попытке записи по const* Я имел ввиду "проявит себя" на этапе компиляции. По сути то же самое. Вне тела функции наличие квалификатора const никак не ограничивает передачу параметров по сравнению с вариантом без квалификатора const (в прототипе функции). Изменено 7 января, 2014 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 7 января, 2014 Опубликовано 7 января, 2014 · Жалоба Предъявите объявление led9. typedef struct { uint16_t leds; uint32_t dels; } thread_init; const thread_init led8 = {0x0100, 500}; const thread_init led9 = {0x0200, 498}; const thread_init led10 = {0x0400, 496}; const thread_init led11 = {0x0800, 494}; const thread_init led12 = {0x1000, 492}; const thread_init led13 = {0x2000, 490}; const thread_init led14 = {0x4000, 488}; const thread_init led15 = {0x8000, 486}; void Led_thread(void const *arg); // прототип osThreadId Led8_id; osThreadId Led9_id; osThreadId Led10_id; osThreadId Led11_id; osThreadId Led12_id; osThreadId Led13_id; osThreadId Led14_id; osThreadId Led15_id; osThreadDef(Led_thread, osPriorityNormal, 1, 0); int32_t main(void) { ... Led8_id = osThreadCreate(osThread(Led_thread), (void *)&led8); Led9_id = osThreadCreate(osThread(Led_thread), (void *)&led9); Led10_id = osThreadCreate(osThread(Led_thread), (void *)&led10); Led11_id = osThreadCreate(osThread(Led_thread), (void *)&led11); Led12_id = osThreadCreate(osThread(Led_thread), (void *)&led12); Led13_id = osThreadCreate(osThread(Led_thread), (void *)&led13); Led14_id = osThreadCreate(osThread(Led_thread), (void *)&led14); Led15_id = osThreadCreate(osThread(Led_thread), (void *)&led15); ... } void Led_thread(void const *arg) { while (true) { GPIOB->BSRR = ((thread_init *)arg)->leds; osDelay(((thread_init *)arg)->dels); GPIOB->BSRR = ((thread_init *)arg)->leds << 16; osDelay(((thread_init *)arg)->dels); } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 8 января, 2014 Опубликовано 8 января, 2014 (изменено) · Жалоба Тем, что второй вариант не компилируется. Keil V5.1.0 А (void *)&mass скомпилируется, если это идентификатор массива? Кейла 5-ого под рукой нет чтобы проверить. Идентификаторы массивов, структур и юнионов должны (были) отличаться в применении. При явном преобразовании адреса логично было бы чтобы выражение с идентификатором было приведено к адресу силами самого программиста, дабы не возникало неоднозначностей. Жаль, в Си нет операторов детипизации указателей, сохраняя исходное адресное пространство. В идеале ещё как-то наследующих выравнивание и другие атрибуты. Вручную для безопасной работы приходится объявлять указатель на void и потом его присваивать к другому типизированному указателю. Изменено 8 января, 2014 пользователем GetSmart Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 8 января, 2014 Опубликовано 8 января, 2014 · Жалоба А (void *)&mass скомпилируется, если это идентификатор массива? Кейла 5-ого под рукой нет чтобы проверить. Проверьте на том, что имеете. Мое мнение - для массива &mass и mass - одно и то же. Особенность языка. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться