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

В Keil CMSIS-RTOS RTX в параметрах задач указано:

void job1 (void const *arg)

Что это, зачем? Писал, не задумываясь. Теперь хочу просветиться.

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


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

ну к примеру у вас на контроллере два 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 синтаксис вызова не в курсе, но суть передал - вызов задач с конкретными параметрами.

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


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

если оно будет на стеке, то по моменту запуска самой задачи естветсвено всё уплывет.

 

то есть так нельзя

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 );

 

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


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

то есть как реально в RTX синтаксис вызова не в курсе, но суть передал - вызов задач с конкретными параметрами.

Спасибо! Понял. Проверил в действии. Работает.

 

Нужно поправить - брать адрес структуры.

task_start( mb_task, ..., (void*)&mb_cfg );

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


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

Вообще-то компилятор должен "съедать" этот параметр при вызове функции и без явного преобразования. Как и для параметра "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 );

Второй вариант тоже будет на стеке. Просто менять его значения нельзя будет.

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

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


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

Какая разница в данном случае, с амперсандом или без? В случае когда голый идентификатор структуры без указания поля. Однозначнее, конечно, было бы с амперсандом, но на данный момент в Си оба варианта вроде бы одинаковые.

Возможно, в других языках варианты одинаковые. Но не в С. В C можно структуру передавать в функцию, именно, по значению, а не по ссылке. Т.е., имя структуры не есть ее адрес. В отличие от массива.

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


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

Возможно, в других языках варианты одинаковые. Но не в С.

Чем отличается результат двух вариантов выражений со структурами ниже?

(void*)&mb_cfg
и
(void*)mb_cfg

Если отличаются, то в каких компиляторах.

 

Идентификатор/имя массива тоже не является адресом его первого элемента. Иначе выражение &mass было бы аналогом &(&mass[0]). Взятие адреса от адреса в Си допустимо?

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

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


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

Чем отличается результат двух вариантов выражений со структурами ниже?

(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:

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


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

Квалификатор const не запретит передачу локальной переменной. Не встать на грабли - забота программиста. const в параметре "проявит себя" только внутри тела функции, когда этот указатель без явного преобразования будет передан параметром или присвоен другому типизированному указателю на константу.

не знаю как в высших материях, но в дизамсе передается просто адрес. Задача компилятора - ругатся при попытке записи по const*

 

Второй вариант тоже будет на стеке. Просто менять его значения нельзя будет.

 

если это AVR то будет во флеше, если ARM то как указано в линкере ROM_region. А в других архитектурах как решит компиляторы, но размещать const на стеке вызывающей задачи - сомнительно.

 

Нужно поправить - брать адрес структуры.

task_start( mb_task, ..., (void*)&mb_cfg );

 

да, мой косяк. Вместо компилятора под руками была текила, и это зло вчера меня победило

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


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

Led9_id = osThreadCreate(osThread(Led_thread), (void *)led9);

А в каком компиляторе работают оба? :rolleyes:

Предъявите объявление led9.

Проверьте для корректности все предыдущие версии Кейла. Если раньше оба варианта допускались, то как разработчики это обосновали и обосновали ли?

 

если это AVR то будет во флеше,

То есть от компилятора не зависит?

 

не знаю как в высших материях, но в дизамсе передается просто адрес. Задача компилятора - ругатся при попытке записи по const*

Я имел ввиду "проявит себя" на этапе компиляции. По сути то же самое. Вне тела функции наличие квалификатора const никак не ограничивает передачу параметров по сравнению с вариантом без квалификатора const (в прототипе функции).

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

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


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

Предъявите объявление 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);
 }
}

 

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


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

Тем, что второй вариант не компилируется.

Keil V5.1.0

А (void *)&mass скомпилируется, если это идентификатор массива? Кейла 5-ого под рукой нет чтобы проверить. Идентификаторы массивов, структур и юнионов должны (были) отличаться в применении. При явном преобразовании адреса логично было бы чтобы выражение с идентификатором было приведено к адресу силами самого программиста, дабы не возникало неоднозначностей.

 

Жаль, в Си нет операторов детипизации указателей, сохраняя исходное адресное пространство. В идеале ещё как-то наследующих выравнивание и другие атрибуты. Вручную для безопасной работы приходится объявлять указатель на void и потом его присваивать к другому типизированному указателю.

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

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


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

А (void *)&mass скомпилируется, если это идентификатор массива? Кейла 5-ого под рукой нет чтобы проверить.

Проверьте на том, что имеете.

Мое мнение - для массива &mass и mass - одно и то же. Особенность языка.

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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