quicc2_scc_serial.c
来自「开放源码实时操作系统源码.」· 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 sent
static void
quicc2_scc_serial_flush(quicc2_scc_serial_info *scc_chan)
{
volatile struct scc_bd *txbd = scc_chan->txbd;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?