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

 
 
> 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
 
Start new topic
Ответов
Artkop
сообщение Jul 30 2010, 07:39
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 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



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

 


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


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