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

 
 
> Прерывания в 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
Ответов
AVR
сообщение Feb 7 2011, 21:07
Сообщение #2


фанат Linux'а
*****

Группа: Свой
Сообщений: 1 353
Регистрация: 23-10-05
Из: SPB.RU
Пользователь №: 10 008



Я правильно понимаю, что автор темы собирается при помощи GPIO генерировать видеосигнал? Я конечно слышал что делают PAL/VGA/USB на AVRках, но там выверяют каждый такт и 100% под одну задачу.

Задача и в правду не реализуема, не будет синхронизации по вполне очевидным причинам.
Разве что кадр в аппаратную реализацию подобного адаптера гнать через небольшой буферчик, если у него памяти мало, я такие видел...


--------------------
Go to the top of the page
 
+Quote Post
Allregia
сообщение Feb 8 2011, 13:54
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Цитата(AVR @ Feb 7 2011, 23:07) *
Я правильно понимаю, что автор темы собирается при помощи GPIO генерировать видеосигнал? Я конечно слышал что делают PAL/VGA/USB на AVRках, но там выверяют каждый такт и 100% под одну задачу.


С ARM/Cortex проще - гнать строку через DMA в SPI после ССИ, т.о. во время прямого хода процессор может заниматься другими делами.
Линух тут ясное дело ни причем, или лезть на самое его дно.
Go to the top of the page
 
+Quote Post



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

 


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


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