Kalyan 0 22 мая, 2018 Опубликовано 22 мая, 2018 (изменено) · Жалоба Добрый день. Управляю ТФТ дисплем напряую через FSMS. Заполняю буфер и через DMA2 M2M передаю его в FSMS. По окончанию передачи получаю прерывание TC, генерирую новый буфер и опять передаю через DMA. Все работает пока не вызываться обработчик прерывания от таймера. Если этот обработчик занимает определенное время то прерывание TC от дма не вызывается никогда, прерывания ошибок от дма тоже не приходят. В регистрах дма наблюдаю след состояния: LISR - флажков прерываний нету CR - EN включен и прерывание TC тоже включено. NDTR - количество байт уменьшилось на 20. то есть дма передало 20 байт FCR - FS (FIFO status) == 5 что означает что FIFO полная. Собственно не понятно почему дма перестает отправлять данные и заполняется его FIFO. Инит дма DMA_InitTypeDef DMA_InitStructure; // Deinitialize DMA Streams DMA_DeInit(DMA2_Stream0); // half_word_cntr*2 - size in byte // memory it is FSMC, DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord, 16b bus // Peripheral it is img frame buff, DMA_PeripheralDataSize_Byte - need for little endianformat on FSMC bus // Configure DMA Initialization Structure DMA_InitStructure.DMA_BufferSize = half_word_cntr*2; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)data_p; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable; DMA_InitStructure.DMA_Priority = DMA_Priority_High; // Configure TX DMA DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToMemory; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)TFT_FSMC_BASE_ADDRESS; DMA_Init(DMA2_Stream0, &DMA_InitStructure); DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_TCIF0); DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0); // Transfer error DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_TEIF0); DMA_ClearITPendingBit(DMA2_Stream0, DMA_FLAG_TEIF0); // Direct mode error DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_DMEIF0); DMA_ClearITPendingBit(DMA2_Stream0, DMA_FLAG_DMEIF0); //FIFO overrun/underrun DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_FEIF0); DMA_ClearITPendingBit(DMA2_Stream0, DMA_FLAG_FEIF0); DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE); DMA_ITConfig(DMA2_Stream0, DMA_IT_TE, ENABLE); DMA_ITConfig(DMA2_Stream0, DMA_IT_DME, ENABLE); DMA_ITConfig(DMA2_Stream0, DMA_IT_FE, ENABLE); и вот обработчик прерывания от таймера из за которого перестает работать дма (исключительно в целях отладки) static inline void timer_1ms_handler(void) { status_led_time_proc(); for (uint8_t i = 0; i < 45; i++) asm("nop"); } приоритеты прерываний #define IRQ_TIMER_PREEM_PRIO 15 #define IRQ_TIMER_SUB_PRIO 0 #define IRQ_TFT_DMA_TC_PREEM_PRIO 0 #define IRQ_TFT_DMA_TC_TIMER_SUB_PRIO 0 Буду благодарен за идеи. Изменено 22 мая, 2018 пользователем IgorKossak [codebox] для длинного кода. [code]-для короткого!!! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 22 мая, 2018 Опубликовано 22 мая, 2018 · Жалоба В прерывании от таймера не вижу очистки бита вызвавшего прерывание. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kalyan 0 22 мая, 2018 Опубликовано 22 мая, 2018 · Жалоба Очистка на уровень выше, в самом хендлере void TIMIMER_IRQ_Handler(void) { if (TIM_GetITStatus(DELAY_TIMER, TIM_IT_Update) != RESET) { timer_1ms_handler(); TIM_ClearITPendingBit(DELAY_TIMER, TIM_IT_Update); } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 22 мая, 2018 Опубликовано 22 мая, 2018 · Жалоба void TIMIMER_IRQ_Handler(void)} Нет такого названия обработчика прерывания. TIM_ClearITPendingBit(DELAY_TIMER, TIM_IT_Update); Лучше сброс флага производить не в конце прерывания, т.к. можно словить повторные вхождения. Или ставить барьер. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться