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 + -
显示快捷键?