|
|
  |
Как сделать программную задержку на STM32, без использования таймеров |
|
|
|
Jan 7 2013, 12:38
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(KnightIgor @ Jan 7 2013, 12:20)  Какие грабли, если его читать? Если только читать - никаких. Однако и здесь, и здесь, при инициализации предлагается запись в DWT_CYCCNT. Как будет вызываться инициализация, единожды или при каждой задержке, оставим за скобками, ибо это отдельный вопрос. Итого. Я бы рекомендовал исключить строку: Код DWT_CYCCNT = 0; Цитата(HHIMERA @ Jan 7 2013, 15:59)  И в Cortex M0 есть??? Ну самостоятельно посмотреть?
|
|
|
|
|
Jan 7 2013, 12:46
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(Tahoe @ Jan 7 2013, 15:38)  самостоятельно посмотреть? Смотрел... Дошёл до Цитата This document is only available in a PDF version to registered ARM customers. и усё... )))
|
|
|
|
|
Jan 8 2013, 07:16
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(HHIMERA @ Jan 7 2013, 19:46)  Смотрел... Дошёл до
и усё... ))) Так зарегистрируйтесь, это не сложно. Впрочем, не поможет, в М0 и М0+ такого регистра нет.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
Jan 8 2013, 08:52
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(SSerge @ Jan 8 2013, 11:16)  в М0 и М0+ такого регистра нет. Вот и я о том же... И если последние редакции CMSIS в файлах core_cm3.h и core_cm4.h содержат информацию о DWT, то в core_cm0.h она отсутствует напрочь... Да и в самом железе STM32F0XX DWT не работает...
|
|
|
|
|
Jan 27 2013, 00:00
|
Местный
  
Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672

|
Цитата(HHIMERA @ Jan 7 2013, 06:59)  Угу... щазз... А ещё есть code reordering... Или будете доказывать, что и code reordering "Никакого отношения к оптимизации"??? Не стоит путать божий дар с яичничей, а key word "volatile" с оптимизирующим компилятором FYI
--------------------
|
|
|
|
|
Jan 27 2013, 10:23
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(Tahoe @ Jan 7 2013, 13:38)  Итого. Я бы рекомендовал исключить строку: Код DWT_CYCCNT = 0; Логично. Но один разочек при старте не мешает: Цитата "The debugger must initialize this to 0 when first enabling" (на стр. 11-19 документа ). Кстати, снова о "подводных" камнях: там же по тексту DWT счетчик явно предлагается для отсчета коротких времен в приложении: Цитата Applications and debuggers can use the counter to measure elapsed execution time. By subtracting a start and an end time, an application can measure time between in-core clocks (other than when Halted in debug). This is valid to 2^32 core clock cycles (for example,almost 86 seconds at 50MHz). DWT действительно нет в -M0. Тогда можно использовать SYSTICK: находить разницу между двумя значениями SYST_CVR с учетом значения перезагрузки SYST_RVR. Чаще всего SYSTICK запускают на генерацию перрывания каждые 1ms. То есть, вполне можно запускать программные задержки на меньшие времена (десятки - сотни мкс).
Сообщение отредактировал KnightIgor - Jan 27 2013, 10:36
|
|
|
|
|
Jan 27 2013, 15:05
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(KnightIgor @ Jan 27 2013, 14:23)  Но один разочек при старте не мешает: Цитата "The debugger must initialize this to 0 when first enabling" Дело за малым - как-либо узнать, что текущий "enabling" будет действительно "first", а не "second", "third" или "hundredfivehundred".  Хотя решение, конечно, очевидно: просто инициализировать счетчик при старте. По крайней мере, для периодических задач профилирования, это не станет серьезной проблемой. Разве что экхотика какая, например, время стартапа подсчитывается, но и в этом случае, по идее, к моменту перехода на main() подсчет должен быть уже выполнен. Другой экзотики в голову не приходит. Цитата(KnightIgor @ Jan 27 2013, 14:23)  DWT счетчик явно предлагается для отсчета коротких времен в приложении А вот этого не видел. Мерси. Насчет моих предположений про DWT, вот чуть конкретнее, в контексте отладчика: Цитата(IAR: What is your application doing inside your microcontroller? Debugging software applications on ARM Cortex-M3 and Cortex-M4 devices[/url) Data Watchpoint and Trace The Data Watchpoint and Trace (DWT) provides a set of functions that collect information from the system buses and generates events to the ITM for packetizing and time stamping and further distribution on the SWO channel. ... и далее по тексту, правда инфы не густо.
|
|
|
|
|
Jan 31 2013, 12:35
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 22-01-13
Пользователь №: 75 284

|
Ну а вот я попробывал сделать так: Код #define F_CPU 8000000UL void delay_us(uint32_t us) { for(volatie unsigned int i=0;i<((F_CPU/1000000-3)*us);i++) {} } где цифра "3" в условии цикла - это поправка, связанная с тем что на создание и сравнение условия также уходят такты. Я поставил аргумент функции 5 млн (т.е 5 секунд), засекал на внешнем таймере: получается довольно точно 5,3 с. Без поправочного коэффициента получается 8,4 с. И, кстате, скажите кто знает: что значит "UL" после частоты? И когда обьявляем переменную "uint16_t" - что значит _t ? И всегда ли эта переменная занимает одну ячейку памяти или под неё выделяется целые 32 бита? И что просходит с переменной обьявленной таким способом, если мы записываем в неё например 1млн? Что плохого/хорошего скажите про всё это?
|
|
|
|
|
Jan 31 2013, 13:13
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(allsettingsdone @ Jan 31 2013, 16:35)  И, кстате, скажите кто знает: что значит "UL" после частоты? Это значит, что константа имеет тип unsigned long. Этот суффикс имеет смысл приписывать, если код может использоваться на системах с 16-битным типом int (когда 8000000 не помещается в int), что для приведённого примера не актуально. Цитата(allsettingsdone @ Jan 31 2013, 16:35)  И когда обьявляем переменную "uint16_t" - что значит _t ? Ничего это не значит. Тип uint16_t, как и многие другие подобные типы, объявлен в файле stdint.h в соответствии со стандартом C99. Просто кто-то так назвал эти типы. Цитата(allsettingsdone @ Jan 31 2013, 16:35)  И всегда ли эта переменная занимает одну ячейку памяти или под неё выделяется целые 32 бита? Что есть ячейка памяти? Бит? Байт? 2 байта? 4 байта? 16 байт? И т.д. Так или иначе, ответ зависит от контекста: если переменная размещается в регистре или стеке, то скорее всего она занимает 32 бита. Статические переменные могут занимать меньше памяти. Цитата(allsettingsdone @ Jan 31 2013, 16:35)  И что просходит с переменной обьявленной таким способом, если мы записываем в неё например 1млн? Если в uint16_t записать 1000000, то скорее всего там окажется 16960 (то есть срежутся старшие биты). Цитата(allsettingsdone @ Jan 31 2013, 16:35)  Что плохого/хорошего скажите про всё это? Код хорош тем, что прост, но плох тем, что время исполнения зависит от версии компилятора, уровня оптимизации, скорости процессора и т.д. Кстати, вам совсем не помешает почитать учебник по языку Си.
|
|
|
|
|
Jan 31 2013, 13:25
|
Частый гость
 
Группа: Свой
Сообщений: 112
Регистрация: 1-05-09
Из: Ростов-на-Дону
Пользователь №: 48 518

|
Цитата(allsettingsdone @ Jan 31 2013, 16:35)  Ну а вот я попробывал сделать так: Код #define F_CPU 8000000UL void delay_us(uint32_t us) { for(volatie unsigned int i=0;i<((F_CPU/1000000-3)*us);i++) {} } где цифра "3" в условии цикла - это поправка, связанная с тем что на создание и сравнение условия также уходят такты. Я поставил аргумент функции 5 млн (т.е 5 секунд), засекал на внешнем таймере: получается довольно точно 5,3 с. Без поправочного коэффициента получается 8,4 с. Лучше уберите этот поправочный коэффициент, а то придет время и понадобится вам задержка меньше чем 3 мкс. Если нужно точно засечь время, лучше использовать таймеры, например, системный.
--------------------
«У современных мобильных телефонов такая же вычислительная мощь, что и у компьютеров NASA в 60-е годы. И в то время этого хватало, чтобы запустить человека в космос, а сегодня — только чтобы запускать птиц в свиней.»
|
|
|
|
|
Jan 31 2013, 14:05
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(allsettingsdone @ Jan 31 2013, 16:35)  когда обьявляем переменную "uint16_t" - что значит _t ? И всегда ли эта переменная занимает одну ячейку памяти или под неё выделяется целые 32 бита? Аккуратнее с такими вопросами. Грамотного Си-программера, _абсолютно_ не должно волновать, сколько там ячеек занимает uint16_t. Единственное, что он должен твердо помнить, что: 1. Это беззнаковый тип. 2. Что размер этого типа 16 бит. Когда программер станет опытным, он узнает ответ и на вопрос о "ячейках", но пока, упаси Б-г об этом задумываться. Потому что итог будет печальным - программа на ассемблере, писаная Си-синтаксисом. Цитата(allsettingsdone @ Jan 31 2013, 16:35)  И что просходит с переменной обьявленной таким способом, если мы записываем в неё например 1млн? См. выше. Единственное, что должен знать грамотный Си-программер, это что при записи в uint16_t числа > 0xFFFF, произойдет переполнение переменной этого типа. И, повторюсь, не дай Б-г начать задумываться о чем-то бОльшем. Во всяком случае, на данном этапе.
|
|
|
|
|
Jan 31 2013, 16:21
|
Участник

Группа: Участник
Сообщений: 32
Регистрация: 22-01-13
Пользователь №: 75 284

|
Так а на чем же остановиться в поиске функции для програмной задержки?
|
|
|
|
|
Jan 31 2013, 16:43
|
Местный
  
Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600

|
Цитата(allsettingsdone @ Jan 31 2013, 20:21)  Так а на чем же остановиться в поиске функции для програмной задержки? Да на чем угодно, лишь бы написано было понятно и пользоваться удобно: Код //////////////////////////////////////////////////////////////////////////////// // DELAY /////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// #pragma inline void BspDelayTicks( uint32_t Ticks ) { if (!(SCB_DEMCR & 0x01000000)) { CoreDebug->DEMCR |= 0x01000000; DWT->CYCCNT = 0; DWT->CTRL |= 1 << DWT_CTRL_CYCCNTENA_Pos; // enable the counter }
while( DWT->CYCCNT < Ticks ); }
//////////////////////////////////////////////////////////////////////////////// #pragma inline void BspDelay_uSec( volatile uint32_t uSec ) { while( uSec-- ) { BspDelayTicks( BSP_MCLK_HZ/1000000 ); } }
//////////////////////////////////////////////////////////////////////////////// #pragma inline void BspDelay_mSec( volatile uint32_t mSec ) { while( mSec-- ) { BspDelayTicks( BSP_MCLK_HZ/1000 ); } }
|
|
|
|
|
Jan 31 2013, 19:36
|
Местный
  
Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126

|
Цитата(Tahoe @ Jan 31 2013, 19:43)  лишь бы написано было понятно Код if (!(SCB_DEMCR & 0x01000000)) { CoreDebug->DEMCR |= 0x01000000; Да вроде как и понятно... но вот глаз режет... Вроде как ... Код CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|