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

 
 
 
Reply to this topicStart new topic
> Keil RL-RTX, две задачи испол. одну функцию
Artkop
сообщение Jul 30 2010, 06:35
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 11-06-08
Пользователь №: 38 217



Всем привет!

Использую операционку Keil RL-RTX.
Определено две задачи, имеющие одинаковый приоритет и выполняющиеся параллельно:

CODE
//----------------------------------------------------------------------------------------------------
/*! \brief Задача RTX для работы с радиомодемом 1, подключенным к порту uart 0 */
//----------------------------------------------------------------------------------------------------
__task void modem1(void)
{
while(1)
{
RadiomModemSubsystem(RADIO_MODEM_1);
}
}
//----------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------
/*! \brief Задача RTX для работы с радиомодемом 2, подключенным к порту uart 2*/
//----------------------------------------------------------------------------------------------------
__task void modem2(void)
{
while(1)
{
RadiomModemSubsystem(RADIO_MODEM_2);
}
}
//----------------------------------------------------------------------------------------------------


Как видно, задачи вызывают одну и туже функцию. Создается ли для каждой задачи свой экземпляр функции со своими локальными переменными? Вот эта функция:

CODE
static unsigned char Modem1Buffer[BUF_MAX_SIZE] = {0x00};
static unsigned char Modem2Buffer[BUF_MAX_SIZE] = {0x00};

void RadiomModemSubsystem(unsigned char numModem)
{
unsigned char queue = UNKNOWN_QUEUE;
unsigned char *dataBuf = 0;

switch(numModem)
{
case RADIO_MODEM_1:
queue = MODEM_1_QUEUE;
dataBuf = &Modem1Buffer[0];
break;
case RADIO_MODEM_2:
queue = MODEM_2_QUEUE;
dataBuf = &Modem2Buffer[0];
break;
default:
return;
}
// здесь управление и обмен с модемом
}


Интересует, что будет с переменными queue и *dataBuf. Задача modem 1 вызывает функцию RadiomModemSubsystem с параметром RADIO_MODEM_1. Для локальных переменных queue и *dataBuf выделяется память, идет выполнение. Задача modem 1 израсходовала свой квант времени и теперь выполняется задача modem 2. Задача modem 2 вызывает функцию RadiomModemSubsystem с параметром RADIO_MODEM_2 и для локальных переменных queue и *dataBuf выделяется новая память (то есть, это экземпляр функции для другой задачи), правильно? Не будет ситуации, что адреса локальных переменных совпадут, и мы перепишем буфер dataBuf и номера очереди queue другой задачи.
Go to the top of the page
 
+Quote Post
Quasar
сообщение Jul 30 2010, 06:47
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 257
Регистрация: 2-12-06
Из: Default City
Пользователь №: 23 021



Цитата(Artkop @ Jul 30 2010, 10:35) *
Создается ли для каждой задачи свой экземпляр функции со своими локальными переменными?


Функция остается в одном экземпляре smile.gif. Просто кусок кода во флешь. А локальные переменные в ней находятся в своем потоке (в стеке конкретной задачи). При переключении контекста двух этих задач они будут иметь значения текущей задачи и их значения ни как не связаны со значениями параллельно выполняемых задач.

А вот если их сделать static то тогда, они начнут вести себя как глобальные переменные в плане много поточности.

А функция RadiomModemSubsystem написана странно, почему нельзя сразу передавать ей queue и dataBuf? Нафига этот switch нужен?
Go to the top of the page
 
+Quote Post
Artkop
сообщение Jul 30 2010, 07:39
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 11-06-08
Пользователь №: 38 217



То есть, локальная переменная функции становится локальной переменной задачи? Тогда если сделать локальный буфер внутри функции на много байт и вызвать ее из задачи, такая функция вполне может привести к переполнению стека! (В RL-RTX он по умолчанию 64 байта.)

А функция RadiomModemSubsystem принимает на вход только номер модема, т.к. переменная queue - это номер очередь FIFO для пакетов радиомодема, и в месте вызова (в main) про подсистему обработки очередей ничего не известно. Для main она скрыта. (h файл соответствующий я не подключаю, там и так дофига всего подключено, сложно разобраться потом).

Вот как это выглядит:
Код
void RadiomModemSubsystem(unsigned char numModem)
{
    unsigned char queue = UNKNOWN_QUEUE;
    unsigned char *dataBuf = 0;

    switch(numModem)
    {
        case RADIO_MODEM_1:
            queue = MODEM_1_QUEUE;
            dataBuf = &Modem1Buffer[0];
            break;
        case RADIO_MODEM_2:
            queue = MODEM_2_QUEUE;
            dataBuf = &Modem2Buffer[0];
            break;
        default:
            return;
    }

    if (QueueIsEmpty(queue) == QUEUE_NOT_EMPTY) // если в очереди есть данные на отправку по радиомодему
    {
        FreeString(&dataBuf[0], BUF_MAX_SIZE);   // очищаем буфер

        SetRadioModemToCtrlMode(numModem);
        SendCmdToRadioModem(RM_REQUEST_STATUS, &dataBuf[0], numModem);    // отправляем команду
        ReceivePacketFromRadioModem(&dataBuf[0], numModem);                        // получаем статус модема
        // обрабатываем статус ..
                // ..
        SetRadioModemToDataMode(numModem);        

        RetrieveDataFromQueue(&dataBuf[0], &sizeOfData, queue); // извлекаем пакет из очереди
        
        // оправляем пакет ...
    }

}


А буфер радиомодема dataBuf можно и так сделать:

__task void modem2(void)
{
unsigned char Modem2Buffer[BUF_MAX_SIZE] = {0x00};
while(1)
{
RadiomModemSubsystem(RADIO_MODEM_2, &Modem2Buffer[0]);
}
}

но тогда задачу нужно инициализировать с помощью ф-ии os_tsk_create_user (делать ей стек большой отдельно). В этом нет необходимости.

Сообщение отредактировал Artkop - Jul 30 2010, 07:46
Go to the top of the page
 
+Quote Post
evg123
сообщение Aug 3 2010, 11:44
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 353
Регистрация: 11-09-06
Из: Минск
Пользователь №: 20 282



Вы можете в отладчике увидеть, как у вас там организуются разные переменные. Установить точки прерывания на вызове функции в разных задачах, и посмотреть как они отрабатывают. Кстати ulink позволяет устанавивать прерывания на лету.
Go to the top of the page
 
+Quote Post
Artkop
сообщение Aug 3 2010, 18:36
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 11-06-08
Пользователь №: 38 217



Да, я ulink2 пользуюсь. Могу поставить 2 точки останова для двух задач RTX и у переменной queue видимо будут два разных адреса? Завтра на работе проверю. Спасибо за идею!

Сообщение отредактировал Artkop - Aug 3 2010, 18:38
Go to the top of the page
 
+Quote Post
Artkop
сообщение Aug 4 2010, 09:59
Сообщение #6


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 11-06-08
Пользователь №: 38 217



Локальные переменные функции располагаются в регистрах общего назначения контроллера и при смене задачи сохраняются в область стека Register Context Storage. Соответственно при продолжении выполнения задачи этот контекст восстанавливается. Видимо как то так.

Сообщение отредактировал Artkop - Aug 4 2010, 10:00
Go to the top of the page
 
+Quote Post
Shein
сообщение Feb 5 2011, 12:25
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 45
Регистрация: 4-03-07
Пользователь №: 25 855



Коллеги, кто-нибудь может подсказать, какие требования к размерам глобальніх стеков у RTX-kernel?
В доке сказано:
Цитата
The other stack spaces need to be configured from the ARM startup file. All tasks run in user mode. The task scheduler switches the user/system mode stack between tasks. For this reason, the default user/system mode stack (which is defined in the startup file) is used until the first task is created and started. The default stack requirements are very small, so it is optimal to set the user/system stack in the startup file to 64 bytes.

т.е. получается что для нее достаточно задать минимум объема стека для user/system режимов и все?
Нужно ли задавать стек для режима Supervisor и сколько? Я так понимаю что нужно, т.к.она же пользуются swi. Но явного указания на это и сколько я в доках не нашел.
Остальные (IRQ/FIQ) нужно задавать соответственно при использовании моих обработыиков, для RTX они не нужны, так?


Доавлено:
Вопрос снят, надо внимательно читать доки sm.gif
Цитата
Minimum stack sizes for RTX kernel configured in STARTUP.S are:

Supervisor Mode 32 bytes (0x00000020)
Interrupt Mode 64 bytes (0x00000040)
User Mode 80 bytes (0x00000050)


Сообщение отредактировал Shein - Feb 5 2011, 15:59
Go to the top of the page
 
+Quote Post

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

 


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


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