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

Keil RL-RTX

Всем привет!

 

Использую операционку Keil RL-RTX.

Определено две задачи, имеющие одинаковый приоритет и выполняющиеся параллельно:

 

//----------------------------------------------------------------------------------------------------
/*! \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);
}
}
//----------------------------------------------------------------------------------------------------

 

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

 

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 другой задачи.

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


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

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

 

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

 

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

 

А функция RadiomModemSubsystem написана странно, почему нельзя сразу передавать ей queue и dataBuf? Нафига этот switch нужен?

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


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

То есть, локальная переменная функции становится локальной переменной задачи? Тогда если сделать локальный буфер внутри функции на много байт и вызвать ее из задачи, такая функция вполне может привести к переполнению стека! (В 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

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


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

Вы можете в отладчике увидеть, как у вас там организуются разные переменные. Установить точки прерывания на вызове функции в разных задачах, и посмотреть как они отрабатывают. Кстати ulink позволяет устанавивать прерывания на лету.

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


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

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

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

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


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

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

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

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


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

Коллеги, кто-нибудь может подсказать, какие требования к размерам глобальніх стеков у 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 они не нужны, так?

 

 

Доавлено:

Вопрос снят, надо внимательно читать доки :)

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

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


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

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

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

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

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

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

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

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

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

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