Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как сделать программную задержку на STM32
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2
Firer
Пожалуйста подскажите.
Пишу в FreeRTOS.
Нужно написать библиотеку работы с LCD.
Там нужна задержка около 1мкс.
Как ее сделать?
Может функцию на ассемблере кто подскажет?
Потому что Keil оптимизирует в ничто вот такой код:
i = 100;
while (i --)
;
Porty
используй специально для этого предназначенное ключевое слово "volatile", оно говорит компилятору чтоб не оптимизировал значение и работу с этой переменной или кодом.

volatile int i;

...

i = 100;
while (i --)
;
MikeC
Попробуйте вставить __no_operation() в тело цикла.
ChipKiller
Цитата("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
Firer
C volatile все равно оптимизит.
Вот я тут сам нашаманил.
Вопрос - на сколько тактов процессора эта функция делает задержку? Сам цикл.
Вносит ли переход сброс конвейера и глотает ли он доп.циклы?
Или 10*2 циклов получается ровно?


__asm void delay_us(void)
{
mov r0,#10
loop
subs r0,#1
bne loop
}
demiurg_spb
Цитата(Firer @ Feb 10 2012, 16:46) *
C volatile все равно оптимизит.
Не верю.
scifi
Цитата(Firer @ Feb 10 2012, 17:46) *
Вопрос - на сколько тактов процессора эта функция делает задержку? Сам цикл.

Железобетонный способ - измерить с секундомером. Для этого делается задержка не на 10 циклов, а на 10^9 циклов или около того. Не слишком маленькая, чтобы погрешность отсчёта времени была мала, и не слишком большая, чтобы не уснуть с секундомером в руке.
Кстати, задержки для LCD, как правило, не должны быть точными. Обычно достаточно, чтобы было "гарантированно не меньше N циклов".
Юрий_СВ
Цитата(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;
}


И ещё замечание.. практически гарантировано не будет заоптимизировано обращение к портам.
Но ваш вариант лучше - точнее.
ukpyr
Код
    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) )
smk
В простых примерах от Keil есть программные задержки. Работают.
smk
Вот такое еще работает: DelayMS(2);
KnightIgor
Цитата(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мкс аддитивная составляющая будет небольшой и постоянной.
AHTOXA
Цитата(KnightIgor @ Feb 11 2012, 17:38) *
Посмотрите DWT счетчик

Ух ты! Отличная штука, не знал про неё. Проверил на STM32F103 - работает.
scifi
Действительно, очень интересно. Спасибо за наводку!
ReAl
Очень жаль, что остальные счётчики все 8-битные.
На оффтопике (LPC17xx) для счётчика циклов достаточно RIT, который остался в наследство от предыдущих LPC а для осевого тика времени в Cortex-M3 стандартизированный таймер нашёлся.
Altemir
Цитата(ReAl @ Feb 15 2012, 21:02) *
Очень жаль, что остальные счётчики все 8-битные.
На оффтопике (LPC17xx) для счётчика циклов достаточно RIT, который остался в наследство от предыдущих LPC...

Вот только в LPC177x его не оказалось sad.gif Хотя в LPC176x есть, для этих целей и пользую.
Прошу прощения тоже за оффтоп.
KnightIgor
Счетчик надо проинициализировать (включить): - должен подкорректировать, т.к. признаком уже включенного таймера должен служить бит в 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
    }

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


Это прискорбно, но не все знают ASM. Ваши функции "из коробки" у меня не заработали. Возможно их надо подкорректировать самую малость, но как именно я не знаю((( Кроме того не очень приятно использовать функцию, если не понимаешь как она работает. Естественно это не ваша вина, что я не в состоянии переделать их под себя. Но отсюда и пляски с бубном.
AHTOXA
Цитата(ukpyr @ Jun 28 2012, 15:01) *
не понятно зачем пляски с бубном, выше приводились задержки на инлайн-асме - работают отлично

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

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

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

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

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

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

Tahoe
Цитата(_Артём_ @ 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
pitt
Цитата(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" запрещает компилятору надеятся, что значение переменной ему известно и требует его обновления при каждом обращении.
KnightIgor
Цитата(Tahoe @ Jan 6 2013, 21:50) *
Напрямую - нет. Но не хотелось бы получить граблями по лбу на ровном месте. Когда какой-нить плагин в IAR станет криво работать, уйдет время на то, что бы вспомнить, что сам заложил эту мину.

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

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

Можно. Я написал "по сути для чтения". То есть, программа профилирования может, конечно, каждый раз сбрасывать его перед измерением. Однако кто профилирование пишет, тоже не дурак, чтобы делать это instrusive, то есть с вмешательством в процесс. С большой вероятностью для измерения времен используется разница между считаными значениями свободно бегущего счетчика, то есть, без его пересброса. Во всяком случае в моих программах пока никаких непоняток не было.
HHIMERA
Цитата(pitt @ Jan 7 2013, 06:02) *
Никакого отношения к оптимизации. Ключевое слово "volatile" запрещает компилятору надеятся, что значение переменной ему известно и требует его обновления при каждом обращении.

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

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

И в Cortex M0 есть???
Tahoe
Цитата(KnightIgor @ Jan 7 2013, 12:20) *
Какие грабли, если его читать?

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

Итого. Я бы рекомендовал исключить строку:
Код
DWT_CYCCNT  = 0;


Цитата(HHIMERA @ Jan 7 2013, 15:59) *
И в Cortex M0 есть???

Ну самостоятельно посмотреть?
HHIMERA
Цитата(Tahoe @ Jan 7 2013, 15:38) *
самостоятельно посмотреть?


Смотрел... Дошёл до
Цитата
This document is only available in a PDF version to registered ARM customers.

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

и усё... )))

Так зарегистрируйтесь, это не сложно.
Впрочем, не поможет, в М0 и М0+ такого регистра нет.
HHIMERA
Цитата(SSerge @ Jan 8 2013, 11:16) *
в М0 и М0+ такого регистра нет.

Вот и я о том же...
И если последние редакции CMSIS в файлах core_cm3.h и core_cm4.h содержат информацию о DWT, то в core_cm0.h она отсутствует напрочь...
Да и в самом железе STM32F0XX DWT не работает...
pitt
Цитата(HHIMERA @ Jan 7 2013, 06:59) *
Угу... щазз...
А ещё есть code reordering...
Или будете доказывать, что и code reordering "Никакого отношения к оптимизации"???

Не стоит путать божий дар с яичничей, а key word "volatile" с оптимизирующим компилятором FYI
HHIMERA
Ну так и не путайте... biggrin.gif
KnightIgor
Цитата(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. То есть, вполне можно запускать программные задержки на меньшие времена (десятки - сотни мкс).
Tahoe
Цитата(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.

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

allsettingsdone
Ну а вот я попробывал сделать так:
Код
#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млн?
Что плохого/хорошего скажите про всё это?
scifi
Цитата(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) *
Что плохого/хорошего скажите про всё это?

Код хорош тем, что прост, но плох тем, что время исполнения зависит от версии компилятора, уровня оптимизации, скорости процессора и т.д.
Кстати, вам совсем не помешает почитать учебник по языку Си.
PoReX
Цитата(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 мкс. Если нужно точно засечь время, лучше использовать таймеры, например, системный.
Tahoe
Цитата(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, произойдет переполнение переменной этого типа. И, повторюсь, не дай Б-г начать задумываться о чем-то бОльшем. Во всяком случае, на данном этапе.
allsettingsdone
Так а на чем же остановиться в поиске функции для програмной задержки?
Tahoe
Цитата(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 );
    }
}
HHIMERA
Цитата(Tahoe @ Jan 31 2013, 19:43) *
лишь бы написано было понятно
Код
    if (!(SCB_DEMCR & 0x01000000))
    {
        CoreDebug->DEMCR    |=    0x01000000;

Да вроде как и понятно... но вот глаз режет...

Вроде как ...
Код
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
Tahoe
Цитата(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 );
allsettingsdone
Цитата(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
Какие вы библиотеки используете для этого, что пользователь должен задейфайнить сам? Ничего не понимаю
HHIMERA
Цитата(allsettingsdone @ Feb 1 2013, 14:08) *
что пользователь должен задейфайнить сам? Ничего не понимаю

А что там понимать...
Дефайн SCB_DEMCR описан в начале темы...
А CoreDebug->DEMCR, DWT->CYCCNT и DWT->CTRL есть в налиии в последних CMSIS... в старых отсутствуют...
Просто как-то... "Смешались в кучу кони, люди" (С)... ))
Tahoe
Цитата(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, означающая частоту ядра процессора в Герцах.
polyname
Цитата
Что плохого/хорошего скажите про всё это?
рабочий код был дан давно:
http://electronix.ru/forum/index.php?s=&am...t&p=1025991
работает четко, без всяких попроавочных коэффициентов (на чистом С компилятор может сгенерить что угодно в зависимости от настроек оптимизации). И вычисления количества циклов происходит во время компиляции, а не как у многих тут, которые суют деления/умножения, и даже плавучку в функцию задержки.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.