Перейти к содержанию
    

VladislavS

Свой
  • Постов

    1 242
  • Зарегистрирован

  • Посещение

  • Победитель дней

    9

Весь контент VladislavS


  1. Не нахожу. Код автора статьи (без delay, он тут ни на что не влияет) я бы написал так. using LEDS = PinList<PA_5,PC_5,PC_8,PC_9>; for(;;) LEDS::toggle(); Что для STM32 в процессе компиляции превратиться во что-то такое for(;;) { // PA5 toggle if (GPIOA->ODR & (1<<5)) *((volatile uint16_t *)&GPIOA->BSRR+1) = (1<<5); else GPIOA->BSRR = (1<<5); // PC5,PC8,PC9 toggle GPIOC->BSRR = (((1<<5)|(1<<8)|(1<<9)) << 16) | (~GPIOC->ODR & ((1<<5)|(1<<8)|(1<<9))); } Естественно не в ODR ^=, ибо это неправильно. Ну и из-под ARM Compiler v6 будет как-то так MOVS r0,#0x14 MOVW r2,#0x320 MOVW r3,#0x818 MOVT r0,#0x4800 // R0 = &GPIOA->ODR MOV r12,#0x20 MOVT r2,#0x320 MOVT r3,#0x4800 // R3 = &GPIOC->BSRR main: // if (GPIOA->ODR & (1<<5)) LDR r1,[r0,#0x00] LSLS r1,r1,#26 ITE PL // GPIOA->BSRR = (1<<5) STRPL r12,[r0,#0x04] // *((volatile uint16_t *)&GPIOA->BSRR+1) = (1<<5); STRHMI r12,[r0,#0x06] // GPIOC->BSRR = (((1<<5)|(1<<8)|(1<<9)) << 16) | (~GPIOC->ODR & ((1<<5)|(1<<8)|(1<<9))); LDR r1,[r0,#0x800] AND r1,r1,#0x320 EORS r1,r1,r2 STR r1,[r3,#0x00] B main И никто в лужу не сел, как ни странно.
  2. Просто автор не владеет (или не владел в 2019 году) настоящим кунг-фу. Если закрыть глаза на то что нельзя через ODR ^= PIN мигать светодиодами, то соревноваться ему надо было с кодом for(;;) { GPIOA->ODR ^= (1 << 5); GPIOC->ODR ^= (1 << 5) | (1 << 8) | (1 << 9); delay(); } Вот если бы его класс сам делал подобную оптимизацию (а это на плюсах, в отличи от си возможно), то тогда и можно было засчитывать победу. В общем случае это не так. Макросом невозможно учесть все особенности архитектуры порта контроллера. В сочетании с классами, умеющими объединять/сортировать пины в порты эффект можно получить заметный.
  3. Да, что-то 85 просмотрел. Конечно можно.
  4. Так нельзя из кварца 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 МГц.
  5. Stm32F407 SPI+DMA

    Достаём хрустальный шар. Приём UART через DMA путём опроса могу нафантазировать разными способами: 1. Опрашиваем в главном цикле флаг RXNE. Если он вскочил, то запускаем DMA на передачу данных из DR в память. Ждём окончания передачи опять же опросом флагов DMA. Выключаем DMA. 2. Запускаем DMA на приём байта из DR. В основном цикле опрашиваем флаги DMA на предмет окончания приёма. Выключаем DMA. 3. Можно ещё извращённых методов придумать с опросом флагов UART через DMA... В сочетании с HAL на 2400-9600, пожалуй, взлетит. 🙂 Убираем хрустальный шар.
  6. makefile это своего рода программа. Я бы вызывал make с параметром CONFIG=XXX и в зависимости от значения CONFIG формировал разные ключи компиляции и директорию куда компилировать.
  7. Много ядер - много VTOR-ов. Но я скорее обратил внимание на количество разных областей памяти. Одних только SRAM штук 8 насчитал. И флэшек штуки три. Ну и два ядра тоже не стимулируют шаблонный подход.
  8. Ещё бы понять в каком месте оно Cortex-M....
  9. Не из вредности, а чисто поддержать разговор 🙂 Вот такое интересно отлаживать, а мы тут VTOR не можем решить где прописать.
  10. Даже Cortex-M бывают очень разные.
  11. Это нужно только чтобы Cortex-M стартанул в железе без всяких загрузчиков. У других ядер другие условности. Если вы стартуете из-под загрузчика, то можете сделать как захочет ваша левая пятка. Другое дело, что особого смысла переделывать этот механизм нет, только себя путать.
  12. Я имел в виду не наличие VTOR как такового, а есть ли в приложении телодвижения с ним.
  13. Зачем бедному загрузчику знать есть у вас VTOR или нет у вас VTOR, пользуетесь вы начальной таблицей векторов или формируете её в SRAM, делает приложение ремап или нет? Представьте ситуацию, что нет никакого загрузчика. Ваше приложение (пусть это будет Cortex-M) стартануло с 0x0800'0000 со значением VTOR=0. Разве это оптимальная конфигурация?
  14. Почему приложение само себе VTOR не устанавливает? Ведь только оно знает где у него таблица векторов.
  15. Да нет никакой галки. IAR-у вообще по барабану с какого адреса грузить. Что в icf и соответственно в elf написано, туда и грузит. Оттуда же и запускает. Думаете ему есть разница с 0x0800'0000, 0x0801'0000 или 0x2000'0000 грузить?
  16. 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__);
  17. У GCC это встроенные функции с примерно такой обёрткой float ceil(float __x) { return __builtin_ceilf(__x); }
  18. У IAR это встроенная функция. #define __arm_rsr __iar_builtin_rsr #define __get_PRIMASK() (__arm_rsr("PRIMASK"))
  19. Можно компилятор "напугать" каким-нибудь барьером типа ISB.
  20. Состояние выхода зависит от значения счётчика на входе компаратора и режима работы, всё. Меняется состояние счётчика по счёту или каким-то внешним воздействием - компаратору по барабану.
  21. Не вижу тут требование отсутствия Autoend. Количество данных заранее известно. В моей функции просто заменяете отправку из буфера base()->TXDR = *data++; на отправку сначала одной константы I2C1->TXDR = SSD1306_DATA;, а потом в цикле I2C1->TXDR = fill;. И вообще, подобные вещи с DMA делают. Но это можно следующим шагом переделать после того как просто заработает. Ну и осциллоглядом контролировать обязательно. При всём уважении, но у F401 реализация I2C старая как у F103 скорее. У L051 новая как в моих функциях.
  22. Реально надо или вы себе это придумали и героически боретесь?
  23. Только ограничение YYYY на 255 немного портит малину. Если данных мало, то всё просто Если надо передавать много, то чуть сложнее Оба случая можно под шаблон объединить
×
×
  • Создать...