|
CANFestival и STM32F103, timer.c |
|
|
|
Jun 10 2011, 09:37
|
Группа: Участник
Сообщений: 13
Регистрация: 5-04-11
Пользователь №: 64 157

|
Здраствуйте! Так как я с МК и КЭНом(CANFestival) дело не имел, пытаюсь перепесать фаил timer.c от AVR(./drivers/AVR/timer_AVR.c) для STM32. Застрял на 2 defines(для начало  ): CODE // Define the timer registers #define TimerAlarm OCR3B #define TimerCounter TCNT3 какие регистры соответствуют на STM32F103?
|
|
|
|
|
Jul 18 2011, 09:42
|
Группа: Участник
Сообщений: 13
Регистрация: 5-04-11
Пользователь №: 64 157

|
Помучившись с даташит от разных МК я пришёл к такому решению проблемы: CODE NVIC_InitTypeDef NVIC_InitStructure; TIM_TimeBaseInitTypeDef TIM_InitStructure; #define TIM2_IRQChannel ((u8)0x1C) /* TIM2 global Interrupt (alte Bibliothek)*/
#define TimerAlarm TIM2->CCMR1 #define TimerCounter TIM_GetCounter(TIM2)
#define TIMER_INTERRUPT_LEVEL 1
void timer_can_irq_handler(void);
/************************** Modul variables **********************************/ // Store the last timer value to calculate the elapsed time static TIMEVAL last_time_set = TIMEVAL_MAX;
void initTimer(void) /****************************************************************************** Initializes the timer, turn on the interrupt and put the interrupt time to zero INPUT void OUTPUT void ******************************************************************************/ { //TODO: check RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //TIM2 mit einem Takt versorgen
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQChannel; //Interrupt Kanal auswählen. Hier TIM2 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; //Interrupt Priorität festlegen NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //Interrupt Unterpriorität festlegen NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //Aktivieren des Interrupts NVIC_Init(&NVIC_InitStructure); //Konfiguration übernehmen
TIM_InitStructure.TIM_Prescaler = 2000; // Clock Teiler 72MHz / 2000 = 36kHz TIM_InitStructure.TIM_Period = 36000; // Anzahl Durchläufe bis Überlauf Interrupt 36kHz / 36000 = 1s TIM_InitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //Keine Clock Division TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up; //Hochzählender Timer Modus TIM_TimeBaseInit(TIM2, &TIM_InitStructure); //Konfiguration Übernehmen TIM_Cmd(TIM2, ENABLE); //Timer Aktivieren
TIM_ClearFlag(TIM2, TIM_FLAG_Update); //Interrupt Flag von TIM2 löschen TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //Interrupt für TIM2 Aktivieren TIM_ClearFlag(TIM2, TIM_FLAG_Update); //Interrupt Flag für TIM2 Löschen //End check
}
void setTimer(TIMEVAL value) /****************************************************************************** Set the timer for the next alarm. INPUT value TIMEVAL (unsigned long) OUTPUT void ******************************************************************************/ { TimerAlarm += value; // Add the desired time to timer interrupt time }
TIMEVAL getElapsedTime(void) /****************************************************************************** Return the elapsed time to tell the stack how much time is spent since last call. INPUT void OUTPUT value TIMEVAL (unsigned long) the elapsed time ******************************************************************************/ { unsigned int timer = TimerCounter; // Copy the value of the running timer // Calculate the time difference return timer > last_time_set ? timer - last_time_set : last_time_set - timer; }
//*---------------------------------------------------------------------------- //* Function Name : timer_can_irq_handler //* Object : C handler interrupt function by the interrupts //* assembling routine //* Output Parameters : calls TimeDispatch //*---------------------------------------------------------------------------- //void timer_can_irq_handler(void) void TIM2_IRQHandler(void) { last_time_set = TimerCounter; TimeDispatch(); // Call the time handler of the stack to adapt the elapsed time }
правильно ли выбраны регистры? Какие параметры для TIM_InitStructure, чтобы Цитата graphScheduler can handle short clock value ranges limitation found on some µC. As an example, value range for a 16bit clock counter with 4µs tick is crossed within 0.26 seconds... Long alarms must be segmented. Chronogram illustrate a long alarm (A) and a short periodic alarm (  , with a A value > clock range > B value. Values t0...t8 are successive setTimer call parameter values. t1 illustrates an intermediate call to TimeDispatch, caused by a delay longer than clock range. Because of long alarm segmentation, at the end of t1, TimeDispatch call will not trig any alarm callback.
|
|
|
|
|
Oct 12 2011, 08:33
|
Группа: Участник
Сообщений: 13
Регистрация: 5-04-11
Пользователь №: 64 157

|
CiA 402 пока проблема с прерываниями(interrupts): TIM2 и Heartbeat с 50ms съедают все ресурсы. а может быть собака в другом месте зарыта?
|
|
|
|
|
Oct 13 2011, 18:03
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(Minti @ Oct 12 2011, 12:33)  CiA 402 пока проблема с прерываниями(interrupts): TIM2 и Heartbeat с 50ms съедают все ресурсы. а может быть собака в другом месте зарыта? Конечно в другом! Для сравнения в моей реализации CANopen на STM32F1xx (тактовая 24МГц) загрузка не превышает 20% (внутри стоит RTOS). В среднем же загрузка около 2..3% в типовых задачах (профиль 401), если по уму настроить PDOсы самого узла.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Oct 13 2011, 20:10
|
Группа: Участник
Сообщений: 13
Регистрация: 5-04-11
Пользователь №: 64 157

|
такое ощущение, что таймер перебевает "инфинити луп" и второе при этом теряет данные. Forger, какой тик у вашего таймера?
|
|
|
|
|
Oct 13 2011, 21:45
|

Профессионал
    
Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831

|
Цитата(Minti @ Oct 14 2011, 00:10)  Forger, какой тик у вашего таймера? У RTOS 1 мс, для CANopen тоже (потом будет 0,1 мс). Таймер CANopen пока используется лишь для Hearbeat Consumer/Producer и светодиодов (по стандарту). Все остальное - по событию. 0,1 мс нужен для правильной отработки Inhibit timer (PDO) и EMCY объектов. Поэтому пока что для RTOS и CANopen используется один и тот же таймер.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Oct 14 2011, 06:52
|
Профессионал
    
Группа: Свой
Сообщений: 1 817
Регистрация: 14-02-07
Из: наших, которые работают за бугром
Пользователь №: 25 368

|
Цитата Heartbeat с 50ms Чего-то очень часто. Вам действительно необходимо определение потери узла так быстро? Обычно это время от 0,5с и выше. У меня на STM32F TIM2 крутится с шагом 8µS, а как системный таймер я настроил SysTick на 1мс. У вас помоему TIM2 неправильно настроен. CANFestival считает, что он должен увеличиваться каждые 8µS, и прерывание должно по сравнению генерироваться, а у вас немного другое получается. Я уже выкладывал свои исходники на порт - посмотрите, как там таймер настроен. http://permalink.gmane.org/gmane.comp.embe...canfestival/507ПС. Хммм, только дров таймера там как-раз и нету. Вечером тогда выложу. Цитата 0,1 мс нужен для правильной отработки Inhibit timer (PDO) и EMCY объектов. Кстати, в CanFestival мне нравится как это дело реализовано. Благодаря 8µS шагу - все эти дела обрабатываются очень четко.
|
|
|
|
|
Oct 14 2011, 11:20
|
Группа: Участник
Сообщений: 13
Регистрация: 5-04-11
Пользователь №: 64 157

|
Цитата(syoma @ Oct 14 2011, 08:52)  Чего-то очень часто. Вам действительно необходимо определение потери узла так быстро? Обычно это время от 0,5с и выше. У меня на STM32F TIM2 крутится с шагом 8µS настроил Heartbeat на 0,5с. ТIM2 настроеть с шагом меньше чем 1ms не получается, interrupt USART2 теряется. Цитата(syoma @ Oct 14 2011, 08:52)  , а как системный таймер я настроил SysTick на 1мс. У вас помоему TIM2 неправильно настроен. CANFestival считает, что он должен увеличиваться каждые 8µS, и прерывание должно по сравнению генерироваться, а у вас немного другое получается. А вот тут пожалуйста поподробнее. Зачем SysTick настраевать(если что извените за нубский вопрос)? Что неправельно в настроиках TIM2? Цитата(syoma @ Oct 14 2011, 08:52)  ПС. Хммм, только дров таймера там как-раз и нету. Вечером тогда выложу. Буден очень благодарен! RTOS нету.
|
|
|
|
|
Oct 15 2011, 17:01
|
Профессионал
    
Группа: Свой
Сообщений: 1 817
Регистрация: 14-02-07
Из: наших, которые работают за бугром
Пользователь №: 25 368

|
Вот мои текущие реализации драйверов таймера и CAN- контроллера для CANfestival и STM32F105. F103 должен быть вроде такой же. В качестве библиотеки использовалась STM32F10x Standard Peripherals Library версия 3.5.0 с сайта ST. Цитата Зачем SysTick настраевать(если что извените за нубский вопрос)? Systick я настроил на прерывание каждые 1мс чисто для своих нужд - например каждую мс входы опрашивать и т.д. в Canfestival он не учавствует. Цитата А почему не 1мкс, не 100мкс, а именно 8? Зачем там такая точность? Я это дело не разрабатывал, а использовал как есть. Поэтому не знаю. Оно так работает, а мне больше и не надо.
|
|
|
|
|
Oct 18 2011, 12:30
|
Группа: Участник
Сообщений: 13
Регистрация: 5-04-11
Пользователь №: 64 157

|
syoma, большое спасибо за исходный текст! Есть ещё парочку вопросов Ваша текущая реализация драйверов таймера: CODE ... /* Compute the prescaler value APB1 divided by two, but this is fixed by timer itself */ PrescalerValue = (uint16_t) ((SystemCoreClock) / 125000) - 1; /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 65535; TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* Prescaler configuration */ TIM_PrescalerConfig(TIM2, PrescalerValue, TIM_PSCReloadMode_Immediate); ...
Какое значение у SystemCoreClock? 72MHz? формула вычисления шага: Tick := SystemCoreClock / (TIM_Prescaler+1) / TIM_Period Как я понял TIM_Period у вас в формулу не берется. Это из-за "Output Compare Timing Mode configuration"? Цитата Systick я настроил на прерывание каждые 1мс чисто для своих нужд - например каждую мс входы опрашивать и т.д. в Canfestival он не учавствует. Тогда где у вас в программе этот блок стоит: if (canReceive(&m)) canDispatch(Obj_Data, &m); в "инфинити луп"? Запустил МК с вашими реализациами. USART2 interrupt работает стабильно, а вот функция ConfigureSlaveNode(тут находится CanFestival-3\examples\DS401_Master\TestMasterMicroMod.c) теряется. Обнаружил вот такой феномен: ставлю ТIМ2 на большой шаг ~2с, выполняю ConfigureSlaveNode(доходит до конца), ставлю ТIМ2 шаг обратно и колёсики начинают крутится. Можно ли решить эту проблему по другому?
|
|
|
|
|
Oct 18 2011, 15:13
|
Профессионал
    
Группа: Свой
Сообщений: 1 817
Регистрация: 14-02-07
Из: наших, которые работают за бугром
Пользователь №: 25 368

|
SystemCoreClock - 72MHz. Мне нужно было задать делитель так, чтобы таймер увеличивался каждые 8µs. Это получается если Prescaler=575. TIM_Period в этом случае нафиг не нужен. TIM_Period нужен только чтобы таймер проходил полный круг перед сбросом в 0. Вы возможно путаете - каждые 8µS таймер должен увеличиваться, а не переполняться. Короче правильность работы этого таймера проверяется легко - запускаете heartbeat generation например на 2с - и наблюдаете в любом CANанализаторе по таймстампингу насколько точно приходят сообщения. Если таймер настроен правильно, то должно быть 2+-0,001с
canDispatch стоит в основном инфинити луп, но не в функции, которая раз в 1мс вызывается. Это изза того, что за 1мс может много сообщений прийти и все их нужно успеть обработать. Если бы canDispatch только раз в мс вызывался, то сообщения терялись бы. ConfigureSlaveNode я только сегодня тестить буду. Не ожидаю никаких проблем. Что у Вас теряется?
|
|
|
|
|
Oct 18 2011, 19:06
|
Группа: Участник
Сообщений: 13
Регистрация: 5-04-11
Пользователь №: 64 157

|
Цитата(syoma @ Oct 18 2011, 17:13)  canDispatch стоит в основном инфинити луп, но не в функции, которая раз в 1мс вызывается. Идею с SysTick'ом я теперь понял, спасибо. Вкручу для USART'а. Цитата(syoma @ Oct 18 2011, 17:13)  ConfigureSlaveNode я только сегодня тестить буду. Не ожидаю никаких проблем. Что у Вас теряется? Программирую в Atollic TrueSTUDIO®/STM32 Lite, ставил в ConfigureSlaveNode breakpoints в case 1 и case 3, последний не достигался. Потом увеличил ТIM2 Prescaler, примерно до case 16 дошёл. И так я Prescaler увеличивал пока полностью функтию не пробежал. На днях вкручу SysTick, может этот феномен пропадёт. PS: есть ещё один вопросик. Есть ли разниза между ними: TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; TIM_PrescalerConfig(TIM2, PrescalerValue, TIM_PSCReloadMode_Immediate);
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|