Firer 0 10 февраля, 2012 Опубликовано 10 февраля, 2012 · Жалоба Пожалуйста подскажите. Пишу в FreeRTOS. Нужно написать библиотеку работы с LCD. Там нужна задержка около 1мкс. Как ее сделать? Может функцию на ассемблере кто подскажет? Потому что Keil оптимизирует в ничто вот такой код: i = 100; while (i --) ; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
porty 0 10 февраля, 2012 Опубликовано 10 февраля, 2012 · Жалоба используй специально для этого предназначенное ключевое слово "volatile", оно говорит компилятору чтоб не оптимизировал значение и работу с этой переменной или кодом. volatile int i; ... i = 100; while (i --) ; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MikeC 0 10 февраля, 2012 Опубликовано 10 февраля, 2012 · Жалоба Попробуйте вставить __no_operation() в тело цикла. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ChipKiller 0 10 февраля, 2012 Опубликовано 10 февраля, 2012 · Жалоба Может функцию на ассемблере кто подскажет? 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 0 10 февраля, 2012 Опубликовано 10 февраля, 2012 · Жалоба C volatile все равно оптимизит. Вот я тут сам нашаманил. Вопрос - на сколько тактов процессора эта функция делает задержку? Сам цикл. Вносит ли переход сброс конвейера и глотает ли он доп.циклы? Или 10*2 циклов получается ровно? __asm void delay_us(void) { mov r0,#10 loop subs r0,#1 bne loop } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg_spb 0 10 февраля, 2012 Опубликовано 10 февраля, 2012 · Жалоба C volatile все равно оптимизит.Не верю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 10 февраля, 2012 Опубликовано 10 февраля, 2012 · Жалоба Вопрос - на сколько тактов процессора эта функция делает задержку? Сам цикл. Железобетонный способ - измерить с секундомером. Для этого делается задержка не на 10 циклов, а на 10^9 циклов или около того. Не слишком маленькая, чтобы погрешность отсчёта времени была мала, и не слишком большая, чтобы не уснуть с секундомером в руке. Кстати, задержки для LCD, как правило, не должны быть точными. Обычно достаточно, чтобы было "гарантированно не меньше N циклов". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Буян 0 10 февраля, 2012 Опубликовано 10 февраля, 2012 (изменено) · Жалоба Вопрос - на сколько тактов процессора эта функция делает задержку? Сам цикл. Вносит ли переход сброс конвейера и глотает ли он доп.циклы? Или 10*2 циклов получается ровно? ПМСМ, переход (кроме последнего раза) будет заново заполнять конвеер. (не заполняет тогда, когда не выполняется условие - нет перехода) Лучше 1 раз посчитать, используя системный таймер, с предделением 1. (Вызов функции тоже переход с заполнением конвеера.) Более того, время выполнения, возможно, будеть зависеть от модели контроллера (разрядность памяти) и настроек регистра доступа к памяти. Мне тоже интересна эта тема. Если посчитаете системным таймером - поделистесь, пожалуйста. По крайней мере на IAR вариант с volatile у меня работает. void delay_y() { volatile u32_t i, ty; for(i=0; i<10000; i++) ty=GPIOA_ODR; } И ещё замечание.. практически гарантировано не будет заоптимизировано обращение к портам. Но ваш вариант лучше - точнее. Изменено 10 февраля, 2012 пользователем Юрий_СВ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ukpyr 0 10 февраля, 2012 Опубликовано 10 февраля, 2012 · Жалоба 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 0 11 февраля, 2012 Опубликовано 11 февраля, 2012 · Жалоба В простых примерах от Keil есть программные задержки. Работают. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
smk 0 11 февраля, 2012 Опубликовано 11 февраля, 2012 · Жалоба Вот такое еще работает: DelayMS(2); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 11 февраля, 2012 Опубликовано 11 февраля, 2012 (изменено) · Жалоба Пожалуйста подскажите. Пишу в 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мкс аддитивная составляющая будет небольшой и постоянной. Изменено 11 февраля, 2012 пользователем KnightIgor Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 14 11 февраля, 2012 Опубликовано 11 февраля, 2012 · Жалоба Посмотрите DWT счетчик Ух ты! Отличная штука, не знал про неё. Проверил на STM32F103 - работает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
scifi 1 11 февраля, 2012 Опубликовано 11 февраля, 2012 · Жалоба Действительно, очень интересно. Спасибо за наводку! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ReAl 0 15 февраля, 2012 Опубликовано 15 февраля, 2012 · Жалоба Очень жаль, что остальные счётчики все 8-битные. На оффтопике (LPC17xx) для счётчика циклов достаточно RIT, который остался в наследство от предыдущих LPC а для осевого тика времени в Cortex-M3 стандартизированный таймер нашёлся. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться