quicc2_scc_serial.c

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

C
852
字号
    IMM->io_regs[PORT_D].pdir |=  QUICC2_SCC1_PORTD_PDIR;    IMM->io_regs[PORT_D].podr &= ~QUICC2_SCC1_PORTD_PPAR;    // Set-up the PORT C pins    IMM->io_regs[PORT_C].psor &= ~QUICC2_SCC1_PORTC_PPAR;    IMM->io_regs[PORT_C].ppar |=  QUICC2_SCC1_PORTC_PPAR;    IMM->io_regs[PORT_C].pdir &= ~QUICC2_SCC1_PORTC_PPAR;    IMM->io_regs[PORT_C].podr &= ~QUICC2_SCC1_PORTC_PPAR;    // Select the baud rate generator and connect it     IMM->cpm_mux_cmxscr &= QUICC2_CMX_SCC1_CLR;    switch (BRG_index) {    case 1:      scc_chan->brg = &(IMM->brgs_brgc1);      IMM->cpm_mux_cmxscr |= QUICC2_CMX_SCC1_BRG1;      break;    case 2:      scc_chan->brg = &(IMM->brgs_brgc2);      IMM->cpm_mux_cmxscr |= QUICC2_CMX_SCC1_BRG2;      break;    case 3:      scc_chan->brg = &(IMM->brgs_brgc3);      IMM->cpm_mux_cmxscr |= QUICC2_CMX_SCC1_BRG3;      break;    case 4:      scc_chan->brg = &(IMM->brgs_brgc4);      IMM->cpm_mux_cmxscr |= QUICC2_CMX_SCC1_BRG4;      break;    }#ifdef CYGPKG_HAL_POWERPC_VADS         // Enable the transciever    bcsr->bcsr1 &= ~(QUICC2_BCSR_EN_SCC1);#endif    break;  case 2:    // Put the data into the info structure     scc_chan->scc_cpcr = QUICC2_CPCR_SCC2;    scc_chan->scc_regs = &(IMM->scc_regs[1]);    scc_chan->scc_pram = &(IMM->pram.serials.scc_pram[1]);    scc_chan->int_vector = CYGNUM_HAL_INTERRUPT_SCC2;    // Set-up the PORT D pins    IMM->io_regs[PORT_D].psor &= ~QUICC2_SCC2_PORTD_PPAR;    IMM->io_regs[PORT_D].ppar |=  QUICC2_SCC2_PORTD_PPAR;    IMM->io_regs[PORT_D].pdir &= ~QUICC2_SCC2_PORTD_PPAR;    IMM->io_regs[PORT_D].pdir |=  QUICC2_SCC2_PORTD_PDIR;    IMM->io_regs[PORT_D].podr &= ~QUICC2_SCC2_PORTD_PPAR;    // Set-up the PORT C pins    IMM->io_regs[PORT_C].psor &= ~QUICC2_SCC2_PORTC_PPAR;    IMM->io_regs[PORT_C].ppar |=  QUICC2_SCC2_PORTC_PPAR;    IMM->io_regs[PORT_C].pdir &= ~QUICC2_SCC2_PORTC_PPAR;    IMM->io_regs[PORT_C].podr &= ~QUICC2_SCC2_PORTC_PPAR;    // Select the baud rate generator and connect it     IMM->cpm_mux_cmxscr &= QUICC2_CMX_SCC2_CLR;    switch (BRG_index) {    case 1:      scc_chan->brg = &(IMM->brgs_brgc1);      IMM->cpm_mux_cmxscr |= QUICC2_CMX_SCC2_BRG1;      break;    case 2:      scc_chan->brg = &(IMM->brgs_brgc2);      IMM->cpm_mux_cmxscr |= QUICC2_CMX_SCC2_BRG2;      break;    case 3:      scc_chan->brg = &(IMM->brgs_brgc3);      IMM->cpm_mux_cmxscr |= QUICC2_CMX_SCC2_BRG3;      break;    case 4:      scc_chan->brg = &(IMM->brgs_brgc4);      IMM->cpm_mux_cmxscr |= QUICC2_CMX_SCC2_BRG4;      break;    } #ifdef CYGPKG_HAL_POWERPC_VADS     // Enable the transciever    bcsr->bcsr1 &= ~(QUICC2_BCSR_EN_SCC2);#endif    break;  default:    diag_printf("Incorrect SCC index in quicc2_scc_serial_init_info \n");    break;  }  // Initialize common SCC PRAM  scc_chan->tbase = (scc_bd *) (QUICC2_VADS_IMM_BASE + TxBD);  scc_chan->rbase = (scc_bd *) (QUICC2_VADS_IMM_BASE + RxBD);  scc_chan->txbd  = (scc_bd *) (QUICC2_VADS_IMM_BASE + TxBD);  scc_chan->rxbd  = (scc_bd *) (QUICC2_VADS_IMM_BASE + RxBD);  scc_chan->txsize = TxSIZE;  scc_chan->rxsize = RxSIZE;  scc_chan->scc_pram->rbase = RxBD;  scc_chan->scc_pram->tbase = TxBD;  scc_chan->scc_pram->rfcr  = 0x10;  scc_chan->scc_pram->tfcr  = 0x10;  scc_chan->scc_pram->mrblr = RxSIZE;  // Initialize UART PRAM  uart_pram = &(scc_chan->scc_pram->SpecificProtocol.u);      uart_pram->max_idl = 4;  uart_pram->brkcr   = 1;  uart_pram->brkln   = 0;  uart_pram->parec   = 0;  uart_pram->frmec   = 0;  uart_pram->nosec   = 0;  uart_pram->brkec   = 0;  uart_pram->uaddr1  = 0;  uart_pram->uaddr2  = 0;  uart_pram->toseq   = 0;  uart_pram->cc[0] = 0x8000;  uart_pram->cc[1] = 0x8000;  uart_pram->cc[2] = 0x8000;  uart_pram->cc[3] = 0x8000;  uart_pram->cc[4] = 0x8000;  uart_pram->cc[5] = 0x8000;  uart_pram->cc[6] = 0x8000;  uart_pram->cc[7] = 0x8000;  uart_pram->rccm  = 0xC0FF;  // Initialize registers  scc_chan->scc_regs->gsmr_l = QUICC2_SCC_GSMR_L_INIT;  scc_chan->scc_regs->gsmr_h = QUICC2_SCC_GSMR_H_INIT;  // scc_chan->scc_regs->psmr   = 0x8000;  // Set by config  scc_chan->scc_regs->todr   = 0;  //  scc_chan->scc_regs->dsr    = 0x7e7e; // Set by config  scc_chan->scc_regs->scce   = 0xffff;  scc_chan->scc_regs->sccm   = (QUICC2_SCCE_BSY | QUICC2_SCCE_TX | QUICC2_SCCE_RX);  /* setup RX buffer descriptors */  rxbd = (struct scc_bd *)((char *) QUICC2_VADS_IMM_BASE + RxBD);  for (i = 0;  i < RxNUM;  i++) {    rxbd->ctrl   = QUICC2_BD_CTL_Ready | QUICC2_BD_CTL_Int;    rxbd->length = 0;    rxbd->buffer = RxBUF;    RxBUF += RxSIZE;    rxbd++;  }  rxbd--;  rxbd->ctrl |= QUICC2_BD_CTL_Wrap;  // Last buffer  /* setup TX buffer descriptors */  txbd = (struct scc_bd *)((char *) QUICC2_VADS_IMM_BASE + TxBD);  for (i = 0;  i < TxNUM;  i++) {    txbd->ctrl   = 0;    txbd->length = 0;    txbd->buffer = TxBUF;    TxBUF += TxSIZE;    txbd++;  }  txbd--;  txbd->ctrl |= QUICC2_BD_CTL_Wrap;  // Last buffer    // Issue Init RX & TX Parameters Command   while (IMM->cpm_cpcr & QUICC2_CPCR_READY);  IMM->cpm_cpcr = scc_chan->scc_cpcr | QUICC2_CPCR_INIT_TX_RX | QUICC2_CPCR_READY;  while (IMM->cpm_cpcr & QUICC2_CPCR_READY);  return;}// Function to initialize the device.  Called at bootstrap time.static bool quicc2_scc_serial_init(struct cyg_devtab_entry *tab){  serial_channel *chan = (serial_channel *)tab->priv;  quicc2_scc_serial_info *scc_chan = (quicc2_scc_serial_info *)chan->dev_priv;  volatile t_PQ2IMM *IMM = (volatile t_PQ2IMM *) QUICC2_VADS_IMM_BASE;  int TxBD, RxBD;  static int first_init = 1;  int cache_state;    HAL_DCACHE_IS_ENABLED(cache_state);  HAL_DCACHE_SYNC();  HAL_DCACHE_DISABLE();#ifdef CYGDBG_IO_INIT  diag_printf("QUICC2_SCC SERIAL init - dev: %x\n",               scc_chan->channel);#endif    if (first_init) {        // Set up tables since many fields are dynamic [computed at runtime]        first_init = 0;#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC2_SCC_SCC1        // Totally reset the CP        while (IMM->cpm_cpcr & QUICC2_CPCR_READY);        IMM->cpm_cpcr = QUICC2_CPCR_RESET | QUICC2_CPCR_READY;        while (IMM->cpm_cpcr & QUICC2_CPCR_READY);        TxBD = 0x2800;  // Note: this should be configurable        RxBD = TxBD + CYGNUM_IO_SERIAL_POWERPC_QUICC2_SCC_SCC1_TxNUM*8;        quicc2_scc_serial_init_info(&quicc2_scc_serial_info1,                                    1, // indicates SCC1                                    CYGNUM_IO_SERIAL_POWERPC_QUICC2_SCC_SCC1_BRG,                                    TxBD,                                     CYGNUM_IO_SERIAL_POWERPC_QUICC2_SCC_SCC1_TxNUM,                                    CYGNUM_IO_SERIAL_POWERPC_QUICC2_SCC_SCC1_TxSIZE,                                    ALIGN_TO_CACHELINES(&quicc2_scc1_txbuf[0][0]),                                    RxBD,                                     CYGNUM_IO_SERIAL_POWERPC_QUICC2_SCC_SCC1_RxNUM,                                    CYGNUM_IO_SERIAL_POWERPC_QUICC2_SCC_SCC1_RxSIZE,                                    ALIGN_TO_CACHELINES(&quicc2_scc1_rxbuf[0][0])                                    );#else#ifdef CYGPKG_HAL_POWERPC_MPC8260        // Ensure that SCC1 side is initialized first        diag_init(); // (pull in constructor that inits diag channel)        TxBD = 0x2900;  // Note : this should be inferred from the                        // chip state#else        // there is no diag device wanting to use the QUICC, so prepare it        // for SCC2 use only.        while (IMM->cpm_cpcr & QUICC2_CPCR_READY); // Totally reset the CP        IMM->cpm_cpcr = QUICC2_CPCR_RESET | QUICC2_CPCR_READY;        while (IMM->cpm_cpcr & QUICC2_CPCR_READY);        TxBD = 0x2800; // Note: this should be configurable#endif#endif#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC2_SCC_SCC2        RxBD = TxBD + CYGNUM_IO_SERIAL_POWERPC_QUICC2_SCC_SCC2_TxNUM*8;        quicc2_scc_serial_init_info(&quicc2_scc_serial_info2,                                    2, // indicates SCC2                                    CYGNUM_IO_SERIAL_POWERPC_QUICC2_SCC_SCC2_BRG,                                    TxBD,                                     CYGNUM_IO_SERIAL_POWERPC_QUICC2_SCC_SCC2_TxNUM,                                    CYGNUM_IO_SERIAL_POWERPC_QUICC2_SCC_SCC2_TxSIZE,                                    ALIGN_TO_CACHELINES(&quicc2_scc2_txbuf[0][0]),                                    RxBD,                                     CYGNUM_IO_SERIAL_POWERPC_QUICC2_SCC_SCC2_RxNUM,                                    CYGNUM_IO_SERIAL_POWERPC_QUICC2_SCC_SCC2_RxSIZE,                                    ALIGN_TO_CACHELINES(&quicc2_scc2_rxbuf[0][0])            );#endif    }    // Really only required for interrupt driven devices    (chan->callbacks->serial_init)(chan);      if (chan->out_cbuf.len != 0) {        cyg_drv_interrupt_create(scc_chan->int_vector,                                 0, // CYGARC_SIU_PRIORITY_HIGH, - unused                                  (cyg_addrword_t)chan,   //  Data item passed to interrupt handler                                 quicc2_scc_serial_ISR,                                 quicc2_scc_serial_DSR,                                 &scc_chan->serial_interrupt_handle,                                 &scc_chan->serial_interrupt);        cyg_drv_interrupt_attach(scc_chan->serial_interrupt_handle);        cyg_drv_interrupt_acknowledge(scc_chan->int_vector);        cyg_drv_interrupt_unmask(scc_chan->int_vector);    }    quicc2_scc_serial_config_port(chan, &chan->config, true);    if (cache_state)        HAL_DCACHE_ENABLE();    return true;}// This routine is called when the device is "looked" up (i.e. attached)static Cyg_ErrNo quicc2_scc_serial_lookup(struct cyg_devtab_entry **tab,                   struct cyg_devtab_entry *sub_tab,                  const char *name){    serial_channel *chan = (serial_channel *)(*tab)->priv;    (chan->callbacks->serial_init)(chan);  // Really only required for interrupt driven devices    return ENOERR;}// Force the current transmit buffer to be sentstatic voidquicc2_scc_serial_flush(quicc2_scc_serial_info *scc_chan){  volatile struct scc_bd *txbd = scc_chan->txbd;

⌨️ 快捷键说明

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