Jump to content

    

Brain13

Участник
  • Content Count

    65
  • Joined

  • Last visited

Community Reputation

0 Обычный

About Brain13

  • Rank
    Участник
  1. Нет, запрещенное походу не разбудит... http://infocenter.arm.com/help/index.jsp?t...a/BABGGICD.html То есть разбудит процессор только разрешенное(я так понимаю в NVIC) прерывание с более выским приоритетом.
  2. Тема начинается со слов "Предположим, что программа должна дождаться получения байта по UART" В системе присутствует множество источников прерываний: SPI, UART, SysTick, Таймеры, Внешние прерывания и прочее. Но все это к решению задачи не относится. Если это так важно, то я делал код для бутлоадера, который при переполнении буфера ждет пока хотябы один байт будет отправлен в UART и тогда в буфере появится место для добавления еще одного байта. Та же самая песня с чтением байта из пустого буфера. И да, в момент когда мы работаем с UARTом другая периферия пока не используется и у МК другой работы нет. Только обьясните как это знание поможет Вам решить проблему с WFI? Использовать таймер или любую другую периферию для ожидания байта по UART - вот это решение через анус. Понятое дело, что в конечом итоге процессор проснется, но это костыль и надежда на "авось его что-нибудь другое разбудит".
  3. Я делаю реальную систему, но если я хочу дождаться прервания по UART причем тут прерывание по таймеру? Часто бывают случаи когда нужно дождаться какого либо события и только потом действовать. А while(xxx) {} не сильно хороший вариант, ибо потребление. Вот именно, что не кирпич, ведь мы запрещаем не само прерывание, а вызов его обработчика. При появлении запроса на прерывание процессор проснется, а вызов обработчика произойдет после __enable_irq();. Я проверил, такой код работает и не виснет(STM32F3DISCOVERY): int main(int argc, char* argv[]) { RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); GPIO_InitTypeDef gpio; gpio.GPIO_Mode = GPIO_Mode_OUT; gpio.GPIO_OType = GPIO_OType_PP; gpio.GPIO_Pin = GPIO_Pin_9; gpio.GPIO_PuPd = GPIO_PuPd_NOPULL; gpio.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOE, &gpio); GPIO_ResetBits(GPIOE, GPIO_Pin_9); gpio.GPIO_Mode = GPIO_Mode_IN; gpio.GPIO_OType = GPIO_OType_PP; gpio.GPIO_Pin = GPIO_Pin_0; gpio.GPIO_PuPd = GPIO_PuPd_NOPULL; gpio.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(GPIOA, &gpio); EXTI_InitTypeDef exti; exti.EXTI_Line = EXTI_Line0; exti.EXTI_Mode = EXTI_Mode_Interrupt; exti.EXTI_Trigger = EXTI_Trigger_Rising; exti.EXTI_LineCmd = ENABLE; EXTI_Init(&exti); NVIC_InitTypeDef nvic; nvic.NVIC_IRQChannel = EXTI0_IRQn; nvic.NVIC_IRQChannelPreemptionPriority = 0x0F; nvic.NVIC_IRQChannelSubPriority = 0x0F; nvic.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvic); // Infinite loop while (1) { for(;;) { __disable_irq(); if(flag) break; __WFI(); __enable_irq(); __NOP(); __NOP(); __NOP(); } __enable_irq(); if(GPIO_ReadOutputData(GPIOE) & GPIO_Pin_9) { GPIO_ResetBits(GPIOE, GPIO_Pin_9); } else { GPIO_SetBits(GPIOE, GPIO_Pin_9); } flag = 0; } } void EXTI0_IRQHandler(void) { if((EXTI_GetITStatus(EXTI_Line0) != RESET)) { flag = 1; EXTI_ClearITPendingBit(EXTI_Line0); } }
  4. Кажется, я нашел ответ: http://infocenter.arm.com/help/index.jsp?t...a/BABGGICD.html Т. е. код должен быть примерно таким: while(1) { __disable_irq(); if(Uart.DataAvailable()) { break; } __WFI(); __enable_irq(); __NOP(); } Соотетственно если байт придет перед инструкией WFI, то произойдет запрос прерывания, но обработчик не вызовется(прерывания запрещены), потом вызовется WFI, но он не усыпит прессор так как есть запрос на прерывание, потом исполнится enable_irq, после которого(в течение 0-2 инструкций) вызовется обработчик прерывания. Теперь осталось это проверить. Во-первых, это - костыль. Во-вторых, еще не хватает мне таймер на это тратить, они же не бесплатно в МК даются - это ценный ресурс.
  5. Не уверен, что понял Ваш вопрос, но постараюсь расписать поподробнее. В крайнем случае имеем код типа __disable_irq(); // тут проверки на наличие принятого байта __enable_irq(); __WFI(); Если проверка покажет, что байт еще не пришел, то исполнение дойдет до строчки __enable_irq. Если искомый байт придет вот в этот момент - исполненится прерывание. После возвращения из прерывания исполнится инструкция WFI, которая будет ожидать нового прерывания, соответственно ядро не проснется. (понятное дело, других прерываний в примере нет) Вопрос: как дождаться прерывания с использованием WFI и гарантированно проснуться?
  6. Здравствуйте! Я тут задумался о такой потенциальной проблеме при использовании инструкции WFI: Предположим, что программа должна дождаться получения байта по UART, логичным был бы код while(!Uart.DataAvailable()) { __WFI(); } // тут обработка данных Но проблема в том что искомый байт может придти между Uart.DataAvailable() и __WFI(), вызовется обработчик прерывания, после которого вызовется __WFI() и МК больше никогда не проснется. Вставка критических секций: __disable_irq(); // тут что-то __enable_irq(); __WFI(); не спасет ситуацию, так как между __enable_irq(); и __WFI(); может проскочить нужное прерывание(а может не проскочить). Поиски вывели меня на вот эту англоязычную тему: http://community.arm.com/message/8927 и доку http://infocenter.arm.com/help/index.jsp?t...a/BIHBFEIB.html Но я так и не понял, что есть решение проблемы. Так есть ли в Cortex-M гарантированный способ проснуться после WFI?
  7. Да, спасибо, видел такое решение. Версию компилятора менять не собираюсь. Если надо, буду пользоваться одной версией хоть всю жизнь устройства. Выигрыш около 700-800байт, при размере флеша 8к. У меня и так все под завязку, так что стоит. Кстати, а есть в природе простой и надежный алгоритм шифрования для 8 битников? что-то подобное xtea, но без 32 битных чисел?
  8. Здравствуйте. Имеется проект на stm8 на iar'е. Устройство имеет шифрованный протокол связи с верхним уровнем. Устройство должно иметь возможность обновлять прошивку через бутлоадер. Дело в том, что шифрование занимают много места и используют операции с 32 битными числами. Компилятор, понятное дело подтянул все необходимые функции для работы с такими числами. Я собираюсь сделать библиотеку с функциями шифрования и разместить ее в области бутлоадера. Но у меня появился ряд вопросов: 1) Как мне разместить библиотеку в области бутлоадера? 2) Как сделать так, чтобы и основная программа и бутлдоадер могли обращаться к функциям одной и той же библиотеки ? 3) Я правильно понимаю, что функции для работы с 32 битными числами уже будут в библиотеке? 4) Если я буду использовать операции с 32 битными числами в основной программе, то будут использоваться функции из библиотеки или подтянутся новые экземпляры тех же функций?
  9. stm32f4, EXTI, PD6

    Тактирование порта подано?
  10. С одним АЦП то же самое(между периодами 300 отсчетов). Но если включить DMA FIFO работает нормально (75 отсчетов). Без DMA FIFO, но с ADC_EOCOnEachRegularChannelCmd(ADC1, ENABLE); тоже нормально. С DMA FIFO и EOC одновременно - тоже норм. С двумя/тремя ни с FIFO, ни без него не пашет.
  11. Есть некоторые наблюдения: Если закомментировать строку ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE); Ничего не изменяется, все равно период между фронтами 300 отсчетов на 32кгц. Попробовал запустить 2 ацп в ADC_DMAAccessMode_2. DMA пересылает по 4 байта(DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;) И все равно период между фронтами 300 отсчетов на 32кгц! O_o. Такое ощущение, что параметры АЦП не влияют ни на что. Но, при увеличении делителя частоты АЦП в два раза(ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;) период между фронтами уменьшается почти вдвое до 148 отсчетов. Мне кажется, что проблема с триггером DMA. Но вот где она не знаю.
  12. Частота семплирования 9.6 Мгц - много. Да, это triple interleaved mode. По идее максимум 2.4 на 1 АЦП, 7.2 на все три. А у меня 9.6, соответственно что-то не так. А что нормального в дребезге результатов АЦП? Первый раз слышу, что дергание результатов от нуля до максимума это нормально. Пара единиц - нормально, а у меня - фигня какая-то.
  13. Подобные темы уже поднимались, но уже приведенные исходники у меня так и не заработали стабильно. Плата STM32F4Discovery. Имеется код: void init() { ADC_InitTypeDef ADC_InitStructure; DMA_InitTypeDef DMA_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_ADC3, ENABLE); /* Configure ADC Channel 12 pin as analog input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOC, &GPIO_InitStructure); DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC_CDR_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = adc_buffer_count; 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_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream0, &DMA_InitStructure); /* DMA2_Stream0 enable */ DMA_Cmd(DMA2_Stream0, ENABLE); /******************************************************************************/ /* ADCs configuration: triple interleaved with 5cycles delay to reach 6Msps */ /******************************************************************************/ /* ADC Common configuration *************************************************/ ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_Interl; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInit(&ADC_CommonInitStructure); /* ADC1 regular channel 12 configuration ************************************/ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_ExternalTrigConv = 0; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC1, &ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_3Cycles); /* Enable ADC1 DMA */ ADC_DMACmd(ADC1, ENABLE); /* ADC2 regular channel 12 configuration ************************************/ ADC_Init(ADC2, &ADC_InitStructure); /* ADC2 regular channel12 configuration */ ADC_RegularChannelConfig(ADC2, ADC_Channel_11, 1, ADC_SampleTime_3Cycles); /* ADC3 regular channel 12 configuration ************************************/ ADC_Init(ADC3, &ADC_InitStructure); /* ADC3 regular channel12 configuration *************************************/ ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 1, ADC_SampleTime_3Cycles); /* Enable DMA request after last transfer (multi-ADC mode) ******************/ ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE); /* Enable ADC1 **************************************************************/ ADC_Cmd(ADC1, ENABLE); /* Enable ADC2 **************************************************************/ ADC_Cmd(ADC2, ENABLE); /* Enable ADC3 **************************************************************/ ADC_Cmd(ADC3, ENABLE); /* Start ADC1 Software Conversion */ ADC_SoftwareStartConv(ADC1); } int main() { for(int i=0;i<adc_buffer_count;i++) { ADCConvertedValue[i] = 0; } init(); delay(10000000); for(;;); return 0; } Изменения относительно примера в комплекте STMF4 Periferial Lib: DMA в режиме normal, режим доступап dma 1. Частоты настроены: SYSCLK 144 МГц, APB2 72 МГц, APB1 36 МГц. На PC1 подаю меандр 32кГц. Ставлю брейкпоинт на строке "for(;;);", массив ADCConvertedValue заполнен значениями. Но вот в чем странность: Между период меандра судя по отсчетам АЦП - ровно 300 отсчетов. То есть: Частота семплирования 300*32000 = 9,6 МГц. Что многовато. Есть и вторая странность. Такое ощущение, что отсчеты складываются в неправильном порядке, привожу кусок массива(повторяющиеся значения убрал): переменная тип значение ADCConvertedValue[144] short 4 ADCConvertedValue[145] short 3 ADCConvertedValue[146] short 4 ADCConvertedValue[147] short 4095 ADCConvertedValue[148] short 4095 ADCConvertedValue[149] short 4 ADCConvertedValue[150] short 4095 ADCConvertedValue[151] short 4095 ADCConvertedValue[152] short 4095 ADCConvertedValue[153] short 4095 ADCConvertedValue[154] short 4095 ... ADCConvertedValue[292] short 4095 ADCConvertedValue[293] short 4095 ADCConvertedValue[294] short 4095 ADCConvertedValue[295] short 4095 ADCConvertedValue[296] short 10 ADCConvertedValue[297] short 4095 ADCConvertedValue[298] short 4095 ADCConvertedValue[299] short 16 ADCConvertedValue[300] short 4 ADCConvertedValue[301] short 12 ADCConvertedValue[302] short 16 ADCConvertedValue[303] short 2 ADCConvertedValue[304] short 3 ADCConvertedValue[305] short 3 ... ADCConvertedValue[300] short 4 ADCConvertedValue[301] short 12 ADCConvertedValue[302] short 16 ADCConvertedValue[303] short 2 ADCConvertedValue[304] short 3 ADCConvertedValue[305] short 3 Видно дергание сигнала при переходе из единицы в ноль и обратно. Иногда получается без дергания. Мозг уже кипит, не могу найти ошибку. Подскажите в чем дело.
  14. Абстрактный метод = виртуальный метод без реализации. Хммм... а я думал что, для вызова виртуальных методов необходимо вначале узнать реальный тип объекта, а лишь затем вызвать его переопределенный метод. Я считал, что определением реального типа объекта и занимается rtti. Походу я чего-то не понимаю. Вот в вике написано о виртуальных методах: Так получается что инфа о типе не используется, а используется таблица указателей на виртуальные функции (vtbl)? А что тогда делает rtti, и зачем нужен dynamic_cast<>? Можно примерчик?
  15. Чтобы не плодить новые темы пишу здесь. Здравствуйте. Решил попробовать использовать полиморфизм в МК. написал такой код: // IOutDevice.h class IOutDevice { public: virtual void On(void) = 0; virtual void Off(void) = 0; }; // PC0LED.h class PC0_LED : public IOutDevice { public: PC0_LED(); virtual void On(void); virtual void Off(void); }; // PC0LED.cpp PC0_LED::PC0_LED() { } void PC0_LED::On() { GPIO_PinOutSet(gpioPortC, 0); } void PC0_LED::Off() { GPIO_PinOutClear(gpioPortC, 0); } // PC1LED.h class PC1_LED : public IOutDevice { public: PC1_LED(); virtual void On(void); virtual void Off(void); }; // PC1LED.cpp PC1_LED::PC1_LED() { } void PC1_LED::On() { GPIO_PinOutSet(gpioPortC, 1); } void PC1_LED::Off() { GPIO_PinOutClear(gpioPortC, 1); } // main.cpp int main(void) { init(); PC0_LED pc0; PC1_LED pc1; IOutDevice*dev[2]; dev[0] = &pc0; dev[1] = &pc1; while (1) { dev[0]->On(); dev[1]->On(); delay(2000000); dev[0]->Off(); dev[1]->Off(); delay(2000000); } } // Интерфейс IOutDevice, и 2 класса его реализующих для PC0 и PC1. Все время думал, что для абстрактных методов необходим rtti. И компилировал без опции -fno-rtti (размер программы 10456). В этом топике увидел, что работает и с опцией -fno-rtti, попробовал - раотает (размер программы 2228). Вопрос: почему код успешно компилируется с опцией -fno-rtti без ошибок? Разве для использования абстрактных методов не нужен rtti?