-
Постов
1 240 -
Зарегистрирован
-
Посещение
-
Победитель дней
9
Сообщения, опубликованные VladislavS
-
-
Так нельзя из кварца 12 МГц получить 170.
Вход PLL должен быть больше 2.66 МГц , то есть 3, 4, 6 или 12 МГц. Частота PLL должна быть 96-344 МГц.
В этих ограничениях ближайшее что можно получить : 12/4*113/2= 169,5 МГц или более красивое 12/3*84/2 (12/2*56/2, 12*28/2) = 168 МГц.
-
-
Достаём хрустальный шар.
Приём UART через DMA путём опроса могу нафантазировать разными способами:
1. Опрашиваем в главном цикле флаг RXNE. Если он вскочил, то запускаем DMA на передачу данных из DR в память. Ждём окончания передачи опять же опросом флагов DMA. Выключаем DMA.
2. Запускаем DMA на приём байта из DR. В основном цикле опрашиваем флаги DMA на предмет окончания приёма. Выключаем DMA.
3. Можно ещё извращённых методов придумать с опросом флагов UART через DMA...
В сочетании с HAL на 2400-9600, пожалуй, взлетит. 🙂
Убираем хрустальный шар.
-
makefile это своего рода программа. Я бы вызывал make с параметром CONFIG=XXX и в зависимости от значения CONFIG формировал разные ключи компиляции и директорию куда компилировать.
-
6 часов назад, jcxz сказал:
В таком же, в каком многоядерность имеет отношение к VTOR
Много ядер - много VTOR-ов. Но я скорее обратил внимание на количество разных областей памяти. Одних только SRAM штук 8 насчитал. И флэшек штуки три. Ну и два ядра тоже не стимулируют шаблонный подход.
-
Ещё бы понять в каком месте оно Cortex-M....
-
-
12 минут назад, haker_fox сказал:
Ой, я вёл разговор только в контексте ARM. Cortex-M
Даже Cortex-M бывают очень разные.
-
3 минуты назад, haker_fox сказал:
Поэтому, первые два адреса таблицы (стэк и старт) всё равно есть.
Это нужно только чтобы Cortex-M стартанул в железе без всяких загрузчиков. У других ядер другие условности. Если вы стартуете из-под загрузчика, то можете сделать как захочет ваша левая пятка. Другое дело, что особого смысла переделывать этот механизм нет, только себя путать.
-
Я имел в виду не наличие VTOR как такового, а есть ли в приложении телодвижения с ним.
-
34 минуты назад, Arlleex сказал:
А разве это удобно?
Зачем бедному загрузчику знать есть у вас VTOR или нет у вас VTOR, пользуетесь вы начальной таблицей векторов или формируете её в SRAM, делает приложение ремап или нет?
34 минуты назад, Arlleex сказал:поэтому изначально VTOR даже не трогают
Представьте ситуацию, что нет никакого загрузчика. Ваше приложение (пусть это будет Cortex-M) стартануло с 0x0800'0000 со значением VTOR=0. Разве это оптимальная конфигурация?
-
Почему приложение само себе VTOR не устанавливает? Ведь только оно знает где у него таблица векторов.
-
Да нет никакой галки. IAR-у вообще по барабану с какого адреса грузить. Что в icf и соответственно в elf написано, туда и грузит. Оттуда же и запускает. Думаете ему есть разница с 0x0800'0000, 0x0801'0000 или 0x2000'0000 грузить?
-
IAR достаточно умный, чтобы при старте отладки кортексов установить стек и передать управление на ResetHandler самостоятельно на основе icf. Единственное, что должна прошивка сделать самостоятельно, это установить VTOR или сделать ремап, где это надо. Лучше это делать не в загрузчике, а в основной прошивке, потому что прошивка с таблицей векторов может поступать совершенно непредсказуемо.
extern void(*__vector_table[])(); SCB->VTOR = (uint32_t)&__vector_table;
Этот простой код позволяет отлаживать код в какой угодно области памяти, хоть в SRAM. Просто переписав icf.
Если нет VTOR, то там ремап есть. Для отладки в SRAM под условной компиляцией ремап делаю
#ifdef __DEBUG_SRAM__ // REMAP SRAM -> 0x00000000 SYSCFG->CFGR1 = _VAL2FLD(SYSCFG_CFGR1_MEM_MODE,3); #endif
При отладке чем-то менее умным ставлю в стартапе установку стека на основе скрипта линкера
extern void* __reserved_for_stack_end__; __set_MSP((uint32_t)&__reserved_for_stack_end__);
- 1
-
У GCC это встроенные функции с примерно такой обёрткой
float ceil(float __x) { return __builtin_ceilf(__x); }
-
У IAR это встроенная функция.
#define __arm_rsr __iar_builtin_rsr #define __get_PRIMASK() (__arm_rsr("PRIMASK"))
-
Можно компилятор "напугать" каким-нибудь барьером типа ISB.
-
asm volatile("....") не пробовали?
-
13 часов назад, Xenia сказал:
Ну, а что произойдет на линии, если я раньше срока запишу единичку в EGR? Инвертируется ли в этот момент сигнал на выходном пине или нет?
Состояние выхода зависит от значения счётчика на входе компаратора и режима работы, всё. Меняется состояние счётчика по счёту или каким-то внешним воздействием - компаратору по барабану.
-
7 часов назад, Mark16 сказал:
Пытаюсь этот исходник на stm32 перенести .
Не вижу тут требование отсутствия Autoend. Количество данных заранее известно. В моей функции просто заменяете отправку из буфера base()->TXDR = *data++; на отправку сначала одной константы I2C1->TXDR = SSD1306_DATA;, а потом в цикле I2C1->TXDR = fill;.
И вообще, подобные вещи с DMA делают. Но это можно следующим шагом переделать после того как просто заработает. Ну и осциллоглядом контролировать обязательно.
23 минуты назад, AlanDrakes сказал:Заточено под F401 (но I2C периферия в L05x не особенно отличается - проверил по референсу).
При всём уважении, но у F401 реализация I2C старая как у F103 скорее. У L051 новая как в моих функциях.
-
4 часа назад, Mark16 сказал:
ну мне без автостопа как-то надо.
Реально надо или вы себе это придумали и героически боретесь?
-
Только ограничение YYYY на 255 немного портит малину. Если данных мало, то всё просто
Спойлерbool MasterWrite(const uint8_t hw_adr, uint8_t *data, uint8_t len) { base()->CR2 = _VAL2FLD(I2C_CR2_NBYTES,len) | hw_adr | I2C_CR2_AUTOEND | I2C_CR2_START; while(len--) { if(!waitISRBitSet<I2C_ISR_TXIS>()) return false; base()->TXDR = *data++; } return true; } // Ожидание статусных бит с обработкой ошибок и антизацикливанием static inline bool waitISRBitSet() { uint32_t sr; uint32_t timeout_counter=1'000'000; do { sr=base()->ISR; if(sr&( I2C_ISR_NACKF | I2C_ISR_ARLO | I2C_ISR_BERR)) { base()->ICR = I2C_ICR_NACKCF | I2C_ICR_BERRCF | I2C_ICR_ARLOCF; return false; } if(--timeout_counter == 0) return false; } while( !(sr&Bit) ); return true; }
Тут base() понимать как I2C1, I2C2 и т.д. Эта функция член класса позволяет "протащить" указатель на периферию в constexpr контекст. Без плюсов можно просто указателем на I2C_TypeDef обойтись.
template<uint32_t PI2C> class TI2C { static inline auto base() { return (I2C_TypeDef *)PI2C; } }
Если надо передавать много, то чуть сложнее
Спойлерbool MasterWrite(const uint8_t hw_adr, uint8_t *data, uint32_t len) { bool first_part = true; while(len) { if(len<256) { base()->CR2 = _VAL2FLD(I2C_CR2_NBYTES,len) | hw_adr | I2C_CR2_AUTOEND | (first_part?I2C_CR2_START:0); while(len) { if(!waitISRBitSet<I2C_ISR_TXIS>()) return false; base()->TXDR = *data++; len--; } } else { base()->CR2 = _VAL2FLD(I2C_CR2_NBYTES,255) | hw_adr | I2C_CR2_RELOAD | (first_part?I2C_CR2_START:0); first_part=false; for(uint32_t i=255; i--;) { if(!waitISRBitSet<I2C_ISR_TXIS>()) return false; base()->TXDR = *data++; } if(!waitISRBitSet<I2C_ISR_TCR>()) return false; len-=255; } } return true; }
Оба случая можно под шаблон объединить
Спойлерtemplate<typename TLen> static inline bool MasterWrite(const uint8_t hw_adr, uint8_t *data, TLen len) { if constexpr(sizeof(TLen)==1) { base()->CR2 = _VAL2FLD(I2C_CR2_NBYTES,len) | hw_adr | I2C_CR2_AUTOEND | I2C_CR2_START; while(len--) { if(!waitISRBitSet<I2C_ISR_TXIS>()) return false; base()->TXDR = *data++; } } else { bool first_part = true; while(len) { if(len<256) { base()->CR2 = _VAL2FLD(I2C_CR2_NBYTES,len) | hw_adr | I2C_CR2_AUTOEND | (first_part?I2C_CR2_START:0); while(len) { if(!waitISRBitSet<I2C_ISR_TXIS>()) return false; base()->TXDR = *data++; len--; } } else { base()->CR2 = _VAL2FLD(I2C_CR2_NBYTES,255) | hw_adr | I2C_CR2_RELOAD | (first_part?I2C_CR2_START:0); first_part=false; for(uint32_t i=255; i--;) { if(!waitISRBitSet<I2C_ISR_TXIS>()) return false; base()->TXDR = *data++; } if(!waitISRBitSet<I2C_ISR_TCR>()) return false; len-=255; } } } return true; }
-
Данные в памяти размещает линкер. У keil линкером команует так называемый скаттер-файл. Заводите в нём секцию по нужному адресу и размещаете в ней свою константу.
А ещё, пятой точкой чую, что фигню какую-то хотите сделать и вам это не надо 🙂
-
И снова CUBE IDE
в Cредства разработки для МК
Опубликовано · Пожаловаться
Да, что-то 85 просмотрел. Конечно можно.