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