mpc8xxx_serial.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,017 行 · 第 1/3 页

C
1,017
字号
    if (baud_divisor == 0) return false;    // Disable channel during setup    ctl->smc_smcmr = MPC8XXX_SMCMR_UART;  // Disabled, UART mode    HAL_IO_BARRIER();  // Inforce I/O ordering    // Disable port interrupts while changing hardware    _lcr = smc_select_word_length[new_config->word_length - CYGNUM_SERIAL_WORD_LENGTH_5] |         smc_select_stop_bits[new_config->stop] |        smc_select_parity[new_config->parity];    // Stop transmitter while changing baud rate    IMM->cpm_cpcr = smc_chan->channel | CPCR_STOP_TX | CPCR_FLG;    HAL_IO_BARRIER();  // Inforce I/O ordering    // Set baud rate generator    *smc_chan->brg = 0x10000 | (UART_BITRATE(baud_divisor)<<1);    // Enable channel with new configuration    ctl->smc_smcmr = MPC8XXX_SMCMR_UART|MPC8XXX_SMCMR_TEN|MPC8XXX_SMCMR_REN|_lcr;    HAL_IO_BARRIER();  // Inforce I/O ordering    IMM->cpm_cpcr = smc_chan->channel | CPCR_INIT_TX_RX_PARAMS | CPCR_FLG;    if (new_config != &chan->config) {        chan->config = *new_config;    }    return true;}// Function to set up internal tables for device.static voidmpc8xxx_smc_serial_init_info(mpc8xxx_sxx_serial_info *smc_chan,                             t_Smc_Pram *uart_pram,                             volatile struct smc_regs_8260 *ctl,                             unsigned long *brg,                             int TxBD, int TxNUM, int TxSIZE,                             cyg_uint8 *TxBUF,                             int RxBD, int RxNUM, int RxSIZE,                             cyg_uint8 *RxBUF){    struct cp_bufdesc *txbd, *rxbd;    int i;        smc_chan->pram = (void *)uart_pram;    smc_chan->ctl = (void *)ctl;    // Set up baud rate generator    smc_chan->brg = (void *)brg;    // Disable channel during setup    ctl->smc_smcmr = MPC8XXX_SMCMR_UART;  // Disabled, UART mode    // Rx, Tx function codes (used for access)    uart_pram->rfcr = 0x18;    uart_pram->tfcr = 0x18;    // Pointers to Rx & Tx buffer descriptor rings    uart_pram->rbase = RxBD;    uart_pram->tbase = TxBD;    /* tx and rx buffer descriptors */    txbd = (struct cp_bufdesc *)((char *)IMM + TxBD);    rxbd = (struct cp_bufdesc *)((char *)IMM + RxBD);    smc_chan->txbd = txbd;    smc_chan->tbase = txbd;    smc_chan->txsize = TxSIZE;    smc_chan->rxbd = rxbd;    smc_chan->rbase = rxbd;    smc_chan->rxsize = RxSIZE;    /* set max_idle feature - generate interrupt after 4 chars idle period */    uart_pram->max_idl = 4;    /* 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;    /* setup RX buffer descriptors */    for (i = 0;  i < RxNUM;  i++) {        rxbd->length = 0;        rxbd->buffer = RxBUF;        rxbd->ctrl   = _BD_CTL_Ready | _BD_CTL_Int;        if (i == (RxNUM-1)) rxbd->ctrl |= _BD_CTL_Wrap;  // Last buffer        RxBUF += RxSIZE;        rxbd++;    }    /* setup TX buffer descriptors */    for (i = 0;  i < TxNUM;  i++) {        txbd->length = 0;        txbd->buffer = TxBUF;        txbd->ctrl   = 0;        if (i == (TxNUM-1)) txbd->ctrl |= _BD_CTL_Wrap;  // Last buffer        TxBUF += TxSIZE;        txbd++;    }    /*     *  Reset Rx & Tx params     */    HAL_IO_BARRIER();  // Inforce I/O ordering    IMM->cpm_cpcr = smc_chan->channel | CPCR_INIT_TX_RX_PARAMS | CPCR_FLG;    HAL_IO_BARRIER();  // Inforce I/O ordering    /*     *  Clear any previous events. Enable interrupts.     *  (Section 16.15.7.14 and 16.15.7.15)     */    ctl->smc_smce = 0xFF;    ctl->smc_smcm = SMCE_Bsy|SMCE_Tx|SMCE_Rx;}// Internal function to actually configure the hardware to desired baud rate, etc.static boolmpc8xxx_scc_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init){    mpc8xxx_sxx_serial_info *scc_chan = (mpc8xxx_sxx_serial_info *)chan->dev_priv;    unsigned int baud_divisor = select_baud[new_config->baud];    volatile struct scc_regs_8260 *regs = (volatile struct scc_regs_8260*)scc_chan->ctl;    if (baud_divisor == 0) return false;    // Set baud rate generator    *scc_chan->brg = 0x10000 | (UART_BITRATE(baud_divisor)<<1);    // Disable channel during setup    HAL_IO_BARRIER();  // Inforce I/O ordering    regs->gsmr_l = 0;    regs->psmr = MPC8XXX_SCC_PSMR_ASYNC |         scc_select_word_length[new_config->word_length - CYGNUM_SERIAL_WORD_LENGTH_5] |         scc_select_stop_bits[new_config->stop] |        scc_select_parity[new_config->parity];    // Enable channel with new configuration    regs->gsmr_h = 0x20;          // 8bit FIFO    regs->gsmr_l = 0x00028004;    // 16x TxCLK, 16x RxCLK, UART    /*     *  Init Rx & Tx params for SCCX     */    HAL_IO_BARRIER();  // Inforce I/O ordering    IMM->cpm_cpcr = CPCR_INIT_TX_RX_PARAMS | scc_chan->channel | CPCR_FLG;    HAL_IO_BARRIER();  // Inforce I/O ordering    regs->gsmr_l |= GSMR_L1_ENT | GSMR_L1_ENR;  // Enable Rx, Tx    if (new_config != &chan->config) {        chan->config = *new_config;    }    return true;}// Function to set up internal tables for device.static voidmpc8xxx_scc_serial_init_info(mpc8xxx_sxx_serial_info *scc_chan,                              volatile t_Scc_Pram *uart_pram,                             volatile struct scc_regs_8260 *ctl,                             unsigned long *brg,                             int TxBD, int TxNUM, int TxSIZE,                             cyg_uint8 *TxBUF,                             int RxBD, int RxNUM, int RxSIZE,                             cyg_uint8 *RxBUF){    struct cp_bufdesc *txbd, *rxbd;    int i;    // Disable channel during setup    ctl->gsmr_l = 0;    scc_chan->pram = (void *)uart_pram;    scc_chan->ctl = (void *)ctl;    // Set up baud rate generator    scc_chan->brg = brg;    /*     *  Set Rx and Tx function code     *  (Section 16.15.4.2)     */    uart_pram->rfcr = 0x18;    uart_pram->tfcr = 0x18;    /*     *  Set pointers to buffer descriptors.     *  (Sections 16.15.4.1, 16.15.7.12, and 16.15.7.13)     */    uart_pram->rbase = RxBD;    uart_pram->tbase = TxBD;    /* tx and rx buffer descriptors */    txbd = (struct cp_bufdesc *)((char *)IMM + TxBD);    rxbd = (struct cp_bufdesc *)((char *)IMM + RxBD);    scc_chan->txbd = txbd;    scc_chan->tbase = txbd;    scc_chan->txsize = TxSIZE;    scc_chan->rxbd = rxbd;    scc_chan->rbase = rxbd;    scc_chan->rxsize = RxSIZE;    /* max receive buffer length */    uart_pram->mrblr = RxSIZE;    /* set max_idle feature - generate interrupt after 4 chars idle period */    uart_pram->SpecificProtocol.u.max_idl = 4;    /* no last brk char received */    uart_pram->SpecificProtocol.u.brkln = 0;    /* no break condition occurred */    uart_pram->SpecificProtocol.u.brkec = 0;    /* 1 break char sent on top XMIT */    uart_pram->SpecificProtocol.u.brkcr = 1;    /* character mask */    uart_pram->SpecificProtocol.u.rccm  = 0xC0FF;    /* control characters */    for (i = 0;  i < 8;  i++) {        uart_pram->SpecificProtocol.u.cc[i] = 0x8000;  // Mark unused    }    /* setup RX buffer descriptors */    for (i = 0;  i < RxNUM;  i++) {        rxbd->length = 0;        rxbd->buffer = RxBUF;        rxbd->ctrl   = _BD_CTL_Ready | _BD_CTL_Int;        if (i == (RxNUM-1)) rxbd->ctrl |= _BD_CTL_Wrap;  // Last buffer        RxBUF += RxSIZE;        rxbd++;    }    /* setup TX buffer descriptors */    for (i = 0;  i < TxNUM;  i++) {        txbd->length = 0;        txbd->buffer = TxBUF;        txbd->ctrl   = 0;        if (i == (TxNUM-1)) txbd->ctrl |= _BD_CTL_Wrap;  // Last buffer        TxBUF += TxSIZE;        txbd++;    }    /*     *  Reset Rx & Tx params     */    HAL_IO_BARRIER();  // Inforce I/O ordering    IMM->cpm_cpcr = scc_chan->channel | CPCR_INIT_TX_RX_PARAMS | CPCR_FLG;    /*     *  Clear any previous events. Enable interrupts.     *  (Section 16.15.7.14 and 16.15.7.15)     */    HAL_IO_BARRIER();  // Inforce I/O ordering    ctl->scce = 0xFFFF;    ctl->sccm = (SCCE_Bsy | SCCE_Tx | SCCE_Rx);}// Function to initialize the device.  Called at bootstrap time.static bool mpc8xxx_sxx_serial_init(struct cyg_devtab_entry *tab){    serial_channel *chan = (serial_channel *)tab->priv;    mpc8xxx_sxx_serial_info *smc_chan = (mpc8xxx_sxx_serial_info *)chan->dev_priv;    int TxBD, RxBD;    int cache_state;    HAL_DCACHE_IS_ENABLED(cache_state);    HAL_DCACHE_SYNC();    HAL_DCACHE_DISABLE();#ifdef CYGDBG_IO_INIT    diag_printf("MPC8XXX_SMC SERIAL init - dev: %x.%d = %s\n", smc_chan->channel, smc_chan->int_num, tab->name);#endif#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC8XXX_SMC1    if (chan == &mpc8xxx_sxx_serial_channel_smc1) {        TxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC1_TxNUM);        RxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC1_RxNUM);        mpc8xxx_smc_serial_init_info(&mpc8xxx_sxx_serial_info_smc1,                                     (t_Smc_Pram *)((char *)IMM + DPRAM_SMC1_OFFSET),                                     &IMM->smc_regs[SMC1],                                     (unsigned long *)&IMM->brgs_brgc7,                                     TxBD,                                      CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC1_TxNUM,                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC1_TxSIZE,                                     &mpc8xxx_smc1_txbuf[0],                                     RxBD,                                      CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC1_RxNUM,                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC1_RxSIZE,                                     &mpc8xxx_smc1_rxbuf[0]            );    }#endif#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC8XXX_SMC2#warning "Serial driver on SMC2 is unverified"    if (chan == &mpc8xxx_sxx_serial_channel_smc2) {        TxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC2_TxNUM);        RxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC2_RxNUM);        mpc8xxx_smc_serial_init_info(&mpc8xxx_sxx_serial_info_smc2,                                     &IMM->pram[3].scc.pothers.smc_modem.psmc.u, // PRAM                                     &IMM->smc_regs[1], // Control registers                                     &IMM->brgs_brgc7,                                     TxBD,                                      CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC2_TxNUM,                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC2_TxSIZE,                                     &mpc8xxx_smc2_txbuf[0],                                     RxBD,                                      CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC2_RxNUM,                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SMC2_RxSIZE,                                     &mpc8xxx_smc2_rxbuf[0]            );    }#endif#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC8XXX_SCC1    if (chan == &mpc8xxx_sxx_serial_channel_scc1) {        TxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC1_TxNUM);        RxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC1_RxNUM);        mpc8xxx_scc_serial_init_info(&mpc8xxx_sxx_serial_info_scc1,                                     &IMM->pram.serials.scc_pram[SCC1],                                     &IMM->scc_regs[SCC1],                                     (unsigned long *)&IMM->brgs_brgc1,                                     TxBD,                                      CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC1_TxNUM,                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC1_TxSIZE,                                     &mpc8xxx_scc1_txbuf[0],                                     RxBD,                                      CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC1_RxNUM,                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC1_RxSIZE,                                     &mpc8xxx_scc1_rxbuf[0]            );    }#endif#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC8XXX_SCC2#warning "Serial driver on SCC2 is unverified"    if (chan == &mpc8xxx_sxx_serial_channel_scc2) {        TxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC2_TxNUM);        RxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC2_RxNUM);        mpc8xxx_scc_serial_init_info(&mpc8xxx_sxx_serial_info_scc2,                                     &IMM->pram[1].scc.pscc.u, // PRAM                                     &IMM->scc_regs[1],        // Control registers                                     &IMM->brgs_brgc2,                                     TxBD,                                      CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC2_TxNUM,                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC2_TxSIZE,                                     &mpc8xxx_scc2_txbuf[0],                                     RxBD,                                      CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC2_RxNUM,                                     CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC2_RxSIZE,                                     &mpc8xxx_scc2_rxbuf[0]            );    }#endif#ifdef CYGPKG_IO_SERIAL_POWERPC_MPC8XXX_SCC3#warning "Serial driver on SCC3 is unverified"    if (chan == &mpc8xxx_sxx_serial_channel_scc3) {        TxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC3_TxNUM);        RxBD = _mpc8xxx_allocBd(sizeof(struct cp_bufdesc)*CYGNUM_IO_SERIAL_POWERPC_MPC8XXX_SCC3_RxNUM);        mpc8xxx_scc_serial_init_info(&mpc8xxx_sxx_serial_info_scc3,                                     &IMM->pram[2].scc.pscc.u, // PRAM                                     &IMM->scc_regs[2],        // Control registersn                                     &IMM->brgs_brgc3,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?