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

 
 
> Как сделать программную задержку на STM32, без использования таймеров
Firer
сообщение Feb 10 2012, 12:51
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 294
Регистрация: 7-01-05
Пользователь №: 1 832



Пожалуйста подскажите.
Пишу в FreeRTOS.
Нужно написать библиотеку работы с LCD.
Там нужна задержка около 1мкс.
Как ее сделать?
Может функцию на ассемблере кто подскажет?
Потому что Keil оптимизирует в ничто вот такой код:
i = 100;
while (i --)
;
Go to the top of the page
 
+Quote Post
5 страниц V   1 2 3 > »   
Start new topic
Ответов (1 - 66)
Porty
сообщение Feb 10 2012, 13:11
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 246
Регистрация: 28-05-08
Из: г. Ижевск
Пользователь №: 37 893



используй специально для этого предназначенное ключевое слово "volatile", оно говорит компилятору чтоб не оптимизировал значение и работу с этой переменной или кодом.

volatile int i;

...

i = 100;
while (i --)
;
Go to the top of the page
 
+Quote Post
MikeC
сообщение Feb 10 2012, 13:13
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 16
Регистрация: 2-09-05
Пользователь №: 8 169



Попробуйте вставить __no_operation() в тело цикла.
Go to the top of the page
 
+Quote Post
ChipKiller
сообщение Feb 10 2012, 13:15
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 31
Регистрация: 26-12-11
Пользователь №: 69 097



Цитата("Firer")
Может функцию на ассемблере кто подскажет?
Код
XTAL_CLK    equ    24000 ; частота тактирования в килогерцах
....

Delay_us    PROC
        push {lr,r4}
del_us     mov    r4,#((XTAL_CLK/1000)/3)
del1u    subs r4,r4,#1
        bne    del1u
        subs r0,r0,#1
        bne    del_us        
        pop {lr,r4}
        bx    lr
    ENDP
Go to the top of the page
 
+Quote Post
Firer
сообщение Feb 10 2012, 13:46
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 294
Регистрация: 7-01-05
Пользователь №: 1 832



C volatile все равно оптимизит.
Вот я тут сам нашаманил.
Вопрос - на сколько тактов процессора эта функция делает задержку? Сам цикл.
Вносит ли переход сброс конвейера и глотает ли он доп.циклы?
Или 10*2 циклов получается ровно?


__asm void delay_us(void)
{
mov r0,#10
loop
subs r0,#1
bne loop
}
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Feb 10 2012, 17:10
Сообщение #6


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Firer @ Feb 10 2012, 16:46) *
C volatile все равно оптимизит.
Не верю.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
scifi
сообщение Feb 10 2012, 17:19
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Firer @ Feb 10 2012, 17:46) *
Вопрос - на сколько тактов процессора эта функция делает задержку? Сам цикл.

Железобетонный способ - измерить с секундомером. Для этого делается задержка не на 10 циклов, а на 10^9 циклов или около того. Не слишком маленькая, чтобы погрешность отсчёта времени была мала, и не слишком большая, чтобы не уснуть с секундомером в руке.
Кстати, задержки для LCD, как правило, не должны быть точными. Обычно достаточно, чтобы было "гарантированно не меньше N циклов".
Go to the top of the page
 
+Quote Post
Юрий_СВ
сообщение Feb 10 2012, 17:59
Сообщение #8


Участник
*

Группа: Участник
Сообщений: 73
Регистрация: 4-05-08
Пользователь №: 37 272



Цитата(Firer @ Feb 10 2012, 16:46) *
Вопрос - на сколько тактов процессора эта функция делает задержку? Сам цикл.
Вносит ли переход сброс конвейера и глотает ли он доп.циклы?
Или 10*2 циклов получается ровно?

ПМСМ, переход (кроме последнего раза) будет заново заполнять конвеер.
(не заполняет тогда, когда не выполняется условие - нет перехода)

Лучше 1 раз посчитать, используя системный таймер, с предделением 1.
(Вызов функции тоже переход с заполнением конвеера.)

Более того, время выполнения, возможно, будеть зависеть от модели контроллера (разрядность памяти)
и настроек регистра доступа к памяти.

Мне тоже интересна эта тема. Если посчитаете системным таймером - поделистесь, пожалуйста.

По крайней мере на IAR вариант с volatile у меня работает.
Код
void delay_y()
{
volatile u32_t i, ty;
for(i=0; i<10000; i++) ty=GPIOA_ODR;
}


И ещё замечание.. практически гарантировано не будет заоптимизировано обращение к портам.
Но ваш вариант лучше - точнее.

Сообщение отредактировал Юрий_СВ - Feb 10 2012, 18:40
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Feb 10 2012, 18:10
Сообщение #9


Профессионал
*****

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



Код
    inline void _delay_loops(U32 loops) {
        asm volatile (
            "1: SUBS %[loops], %[loops], #1 \n"
            "   BNE 1b \n"
            : [loops] "+r"(loops)
        );
    }
    #define delay_us( US ) _delay_loops( (U32)((double)US * F_CPU / 3000000.0) )
    #define delay_ms( MS ) _delay_loops( (U32)((double)MS * F_CPU / 3000.0) )
    #define delay_s( S )   _delay_loops( (U32)((double)S  * F_CPU / 3.0) )
Go to the top of the page
 
+Quote Post
smk
сообщение Feb 11 2012, 06:34
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



В простых примерах от Keil есть программные задержки. Работают.


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
smk
сообщение Feb 11 2012, 07:47
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 2 246
Регистрация: 17-03-05
Из: Украина, Киев
Пользователь №: 3 446



Вот такое еще работает: DelayMS(2);


--------------------
Живи днем так, чтобы ночью ты спал спокойно.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Feb 11 2012, 11:38
Сообщение #12


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(Firer @ Feb 10 2012, 13:51) *
Пожалуйста подскажите.
Пишу в FreeRTOS.
Нужно написать библиотеку работы с LCD.
Там нужна задержка около 1мкс.
Как ее сделать?

Посмотрите DWT счетчик (DWT_CYCCN, описано тут и здесь): присутствует во всех Cortex по стандарту ARM. Это 32-битное слово, которое "тикает" с частотой ядра.
Счетчик надо проинициализировать (включить):
Код

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

    if (!(DWT_CONTROL & 1))
    {
        SCB_DEMCR  |= 0x01000000;
        DWT_CYCCNT  = 0;
        DWT_CONTROL|= 1; // enable the counter
    }


Задержки можно организовывать так:

Код
uint32_t DWT_Get(void)
{
    return DWT_CYCCNT;
}
__inline
uint8_t DWT_Compare(int32_t tp)
{
    return (((int32_t)DWT_Get() - tp) < 0);
}

void DWT_Delay(uint32_t us) // microseconds
{
    int32_t tp = DWT_Get() + us * (SystemCoreClock/1000000));
    while (DWT_Compare(tp));
}


Безусловно, по причине задержек исполнения самих инструкций абсолютно точно не будет. Однако же, скажем при 72MHz ядра, даже для 1мкс аддитивная составляющая будет небольшой и постоянной.

Сообщение отредактировал KnightIgor - Feb 11 2012, 11:49
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 11 2012, 16:05
Сообщение #13


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(KnightIgor @ Feb 11 2012, 17:38) *
Посмотрите DWT счетчик

Ух ты! Отличная штука, не знал про неё. Проверил на STM32F103 - работает.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
scifi
сообщение Feb 11 2012, 18:31
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Действительно, очень интересно. Спасибо за наводку!
Go to the top of the page
 
+Quote Post
ReAl
сообщение Feb 15 2012, 17:02
Сообщение #15


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Очень жаль, что остальные счётчики все 8-битные.
На оффтопике (LPC17xx) для счётчика циклов достаточно RIT, который остался в наследство от предыдущих LPC а для осевого тика времени в Cortex-M3 стандартизированный таймер нашёлся.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Altemir
сообщение Feb 16 2012, 05:55
Сообщение #16


Местный
***

Группа: Свой
Сообщений: 249
Регистрация: 2-05-06
Из: Россия, Поволжье
Пользователь №: 16 686



Цитата(ReAl @ Feb 15 2012, 21:02) *
Очень жаль, что остальные счётчики все 8-битные.
На оффтопике (LPC17xx) для счётчика циклов достаточно RIT, который остался в наследство от предыдущих LPC...

Вот только в LPC177x его не оказалось sad.gif Хотя в LPC176x есть, для этих целей и пользую.
Прошу прощения тоже за оффтоп.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Jun 28 2012, 07:42
Сообщение #17


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Счетчик надо проинициализировать (включить): - должен подкорректировать, т.к. признаком уже включенного таймера должен служить бит в SCB_DEMCR, а не в DWT_CONTROL - связано с работой под отладчиком.
Код

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

    if (!(SCB_DEMCR & 0x01000000))
    {
        SCB_DEMCR  |= 0x01000000;
        DWT_CYCCNT  = 0;
        DWT_CONTROL|= 1; // enable the counter
    }

Go to the top of the page
 
+Quote Post
ukpyr
сообщение Jun 28 2012, 09:01
Сообщение #18


Профессионал
*****

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



не понятно зачем пляски с бубном, выше приводились задержки на инлайн-асме - работают отлично
Go to the top of the page
 
+Quote Post
Влад Р.
сообщение Jun 28 2012, 11:54
Сообщение #19


Частый гость
**

Группа: Свой
Сообщений: 87
Регистрация: 9-12-10
Пользователь №: 61 511



Цитата(ukpyr @ Jun 28 2012, 12:01) *
не понятно зачем пляски с бубном, выше приводились задержки на инлайн-асме - работают отлично


Это прискорбно, но не все знают ASM. Ваши функции "из коробки" у меня не заработали. Возможно их надо подкорректировать самую малость, но как именно я не знаю((( Кроме того не очень приятно использовать функцию, если не понимаешь как она работает. Естественно это не ваша вина, что я не в состоянии переделать их под себя. Но отсюда и пляски с бубном.

Сообщение отредактировал Влад Р. - Jun 28 2012, 11:54
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 28 2012, 17:43
Сообщение #20


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(ukpyr @ Jun 28 2012, 15:01) *
не понятно зачем пляски с бубном, выше приводились задержки на инлайн-асме - работают отлично

DWT применим не только для задержек, но и для профилировки - очень удобно измерять время выполнения кусков кода.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Jan 6 2013, 16:07
Сообщение #21


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



С виду все красиво, хотел воспользоваться вышеприведенным способом организации задержек через DWT. Но, как я понимаю, возможен конфликт с отладчиком, который использует ресурсы DWT?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 6 2013, 16:20
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Tahoe @ Jan 6 2013, 18:07) *
С виду все красиво, хотел воспользоваться вышеприведенным способом организации задержек через DWT. Но, как я понимаю, возможен конфликт с отладчиком, который использует ресурсы DWT?

А отладчик использует? С чего вы взяли?
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Jan 6 2013, 16:53
Сообщение #23


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



Цитата(_Артём_ @ Jan 6 2013, 20:20) *
А отладчик использует? С чего вы взяли?

Понятия не имею, использует или нет. Логика подсказывает, что вполне может использовать для профилирования чего-либо.

Да и кроме логики, есть основания думать, что использует.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 6 2013, 20:26
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Tahoe @ Jan 6 2013, 18:53) *
Логика подсказывает, что вполне может использовать для профилирования чего-либо.

Может для профилирования и используется отладчиком. Тогда конфликт будет.
Но вы используете это самое профилирование? Если нет, то думаю можно использовать DWT в своей программе. Я использовал, конфликтов не заметил. В работающим устройстве тем более откуда конфликтам взяться?

P.S. А что таймеров stm32 вам мало что ли?

Go to the top of the page
 
+Quote Post
Tahoe
сообщение Jan 6 2013, 20:50
Сообщение #25


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



Цитата(_Артём_ @ Jan 7 2013, 00:26) *
Но вы используете это самое профилирование?

Напрямую - нет. Но не хотелось бы получить граблями по лбу на ровном месте. Когда какой-нить плагин в IAR станет криво работать, уйдет время на то, что бы вспомнить, что сам заложил эту мину.


Цитата(_Артём_ @ Jan 7 2013, 00:26) *
В работающим устройстве тем более откуда конфликтам взяться?

Так в работающем устройстве и отладчик отсутствует. Соотв. и проблемы нет.


Цитата(_Артём_ @ Jan 7 2013, 00:26) *
P.S. А что таймеров stm32 вам мало что ли?

Таймеров хватает, повёлся на это:
Цитата(KnightIgor @ Feb 11 2012, 15:38) *
присутствует во всех Cortex по стандарту ARM
Go to the top of the page
 
+Quote Post
pitt
сообщение Jan 7 2013, 02:02
Сообщение #26


Местный
***

Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672



Цитата(Porty @ Feb 10 2012, 08:11) *
используй специально для этого предназначенное ключевое слово "volatile", оно говорит компилятору чтоб не оптимизировал значение и работу с этой переменной или кодом.

Цитата
Wikipedia
In computer programming, particularly in the C, C++, C#, and Java programming languages, a variable or object declared with the volatile keyword usually has special properties related to optimization and/or threading. Generally speaking, the volatile keyword is intended to prevent the compiler from applying any optimizations on the code that assume values of variables cannot change "on their own."

Никакого отношения к оптимизации. Ключевое слово "volatile" запрещает компилятору надеятся, что значение переменной ему известно и требует его обновления при каждом обращении.


--------------------
Прокричал немой глухому:"...Спасибо за внимание!"
http://www.youtube.com/watch?v=3Nnj4ky4Z_g
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Jan 7 2013, 08:20
Сообщение #27


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(Tahoe @ Jan 6 2013, 21:50) *
Напрямую - нет. Но не хотелось бы получить граблями по лбу на ровном месте. Когда какой-нить плагин в IAR станет криво работать, уйдет время на то, что бы вспомнить, что сам заложил эту мину.

Этот счетчик является лишь частью узла отладки и по сути только для чтения. Он крутится по кругу с частотой ядра. Какие грабли, если его читать?
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 7 2013, 10:20
Сообщение #28


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(KnightIgor @ Jan 7 2013, 10:20) *
Этот счетчик является лишь частью узла отладки и по сути только для чтения. Он крутится по кругу с частотой ядра. Какие грабли, если его читать?

Не только для чтения. Писать его тоже можно.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Jan 7 2013, 10:31
Сообщение #29


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(_Артём_ @ Jan 7 2013, 11:20) *
Не только для чтения. Писать его тоже можно.

Можно. Я написал "по сути для чтения". То есть, программа профилирования может, конечно, каждый раз сбрасывать его перед измерением. Однако кто профилирование пишет, тоже не дурак, чтобы делать это instrusive, то есть с вмешательством в процесс. С большой вероятностью для измерения времен используется разница между считаными значениями свободно бегущего счетчика, то есть, без его пересброса. Во всяком случае в моих программах пока никаких непоняток не было.
Go to the top of the page
 
+Quote Post
HHIMERA
сообщение Jan 7 2013, 11:59
Сообщение #30


Местный
***

Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126



Цитата(pitt @ Jan 7 2013, 06:02) *
Никакого отношения к оптимизации. Ключевое слово "volatile" запрещает компилятору надеятся, что значение переменной ему известно и требует его обновления при каждом обращении.

Угу... щазз...
А ещё есть code reordering...
Или будете доказывать, что и code reordering "Никакого отношения к оптимизации"???

Цитата(KnightIgor @ Feb 11 2012, 15:38) *
Посмотрите DWT счетчик (DWT_CYCCN, описано тут и здесь): присутствует во всех Cortex по стандарту ARM.

И в Cortex M0 есть???
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Jan 7 2013, 12:38
Сообщение #31


Местный
***

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

Ну самостоятельно посмотреть?
Go to the top of the page
 
+Quote Post
HHIMERA
сообщение Jan 7 2013, 12:46
Сообщение #32


Местный
***

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

и усё... )))
Go to the top of the page
 
+Quote Post
SSerge
сообщение Jan 8 2013, 07:16
Сообщение #33


Профессионал
*****

Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528



Цитата(HHIMERA @ Jan 7 2013, 19:46) *
Смотрел... Дошёл до

и усё... )))

Так зарегистрируйтесь, это не сложно.
Впрочем, не поможет, в М0 и М0+ такого регистра нет.


--------------------
Russia est omnis divisa in partes octo.
Go to the top of the page
 
+Quote Post
HHIMERA
сообщение Jan 8 2013, 08:52
Сообщение #34


Местный
***

Группа: Участник
Сообщений: 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 не работает...
Go to the top of the page
 
+Quote Post
pitt
сообщение Jan 27 2013, 00:00
Сообщение #35


Местный
***

Группа: Участник
Сообщений: 328
Регистрация: 1-06-06
Из: USA
Пользователь №: 17 672



Цитата(HHIMERA @ Jan 7 2013, 06:59) *
Угу... щазз...
А ещё есть code reordering...
Или будете доказывать, что и code reordering "Никакого отношения к оптимизации"???

Не стоит путать божий дар с яичничей, а key word "volatile" с оптимизирующим компилятором FYI


--------------------
Прокричал немой глухому:"...Спасибо за внимание!"
http://www.youtube.com/watch?v=3Nnj4ky4Z_g
Go to the top of the page
 
+Quote Post
HHIMERA
сообщение Jan 27 2013, 09:33
Сообщение #36


Местный
***

Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126



Ну так и не путайте... biggrin.gif

Сообщение отредактировал HHIMERA - Jan 27 2013, 09:33
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Jan 27 2013, 10:23
Сообщение #37


Знающий
****

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Jan 27 2013, 15:05
Сообщение #38


Местный
***

Группа: Свой
Сообщений: 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". sm.gif

Хотя решение, конечно, очевидно: просто инициализировать счетчик при старте. По крайней мере, для периодических задач профилирования, это не станет серьезной проблемой. Разве что экхотика какая, например, время стартапа подсчитывается, но и в этом случае, по идее, к моменту перехода на 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.

... и далее по тексту, правда инфы не густо.

Go to the top of the page
 
+Quote Post
allsettingsdone
сообщение Jan 31 2013, 12:35
Сообщение #39


Участник
*

Группа: Участник
Сообщений: 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млн?
Что плохого/хорошего скажите про всё это?
Go to the top of the page
 
+Quote Post
scifi
сообщение Jan 31 2013, 13:13
Сообщение #40


Гуру
******

Группа: Свой
Сообщений: 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) *
Что плохого/хорошего скажите про всё это?

Код хорош тем, что прост, но плох тем, что время исполнения зависит от версии компилятора, уровня оптимизации, скорости процессора и т.д.
Кстати, вам совсем не помешает почитать учебник по языку Си.
Go to the top of the page
 
+Quote Post
PoReX
сообщение Jan 31 2013, 13:25
Сообщение #41


Частый гость
**

Группа: Свой
Сообщений: 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-е годы. И в то время этого хватало, чтобы запустить человека в космос, а сегодня — только чтобы запускать птиц в свиней.»
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Jan 31 2013, 14:05
Сообщение #42


Местный
***

Группа: Свой
Сообщений: 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, произойдет переполнение переменной этого типа. И, повторюсь, не дай Б-г начать задумываться о чем-то бОльшем. Во всяком случае, на данном этапе.
Go to the top of the page
 
+Quote Post
allsettingsdone
сообщение Jan 31 2013, 16:21
Сообщение #43


Участник
*

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



Так а на чем же остановиться в поиске функции для програмной задержки?
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Jan 31 2013, 16:43
Сообщение #44


Местный
***

Группа: Свой
Сообщений: 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 );
    }
}
Go to the top of the page
 
+Quote Post
HHIMERA
сообщение Jan 31 2013, 19:36
Сообщение #45


Местный
***

Группа: Участник
Сообщений: 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;
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Jan 31 2013, 20:26
Сообщение #46


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



Цитата(HHIMERA @ Jan 31 2013, 23:36) *
но вот глаз режет...

Да ладно, буквоедствовать... Особенно после этой помойки:
Цитата(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++) {}
}


В показанном коде еще и счетчик сбрасывается, а не разница между текущим и ожидаемым значением вычисляется. wink.gif И потом, основная "ценность" приведенного кода совсем в другом, а именно, в сервисе:
BspDelay_uSec( xxx );
BspDelay_mSec( xxx );
Go to the top of the page
 
+Quote Post
allsettingsdone
сообщение Feb 1 2013, 10:08
Сообщение #47


Участник
*

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



Цитата(Tahoe @ Jan 31 2013, 18:43) *
Да на чем угодно, лишь бы написано было понятно и пользоваться удобно:

Код
////////////////////////////////////////////////////////////////////////////////
// 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 );
    }
}

Это не компитируется, куча ошибок. Например:
identifier "SCB_DEMCR" is undefined
identifier "DWT" is undefined
identifier "DWT_CTRL_CYCCNTENA_Pos" is undefined
identifier "BSP_MCLK_HZ" is undefined
Какие вы библиотеки используете для этого, что пользователь должен задейфайнить сам? Ничего не понимаю

Сообщение отредактировал allsettingsdone - Feb 1 2013, 10:12
Go to the top of the page
 
+Quote Post
HHIMERA
сообщение Feb 1 2013, 10:27
Сообщение #48


Местный
***

Группа: Участник
Сообщений: 226
Регистрация: 10-07-09
Пользователь №: 51 126



Цитата(allsettingsdone @ Feb 1 2013, 14:08) *
что пользователь должен задейфайнить сам? Ничего не понимаю

А что там понимать...
Дефайн SCB_DEMCR описан в начале темы...
А CoreDebug->DEMCR, DWT->CYCCNT и DWT->CTRL есть в налиии в последних CMSIS... в старых отсутствуют...
Просто как-то... "Смешались в кучу кони, люди" (С)... ))
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Feb 1 2013, 12:04
Сообщение #49


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



Цитата(allsettingsdone @ Feb 1 2013, 14:08) *
Это не компитируется, куча ошибок. Например:
identifier "SCB_DEMCR" is undefined
identifier "DWT" is undefined
identifier "DWT_CTRL_CYCCNTENA_Pos" is undefined
identifier "BSP_MCLK_HZ" is undefined
Какие вы библиотеки используете для этого, что пользователь должен задейфайнить сам? Ничего не понимаю

В принципе, HHIMERA уже ответил.
Названия регистров и битов - стандартные, из CMSIS. Обычно, CMSIS подключается в любом проекте на Cortex-M ядре.

А что касается BSP_MCLK_HZ, то, как видно из его префикса и префиксов функций, они указывают на расположение в файле bsp.х Про BSP можно почитать здесь, а лучше здесь. Как явствует из MCLK, это некий clock, в данном случае main clock. HZ указывает на то, что частота задана Герцах. Итого: константа в файле bsp.h, означающая частоту ядра процессора в Герцах.
Go to the top of the page
 
+Quote Post
polyname
сообщение Feb 1 2013, 12:11
Сообщение #50


Частый гость
**

Группа: Участник
Сообщений: 147
Регистрация: 18-05-12
Пользователь №: 71 915



Цитата
Что плохого/хорошего скажите про всё это?
рабочий код был дан давно:
http://electronix.ru/forum/index.php?s=&am...t&p=1025991
работает четко, без всяких попроавочных коэффициентов (на чистом С компилятор может сгенерить что угодно в зависимости от настроек оптимизации). И вычисления количества циклов происходит во время компиляции, а не как у многих тут, которые суют деления/умножения, и даже плавучку в функцию задержки.

Сообщение отредактировал polyname - Feb 1 2013, 12:12
Go to the top of the page
 
+Quote Post
Tahoe
сообщение Feb 1 2013, 12:24
Сообщение #51


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 30-03-06
Из: Москва
Пользователь №: 15 600



Цитата(polyname @ Feb 1 2013, 16:11) *
а не как у многих тут, которые суют деления/умножения, и даже плавучку в функцию задержки.

Если речь про мой код, то могу посоветовать только голову включить. Хотел бы я посмотреть на компилер, препроцессор которого, увидев констатное 8000000/1000, пропустит мимо и отправит вычисляться в рантайм.


Вот что действительно имеет смысл поправить, так это вместо
Код
if (!(SCB_DEMCR & 0x01000000))

для единообразия:
Код
if (!(CoreDebug->DEMCR & 0x01000000))
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 22 2013, 16:02
Сообщение #52


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Код
void dwt_init(void)
{
    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
    DWT->CYCCNT       = 0;                            // reset
    DWT->CTRL        |= 1;                            // enable the counter
}

static __inline uint32_t dwt_dt(uint32_t t0, uint32_t t1)
{
    return (t1 - t0); // всегда верно, даже если t1<t0
}

void dwt_delay(uint32_t us) // microseconds (max = 2^32 / (fcpu*1.0E-6) - 1)
{
    uint32_t t0 = DWT->CYCCNT;
    uint32_t dt = us * (F_CPU/1000000UL); // 1us = 72tics @ 72MHz

    while (dwt_dt(t0, DWT->CYCCNT) < dt)  {;}
}
И нет проблем при попадании момента переполнения счётчика внутрь измеряемого диапазона времени...
Естественно максимальный диапазон не должен превышать одного периода dwt таймера, то бишь типа uint32_t.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
megajohn
сообщение Aug 6 2013, 12:54
Сообщение #53


Профессионал
*****

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



Цитата(KnightIgor @ Jun 28 2012, 11:42) *
Счетчик надо проинициализировать (включить): - должен подкорректировать, т.к. признаком уже включенного таймера должен служить бит в SCB_DEMCR, а не в DWT_CONTROL - связано с работой под отладчиком.
Код

    if (!(SCB_DEMCR & 0x01000000))
    {
...
    }


извиняюсь что поднял старый пост. Но у меня так не тикало на LPC1778 - то есть бит DEMCR_TRCENA был установлен, а DWT->CTRL сброшен. Может всё-таки так ?

Код
    if( !( CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk ) || !( DWT->CTRL & DWT_CTRL_CYCCNTENA_Msk ) )
    {
        DWT->CYCCNT  = 0;
                            CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
        DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; // enable the counter
    }



кстати, кому интересно, расширил разрядность DWT до 64 бит
Код
//----------------------------------------------------------------------------
u64 core_get_cycles_counter( void )
{
    TN_INTSAVE_DATA

    u64 ret = 0;        
    static u32 cch = 0, ccl_prev = 0;
    u32 ccl = DWT->CYCCNT;
    
    tn_disable_interrupt();
    if( ccl_prev > ccl )
        cch++;
    ret = ((u64)cch << 32) + ccl;
    ccl_prev = ccl;
    tn_enable_interrupt();
    
    return ret;
}

//----------------------------------------------------------------------------
u64 get_sys_mks( void )
{
    u64 ret = core_get_cycles_counter() / ( F_CPU / 1000000UL );
    return ret;
}

P.S. в векторе SysTick_Handler системного тика каждую секунду считывает core_get_cycles_counter чтобы DWT->CYCCNT не переполнился более одного раза


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post
Rash
сообщение Aug 7 2013, 06:52
Сообщение #54


Знающий
****

Группа: Свой
Сообщений: 639
Регистрация: 5-09-05
Пользователь №: 8 231



на новых мк приходится штриховать условие (//)
Код
if (!(SCB_DEMCR & 0x01000000))

потом расштриховываешь и всё нормально работает при отладке. Правда это на STM32F4/
С чем связано ещё не разбирался
Go to the top of the page
 
+Quote Post
toweroff
сообщение Aug 7 2013, 07:13
Сообщение #55


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Тут тоже набрел на решение, которое, как мне кажется, зависит только от тактовой частоты - это время доступа с внутреннему ОЗУ
И тогда довольно точно можно подгонять задержки
Код
volatile uint32_t trash_in, trash_out;

for (uint32_t i=0; i<delay; i++) trash_in = trash_out;
Go to the top of the page
 
+Quote Post
megajohn
сообщение Aug 7 2013, 07:40
Сообщение #56


Профессионал
*****

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



Цитата(toweroff @ Aug 7 2013, 11:13) *
Тут тоже набрел на решение, которое, как мне кажется, зависит только от тактовой частоты - это время доступа с внутреннему ОЗУ
И тогда довольно точно можно подгонять задержки


кто юзал IAR и переходил с AVR на CM3 всегда недоумевали - "куда делись привычные __delay_cycles( N ) ?"
а ответ простой - в CM3 есть DMA, который перехватывает системную шину и собственно приостанавливает доступ. Так что на ваших for(i<const) ничего толкового не получишь.

P.S. И как мне говорили, есть еще какие-то факторы. Так что если кто подскажет буду признателен


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post
Rimsky
сообщение Aug 12 2013, 02:14
Сообщение #57





Группа: Участник
Сообщений: 14
Регистрация: 10-06-12
Пользователь №: 72 261



Цитата(ukpyr @ Jun 28 2012, 18:01) *
не понятно зачем пляски с бубном, выше приводились задержки на инлайн-асме - работают отлично

+100

Вот код под IAR
Код
#define __delay_us( US ) __delay_loops( (uint32_t)((double)US * F_CPU / 3000000.0))
#define __delay_ms( MS ) __delay_loops( (uint32_t)((double)MS * F_CPU / 3000.0))
#define __delay_s( S )   __delay_loops( (uint32_t)((double)S  * F_CPU / 3.0))

#pragma inline=forced
void __delay_loops(uint32_t loops){
        asm(    "Metka:    SUBS     %[R1], %[R1], %[imm] \n"
                "       BNE.N    Metka        \n"
                : [R1]"+r" (loops)
        : [imm]"i"(1));
        };

Go to the top of the page
 
+Quote Post
VAI
сообщение Aug 12 2013, 09:03
Сообщение #58


Профессионал
*****

Группа: Модераторы
Сообщений: 1 120
Регистрация: 17-06-04
Пользователь №: 37



Цитата(Rimsky @ Aug 12 2013, 06:14) *
Вот код под IAR....

Постом выше megajohn написал, почему Ваши задержки будут кривыми... + к этому, ещё и срабатывание прерываний во время исполнения циклов.


--------------------
Если зайца бить, его можно и спички научить зажигать
Сколько дурака не бей - умнее не будет. Зато опытнее
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Aug 12 2013, 09:30
Сообщение #59


Профессионал
*****

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



DMA далеко не всегда используется.

можно добавить запрет прерываний:
Код
#define cli() asm volatile ( "CPSID i \n" )
#define sei() asm volatile ( "CPSIE i \n" )

#define __delay_us_cli( US ) cli(); __delay_us( US ); sei();


другой вариант - выделить для задержек таймер.

Сообщение отредактировал ukpyr - Aug 12 2013, 09:36
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 12 2013, 09:38
Сообщение #60


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(ukpyr @ Aug 12 2013, 12:30) *
можно добавить запрет прерываний:

А можно из буханки ржаного хлеба..
ну вы понимаете, о чем я..


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Rimsky
сообщение Aug 12 2013, 14:19
Сообщение #61





Группа: Участник
Сообщений: 14
Регистрация: 10-06-12
Пользователь №: 72 261



Цитата(VAI @ Aug 12 2013, 18:03) *
Постом выше megajohn написал, почему Ваши задержки будут кривыми... + к этому, ещё и срабатывание прерываний во время исполнения циклов.

Да, проверил, есть такой косяк. Сделал по другому, может уже и не в тему топика, поскольку заюзал таймер:

Код
#define F_CPU    24000000UL

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
TIM6->CR1 |= TIM_CR1_CEN;


// Процедура формирования линейной задержки
#pragma inline=forced
void __delay_loops(uint16_t loops)
{
    TIM6->CNT = 0x0000;
    while(loops > TIM6->CNT);
}

#define __delay_us( US ) __delay_loops( (uint16_t)(US * (uint16_t)(F_CPU / 1000000UL)) )

#pragma inline=forced
void __delay_ms(uint16_t ms){
    do{     
        __delay_us(1000);
    }
    while(ms--);
};
Go to the top of the page
 
+Quote Post
Kot_dnz
сообщение Sep 28 2014, 10:45
Сообщение #62





Группа: Новичок
Сообщений: 6
Регистрация: 4-07-14
Пользователь №: 82 154



Цитата(Rash @ Aug 7 2013, 09:52) *
на новых мк приходится штриховать условие (//)
Код
if (!(SCB_DEMCR & 0x01000000))

потом расштриховываешь и всё нормально работает при отладке. Правда это на STM32F4/
С чем связано ещё не разбирался

О, а можно с этого места по подробнее.
Подключен stm32f103, из IAR прошиваю через ST-LINK, функция расшифровки ногодрыга реализована через DWT - все работает как ожидалось.
Сбрасываю питание - функция перестает работать. Никакие электролиты и пр на питании не помогают. Остальные функции работают как нужно.
CODE
void DWT_Init(void)
{
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}

uint32_t DWT_Get(void)
{
return DWT->CYCCNT;
}

inline uint8_t DWT_Compare(int32_t tp)
{
return (((int32_t)DWT_Get() - tp) < 0);
}

void DWT_Delay(uint32_t us) // microseconds
{
int32_t tp = DWT_Get() + us * (F_CPU/1000000);
while (DWT_Compare(tp));
}

что я делаю не так?

Цитата(Kot_dnz @ Sep 28 2014, 13:15) *
[code]void DWT_Init(void)
{
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
}


Сорри, нашел - не хватало строки
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
интересное проявление баго-фичи...

Сообщение отредактировал IgorKossak - Sep 28 2014, 18:59
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
etoja
сообщение Oct 2 2014, 15:01
Сообщение #63


Профессионал
*****

Группа: Свой
Сообщений: 1 121
Регистрация: 14-01-05
Из: Москва
Пользователь №: 1 952



Можно ещё выдавать байт в неиспользуемый SPI, UART или дёргать ножки вывода. Эти операции тоже идут долго.
Go to the top of the page
 
+Quote Post
AVR
сообщение Oct 3 2014, 07:00
Сообщение #64


фанат Linux'а
*****

Группа: Свой
Сообщений: 1 353
Регистрация: 23-10-05
Из: SPB.RU
Пользователь №: 10 008



Цитата(Firer @ Feb 10 2012, 16:51) *
Нужно написать библиотеку работы с LCD.
Там нужна задержка около 1мкс.

Я решаю это так (и на STM32 и на MDR32 и на других):
Код
unsigned int delay_ms(unsigned int ms)
{
    volatile unsigned int i, t = 0;
    //for(i = 0; i < (ms*400); i++) t++; // @ 8 MHz
    for(i = 0; i < (ms*5714); i++) t++;
    return t;
}

unsigned int delay_10us(unsigned int us)
{
    volatile unsigned int i, t = 0;
    //for(i = 0; i < (us*4); i++) t++; // @ 8 MHz
    for(i = 0; i < (us*57); i++) t++;
    return t;
}

Сначала мигаю светодиодом на delay_ms(1000) - периоды были несколько секунд - так вычисляю во сколько раз мне нужно меньше чтобы была как можно ближе к одной секунде. Получил число допустим 5714. Ну а 10 мкс - это в 100 раз меньше - 57.

Знаю какие недостатки этого метода, но лично мне нравится и всё работает стабильно sm.gif


--------------------
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Oct 3 2014, 07:27
Сообщение #65


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(AVR @ Oct 3 2014, 11:00) *
Код
    //for(i = 0; i < (ms*[b]400[/b]); i++) t++; // @ 8 MHz
    for(i = 0; i < (ms*[b]5714[/b]); i++) t++;

    //for(i = 0; i < (us*[b]4[/b]); i++) t++; // @ 8 MHz
    for(i = 0; i < (us*[b]57[/b]); i++) t++;

...мне нравится и всё работает стабильно sm.gif


почему бы и нет?
только маленьчкое замечание: цифры я бы вычислял бы в зависимости от дефайна тактовой. Тем более в STM вроде как они объявлены. Тогда писать новые строчки под разную частоту не понадобиться.
И по закону мерфи - меньше кода, меньше багов...

ЗЫ
И ещё бы добавил ифдеф для делителей меньше 1 или 2... Типа вонинг! не допустимо маленький делитель(умножитель - кому как sm.gif ) для данных функций.
Go to the top of the page
 
+Quote Post
menzoda
сообщение Oct 3 2014, 12:49
Сообщение #66


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 13-09-12
Пользователь №: 73 530



kolobok0, AVR

Для большей точности и повторяемости можно реализовать на ассемблере, получится совсем немного инструкций, можно будет точнее вычислить кол-во тактов на один цикл, не будет плавать из-за смены опций компиляции. Чтобы не мешали прерывания можно их запрещать на время задержки.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 3 2014, 12:56
Сообщение #67


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(kolobok0 @ Oct 3 2014, 10:27) *
только маленьчкое замечание:
И настройки оптимизации, а также версию компилятора прибить гвоздями к этому исходнику. Чтобы времянки случайно не уплыли.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

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

 


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


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