Jump to content

    

varvar

Участник
  • Content Count

    93
  • Joined

  • Last visited

Community Reputation

0 Обычный

About varvar

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

Контакты

  • Сайт
    Array
  • ICQ
    Array

Информация

  • Город
    Array

Recent Profile Visitors

1507 profile views
  1. Заработало!!! (с) Кот Матроскин По крайней мере на первый взгляд, одна задача мигает светодиодом, вторая в USB что-то гонит. Помогла замена #pragma weak PendSVC_ISR = PendSV_Handler в os_target.cpp на #pragma weak __exc_pendsv = PendSV_Handler Может я и не прав, и надо было по другому сделать - но таки моргает :) AHTOXA, спасибо огромное!
  2. почему-то nvic_set_vector_table((uint32_t)&PendSV_Handler, (uint32)VECT_TAB_ADDR+0x38); не помогает - что я не так делаю?
  3. OS:run() не забыл. Приоритет, наверно, 0xFE? С 0xFF не работает - прерывние теряется. PendSV_Handler не вызывается :(
  4. добавил в инициализацию 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. Да, затыкается прерывание. Но что его может затыкать? Флаг поначалу сбрасывался, потом убрал - никак не влияет. Если бы и влиял - влиял бы в обоих случаях. А приоритет попробую порыть как в STM32duino изменить.
  6. Для проверки в прерывание могралку ставлю: 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 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. Он с большим запасом вроде как, и, кроме того, я проверяю перед записью, есть ли там место get_free_size. Короче, мистика какая-то.
  9. Что-то не выходит каменный цветок - вроде как заработало, через несколько десятков секунд опять виснет. Пока оставил следующее решение - работает без вопросов: struct 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. Спасибо огромное - похоже, у меня склероз крепчает - ведь в старых проектах у меня она везде есть!
  11. Опять туплю. На сей раз процессор 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. Так, собственно и так практически все аппаратно - прерывания только меняют режимы и переключают буфера. Таймер запускается от синхроимпульса, аппаратно при срабатывании запускает DMA, тот пишет в SPI. SPI использованы оба - один для белого, второй для черного. Ваша идея очень хороша, конечно, но программа уже как-то работает, трогать не хочется.
  13. да, получилось. Картинка, как влитая. Ноги, правда, пришлось другие использовать. Программа не особо чищена, но все работает. Нужна инициализация, дальше все прерывания делают. Буфера на страницу нет - слишком мало оперативки у процессора, только 20к. Изображение формируется "на лету", белое и черное. #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. И все это с кубовым USB и HAL? Что компилятор может настолько разный размер генерить - не очень похоже (в моем случае GCC). Без HAL размеры несколько скромнее.
  15. Примерно так кода-то делал - на другом процессоре - наложенное изображение дергается, немного, но неприятно. А когда таймер, запускаемый от hsync автоматически запускает DMA безо всяких прерываний - получается абсолютно стабильная картинка. Теоретически и STM32 должно быть то же самое - но пока у меня DMA от таймера запускается - но со временем какая-то беда, что-то не так настраиваю. В примере от ST пишут, что используется CCR1, а что-то непонятное они делают с CCR2 (/Project/STM32xx_StdPeriph_Examples/TIM/OnePulse folder.) В принципе, эта идея вролне совместима с Вашей - вполне можно вместо вызова прерываний запустить DMA, если мой вариант не сработает - попробую Ваш.