//Timer0 中断服务例程 void do_timer0(struct cpu_registers *regs) { irq_mask(INT_TIMER0,IRQ_MASK); timer_ctrl_object.timer_cnt0++; schedule(regs); //调用 schedule() 进程切换 /******************************************************************/ //测试信号机制 if(jiffies==100) current->signal=(1<<(SIGHUP))|(1<<(SIGINT))|(1<<(SIGQUIT)); /******************************************************************/ /*对当前任务的信号位图进行识别处理*/ for(current_singal=0;current_singal<NSIG;current_singal++) { if((current->signal)&(1<<current_singal)) { current->signal&=~(1<<current_singal); do_signal_irq(current_singal,regs); break; } } jiffies++; //时钟滴嗒增1 clean_src_pnd(INT_TIMER0); clean_int_pnd(INT_TIMER0); irq_mask(INT_TIMER0,IRQ_UNMASK); }
//Timer4 中断服务例程 void do_timer4(struct cpu_registers *regs) { irq_mask(INT_TIMER4,IRQ_MASK); timer_ctrl_object.timer_cnt4++; //在这里添加timer3的中断功能代码 // printk("timer4 \n"); clean_src_pnd(INT_TIMER4); clean_int_pnd(INT_TIMER4); irq_mask(INT_TIMER4,IRQ_UNMASK); }
void intrs_setup(void) { // remap interrupts irq_remap(I8259A_BASE, I8259A_BASE + 8); // prepare handler table int i; for (i = 0; i < 8; ++i) { irq_mask(i, false); irq[i] = irq_stub; } for (i = 8; i < 16; ++i) { irq_mask(i, false); irq[i] = irq_slave; } }
int irq_init(uint8_t base) { uint8_t i; printk("Setting up interrupts\n"); printk("\tRegistering all 16 IRQ in IDT\n"); interrupts_set_isr(32, irq0, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(33, irq1, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(34, irq2, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(35, irq3, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(36, irq4, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(37, irq5, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(38, irq6, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(39, irq7, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(40, irq8, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(41, irq9, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(42, irq10, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(43, irq11, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(44, irq12, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(45, irq13, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(46, irq14, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); interrupts_set_isr(47, irq15, INTGATE_PRESENT | INTGATE_32 | INTGATE_KERNEL); printk("\tMasking all interrupts (0-15)\n"); for (i = 0; i < 16; ++i) { irq_mask(i); } printk("\tEnabling hardware interrupts (sti)\n"); __asm__ volatile("sti"); printk("\n"); }
/* return receive bytes */ int uart_rx_sleep(int ch, char *buf, int len) { int receive = 0; if(uart[ch].is_open != 1) { RERR(); return -ENODEV; } while(len > 0) { irq_mask(IRQ_UART0+ch); if(uart[ch].rx_r == uart[ch].rx_w) { /* rx buf is empty now */ uart[ch].sem_rx_empty_valid = 1; irq_unmask(IRQ_UART0+ch); sys_sem_wait(&uart[ch].sem_rx_empty); if(uart[ch].rx_r == uart[ch].rx_w) /* we are abort by uart_rx_sleep_abort */ return receive; } else irq_unmask(IRQ_UART0+ch); while (len > 0 && uart[ch].rx_r != uart[ch].rx_w) { *buf++ = uart[ch].rx_buf[uart[ch].rx_r]; uart[ch].rx_r = (uart[ch].rx_r + 1) % RX_BUF; receive++; len--; } } return receive; }
int event_send(int id, int event) { if (event < 0 || event >= EV_COUNT) { return 1; } if (evqueue[event].front_thread) { // handle event now struct thread *thread = evqueue[event].front_thread; evqueue[event].front_thread = thread->next_evqueue; if (!thread->next_evqueue) evqueue[event].back_thread = NULL; thread->eax = event; thread->event = -1; if (thread->state == TS_RUNNING) { thread_save(thread); } schedule_push(thread); thread->state = TS_QUEUED; } if (event < 240) { irq_mask(event); irq_reset(event); irqstate[event] = 1; } return 0; }
/* return left tx bytes */ int uart_tx(int ch, const char *buf, int len) { unsigned int mask; if(uart[ch].is_open != 1) { RERR(); return -ENODEV; } while(len > 0) { if((uart[ch].tx_w + 1) % TX_BUF == uart[ch].tx_r) { /* bad, tx_buf is full */ RERR("uart:%d, tx_buf is full, cann't fill any more bytes!",ch); break; } uart[ch].tx_buf[uart[ch].tx_w] = *buf++; uart[ch].tx_w = (uart[ch].tx_w + 1) % TX_BUF; len--; } irq_mask(IRQ_UART0 + ch); mask = UART_REG_R(ch, UINTM_OFFSET); mask &= ~(1<<2); /* enable tx interrupt */ UART_REG_W(ch, UINTM_OFFSET, mask); irq_unmask(IRQ_UART0 + ch); return len; }
void some_serial_stuff() { disable_int(); printk("COM1: setting up\n"); outb(PORT + 1, 0x00); outb(PORT + 3, 0x80); outb(PORT + 0, 0x03); outb(PORT + 1, 0x00); outb(PORT + 3, 0x03); outb(PORT + 2, 0xc7); //outb(PORT + 2, 0x07); // debugging: trigger every byte outb(PORT + 4, 0x0b); set_int(0x24, &a_irq4_handler); irq_mask(4, 0); enable_int(); serial_started = 1; printk("COM1: should be upset now\n"); serial_poll(); }
/* * 有了 timer_enable(),我们就可以方便的调整任何一个timer的频率并开启它 */ void timer_enable(unsigned char timerX,unsigned int freq) { switch(timerX) { case TIMER_0: irq_mask(INT_TIMER0,IRQ_MASK); timer_config(TIMER_0,26406/freq,0); timer_start(TIMER_0); irq_rotunie[INT_TIMER0]=&do_timer0; irq_mask(INT_TIMER0,IRQ_UNMASK); break; case TIMER_1: irq_mask(INT_TIMER1,IRQ_MASK); timer_config(TIMER_1,26406/freq,0); timer_start(TIMER_1); irq_rotunie[INT_TIMER1]=&do_timer1; irq_mask(INT_TIMER1,IRQ_UNMASK); break; case TIMER_2: irq_mask(INT_TIMER2,IRQ_MASK); timer_config(TIMER_2,26406/freq,0); timer_start(TIMER_2); irq_rotunie[INT_TIMER2]=&do_timer2; irq_mask(INT_TIMER2,IRQ_UNMASK); break; case TIMER_3: irq_mask(INT_TIMER3,IRQ_MASK); timer_config(TIMER_3,26406/freq,0); timer_start(TIMER_3); irq_rotunie[INT_TIMER3]=&do_timer3; irq_mask(INT_TIMER3,IRQ_UNMASK); break; case TIMER_4: irq_mask(INT_TIMER4,IRQ_MASK); timer_config(TIMER_4,26406/freq,0); timer_start(TIMER_4); irq_rotunie[INT_TIMER4]=&do_timer4; irq_mask(INT_TIMER4,IRQ_UNMASK); break; } }
/* * timer_disable()用于停止指定的timer并关闭与该timer相关的中断 */ int timer_disable(unsigned char timerX) { unsigned int tcon =*timer_ctrl_object.tcon; if(timerX>4) return -1; else { switch(timerX) { case TIMER_0: //停止TIMER0 tcon&=~(1<<TIMER0_START_BIT_TCON); irq_mask(INT_TIMER0,IRQ_MASK); break; case TIMER_1: //停止TIMER1 tcon&=~(1<<TIMER1_START_BIT_TCON); irq_mask(INT_TIMER1,IRQ_MASK); break; case TIMER_2: //停止TIMER2 tcon&=~(1<<TIMER2_START_BIT_TCON); irq_mask(INT_TIMER2,IRQ_MASK); break; case TIMER_3: //停止TIMER3 tcon&=~(1<<TIMER3_START_BIT_TCON); irq_mask(INT_TIMER3,IRQ_MASK); break; case TIMER_4: //停止TIMER4 tcon&=~(1<<TIMER4_START_BIT_TCON); irq_mask(INT_TIMER4,IRQ_MASK); break; } *timer_ctrl_object.tcon =tcon; return 1; } }
/* clear uart tx buffer,return 0 when success */ int uart_tx_buffer_clear(int ch) { if(uart[ch].is_open != 1) return -ENODEV; irq_mask(IRQ_UART0 + ch); uart[ch].tx_r = 0; uart[ch].tx_w = 0; irq_unmask(IRQ_UART0 + ch); return 0; }
/* close the ch * send and receive buf will be clear */ void uart_close(int ch) { if(uart[ch].is_open != 1) { RERR(); return; } irq_mask(IRQ_UART0 + ch); uart[ch].is_open = 0; /* disable all uart interrupt */ UART_REG_W(ch, UINTM_OFFSET, 0x0f); }
void uart_tx_sleep_abort(int ch) { /* don't forbid other process call */ if(uart[ch].is_open != 1) { RERR(); return; } irq_mask(IRQ_UART0 + ch); if(uart[ch].sem_tx_full_valid) { uart[ch].sem_tx_full_valid = 0; /* one time signal */ sys_sem_signal(&uart[ch].sem_tx_full); } irq_unmask(IRQ_UART0 + ch); }
/******************************************************************************* * @brief Stop timer * Function timer_init() must be called before call this function * @author zhanggaoxin * @date 2012-12-26 * @param [in]timer_id: Timer ID * @return T_TIMER * @retval ERROR_TIMER:stop successfully. *******************************************************************************/ T_TIMER timer_stop(T_TIMER timer_id) { if (timer_id >= TIMER_NUM_MAX) return ERROR_TIMER; if (timer_data[timer_id].state == TIMER_INACTIVE) return ERROR_TIMER; irq_mask(); timer_data[timer_id].state = TIMER_INACTIVE; irq_unmask(); return ERROR_TIMER; }
/* return unsent bytes */ int uart_tx_sleep(int ch, const char *buf, int len) { #define ENABLE_SEND() \ do {\ if(UART_REG_R(ch, UINTM_OFFSET) & (1<<2)) {\ /* enable send interrupt */\ irq_mask(IRQ_UART0 + ch);\ mask = UART_REG_R(ch, UINTM_OFFSET);\ mask &= ~(1<<2); /* enable tx interrupt */\ UART_REG_W(ch, UINTM_OFFSET, mask);\ irq_unmask(IRQ_UART0 + ch);\ }\ } while(0) unsigned int mask; if(uart[ch].is_open != 1) { RERR(); return -ENODEV; } while(len > 0) { irq_mask(IRQ_UART0+ch); if((uart[ch].tx_w + 1) % TX_BUF == uart[ch].tx_r) { /* tx_buf is full, wait */ uart[ch].sem_tx_full_valid = 1; irq_unmask(IRQ_UART0+ch); ENABLE_SEND(); sys_sem_wait(&uart[ch].sem_tx_full); if((uart[ch].tx_w + 1) % TX_BUF == uart[ch].tx_r) /* we are abort by uart_tx_sleep_abort */ return len; } else irq_unmask(IRQ_UART0+ch); while(len > 0 && (uart[ch].tx_w + 1) % TX_BUF != uart[ch].tx_r) { uart[ch].tx_buf[uart[ch].tx_w] = *buf++; uart[ch].tx_w = (uart[ch].tx_w + 1) % TX_BUF; len--; } } ENABLE_SEND(); return len; }
/******************************************************************************* * @brief Start timer * When the time reach, the timer callback function will be called. * User must call function timer_stop() to free the timer ID,... * ...in spite of loop is AK_TRUE or AK_FALSE. * Function timer_init() must be called before call this function * @author zhanggaoxin * @date 2012-12-26 * @param [in]ms: specifies the time-out value, in millisecond. * Caution, this value must can be divided by 5. * @param [in]loop: loop or not * @param [in]callback_func: timer callback function. If callback_func is... * ...not AK_NULL, then this callback function... * ...will be called when time reach. * @return T_TIMER: timer ID, user can stop the timer by this ID * @retval ERROR_TIMER: failed *******************************************************************************/ T_TIMER timer_start(T_U16 ms, T_BOOL loop, T_fTIMER_CALLBACK callback_func) { volatile T_U32 i; if (AK_FALSE == MMU_IsPremapAddr((T_U32)callback_func)) { drv_print(err_str, __LINE__, AK_TRUE); while (1); } irq_mask(); for (i=0; i<TIMER_NUM_MAX; i++) { if (timer_data[i].state == TIMER_INACTIVE) { break; } } //No free timer if (i == TIMER_NUM_MAX) { irq_unmask(); drv_print(err_str, __LINE__, AK_TRUE); return ERROR_TIMER; } timer_data[i].state = TIMER_ACTIVE; timer_data[i].loop = loop; timer_data[i].total_delay = ms; timer_data[i].cur_delay = 0; timer_data[i].callback_func = (T_U32)callback_func & 0xFFFF; irq_unmask(); return i; }
/* configure uart0: * 115200,8,n,1 * non fifo mode * no interrupt is enable */ int serial_init(void) { int ch = 0; unsigned int baudrate = 115200; char parity = 'n'; int databits = 8; int stopbits = 1; unsigned int reg; double ddiv; unsigned int div; unsigned int num_one; reg = 0; //normal mode switch(parity) { case 'n': /* no parity */ break; case 'o': /* odd */ reg |= 4UL<<3; break; case 'e': /* even */ reg |= 5UL<<3; break; default: return -EINVAL; } switch(databits) { case 5: case 6: case 7: case 8: reg |= databits - 5; break; default: return -EINVAL; } switch(stopbits) { case 1: case 2: reg |= (stopbits - 1) << 2; break; default: return -EINVAL; } irq_mask(IRQ_UART0 + ch); UART_REG_W(ch, ULCON_OFFSET, reg); /* * pclk: tx level interrupt : rx level interrupt * : enable rx-reiceve timeout : generate rx error interrupt * : normal operation(not loopback mode) * : normal transmit(not send break signal) * : tx interrupt or polling mode(not dma mode) * : rx interrupt or polling mode(not dma mode) * 10 1 1 1 1 0 0 01 01 */ UART_REG_W(ch, UCON_OFFSET, 0xbc5); /* fifo is disable: */ /* tx fifo 0bytes : rx fifo 16bytes : : clear tx fifo : clear rx fifo \ * : fifo disable * 00 10 0 1 1 0 */ UART_REG_W(ch, UFCON_OFFSET, 0x26); ddiv = ((double)pclk / (baudrate * 16)) - 1; div = (unsigned int)ddiv; num_one = (unsigned int)((ddiv - div) * 16); UART_REG_W(ch, UBRDIV_OFFSET, div); UART_REG_W(ch, UDIVSLOT_OFFSET, divslot[num_one]); /* clear source pending interrupt flag */ UART_REG_W(ch,UINTSP_OFFSET, 0x0f); /* disable all uart interrupt */ UART_REG_W(ch, UINTM_OFFSET, 0x0f); /* clear pending interrupt flag */ UART_REG_W(ch,UINTP_OFFSET, 0x0f); return 0; }
int uart_open(int ch, unsigned int baudrate,unsigned int databits, char parity,unsigned int stopbits) { unsigned int reg; double ddiv; unsigned int div; unsigned int num_one; if(ch == 0 || ch > 3) { /* channel 0 is use for terminal */ return -EINVAL; } if(uart[ch].is_open != 0) return -EBUSY; if(baudrate < 1200 || baudrate > 256000) return -EINVAL; reg = 0; //normal mode switch(parity) { case 'n': /* no parity */ break; case 'o': /* odd */ reg |= 4UL<<3; break; case 'e': /* even */ reg |= 5UL<<3; break; default: return -EINVAL; } switch(databits) { case 5: case 6: case 7: case 8: reg |= databits - 5; break; default: return -EINVAL; } switch(stopbits) { case 1: case 2: reg |= (stopbits - 1) << 2; break; default: return -EINVAL; } irq_mask(IRQ_UART0 + ch); UART_REG_W(ch, ULCON_OFFSET, reg); /* * pclk: tx level interrupt : rx level interrupt * : enable rx-reiceve timeout : generate rx error interrupt * : normal operation(not loopback mode) * : normal transmit(not send break signal) * : tx interrupt or polling mode(not dma mode) * : rx interrupt or polling mode(not dma mode) * 10 1 1 1 1 0 0 01 01 */ UART_REG_W(ch, UCON_OFFSET, 0xbc5); /* fifo is enable: * tx interrupt will be generate if fifo less than or equals setting level, * rx interrupt will be gererate if fifo reach setting level. */ /* tx fifo 16bytes : rx fifo 16bytes : : clear tx fifo : clear rx fifo \ * : fifo enable * 01 10 0 1 1 1 */ UART_REG_W(ch, UFCON_OFFSET, 0x27); /* set baudrate */ ddiv = ((double)pclk / (baudrate * 16)) - 1; div = (unsigned int)ddiv; num_one = (unsigned int)((ddiv - div) * 16); UART_REG_W(ch, UBRDIV_OFFSET, div); UART_REG_W(ch, UDIVSLOT_OFFSET, divslot[num_one]); /* clear tx,rx buffer */ uart[ch].tx_w = 0; uart[ch].tx_r = 0; uart[ch].rx_w = 0; uart[ch].rx_r = 0; sys_sem_new(&uart[ch].sem_rx_empty,0); sys_sem_new(&uart[ch].sem_tx_full,0); /* uart1~3 prio: 8 */ switch(ch) { case 1: irq_register_handler(IRQ_UART1, 8, uart1_isr); break; case 2: irq_register_handler(IRQ_UART2, 8, uart2_isr); break; case 3: irq_register_handler(IRQ_UART3, 8, uart3_isr); break; } /* configure uart gpio */ switch(ch) { case 1: /* GPA4:RX, GPA5:TX */ GPACON_REG = (GPACON_REG & ~(0xffUL << 16)) | (0x22UL << 16); break; case 2: /* GPB0:RX, GPB1: TX */ GPBCON_REG = (GPBCON_REG & ~(0xffUL << 0)) | (0x22UL << 0); break; case 3: /* GPB2:RX, GPB3: TX */ GPBCON_REG = (GPBCON_REG & ~(0xffUL << 8)) | (0x22UL << 8); break; } /* clear source pending interrupt flag */ UART_REG_W(ch,UINTSP_OFFSET, 0x0f); /* enable rx, error status interrupt */ UART_REG_W(ch, UINTM_OFFSET, 0x0c); /* clear pending interrupt flag */ UART_REG_W(ch,UINTP_OFFSET, 0x0f); /* channel is open now */ uart[ch].is_open = 1; irq_unmask(IRQ_UART0 + ch); return 0; }
void sys_timer_stop(void) { irq_mask(IRQ_TIMER4_VIC); TINT_CSTAT_REG &= ~(1<<4); //disable interrupt TCON_REG &= ~(1<<20);//stop timer4 }