|
Microbalze MCS и программируемый таймер |
|
|
|
Apr 4 2014, 09:31
|
Группа: Новичок
Сообщений: 6
Регистрация: 3-02-10
Пользователь №: 55 267

|
Здравствуйте. Пытаюсь освоить работу с Programmable Interval Timer в Microbalze Micro Controller System (v1.0). Написал программу суть которой сводится к обработке прерывания (нажатие кнопки на плате) и вывод на шину IO Bus подряд двух разных значений. Программа работает и я с помощью CHipScope Analyzer вижу что между импульсами записи 7 тактов. Далее хочу вставить задержку между обращениями на шину. За основу взял кусок кода из примера http://www.fpgadeveloper.com/2008/10/micro...lcd-driver.html, переделал его перед библиотеку XIOModule и вставляю в свой код обращение к функции delay_us. Тут для меня начинаются непонятки: расстояние между испульсами увеличивается, но связать его со значением которое отправляю в функцию не получается. Отправлял 1 и 10, расстояние между импульсами в обоих случаях равно 273 тактам. При генерации ядра Microbalze MCS для Programmable Interval Timer 1 выбрал такие настойки: Use Timer - вкл., Number of Bits for Timer - 32, Shall Counter Value Be Readable - вкл., Define Prescaler - None, Generate Interrupt - выкл. Далее привожу код: Код #include <stdio.h> #include "platform.h" #include "XIOModule.h"
#define IOBUS_write_fifo (*(volatile u32 *) 0xC0000000)
XIOModule DelayTimer;
void delay_us(u32 time);
void myISR( void ) { IOBUS_write_fifo = 0xA; delay_us(1); IOBUS_write_fifo = 0xB; }
int main() { init_platform();
u32 uGpi0; //external interrupt u8 uIntrId = 16;//XPAR_IOMODULE_0_SYSTEM_INTC_INTERRUPT_0_INTR;
XIOModule NfdsIOMdule;
XIOModule_Initialize(&NfdsIOMdule, XPAR_IOMODULE_0_DEVICE_ID); XIOModule_Start(&NfdsIOMdule);
// Initialize the Timer u32 status; status = XIOModule_Timer_Initialize(&DelayTimer, XPAR_IOMODULE_0_DEVICE_ID); if (status != XST_SUCCESS){ xil_printf("Timer failed to initialize\r\n"); return XST_FAILURE; }
XIOModule_Timer_SetOptions(&DelayTimer, 0, XTC_INT_MODE_OPTION);
microblaze_register_handler(XIOModule_DeviceInterruptHandler, XPAR_IOMODULE_0_DEVICE_ID); XIOModule_Connect(&NfdsIOMdule, uIntrId, myISR, XPAR_IOMODULE_0_DEVICE_ID); XIOModule_Enable(&NfdsIOMdule, uIntrId);
microblaze_enable_interrupts();
while(1) { uGpi0 = XIOModule_DiscreteRead(&NfdsIOMdule, 1); //read gpio (Slide Switches) XIOModule_DiscreteWrite(&NfdsIOMdule, 1, uGpi0); //write gpio (Discrete LEDs) }
cleanup_platform();
return 0; }
void delay_us(u32 time) { XIOModule_SetResetValue(&DelayTimer, 0, time); XIOModule_Timer_Start(&DelayTimer, 0); while(!(XIOModule_IsExpired(&DelayTimer, 0))){} XIOModule_Timer_Stop(&DelayTimer, 0); } В моем понимании обращение delay_us(1) должно давать задержку в 1 такт или я не прав?
|
|
|
|
|
 |
Ответов
(1 - 5)
|
Apr 5 2014, 15:00
|
Группа: Новичок
Сообщений: 6
Регистрация: 3-02-10
Пользователь №: 55 267

|
Golikov A, dm.pogrebnoy спасибо за ответы Цитата us - это микросекунды... потому скорее в 1 микросекунду... да, в исходном примере эта функция использовалась для задержки в микросекундах, но в коде было time * 125 (частота тактирования микроблейза там равна 125 МГц). В моем случае тактовая частота равна 50 МГц, для удобства наблюдения задержки в чипскопе я ее сократил. Цитата Может во время генережки вы ему указали быть микросекундным таймером? Нет, при генерации ядра в коргенераторе для таймера доступны только те параметры, которые я указал. Цитата Опять же вопрос оптимизации, может так оказаться что у вас настолько медленно работает проц, что меньше 273 тиков таймера он отловить не может Частота тактирования равна 50 МГц. Цитата Может что конечно не понял всей затеи автора, но зачем вам две версии структуры для IOModule. Просто изначально я практиковался с обработчиком прерываний и в уже в отлаженую программу вставил пример работы с таймером  . Также мне казалось, что наличие 2-х функций (XIOModule_Initialize и XIOModule_Timer_Initialize) не просто так. Вы хотите сказать, что по сути эти 2 функции делают аналогичное? Я только в начале пути освоения Микроблейза, да и в Си уже давно не практиковался, поэтому критика и пояснение работы кода только приветствуется.
|
|
|
|
|
Apr 5 2014, 15:43
|
Гуру
     
Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454

|
ну так возьмите да поглядите, все исходники драйверов есть. По сути своей все их драйверы перекладывают структуры, да в нужные адреса модулей обращаются. Можно все вообще без драйверов сделать. Кстати что микроблайз тактируется 50 МГц совсем не значит что он 50 миллионов инструкций в секунду выполняет, обращение по шинам не 1 такт, выбор из памяти, кеши, там все так можно завернуть - на троить, что проц просто стоять будет! вот у меня так таймер работает CODE static XTmrCtr _TimerCounter; //структура настройки Таймера XTmrCtr *TimerCounter = &(_TimerCounter); //указатель для удобства использования функций
//Инициализируем таймер InitStatus = XTmrCtr_Initialize(TimerCounter, XPAR_ETHERNET_TIMER_DEVICE_ID);
//если устройство запущено, его надо установить и заново запустить инициализацию if(InitStatus == XST_DEVICE_IS_STARTED) { print("\r\nРучная остановка таймера"); //надо получить данные настройки таймера вручную XTmrCtr_Config *TmrCtrConfigPtr; TmrCtrConfigPtr = XTmrCtr_LookupConfig(XPAR_ETHERNET_TIMER_DEVICE_ID); if(TmrCtrConfigPtr!=NULL) { print("\r\nПолучение структуры таймера"); //заполняем настройки TimerCounter->BaseAddress = TmrCtrConfigPtr->BaseAddress; TimerCounter->IsReady = XIL_COMPONENT_IS_READY; XTmrCtr_Stop(TimerCounter,0); //останавливаем 0 канал XTmrCtr_Stop(TimerCounter,1); //останавливаем 1 канал } //сбрасываем настройки TimerCounter->BaseAddress = 0; TimerCounter->IsReady = 0;
print("\r\nПовторная инициализация таймера"); //инициализируем заново InitStatus = XTmrCtr_Initialize(TimerCounter, XPAR_ETHERNET_TIMER_DEVICE_ID); }
if(InitStatus != XST_SUCCESS) xil_printf("\r\nОшибка инициализации таймера: %d",InitStatus); else { InitStatus = XTmrCtr_SelfTest(TimerCounter, 0); if(InitStatus != XST_SUCCESS) xil_printf("\r\nОшибка самотестирования таймера: %d",InitStatus); else print("\r\nТаймер: OK!");
//настраиваем самоперезагрузку 0 таймера, и включаем прерывание XTmrCtr_SetOptions(TimerCounter, 0, XTC_AUTO_RELOAD_OPTION|XTC_INT_MODE_OPTION);
//настраиваем самоперезагрузку 1 таймера, и включаем прерывание XTmrCtr_SetOptions(TimerCounter, 1, XTC_AUTO_RELOAD_OPTION|XTC_INT_MODE_OPTION);
//задаим начальное значение таким, это время до прерывания //0 канал XTmrCtr_SetResetValue(TimerCounter, 0, TIMER_250MS_INTERVAL); //250 мСек //XTmrCtr_SetResetValue(TimerCounter, 0, TIMER_10MS_INTERVAL); //10 мСек
//1 канал XTmrCtr_SetResetValue(TimerCounter, 1, TIMER_500MS_INTERVAL); //500 мСек
//подключаем обработчик прерывания XTmrCtr_SetHandler(TimerCounter,(XTmrCtr_Handler)InterruptHandler_Timer,(void *)TimerCounter); }
может будет полезно, простите привожу кусок как есть... да вспомнил что таймер у них к нулю считает, как то так...
|
|
|
|
|
Apr 6 2014, 08:36
|

Знающий
   
Группа: Свой
Сообщений: 747
Регистрация: 11-04-07
Пользователь №: 26 933

|
Цитата(Weyland @ Apr 5 2014, 19:00)  Также мне казалось, что наличие 2-х функций (XIOModule_Initialize и XIOModule_Timer_Initialize) не просто так. Вы хотите сказать, что по сути эти 2 функции делают аналогичное? Я только в начале пути освоения Микроблейза, да и в Си уже давно не практиковался, поэтому критика и пояснение работы кода только приветствуется. В микроконтроллере все упрощено, по сравнению с большим микроблейзом. Там посадили на быструю шину LMB аппаратный модуль который отвечает за все сразу. Т.е. сначала инициализируется этот модуль, а потом уже остальные его подсистемы по желанию. В том числе таймеры, прерывания, модуль асинхронного приемопередатчика. Для инициализации всего служит всего одна структура IOModule.
--------------------
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|