Jump to content

    

varvar

Участник
  • Content Count

    93
  • Joined

  • Last visited

Community Reputation

0 Обычный

About varvar

  • Rank
    Частый гость

Контакты

  • Сайт
    http://
  • ICQ
    0

Информация

  • Город
    Оулу

Recent Profile Visitors

1462 profile views
  1. scmRtos для медных чайников

    Заработало!!! (с) Кот Матроскин По крайней мере на первый взгляд, одна задача мигает светодиодом, вторая в USB что-то гонит. Помогла замена #pragma weak PendSVC_ISR = PendSV_Handler в os_target.cpp на #pragma weak __exc_pendsv = PendSV_Handler Может я и не прав, и надо было по другому сделать - но таки моргает :) AHTOXA, спасибо огромное!
  2. scmRtos для медных чайников

    почему-то nvic_set_vector_table((uint32_t)&PendSV_Handler, (uint32)VECT_TAB_ADDR+0x38); не помогает - что я не так делаю?
  3. scmRtos для медных чайников

    OS:run() не забыл. Приоритет, наверно, 0xFE? С 0xFF не работает - прерывние теряется. PendSV_Handler не вызывается :(
  4. scmRtos для медных чайников

    добавил в инициализацию nvic_irq_set_priority(NVIC_TIMER3, (0xFEUL << (8-(CORE_PRIORITY_BITS))) & 0xFF); хорошая новость - прерывания перестали затыкаться. Плохая - система по-прежнему не работает, тут: template<> void TProc0::exec() { for (;;) { digitalWrite(PC13,!digitalRead(PC13)); OS::sleep(100); } } ничего не моргает. Если sleep заменить ардуиновским delay, то светодиод моргает
  5. scmRtos для медных чайников

    Да, затыкается прерывание. Но что его может затыкать? Флаг поначалу сбрасывался, потом убрал - никак не влияет. Если бы и влиял - влиял бы в обоих случаях. А приоритет попробую порыть как в STM32duino изменить.
  6. scmRtos для медных чайников

    Для проверки в прерывание могралку ставлю: static void TIM3_Event() { static uint16_t counter=0; counter++; if(counter>100) { digitalWrite(PC13,!digitalRead(PC13)); counter=0; } OS::system_timer_isr(); } Если процесс выглядит так: namespace OS { template<> void TProc0::exec() { for (;;) { delay(100); } } } все моргает, стоит заменить на namespace OS { template<> void TProc0::exec() { for (;;) { OS::sleep(100); } } } моргание прекращается. Какой приоритет - это надо в ардуиновские исходники лезть смотреть, так что пока не знаю.
  7. scmRtos для медных чайников

    Опять туплю. Пытаюсь заставить работать scmRTOS c STM32F103C8 (платка Blue Pill, операционная система должна работать поверх STM32duino) В качестве системного таймера пытаюсь использовать TIMER3: // If the macro value is 0 (the default), the port uses SysTick as a system // timer. It initializes the timer and starts it. The user must make sure that // the address of the timer interrupt handler (SysTick_Handler) is in the right // place at the interrupt vector table. // If the macro value is 1, then the user has to implement (see docs for details): // 1. extern "C" void __init_system_timer(); // 2. void LOCK_SYSTEM_TIMER() / void UNLOCK_SYSTEM_TIMER(); // 3. In the interrupt handler of the custom timer, the user needs to call // OS::system_timer_isr() #if SCMRTOS_USE_CUSTOM_TIMER == 1 static void TIM3_Event() { OS::system_timer_isr(); } extern "C" void __init_system_timer() { RCC_BASE->APB1ENR |= RCC_APB1ENR_TIM3EN; // TIM3 // TIM3 master counter period 1 msec 48MHz main TIMER3->regs.gen->CR1 &= ~TIMER_CR1_CEN; // disabled TIMER3->regs.gen->PSC = 480 - 1; //new clock = 100kHz TIMER3->regs.gen->ARR = 100 - 1; //period = 16usec TIMER3->regs.gen->CR1 |= TIMER_CR1_DIR; //used as downcounter timer_attach_interrupt(TIMER3, TIMER_UPDATE_INTERRUPT, TIM3_Event); TIMER3->regs.gen->CR1 |= TIMER_CR1_CEN; // enable timer TIMER3->regs.gen->DIER |= TIMER_DIER_UIE; //enable interrupt } INLINE void LOCK_SYSTEM_TIMER() { TIMER3->regs.gen->CR1 &= ~TIMER_CR1_CEN; // disable timer } INLINE void UNLOCK_SYSTEM_TIMER() { TIMER3->regs.gen->CR1 |= TIMER_CR1_CEN; // enable timer } #endif после первого же вызова OS::sleep() прерывание больше не наблюдается. Что я опять делаю не так?
  8. scmRtos для медных чайников

    Цитата(dxp @ Apr 17 2016, 16:51) А уверены, что channel не переполняется? Он с большим запасом вроде как, и, кроме того, я проверяю перед записью, есть ли там место get_free_size. Короче, мистика какая-то.
  9. scmRtos для медных чайников

    Цитата(AHTOXA @ Apr 16 2016, 22:57) Насколько я могу сейчас сообразить, это не должно приводить к зависанию. Что-то не выходит каменный цветок - вроде как заработало, через несколько десятков секунд опять виснет. Пока оставил следующее решение - работает без вопросов: CODEstruct sFifo { uint8_t buf[128]; uint8_t tail; uint8_t head; uint8_t MsgSize; }; sFifo usartRXfifo; OS::TEventFlag GpsFlag; extern "C" void USART1_IRQHandler(void) { OS::TISRW ISR; auto status = USART1->SR; auto data = USART1->DR; if (status & USART_FLAG_RXNE) { if((usartRXfifo.head-usartRXfifo.tail)!=128) { usartRXfifo.buf[usartRXfifo.head & 0x7F]=data; usartRXfifo.head++; } if (data=='\r') { usartRXfifo.MsgSize = usartRXfifo.head-usartRXfifo.tail; GpsFlag.signal_isr(); } } } Может, с другими задачами чего поделить не может - в системе еще IMU крутится и данные в CAN выплевывает.
  10. scmRtos для медных чайников

    Цитата(AHTOXA @ Apr 16 2016, 21:48) При использовании сервисов оси в прерываниях обязательно нужно объявлять в обработчике прерывания переменную типа OS::TISRW: Она обеспечивает перепланировку при выходе из зоны видимости. Спасибо огромное - похоже, у меня склероз крепчает - ведь в старых проектах у меня она везде есть!
  11. scmRtos для медных чайников

    Опять туплю. На сей раз процессор STM32F103, компилятор GCC, версия scmRTOS 5, если это имеет значение. Прерывание: КодOS::channel<uint8_t, 32> UsartRxChannel; .... extern "C" void USART1_IRQHandler(void) {   if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)   {     uint8_t c;     c = USART1->DR;     if (UsartRxChannel.get_free_size()>0) UsartRxChannel.push(c);       } } Как только доходит первый раз до UsartRxChannel.push( c ) - все улетает неведомо куда и прерывания больше не случаются. При использовании TEventFlag signal_isr() никаких странностей не наблюдается, но делать свой буфер, когда есть channel как-то не кошерно . Не подскажете, что я делаю не так?
  12. Цитата(Огурцов @ Apr 3 2016, 21:09) почему бы не использовать spi в режиме slave, дёргать nss строчным синхроимпульсом и заполнять через dma ? минус таймер, плюс всё чисто аппаратно Так, собственно и так практически все аппаратно - прерывания только меняют режимы и переключают буфера. Таймер запускается от синхроимпульса, аппаратно при срабатывании запускает DMA, тот пишет в SPI. SPI использованы оба - один для белого, второй для черного. Ваша идея очень хороша, конечно, но программа уже как-то работает, трогать не хочется.
  13. Цитата(Tarbal @ Apr 1 2016, 18:15) Ну что у вас? Получилось? да, получилось. Картинка, как влитая. Ноги, правда, пришлось другие использовать. Программа не особо чищена, но все работает. Нужна инициализация, дальше все прерывания делают. Буфера на страницу нет - слишком мало оперативки у процессора, только 20к. Изображение формируется "на лету", белое и черное. CODE#define FirstLine 30 #define LastLine 255 #define VIDEO_DELAY 820 #define VIDEO_EXRA_DELAY 400 //#define VIDEO_EXRA_DELAY 1000 uint16_t TestFlag=0x3333; uint16_t LineCnt=0; uint16_t LinePointer=0; uint16_t Vsync_delay; union buff_t { uint16_t wData[26]; uint8_t bData[52]; }; buff_t WhiteBuffer1; buff_t WhiteBuffer2; buff_t BlackBuffer1; buff_t BlackBuffer2; void OSD_init(void) { GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_ICInitTypeDef TIM_ICInitStructure; SPI_InitTypeDef SPI_InitStructure; DMA_InitTypeDef DMA_InitStructure; for (int i=0; i<26; i++) { WhiteBuffer1.wData[i]= ~0x4040; BlackBuffer1.wData[i]= ~0x0004; // WhiteBuffer1[i]= ((i+1)<<8) +i +1; // BlackBuffer1[i]= ((i+1)<<8) +i +1; WhiteBuffer2.wData[i]= ~0x0040; BlackBuffer2.wData[i]= ~0x0404; } RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // Enable GPIO Peripheral clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // for Interrupt RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // timer RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // SPI1 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // Enable DMA1 clock // Configure test pin in output push/pull mode GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); // **************************************************** // Vsync pin // **************************************************** // pin as input GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStructure); // interrupt from Vsync NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); EXTI_ClearITPendingBit(EXTI_Line3);// Clear EXTI Line Pending Bit // Connect EXTI GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource3); // Configure EXTI1 to generate an interrupt on falling edge EXTI_InitStructure.EXTI_Line = EXTI_Line3; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); // **************************************************** // Hsync timer // **************************************************** // pin as input GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStructure); // TIM_TimeBaseStructure.TIM_Period = VIDEO_DELAY + VIDEO_EXRA_DELAY; TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // TIM2 PWM2 Mode configuration: Channel1 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; TIM_OCInitStructure.TIM_Pulse = VIDEO_DELAY; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM2, &TIM_OCInitStructure); // TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0; TIM_ICInit(TIM2, &TIM_ICInitStructure); // TIM_SelectOnePulseMode(TIM2, TIM_OPMode_Single); TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2); TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Trigger); // NVIC_EnableIRQ(TIM2_IRQn); // **************************************************** // SPI as black and white video // **************************************************** // SPI1 slave (black) PA6-MISO PA5-SCK GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx ; SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_Mode = SPI_Mode_Slave; SPI_InitStructure.SPI_CRCPolynomial = 10; // !!! mandatory!!! SPI_Init(SPI1, &SPI_InitStructure); // SPI2 master (white) PB15-MISO PB13-SCK GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx ; SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_CRCPolynomial = 10; // !!! mandatory!!! SPI_Init(SPI2, &SPI_InitStructure); // // **************************************************** // DMA // **************************************************** // Configure DMA1 - Channel5== (memory -> SPI) DMA_DeInit(DMA1_Channel3); //Set DMA registers to default values DMA_StructInit(&DMA_InitStructure); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR; //Address of peripheral the DMA must map to DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)BlackBuffer1.wData; //Variable from which data will be transmitted DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = 26; //Buffer size DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel3, &DMA_InitStructure); //Initialize the DMA // // master SPI black DMA_DeInit(DMA1_Channel5); //Set DMA registers to default values DMA_StructInit(&DMA_InitStructure); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR; //Address of peripheral the DMA must map to DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)WhiteBuffer1.wData; //Variable from which data will be transmitted DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = 26; //Buffer size DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &DMA_InitStructure); //Initialize the DMA DMA_Cmd(DMA1_Channel3, ENABLE); // slave TX // //DMA_ITConfig(DMA1_Channel5, DMA_IT_TC, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // **************************************************** // enables // **************************************************** SPI1->CR2 |= 0x02; // TX DMA Enable SPI2->CR2 |= 0x02; } // Vsync interrupt extern "C" void EXTI3_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line3) != RESET) { EXTI_ClearITPendingBit(EXTI_Line3); if (Vsync_delay > 0) { if (--Vsync_delay==0) { SPI2->CR1 |= 0x0040; // master SPI enable SPI1->CR1 |= 0x0040; // slave SPI enable TIM2->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC1DE; // Capture/Compare 1 DMA request and interrupt enable TIM2->CR1 |= 0x0001; // enabled } } LineCnt=0; LinePointer=0; } } // Hsync interrupt // master 5ch DMA SPI2 extern "C" void TIM2_IRQHandler(void) { TIM2->SR &= ~TIM_IT_CC1; // Clear CC1IF if ((LineCnt > FirstLine) && (LineCnt < LastLine)) { TIM2->CR1 &= ~0x0001; // timer disabled //GPIOA->ODR |= 0x04; TIM2->DIER &= ~TIM_DIER_CC1DE; // DMA TIM disabled SPI2->CR2 |= 0x02; // DMA master enabled DMA1_Channel5->CCR |= DMA_CCR5_EN | DMA_CCR5_TCIE; // enable DMA & int LinePointer++; } if (LineCnt == FirstLine) { DMA1_Channel5->CCR |= DMA_CCR5_EN | DMA_CCR5_TCIE; // enable DMA & int DMA1_Channel3->CCR |= DMA_CCR3_EN; } LineCnt++; } // master DMA IRQ extern "C" void DMA1_Channel5_IRQHandler(void) //void DMA1_Channel5_IRQHandler(void) { DMA1->IFCR = DMA_IFCR_CGIF5; // clear int flag DMA1_Channel5->CCR &= ~(DMA_CCR5_EN | DMA_CCR5_TCIE); // disable DMA & interrupt DMA1_Channel3->CCR &= ~DMA_CCR3_EN; SPI2->CR2 &= ~0x02; // DMA master disabled SPI1->SR &= ~SPI_I2S_FLAG_TXE; // Clear slane SPI TX INT SPI1->CR2 |= 0x80; // slave SPI interrupt enable } // slave SPI IRQ extern "C" void SPI1_IRQHandler(void) { SPI1->SR &= ~SPI_I2S_FLAG_TXE; // Clear SPI2 TX INT SPI1->CR2 &= ~0x80; // SPI1 interrupt disable //GPIOA->ODR &= ~0x04; TIM2->SR &= ~ TIM_SR_CC1OF; // compare flag TIM2->EGR &= ~ TIM_EGR_CC1G; // capture/compare 1 generation TIM2->DIER |= TIM_DIER_CC1DE; // DMA TIM enabled SPI2->CR2 &= ~0x02; // DMA SPI1 disabled if (LineCnt != LastLine) { if(LineCnt & 0x01) { DMA1_Channel5->CMAR = (uint32_t)WhiteBuffer1.wData; DMA1_Channel3->CMAR = (uint32_t)BlackBuffer1.wData; } else { DMA1_Channel5->CMAR = (uint32_t)WhiteBuffer2.wData; DMA1_Channel3->CMAR = (uint32_t)BlackBuffer2.wData; } DMA1_Channel5->CCR |= DMA_CCR5_EN; // enable DMA DMA1_Channel3->CCR |= DMA_CCR3_EN; flag |= 0x01; } else flag |= 0x02; TIM2->CR1 |= 0x0001; // timer enabled }
  14. Цитата(jcxz @ Mar 28 2016, 19:35) Всё в сумме: 29704 (ro code) + 20216 (ro data), причём "ro data" - это в основном шрифты и пиктограммы. Так что, если не считать шрифтов, флеши наберётся на <30К. Да и то из них там много лишнего - MassStorage в USB который там болтается, но пока не используется. Если его да всякую отладку повыкидывать - будет наверное чуть больше 20кил. И все это с кубовым USB и HAL? Что компилятор может настолько разный размер генерить - не очень похоже (в моем случае GCC). Без HAL размеры несколько скромнее.
  15. Цитата(Tarbal @ Mar 28 2016, 17:05) Я бы сделал следующим образом: Подключить строчный синхроимпульс ко входу input capture свободно бегущего таймера. В обработчике прерывания input capture прибавил к захваченному значению требуемое время задержки в тиках таймера (h front porch) и записал полученную сумму в compare register для output compare того же таймера. В обработчике прерывания output compare запускать DMA. Если не все понятно -- могу углубиться в детали. Примерно так кода-то делал - на другом процессоре - наложенное изображение дергается, немного, но неприятно. А когда таймер, запускаемый от hsync автоматически запускает DMA безо всяких прерываний - получается абсолютно стабильная картинка. Теоретически и STM32 должно быть то же самое - но пока у меня DMA от таймера запускается - но со временем какая-то беда, что-то не так настраиваю. В примере от ST пишут, что используется CCR1, а что-то непонятное они делают с CCR2 (/Project/STM32xx_StdPeriph_Examples/TIM/OnePulse folder.) В принципе, эта идея вролне совместима с Вашей - вполне можно вместо вызова прерываний запустить DMA, если мой вариант не сработает - попробую Ваш.