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

 
 
> Прерывания в linux, как написать обработчик
const3
сообщение Jan 29 2011, 15:21
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 16
Регистрация: 29-01-11
Пользователь №: 62 560



Есть плата с мк AT91SAM9G20. На борту стоит linux. Пользуюсь компилятором toolchain openwrt. Перечитал на форумах много инфы, но конкретного не нашел. Я хочу сделать обработчик для таймера, который срабатывает в определенное время, так как linux не является системой с жестким контролем времени, а мне нужно выдавать сигнал строго в определенное время, то средства ОС не годятся.
Привожу код:
CODE

#include <stdio.h>
#include <stdlib.h>
#include "at91sam9.h"
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>


#define MAP_SIZE 4096Ul
#define MAP_MASK (MAP_SIZE - 1)
#define TIMER1_INTERRUPT_LEVEL 4
/*-----------------*/

/* Clock Selection */

/*-----------------*/

#define TC_CLKS 0x7

#define TC_CLKS_MCK2 0x0

#define TC_CLKS_MCK8 0x1

#define TC_CLKS_MCK32 0x2

#define TC_CLKS_MCK128 0x3

#define TC_CLKS_MCK1024 0x4
AT91S_TC *tc1;
AT91S_AIC *aic_map(unsigned int aicbase)
{
int fd;
void *base;

AT91S_AIC *aic;

off_t addr = aicbase;

if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) {
fprintf(stderr, "Cannot open /dev/mem.\n");
exit(EXIT_FAILURE);
}

fprintf(stderr, "/dev/mem opened.\n");

base =
mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
addr & ~MAP_MASK);

if (base == (void *) -1) {
fprintf(stderr, "Cannot open /dev/mem.\n");
exit(EXIT_FAILURE);
}

fprintf(stderr, "Memory mapped at address %p.\n", base);

aic = base + (addr & MAP_MASK);

return aic;
}

AT91S_TC *tc_map(unsigned int tcbase)
{
int fd;
void *base;

AT91S_TC *tc;

off_t addr = tcbase;

if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) {
fprintf(stderr, "Cannot open /dev/mem.\n");
exit(EXIT_FAILURE);
}

fprintf(stderr, "/dev/mem opened.\n");

base =
mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
addr & ~MAP_MASK);

if (base == (void *) -1) {
fprintf(stderr, "Cannot open /dev/mem.\n");
exit(EXIT_FAILURE);
}

fprintf(stderr, "Memory mapped at address %p.\n", base);

tc = base + (addr & MAP_MASK);

return tc;
}

AT91S_PMC *pmc_map(unsigned int pmcbase)
{
int fd;
void *base;

AT91S_PMC *pmc;

off_t addr = pmcbase;

if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) {
fprintf(stderr, "Cannot open /dev/mem.\n");
exit(EXIT_FAILURE);
}

fprintf(stderr, "/dev/mem opened.\n");

base =
mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
addr & ~MAP_MASK);

if (base == (void *) -1) {
fprintf(stderr, "Cannot open /dev/mem.\n");
exit(EXIT_FAILURE);
}

fprintf(stderr, "Memory mapped at address %p.\n", base);

pmc = base + (addr & MAP_MASK);

return pmc;
}


volatile int count_timer1_interrupt;
volatile int y;


void timer1_c_irq_handler ()
//* Begin
{


unsigned int dummy;

//* Acknowledge interrupt status

dummy = tc1->TC_SR;

//* Suppress warning variable "dummy" was set but never used

dummy = dummy;

count_timer1_interrupt++;


}

__inline void AT91F_PMC_EnablePeriphClock (

AT91PS_PMC pPMC, // \arg pointer to PMC controller

unsigned int periphIds) // \arg IDs of peripherals to enable

{

pPMC->PMC_PCER = periphIds;

}


void AT91F_TC_Open ( AT91PS_TC TC_pt,AT91PS_PMC pmc, unsigned int Mode, unsigned int TimerId)

//* Begin

{

unsigned int dummy;



//* First, enable the clock of the TIMER

AT91F_PMC_EnablePeriphClock ( pmc, 1<< TimerId ) ;



//* Disable the clock and the interrupts

TC_pt->TC_CCR = AT91C_TC_CLKDIS ;

TC_pt->TC_IDR = 0xFFFFFFFF ;



//* Clear status bit

dummy = TC_pt->TC_SR;

//* Suppress warning variable "dummy" was set but never used

dummy = dummy;

//* Set the Mode of the Timer Counter

TC_pt->TC_CMR = Mode ;



//* Enable the clock

TC_pt->TC_CCR = AT91C_TC_CLKEN ;

//* End

}
__inline unsigned int AT91F_AIC_ConfigureIt (

AT91PS_AIC pAic, // \arg pointer to the AIC registers

unsigned int irq_id, // \arg interrupt number to initialize

unsigned int priority, // \arg priority to give to the interrupt

unsigned int src_type, // \arg activation and sense of activation

void (*newHandler) () ) // \arg address of the interrupt handler

{

unsigned int oldHandler;

unsigned int mask ;



oldHandler = pAic->AIC_SVR[irq_id];



mask = 0x1 << irq_id ;

//* Disable the interrupt on the interrupt controller

pAic->AIC_IDCR = mask ;

//* Save the interrupt handler routine pointer and the interrupt priority

pAic->AIC_SVR[irq_id] = (unsigned int) newHandler ;

//* Store the Source Mode Register

pAic->AIC_SMR[irq_id] = src_type | priority ;

//* Clear the interrupt on the interrupt controller

pAic->AIC_ICCR = mask ;



return oldHandler;

}
__inline void AT91F_AIC_EnableIt (

AT91PS_AIC pAic, // \arg pointer to the AIC registers

unsigned int irq_id ) // \arg interrupt number to initialize

{

//* Enable the interrupt on the interrupt controller

pAic->AIC_IECR = 0x1 << irq_id ;

}


void timer_init(AT91PS_TC tc,AT91PS_AIC aic,AT91PS_PMC pmc,unsigned int mode,unsigned int timer_id)
{

//init the timer interrupt counter

count_timer1_interrupt=0;




//* Open timer

AT91F_TC_Open(tc,pmc,mode,timer_id);






//* Open Timer interrupt


unsigned int old= AT91F_AIC_ConfigureIt ( aic, timer_id, TIMER1_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_EXT_HIGH_LEVEL, timer1_c_irq_handler);

tc->TC_IER = AT91C_TC_CPCS; // IRQ enable CPC



AT91F_AIC_EnableIt (aic, timer_id);







//* Start timer1

tc->TC_CCR = AT91C_TC_SWTRG ;

}








int main()
{

AT91S_AIC *aic;
AT91S_PMC *pmc;

tc1=tc_map(AT91C_BASE_TC1);
aic=aic_map(AT91C_BASE_AIC);
pmc=pmc_map(AT91C_BASE_PMC);

timer_init(tc1,aic,pmc,TC_CLKS_MCK2,AT91C_ID_TC1);


int i=0;
for( i=0;i<10000000;i++);


printf("\n%d\n",count_timer1_interrupt);

return 0;
}

................................................................................
..........


При выполнении этой команды

//* Start timer1

tc->TC_CCR = AT91C_TC_SWTRG ;

Запускается таймер. Но тут начинается бардак. В терминале начинает выдаватся сообщение о том, что пришло прерывание, обработчик которому не задан.:
handle_irq() irq_num= номер desc=какой-то номер chip()
и тд.

Вывод я сделал такой: контроллер прерываний я запрограмировал правильно, таймер тоже. Но сам обработчик видно не разместился по адресу. Еще такое если старый обработчик не трогать то все работает, просто не делаются те действия, которые я хочу.

Я думаю что все те примеры в Keil относятся к тем системам где нет ОС, и тогда все рабоотает норм, так как используется линейная физическая адресация памяти, а у меня используется виртуальная. Вот и вопрос как заменить обработчик на свой. Был еще вариант сделать модуль я дра, но тоже не могу найти примеров как это делается , подскажите кто сможет ,,, спс

Сообщение отредактировал IgorKossak - Jan 29 2011, 20:17
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
const3
сообщение Jan 30 2011, 00:28
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 16
Регистрация: 29-01-11
Пользователь №: 62 560



Извините за оформление. Просто первый раз создал тему на этом форуме.
ОС я не выбирал, а она стояла уже. Мне дали такое задание разобратся с этим контроллером в универе. Никаких примеров не дали. Спасибо за совет. Буду читать. Код работать не будет? Для контроллера GPIO работает. И еще, если реального времени не добьюсь, а как это сделать посоветуйте. Я хочу сделать видеоадаптер, для начала просто нужно выводить синхроимпульсы и белый экран.
Go to the top of the page
 
+Quote Post
sasamy
сообщение Jan 30 2011, 10:14
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 783
Регистрация: 22-11-08
Пользователь №: 41 858



Цитата(const3 @ Jan 30 2011, 03:28) *
ОС я не выбирал, а она стояла уже. Мне дали такое задание разобратся с этим контроллером в универе. Никаких примеров не дали


На сайте atmel достаточно информации в примерах разной степени паршивости как работать с их контроллерами.

Цитата
Код работать не будет? Для контроллера GPIO работает.


Доступ к регистрам через mmap работает - кто же тут спорит, а то ка вы пытаетесь вынести обработчик прерывания напрямую в пользовательский процесс никогда не заработает в linux.

Цитата
как это сделать посоветуйте. Я хочу сделать видеоадаптер


Тут могу только посоветовать не заниматься ерундой sm.gif
Полезные ссылки по linux (в частности там можно найти презентации по некоторым ключевым моментам)
http://kernelnewbies.org/FAQ
http://free-electrons.com/docs/
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 21:23
Рейтинг@Mail.ru


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