Jump to content

    
Sign in to follow this  
zheka

Keil RTOS и микросекундные задержки.

Recommended Posts

Господа, есть проект в KEIL 5 под STM32F4Discovery, в котором подключена RTOS (Keil RTX). Она мне в принципе не нужна, она требуется для работы библиотеки USB_CDC, попытки отвязать ее от KEIL RTX не принесли успеха.

В Keil RTX есть только миллисекундные задержки, микросекундных - нет.

Пытался прикрутить библиотеку systick - не вышло - компилятор не дает создать свой Systick_Handler, мотивируя это тем, что таковой есть уже в HAL_CM4.C (это файл RTX)

 

Как мне в сложившихся условиях (невозможность отключить RTOS и отсутствие специальной функции в ней) получить функцию, осуществляющую задержку на заданное число микросекунд?

Share this post


Link to post
Share on other sites
Как мне в сложившихся условиях (невозможность отключить RTOS и отсутствие специальной функции в ней) получить функцию, осуществляющую задержку на заданное число микросекунд?

Если не запрещать прерывания и переключение задач, то это будет задержка "N микросекунд или больше", естественно.

А решение очевидное: простой цикл ожидания с использованием одного из аппаратных таймеров. Если не злоупотреблять, то существенного общего замедления программы не будет. Кстати, в STM32F4 есть очень удобный для этих дел счётчик тактов процессора DWT_CYCCNT.

void delay(unsigned int ticks)
{
        unsigned int start = DWT_CYCCNT;
        while (DWT_CYCCNT - start < ticks); /* wait */
}

Share this post


Link to post
Share on other sites

Какие проблемы запретить прерывания в задаче и сделать задержку, потом включить прерывания. Критические секции в rtos как правило это и делают.

Share this post


Link to post
Share on other sites
Если не запрещать прерывания

Какие проблемы запретить прерывания

Взаимоисключающие решения)))

 

А решение очевидное: простой цикл ожидания с использованием одного из аппаратных таймеров.

Не хочется мне занимать таймер.

 

DWT_CYCCNT.

Что нужно подключить к проекту, чтобы компилятор не ругался, что не знает этого идентификатора?

Share this post


Link to post
Share on other sites
Что нужно подключить к проекту, чтобы компилятор не ругался, что не знает этого идентификатора?

Я ничего не подключаю. У меня есть вот такие дефайны:

#define DWT_CTRL   (*(uint32_t volatile*)0xE0001000)
#define DWT_CYCCNT (*(uint32_t volatile*)0xE0001004)
#define SCB_DEMCR  (*(uint32_t volatile*)0xE000EDFC)

Ну и перед использованием этого таймера делаю вот так:

void init_cyccnt(void)
{
        SCB_DEMCR |= 1 << 24;
        DWT_CYCCNT = 0;
        DWT_CTRL |= 1;
}

Share this post


Link to post
Share on other sites
ОК, просто интересно, вы этим так и ползуетесь, или где-то делаете пересчет на микро и миллисекунды?

У меня есть дефайн #define CYCCNT_RATE 168000000. Если нужна микросекунда, то пишу delay(CYCCNT_RATE / 1000000);

Share this post


Link to post
Share on other sites

Можно отвязать CDC от RTX

Там все замучено в ту сторону, что вертится одна задача, обслуживающая служебную информацию через EP0, а так же по задаче на каждую точку

Ничто не мешает оставить просто "дергание" нужных функций из прерывания USB

Отправлять данные можно по SOF, вполне себе рабочий вариант (то есть складывать в буфер, а по SOF проверять и если что-то есть - отправлять кусок до размера точки - 64 байта)

Share this post


Link to post
Share on other sites
Можно отвязать CDC от RTX

Там все замучено в ту сторону, что вертится одна задача, обслуживающая служебную информацию через EP0, а так же по задаче на каждую точку

Ничто не мешает оставить просто "дергание" нужных функций из прерывания USB

Отправлять данные можно по SOF, вполне себе рабочий вариант (то есть складывать в буфер, а по SOF проверять и если что-то есть - отправлять кусок до размера точки - 64 байта)

Так там если только поставить галку напротив USB, сразу подключается RTX...

Share this post


Link to post
Share on other sites
Так там если только поставить галку напротив USB, сразу подключается RTX...

нужно поискать usbcore, usbhw, usbdesc и usbuser для нужного камня

просмотреть их, выбросить все, относящееся к RTX, сделать вызов нужных функций из прерывания вместо передачи сигнала оттуда в задачу

Инициализация останется, только в ней нужно не задачи поднимать, а настроить прерывание, причем в RTX оно делается через SWI, его тоже выбросить

В принципе, дел - на часа три

Также можно покопать старые примеры кейла для 4.х ветки, там были без использования RTX, насколько я помню

Возможно, что не сам CDC, а какой-нибудь HID или MSC, прикрутить к нему обработку CDC для точки (обычно EP0 стандартная служебная, EP1 - контрольная для CDC, там настраиваются параметры порта и прочие вещи, а весь обмен валится через EP2 bulk)

Share this post


Link to post
Share on other sites
Пытался прикрутить библиотеку systick - не вышло - компилятор не дает создать свой Systick_Handler, мотивируя это тем, что таковой есть уже в HAL_CM4.C (это файл RTX)

В чём сложность заменить системный ISR Systick своим?

Share this post


Link to post
Share on other sites
В чём сложность заменить системный ISR Systick своим?

тут тоже не так однозначно. Можно оттуда послать сигнал в задачу, но будет затрачено время на переключение, кстати, по-моему, в том же самом ISR Systick, т.е. сигнал нужно выставлять в самом начале прерывания, до обработок RTOS.

 

 

 

UPD

а можно попробовать такой финт:

1. Задействовать что-то неиспользуемое, например SPI на частоте 10 МГц

2. Настроить его на передачу 10 бит

3. Отправить одно 10-битное слово и заснуть в ожидании сигнала

4. Из прерывания SPI по окончании передачи отправить этот сигнал в задачу

 

По идее, если приоритет у задачи будет повыше, должно получиться

Share this post


Link to post
Share on other sites

Если нужны задержки на несколько микросекунд, то возможно можно просто запретить прерывания и отсчитать нужное кол-во тактов Systick просто читая регистр-счётчик Systick

(конечно с учётом переполнения при достижении величины делителя).

Share this post


Link to post
Share on other sites
Если нужны задержки на несколько микросекунд, то возможно можно просто запретить прерывания и отсчитать нужное кол-во тактов Systick просто читая регистр-счётчик Systick

(конечно с учётом переполнения при достижении величины делителя).

кстати, да

тем более, что 1мкс даже на 100МГц - это всего 100 тактов

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this