Jump to content
    

AHTOXA

Свой
  • Posts

    4,000
  • Joined

  • Last visited

  • Days Won

    1

AHTOXA last won the day on July 9 2022

AHTOXA had the most liked content!

Reputation

2 Обычный

4 Followers

About AHTOXA

  • Rank
    фанат дивана
    Гуру
  • Birthday 09/04/1970

Информация

  • Город
    Array

Recent Profile Visitors

14,355 profile views
  1. Я только удалил вызов reqTxDMA(). Оптимизация -O3. Насчёт везения - я сомневаюсь. Но аргументированно сейчас спорить не готов, надо почитать доку.
  2. Вот что у меня gcc выдал: 08003550 <writeTxFIFO(unsigned char*, unsigned long)>: 8003550: b5f8 push {r3, r4, r5, r6, r7, lr} 8003552: 0005 movs r5, r0 8003554: 2900 cmp r1, #0 8003556: d021 beq.n 800359c <writeTxFIFO(unsigned char*, unsigned long)+0x4c> 8003558: b672 cpsid i 800355a: 4c1b ldr r4, [pc, #108] ; (80035c8 <writeTxFIFO(unsigned char*, unsigned long)+0x78>) 800355c: 4a1b ldr r2, [pc, #108] ; (80035cc <writeTxFIFO(unsigned char*, unsigned long)+0x7c>) 800355e: 6823 ldr r3, [r4, #0] 8003560: 6960 ldr r0, [r4, #20] 8003562: 6852 ldr r2, [r2, #4] 8003564: b662 cpsie i 8003566: 181b adds r3, r3, r0 8003568: 1a9b subs r3, r3, r2 800356a: 2b07 cmp r3, #7 800356c: d818 bhi.n 80035a0 <writeTxFIFO(unsigned char*, unsigned long)+0x50> ... Вот как выглядят __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) { __ASM volatile ("cpsie i" : : : "memory"); } __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) { __ASM volatile ("cpsid i" : : : "memory"); } Всё как и должно быть, клоббер "memory" отрабатывает.
  3. Барьеры для того и придуманы, чтобы говорить компилятору "делай что говорят" 🙂 Вот это : :"memory" в конце asm-вставки говорит компилятору, что вставка "портит" память, и поэтому компилятор не должен делать предположений о её сохранности после вставки. То есть, по идее как раз то, что нужно.
  4. Барьерчики попробуйте. На выбор: /** \brief Instruction Synchronization Barrier \details Instruction Synchronization Barrier flushes the pipeline in the processor, so that all instructions following the ISB are fetched from cache or memory, after the instruction has been completed. */ __attribute__((always_inline)) __STATIC_INLINE void __ISB(void) { __ASM volatile ("isb 0xF":::"memory"); } /** \brief Data Synchronization Barrier \details Acts as a special kind of Data Memory Barrier. It completes when all explicit memory accesses before this instruction complete. */ __attribute__((always_inline)) __STATIC_INLINE void __DSB(void) { __ASM volatile ("dsb 0xF":::"memory"); } /** \brief Data Memory Barrier \details Ensures the apparent order of the explicit memory operations before and after the instruction, without ensuring their completion. */ __attribute__((always_inline)) __STATIC_INLINE void __DMB(void) { __ASM volatile ("dmb 0xF":::"memory"); } Или можно без всяких барьеров, просто asm volatile ("":::"memory"); (тут я не уверен)
  5. Чтобы функция вызывалась один раз, можно создать дополнительную constexpr-переменную, и присвоить ей результат вызова функции: static inline constexpr auto version = getVersion(); И затем из всех модулей не вызывать функцию, а использовать переменную version.
  6. Если получилось, то проблема не в связке openocd-gd405, а в ftdi. То есть надо крутить настройки openocd, которые касаются этого ftdi.
  7. А если к SOM подключить STLink? (У меня GD32F105 прошивался через openocd точно тем же скриптом, что я использовал для STM32).
  8. Если опрос энкодера производится чаще, чем он успевает нащёлкать половину 16-битного диапазона, то всё элементарно: uint32_t getEncoder() { static uint16_t oldCnt = 0; // предыдущее значение счётчика таймера static uint32_t encoder = 0; // а это наш 32-битный энкодер uint16_t newCnt = TIM3->CNT; // новое значение счётчика uint16_t deltaPlus = newCnt - oldCnt; // дельта счётчика, если он считал в плюс. uint16_t deltaMinus = oldCnt - newCnt; // дельта счётчика, если он считал в минус if (deltaPlus < deltaMinus) // выбираем из двух дельт меньшую, и применяем. encoder += deltaPlus; else encoder -= deltaMinus; oldCnt = newCnt; return encoder; } И никаких прерываний не нужно.
  9. Есть, в TIM1 и TIM8. В расширенных таймерах. У вас в инициализации вроде бы всё нормально, но надо ножки включить в режим Alternate output.
  10. Перехожу с STM32F105 на GD32F105. Наткнулся на проблемы с USB OTG в роли device. Я использую реализацию USB CDC из библиотеки libopencm3. На STMF105 всё прекрасно работает, а на GD - не хочет. Сначала вообще не работало, в dwc_poll() для пакета OTG_GRXSTSP_PKTSTS_SETUP_COMP считывался номер эндпоинта 4 вместо 0. Ну это я временно подправил, задав жёстко 0. После этого энумерация стала проходить, обмен некоторое время идёт, но после пары сотен символов затыкается передача, в dwc_ep_write_packet() эндпоинт всё время не пустой. Может быть кто-то запускал USB на GD105, и помнит какие-нибудь нюансы?
  11. Добавлю. Там третий параметр - буква 'L' или 'H'. Это активный уровень (низкий/высокий). То есть, уровень, в который переводится ножка по On(). (На деле любое значение кроме 'L' означает высокий активный уровень). И ещё. Не знаю, как в варианте для STM8/IAR, но в моём варианте можно не объявлять экземпляр класса, можно сразу использовать тип: typedef Pin<'B', 12, 'L'> PB12; // PB12, активный уровень НИЗКИЙ PB12::On(); // перевод PB12 в НИЗКИЙ уровень
  12. Такое бывало, когда отключена оптимизация. Попробуйте включить.
  13. Здесь вы весь регистр обнулили, вместо одного бита. Бит обнулять так: GPIOD->PUPDR &= ~(1UL << GPIO_PUPDR_PUPD8_Pos);
×
×
  • Create New...