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

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

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

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

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

 

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

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


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

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

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

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

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

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


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

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

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


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

Если не запрещать прерывания

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

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

 

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

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

 

DWT_CYCCNT.

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

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


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

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

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

#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;
}

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


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

ОК, просто интересно, вы этим так и ползуетесь, или где-то делаете пересчет на микро и миллисекунды?

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


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

ОК, просто интересно, вы этим так и ползуетесь, или где-то делаете пересчет на микро и миллисекунды?

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

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


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

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

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

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

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

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


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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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


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

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

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

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


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

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

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

 

 

 

UPD

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

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

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

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

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

 

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

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


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

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

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

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


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

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

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

кстати, да

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

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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