Есть плата с мк 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