radioman 0 1 октября, 2012 Опубликовано 1 октября, 2012 · Жалоба Доброго времени суток! Не работают прерывания на AT91SAM9XE512 - ни по таймеру, ни по USART. Инициализация проходит нормально. Программа выходит в главный цикл. Можно управлять портами - включать/выключать светодиоды. Таймер работает. Программирую микроконтроллер через H-Jtag. Программа хранится во внутренней flash памяти. flash.lds, board_cstartup.S, board_lowlevel.c, board_memories.c взяты из примеров ATMEL. В board_lowlevel.c отменен Remap. board_memories.c скорректирован с учетом размера используемой памяти. ------------------------------------------------------------------------------- обработка прерываний в board_cstartup.S //------------------------------------------------------------------------------ /// Handles incoming interrupt requests by branching to the corresponding /// handler, as defined in the AIC. Supports interrupt nesting. //------------------------------------------------------------------------------ irqHandler: /* Save interrupt context on the stack to allow nesting */ sub lr, lr, #4 stmfd sp!, {lr} mrs lr, SPSR stmfd sp!, {r0, lr} /* Write in the IVR to support Protect Mode */ ldr lr, =AT91C_BASE_AIC ldr r0, [lr, #AIC_IVR] str lr, [lr, #AIC_IVR] /* Branch to interrupt handler in Supervisor mode */ msr CPSR_c, #ARM_MODE_SVC stmfd sp!, {r1-r3, r4, r12, lr} blx r0 /* Restore scratch/used registers and LR from User Stack */ /* Disable Interrupt and switch back in IRQ mode */ ldmia sp!, {r1-r3, r4, r12, lr} msr CPSR_c, #ARM_MODE_IRQ | I_BIT /* Acknowledge interrupt */ ldr lr, =AT91C_BASE_AIC str lr, [lr, #AIC_EOICR] /* Restore interrupt context and branch back to calling code */ ldmia sp!, {r0, lr} msr SPSR_cxsf, lr ldmia sp!, {pc}^ ------------------------------------------------------------- Инициализация прерываний в board_lowlevel.c /* Initialize AIC ****************/ AT91C_BASE_AIC->AIC_IDCR = 0xFFFFFFFF; AT91C_BASE_AIC->AIC_SVR[0] = (unsigned int) defaultFiqHandler; for (i = 1; i < 31; i++) { AT91C_BASE_AIC->AIC_SVR = (unsigned int) defaultIrqHandler; } AT91C_BASE_AIC->AIC_SPU = (unsigned int) defaultSpuriousHandler; // Unstack nested interrupts for (i = 0; i < 8 ; i++) { AT91C_BASE_AIC->AIC_EOICR = 0; } -------------------------------------------- Конфигурация таймера в main.c: -------------------------------------------- //------------------------------------------------------------------------------ /// Configures Timer Counter 2 (TC2) to generate an interrupt every 1s. //------------------------------------------------------------------------------ void ConfigureTc2(void) { unsigned int divv, tcclks; // Enable TC2 peripheral clock PMC_EnablePeripheral(AT91C_ID_TC2); /// 1s (= 1Hz) TC_FindMckDivisor(1, BOARD_MCK, &divv, &tcclks); TC_Configure(AT91C_BASE_TC2, tcclks | AT91C_TC_CPCTRG); AT91C_BASE_TC2->TC_RC = (BOARD_MCK / divv)/1; // timerFreq / desiredFreq // Configure interrupt on RC compare AIC_ConfigureIT(AT91C_ID_TC2, 0, ISR_Tc2); AT91C_BASE_TC2->TC_IER = AT91C_TC_CPCS; AIC_EnableIT(AT91C_ID_TC2); } Обработка прерывания ------------------------------ void ISR_Tc2(void) { TC_Stop(AT91C_BASE_TC2); // таймер стоп // Clear status bit to acknowledge interrupt AT91C_BASE_TC2->TC_SR; PIO_Set(&LED_PWR); // светодиод "Питание ВЫКЛ." TC_Start(AT91C_BASE_TC2); // таймер старт } Плата содержит внешнюю память SDRAM и NANDFLASH, но пока они не инициализируются, не используются. Буду благодарен за любую помощь. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
skyvmicro 0 1 октября, 2012 Опубликовано 1 октября, 2012 (изменено) · Жалоба ... Я использовал примерно такую инициализацию таймера на SAM9260. void AT91F_TC_Open ( AT91PS_TC TC_pt, unsigned int Mode, unsigned int TimerId) { //* First, enable the clock of the TIMER AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<< TimerId ); //* Disable the clock and the interrupts TC_pt->TC_CCR = AT91C_TC_CLKDIS; TC_pt->TC_IDR = 0xFFFFFFFF; //* Clear status bit TC_pt->TC_SR; //* Set the Mode of the Timer Counter TC_pt->TC_CMR = Mode | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_WAVE; if( Mode == AT91C_TC_CLKS_TIMER_DIV1_CLOCK ) T_clk_T0 = AT91B_MASTER_CLOCK / 2000; if( Mode == AT91C_TC_CLKS_TIMER_DIV2_CLOCK ) T_clk_T0 = AT91B_MASTER_CLOCK / 8000; if( Mode == AT91C_TC_CLKS_TIMER_DIV3_CLOCK ) T_clk_T0 = AT91B_MASTER_CLOCK / 32000; if( Mode == AT91C_TC_CLKS_TIMER_DIV4_CLOCK ) T_clk_T0 = AT91B_MASTER_CLOCK / 128000; //* Set the value of the reg RC Var_Period_pwm_us_timer0 = (unsigned int)Period_pwm_us; Var_Frequency_pwm_kHz_timer0 = ((100000 / Var_Period_pwm_us_timer0)+5)/10; TC_pt->TC_RC = ((unsigned int)Period_pwm_us * T_clk_T0) / 1000; //* Enable the clock TC_pt->TC_CCR = AT91C_TC_CLKEN; } void timer_init ( void ) //* Begin { //* Open timer0 AT91F_TC_Open(AT91C_BASE_TC0,(unsigned int)CLKS_TIMER0,AT91C_ID_TC0); //* Start timer0 AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; } void init_timer2( unsigned int OverFlow, unsigned char Max_Dev ) { double Value; AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<< AT91C_ID_TC2 ); AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC2->TC_IDR = 0xFFFFFFFF; AT91C_BASE_TC2->TC_SR; AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_WAVE; Value = 0.5 + (AT91B_MASTER_CLOCK / 1000000.0) * (OverFlow / 128.0); Value = Value; AT91C_BASE_TC2->TC_RC = 38924; AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN; AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_TC2, TIMER2_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, timer2_c_irq_handler); AT91C_BASE_TC2->TC_IER = AT91C_TC_CPCS; AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_TC2); AT91C_BASE_TC2->TC_CCR = AT91C_TC_SWTRG; return; } Изменено 1 октября, 2012 пользователем skyv Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
radioman 0 3 октября, 2012 Опубликовано 3 октября, 2012 · Жалоба Я использовал примерно такую инициализацию таймера на SAM9260. void AT91F_TC_Open ( AT91PS_TC TC_pt, unsigned int Mode, unsigned int TimerId) { //* First, enable the clock of the TIMER AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<< TimerId ); //* Disable the clock and the interrupts TC_pt->TC_CCR = AT91C_TC_CLKDIS; TC_pt->TC_IDR = 0xFFFFFFFF; //* Clear status bit TC_pt->TC_SR; //* Set the Mode of the Timer Counter TC_pt->TC_CMR = Mode | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_WAVE; if( Mode == AT91C_TC_CLKS_TIMER_DIV1_CLOCK ) T_clk_T0 = AT91B_MASTER_CLOCK / 2000; if( Mode == AT91C_TC_CLKS_TIMER_DIV2_CLOCK ) T_clk_T0 = AT91B_MASTER_CLOCK / 8000; if( Mode == AT91C_TC_CLKS_TIMER_DIV3_CLOCK ) T_clk_T0 = AT91B_MASTER_CLOCK / 32000; if( Mode == AT91C_TC_CLKS_TIMER_DIV4_CLOCK ) T_clk_T0 = AT91B_MASTER_CLOCK / 128000; //* Set the value of the reg RC Var_Period_pwm_us_timer0 = (unsigned int)Period_pwm_us; Var_Frequency_pwm_kHz_timer0 = ((100000 / Var_Period_pwm_us_timer0)+5)/10; TC_pt->TC_RC = ((unsigned int)Period_pwm_us * T_clk_T0) / 1000; //* Enable the clock TC_pt->TC_CCR = AT91C_TC_CLKEN; } void timer_init ( void ) //* Begin { //* Open timer0 AT91F_TC_Open(AT91C_BASE_TC0,(unsigned int)CLKS_TIMER0,AT91C_ID_TC0); //* Start timer0 AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; } void init_timer2( unsigned int OverFlow, unsigned char Max_Dev ) { double Value; AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1<< AT91C_ID_TC2 ); AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC2->TC_IDR = 0xFFFFFFFF; AT91C_BASE_TC2->TC_SR; AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_WAVE; Value = 0.5 + (AT91B_MASTER_CLOCK / 1000000.0) * (OverFlow / 128.0); Value = Value; AT91C_BASE_TC2->TC_RC = 38924; AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN; AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC, AT91C_ID_TC2, TIMER2_INTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, timer2_c_irq_handler); AT91C_BASE_TC2->TC_IER = AT91C_TC_CPCS; AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_TC2); AT91C_BASE_TC2->TC_CCR = AT91C_TC_SWTRG; return; } Спасибо за ответ. У меня инициализация делается такими же методами. Отличий нет. Поэтому пока проблема не решена. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lotor 0 3 октября, 2012 Опубликовано 3 октября, 2012 · Жалоба Чудес не бывает, что-то упускаете. Я бы выкинул все лишние и попытался настроить прерывание только от таймера для начала. Посмотрите, входит ли хоть раз в обработчик. Средства для этого у Вас имеются. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
radioman 0 3 октября, 2012 Опубликовано 3 октября, 2012 · Жалоба Чудес не бывает, что-то упускаете. Я бы выкинул все лишние и попытался настроить прерывание только от таймера для начала. Посмотрите, входит ли хоть раз в обработчик. Средства для этого у Вас имеются. Спасибо за совет. В обработчик не входит. Выяснил, что прерывание по таймеру работает, просто по нему происходит перезапуск контроллера, а не запускается обработчик ,указанный в конфигурации таймера. Есть подозрение - что то не так в файлах board_cstartup.S, board_lowlevel.c. В них задается первоначальная конфигурация всего контроллера, в том числе и конфигурация прерываний. Но пока не могу понять что не так. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lotor 0 3 октября, 2012 Опубликовано 3 октября, 2012 · Жалоба просто по нему происходит перезапуск контроллера, а не запускается обработчик ,указанный в конфигурации таймера. При срабатывании прерывания от таймера Вы должны попасть на метку irqHandler в board_cstartup.S, а там уже вызовется обработчик таймера. Посмотрите, попадаете ли туда. Сброс контроллера говорит о том, что попадаете на мусор. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
radioman 0 5 октября, 2012 Опубликовано 5 октября, 2012 · Жалоба Проблема решена! В board_lowlevel.c была закоментирована строка BOARD_RemapRam();, именно поэтому при срабатывании прерывания происходил перезапуск программы - т.е. программа переходила не на секцию .vectors, отвечающую за обработку векторов исключений, описанную в board_cstartup.S, а на область flash памяти, где записана программа. Спасибо всем кто помог разобраться. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться