quicc_smc1.c
来自「eCos操作系统源码」· C语言 代码 · 共 880 行 · 第 1/2 页
C
880 行
cyg_hal_sxx_getc_timeout(void* __ch_data, cyg_uint8* ch){ struct port_info *info = (struct port_info *)__ch_data; int delay_count = info->timeout * 10; // delay in .1 ms steps cyg_bool res; CYGARC_HAL_SAVE_GP(); for(;;) { res = cyg_hal_sxx_getc_nonblock(__ch_data, ch); if (res || 0 == delay_count--) break; CYGACC_CALL_IF_DELAY_US(100); } CYGARC_HAL_RESTORE_GP(); return res;}/* * Control/query the state of a port * This function can be called on either an SMC or SCC port */static intcyg_hal_sxx_control(void *__ch_data, __comm_control_cmd_t __func, ...){ struct port_info *info = (struct port_info *)__ch_data; int ret = 0; CYGARC_HAL_SAVE_GP(); switch (__func) { case __COMMCTL_IRQ_ENABLE: HAL_INTERRUPT_UNMASK(info->intnum); info->irq = 1; break; case __COMMCTL_IRQ_DISABLE: ret = info->irq; info->irq = 0; HAL_INTERRUPT_MASK(info->intnum); break; case __COMMCTL_DBG_ISR_VECTOR: ret = info->intnum; break; case __COMMCTL_SET_TIMEOUT: { va_list ap; va_start(ap, __func); ret = info->timeout; info->timeout = va_arg(ap, cyg_uint32); va_end(ap); } default: break; } CYGARC_HAL_RESTORE_GP(); return ret;}/* * Low-level interrupt (ISR) handler * This function can be called on only an SMC port */static intcyg_hal_smcx_isr(void *__ch_data, int* __ctrlc, CYG_ADDRWORD __vector, CYG_ADDRWORD __data){ EPPC *eppc = eppc_base(); volatile struct cp_bufdesc *bd; struct port_info *info = (struct port_info *)__ch_data; volatile struct smc_regs *regs = (volatile struct smc_regs *)((char *)eppc + info->regs); volatile struct smc_uart_pram *uart_pram = (volatile struct smc_uart_pram *)((char *)eppc + info->pram); char ch; int res = 0; CYGARC_HAL_SAVE_GP(); *__ctrlc = 0; if (regs->smc_smce & QUICC_SMCE_RX) { regs->smc_smce = QUICC_SMCE_RX; /* rx buffer descriptors */ bd = info->next_rxbd; if ((bd->ctrl & QUICC_BD_CTL_Ready) == 0) { // then there be a character waiting ch = bd->buffer[0]; bd->length = 1; bd->ctrl |= QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int; if (bd->ctrl & QUICC_BD_CTL_Wrap) { bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase); } else { bd++; } info->next_rxbd = bd; if( cyg_hal_is_break( &ch , 1 ) ) *__ctrlc = 1; } // Interrupt handled. Acknowledge it. HAL_INTERRUPT_ACKNOWLEDGE(info->intnum); res = CYG_ISR_HANDLED; } CYGARC_HAL_RESTORE_GP(); return res;}#if (CYGNUM_HAL_QUICC_SCC1+CYGNUM_HAL_QUICC_SCC2+CYGNUM_HAL_QUICC_SCC3) > 0/* * Initialize an SCC as a uart. * * Comments below reference Motorola's "MPC860 User Manual". * The basic initialization steps are from Section 16.15.8 * of that manual. */ static voidcyg_hal_sccx_init_channel(struct port_info *info, int port){ EPPC *eppc = eppc_base(); int i; volatile struct uart_pram *uart_pram = (volatile struct uart_pram *)((char *)eppc + info->pram); volatile struct scc_regs *regs = (volatile struct scc_regs *)((char *)eppc + info->regs); struct cp_bufdesc *txbd, *rxbd; if (info->init) return; info->init = 1; /* * Set up the Port pins for UART operation. */ switch (port) {#if CYGNUM_HAL_QUICC_SCC1 > 0 case QUICC_CPM_SCC1: eppc->pio_papar |= 0x03; eppc->pio_padir &= ~0x03; eppc->pio_paodr &= ~0x03; /* CTS on PortC.11 */ eppc->pio_pcdir &= 0x800; eppc->pio_pcpar &= 0x800; eppc->pio_pcso |= 0x800; /* RTS on PortB.19 */ eppc->pip_pbpar |= 0x1000; eppc->pip_pbdir |= 0x1000; break;#endif#if CYGNUM_HAL_QUICC_SCC2 > 0 case QUICC_CPM_SCC2:#error FIXME eppc->pio_papar |= 0x0C; eppc->pio_padir &= ~0x0C; eppc->pio_paodr &= ~0x0C; /* CTS on PortC.11 */ eppc->pio_pcdir &= 0xC00; eppc->pio_pcpar &= 0xC00; eppc->pio_pcso |= 0xC00; /* RTS on PortB.19 */ eppc->pip_pbpar |= 0x2000; eppc->pip_pbdir |= 0x2000; break;#endif#if CYGNUM_HAL_QUICC_SCC3 > 0 case QUICC_CPM_SCC3:#if defined(CYGHWR_HAL_POWERPC_MPC8XX_850)#if 0// CAUTION! Enabling these bits made the port get stuck :-( /* CTS/RTS/CD on PortC.4/5/13 */ eppc->pio_pcdir &= 0x0C04; eppc->pio_pcpar &= 0x0C00;// eppc->pio_pcpar |= 0x0004; eppc->pio_pcso |= 0x0C00;#endif /* RxD/TxD on PortB.24/25 */ eppc->pip_pbpar |= 0x00C0; eppc->pip_pbdir |= 0x00C0; eppc->pip_pbodr &= ~0x00C0;#elif defined(CYGHWR_HAL_POWERPC_MPC8XX_852T) eppc->pio_papar |= 0x30; eppc->pio_padir &= ~0x30; eppc->pio_paodr &= ~0x30;#else#error "Cannot route SCC3 I/O"#endif // 850T break;#endif // SCC3 } // Set up baud rate generator. These are allocated from a // pool, based on the port number and type. The allocator // will arrange to have the selected baud rate clock steered // to this device. info->brg = _mpc8xx_allocate_brg(port); *(info->brg) = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1); /* * Set pointers to buffer descriptors. */ uart_pram->rbase = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*info->Rxnum + info->Rxnum); uart_pram->tbase = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*info->Txnum + info->Txnum); /* * SDMA & LCD bus request level 5 */ eppc->dma_sdcr = 1; /* * Set Rx and Tx function code */ uart_pram->rfcr = 0x18; uart_pram->tfcr = 0x18; /* max receive buffer length */ uart_pram->mrblr = 1; /* disable max_idle feature */ uart_pram->max_idl = 0; /* no last brk char received */ uart_pram->brkln = 0; /* no break condition occurred */ uart_pram->brkec = 0; /* 1 break char sent on top XMIT */ uart_pram->brkcr = 1; /* character mask */ uart_pram->rccm = 0xC0FF; /* control characters */ for (i = 0; i < 8; i++) { uart_pram->cc[i] = 0x8000; // Mark unused } /* setup RX buffer descriptors */ rxbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase); info->next_rxbd = rxbd; for (i = 0; i < info->Rxnum; i++) { rxbd->length = 0; rxbd->buffer = ((char *)eppc + (uart_pram->rbase+(info->Rxnum*sizeof(struct cp_bufdesc))))+i; rxbd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int; rxbd++; } rxbd--; rxbd->ctrl |= QUICC_BD_CTL_Wrap; /* setup TX buffer descriptor */ txbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase); txbd->length = 0; txbd->buffer = ((char *)eppc + (uart_pram->tbase+(info->Txnum*sizeof(struct cp_bufdesc)))); txbd->ctrl = 0x2000; /* * Clear any previous events. Mask interrupts. * (Section 16.15.7.14 and 16.15.7.15) */ regs->scc_scce = 0xffff; regs->scc_sccm = 1; // RX interrupts only, for ctrl-c /* * Set 8,n,1 characters */ regs->scc_psmr = (3<<12); regs->scc_gsmr_h = 0x20; // 8bit FIFO regs->scc_gsmr_l = 0x00028004; // 16x TxCLK, 16x RxCLK, UART /* * Init Rx & Tx params for SCCX */ eppc->cp_cr = QUICC_CPM_CR_INIT_TXRX | port | QUICC_CPM_CR_BUSY; regs->scc_gsmr_l |= 0x30; // Enable Rx, Tx info->irq = 0;}static intcyg_hal_sccx_isr(void *__ch_data, int* __ctrlc, CYG_ADDRWORD __vector, CYG_ADDRWORD __data){ EPPC *eppc = eppc_base(); volatile struct cp_bufdesc *bd; struct port_info *info = (struct port_info *)__ch_data; volatile struct scc_regs *regs = (volatile struct scc_regs *)((char *)eppc + info->regs); volatile struct uart_pram *uart_pram = (volatile struct uart_pram *)((char *)eppc + info->pram); char ch; int res = 0; CYGARC_HAL_SAVE_GP(); *__ctrlc = 0; if (regs->scc_scce & QUICC_SMCE_RX) { regs->scc_scce = QUICC_SMCE_RX; /* rx buffer descriptors */ bd = info->next_rxbd; if ((bd->ctrl & QUICC_BD_CTL_Ready) == 0) { // then there be a character waiting ch = bd->buffer[0]; bd->length = 1; bd->ctrl |= QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int; if (bd->ctrl & QUICC_BD_CTL_Wrap) { bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase); } else { bd++; } info->next_rxbd = bd; if( cyg_hal_is_break( &ch , 1 ) ) *__ctrlc = 1; } // Interrupt handled. Acknowledge it. HAL_INTERRUPT_ACKNOWLEDGE(info->intnum); res = CYG_ISR_HANDLED; } CYGARC_HAL_RESTORE_GP(); return res;}#endif // CYGNUM_HAL_QUICC_SCCX/* * Early initialization of comm channels. Must not rely * on interrupts, yet. Interrupt operation can be enabled * in _bsp_board_init(). */voidcyg_hal_plf_serial_init(void){ hal_virtual_comm_table_t* comm; int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); static int init = 0; // It's wrong to do this more than once int chan = 0; if (init) return; init++; // Setup procs in the vector table#if CYGNUM_HAL_QUICC_SMC1 > 0 // Set up SMC1 cyg_hal_smcx_init_channel(&ports[chan], QUICC_CPM_SMC1); CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable! comm = CYGACC_CALL_IF_CONSOLE_PROCS(); CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]); CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sxx_write); CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read); CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sxx_putc); CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc); CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control); CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_smcx_isr); CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout); chan++;#endif#if CYGNUM_HAL_QUICC_SMC2 > 0 // Set up SMC2 cyg_hal_smcx_init_channel(&ports[chan], QUICC_CPM_SMC2); CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable! comm = CYGACC_CALL_IF_CONSOLE_PROCS(); CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]); CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sxx_write); CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read); CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sxx_putc); CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc); CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control); CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_smcx_isr); CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout); chan++;#endif#if CYGNUM_HAL_QUICC_SCC1 > 0 // Set up SCC1 cyg_hal_sccx_init_channel(&ports[chan], QUICC_CPM_SCC1); CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable! comm = CYGACC_CALL_IF_CONSOLE_PROCS(); CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]); CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sxx_write); CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read); CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sxx_putc); CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc); CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control); CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_sccx_isr); CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout); chan++;#endif#if CYGNUM_HAL_QUICC_SCC2 > 0 // Set up SCC2 cyg_hal_sccx_init_channel(&ports[chan], QUICC_CPM_SCC2); CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable! comm = CYGACC_CALL_IF_CONSOLE_PROCS(); CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]); CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sxx_write); CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read); CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sxx_putc); CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc); CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control); CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_sccx_isr); CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout); chan++;#endif#if CYGNUM_HAL_QUICC_SCC3 > 0 // Set up SCC3 cyg_hal_sccx_init_channel(&ports[chan], QUICC_CPM_SCC3); CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable! comm = CYGACC_CALL_IF_CONSOLE_PROCS(); CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]); CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sxx_write); CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read); CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sxx_putc); CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc); CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control); CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_sccx_isr); CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout); chan++;#endif // Restore original console CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);}// EOF quicc_smc1.c
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?