реклама на сайте
подробности

 
 
> Microbalze MCS и программируемый таймер
Weyland
сообщение Apr 4 2014, 09:31
Сообщение #1





Группа: Новичок
Сообщений: 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 такт или я не прав?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 5)
Golikov A.
сообщение Apr 4 2014, 14:35
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



us - это микросекунды... потому скорее в 1 микросекунду...
хотя по коду реально 1 тик таймера. Может во время генережки вы ему указали быть микросекундным таймером?
Опять же вопрос оптимизации, может так оказаться что у вас настолько медленно работает проц, что меньше 273 тиков таймера он отловить не может, попробуйте кратные значения 274 - 548 - 1096 и так далее, ну и 274-275 - 276 -277 тоже может быть интересно
Go to the top of the page
 
+Quote Post
dm.pogrebnoy
сообщение Apr 5 2014, 10:24
Сообщение #3


Знающий
****

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



Может что конечно не понял всей затеи автора, но зачем вам две версии структуры для IOModule. Когда вы инициализируете таймер вы должны пользоваться ранее тнициализированной структурой IOModule, в ваши случае HfdsIOModule. В функцию задержки передавать ссылку на эту структуру или сделать ее глобальной.


--------------------
Go to the top of the page
 
+Quote Post
Weyland
сообщение Apr 5 2014, 15:00
Сообщение #4





Группа: Новичок
Сообщений: 6
Регистрация: 3-02-10
Пользователь №: 55 267



Golikov A, dm.pogrebnoy спасибо за ответы
Цитата
us - это микросекунды... потому скорее в 1 микросекунду...

да, в исходном примере эта функция использовалась для задержки в микросекундах, но в коде было time * 125 (частота тактирования микроблейза там равна 125 МГц). В моем случае тактовая частота равна 50 МГц, для удобства наблюдения задержки в чипскопе я ее сократил.
Цитата
Может во время генережки вы ему указали быть микросекундным таймером?

Нет, при генерации ядра в коргенераторе для таймера доступны только те параметры, которые я указал.
Цитата
Опять же вопрос оптимизации, может так оказаться что у вас настолько медленно работает проц, что меньше 273 тиков таймера он отловить не может

Частота тактирования равна 50 МГц.
Цитата
Может что конечно не понял всей затеи автора, но зачем вам две версии структуры для IOModule.

Просто изначально я практиковался с обработчиком прерываний и в уже в отлаженую программу вставил пример работы с таймером rolleyes.gif . Также мне казалось, что наличие 2-х функций (XIOModule_Initialize и XIOModule_Timer_Initialize) не просто так. Вы хотите сказать, что по сути эти 2 функции делают аналогичное? Я только в начале пути освоения Микроблейза, да и в Си уже давно не практиковался, поэтому критика и пояснение работы кода только приветствуется.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Apr 5 2014, 15:43
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 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);
}



может будет полезно, простите привожу кусок как есть...
да вспомнил что таймер у них к нулю считает, как то так...
Go to the top of the page
 
+Quote Post
dm.pogrebnoy
сообщение Apr 6 2014, 08:36
Сообщение #6


Знающий
****

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



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

В микроконтроллере все упрощено, по сравнению с большим микроблейзом. Там посадили на быструю шину LMB аппаратный модуль который отвечает за все сразу. Т.е. сначала инициализируется этот модуль, а потом уже остальные его подсистемы по желанию. В том числе таймеры, прерывания, модуль асинхронного приемопередатчика. Для инициализации всего служит всего одна структура IOModule.


--------------------
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 28th July 2025 - 04:03
Рейтинг@Mail.ru


Страница сгенерированна за 0.01388 секунд с 7
ELECTRONIX ©2004-2016