quicc_smc_serial.c
来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,115 行 · 第 1/4 页
C
1,115 行
0, // Does not depend on a lower level interface
&cyg_io_serial_devio,
quicc_sxx_serial_init,
quicc_sxx_serial_lookup, // Serial driver may need initializing
&quicc_sxx_serial_channel_scc2
);
#endif // CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC2
#ifdef CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC3
static quicc_sxx_serial_info quicc_sxx_serial_info_scc3 = {
QUICC_CPM_SCC3, // Channel indicator
CYGNUM_HAL_INTERRUPT_CPM_SCC3, // interrupt
_SCC_CHAN
};
#if CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BUFSIZE > 0
static unsigned char quicc_smc_serial_out_buf_scc3[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BUFSIZE];
static unsigned char quicc_smc_serial_in_buf_scc3[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BUFSIZE];
static SERIAL_CHANNEL_USING_INTERRUPTS(quicc_sxx_serial_channel_scc3,
quicc_sxx_serial_funs,
quicc_sxx_serial_info_scc3,
CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BAUD),
CYG_SERIAL_STOP_DEFAULT,
CYG_SERIAL_PARITY_DEFAULT,
CYG_SERIAL_WORD_LENGTH_DEFAULT,
CYG_SERIAL_FLAGS_DEFAULT,
&quicc_smc_serial_out_buf_scc3[0], sizeof(quicc_smc_serial_out_buf_scc3),
&quicc_smc_serial_in_buf_scc3[0], sizeof(quicc_smc_serial_in_buf_scc3)
);
#else
static SERIAL_CHANNEL(quicc_sxx_serial_channel_scc3,
quicc_sxx_serial_funs,
quicc_sxx_serial_info_scc3,
CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_BAUD),
CYG_SERIAL_STOP_DEFAULT,
CYG_SERIAL_PARITY_DEFAULT,
CYG_SERIAL_WORD_LENGTH_DEFAULT,
CYG_SERIAL_FLAGS_DEFAULT
);
#endif
static unsigned char quicc_scc3_txbuf[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxNUM*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_TxSIZE] __attribute__((aligned(HAL_DCACHE_LINE_SIZE)));
static unsigned char quicc_scc3_rxbuf[CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxNUM*CYGNUM_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_RxSIZE] __attribute__((aligned(HAL_DCACHE_LINE_SIZE)));
DEVTAB_ENTRY(quicc_smc_serial_io_scc3,
CYGDAT_IO_SERIAL_POWERPC_QUICC_SMC_SCC3_NAME,
0, // Does not depend on a lower level interface
&cyg_io_serial_devio,
quicc_sxx_serial_init,
quicc_sxx_serial_lookup, // Serial driver may need initializing
&quicc_sxx_serial_channel_scc3
);
#endif // CYGPKG_IO_SERIAL_POWERPC_QUICC_SMC_SCC3
// Internal function to actually configure the hardware to desired baud rate, etc.
static bool
quicc_smc_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init)
{
quicc_sxx_serial_info *smc_chan = (quicc_sxx_serial_info *)chan->dev_priv;
unsigned int baud_divisor = select_baud[new_config->baud];
cyg_uint32 _lcr;
EPPC *eppc = eppc_base();
volatile struct smc_regs *ctl = (volatile struct smc_regs *)smc_chan->ctl;
if (baud_divisor == 0) return false;
// Disable channel during setup
ctl->smc_smcmr = QUICC_SMCMR_UART; // Disabled, UART mode
HAL_IO_BARRIER(); // Inforce I/O ordering
// Disable port interrupts while changing hardware
_lcr = QUICC_SMCMR_CLEN(new_config->word_length + ((new_config->parity == CYGNUM_SERIAL_PARITY_NONE)? 0: 1) + ((new_config->stop == CYGNUM_SERIAL_STOP_2)? 2: 1)) |
smc_select_stop_bits[new_config->stop] |
smc_select_parity[new_config->parity];
// Stop transmitter while changing baud rate
eppc->cp_cr = smc_chan->channel | QUICC_SMC_CMD_Go | QUICC_SMC_CMD_StopTx;
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 = QUICC_SMCMR_UART|QUICC_SMCMR_TEN|QUICC_SMCMR_REN|_lcr;
HAL_IO_BARRIER(); // Inforce I/O ordering
eppc->cp_cr = smc_chan->channel | QUICC_SMC_CMD_Go | QUICC_SMC_CMD_RestartTx;
if (new_config != &chan->config) {
chan->config = *new_config;
}
return true;
}
// Function to set up internal tables for device.
static void
quicc_smc_serial_init_info(quicc_sxx_serial_info *smc_chan,
volatile struct smc_uart_pram *uart_pram,
volatile struct smc_regs *ctl,
int TxBD, int TxNUM, int TxSIZE,
cyg_uint8 *TxBUF,
int RxBD, int RxNUM, int RxSIZE,
cyg_uint8 *RxBUF,
int portBmask,
int port)
{
EPPC *eppc = eppc_base();
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 = _mpc8xx_allocate_brg(port);
// Disable channel during setup
ctl->smc_smcmr = QUICC_SMCMR_UART; // Disabled, UART mode
/*
* Set up the PortB pins for UART operation.
* Set PAR and DIR to allow SMCTXDx and SMRXDx
* (Table 16-39)
*/
eppc->pip_pbpar |= portBmask;
eppc->pip_pbdir &= ~portBmask;
/*
* SDMA & LCD bus request level 5
* (Section 16.10.2.1)
*/
eppc->dma_sdcr = 1;
/*
* 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 *)eppc + TxBD);
rxbd = (struct cp_bufdesc *)((char *)eppc + 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;
/* max receive buffer length */
uart_pram->mrblr = 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 = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
if (i == (RxNUM-1)) rxbd->ctrl |= QUICC_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 |= QUICC_BD_CTL_Wrap; // Last buffer
TxBUF += TxSIZE;
txbd++;
}
/*
* Reset Rx & Tx params
*/
HAL_IO_BARRIER(); // Inforce I/O ordering
eppc->cp_cr = smc_chan->channel | QUICC_SMC_CMD_Go | QUICC_SMC_CMD_InitTxRx;
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 = QUICC_SMCE_BSY|QUICC_SMCE_TX|QUICC_SMCE_RX;
}
// Internal function to actually configure the hardware to desired baud rate, etc.
static bool
quicc_scc_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init)
{
quicc_sxx_serial_info *scc_chan = (quicc_sxx_serial_info *)chan->dev_priv;
unsigned int baud_divisor = select_baud[new_config->baud];
EPPC *eppc = eppc_base();
volatile struct scc_regs *regs = (volatile struct scc_regs *)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->scc_gsmr_l = 0;
regs->scc_psmr = QUICC_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->scc_gsmr_h = 0x20; // 8bit FIFO
regs->scc_gsmr_l = 0x00028004; // 16x TxCLK, 16x RxCLK, UART
/*
* Init Rx & Tx params for SCCX
*/
HAL_IO_BARRIER(); // Inforce I/O ordering
eppc->cp_cr = QUICC_CPM_CR_INIT_TXRX | scc_chan->channel | QUICC_CPM_CR_BUSY;
HAL_IO_BARRIER(); // Inforce I/O ordering
regs->scc_gsmr_l |= (QUICC_SCC_GSMR_L_Tx | QUICC_SCC_GSMR_L_Rx); // Enable Rx, Tx
if (new_config != &chan->config) {
chan->config = *new_config;
}
return true;
}
// Function to set up internal tables for device.
static void
quicc_scc_serial_init_info(quicc_sxx_serial_info *scc_chan,
volatile struct uart_pram *uart_pram,
volatile struct scc_regs *ctl,
int TxBD, int TxNUM, int TxSIZE,
cyg_uint8 *TxBUF,
int RxBD, int RxNUM, int RxSIZE,
cyg_uint8 *RxBUF,
int portAmask, int portBmask, int portCmask,
int port)
{
EPPC *eppc = eppc_base();
struct cp_bufdesc *txbd, *rxbd;
int i;
// Disable channel during setup
ctl->scc_gsmr_l = 0;
scc_chan->pram = (void *)uart_pram;
scc_chan->ctl = (void *)ctl;
// Set up baud rate generator
scc_chan->brg = _mpc8xx_allocate_brg(port);
/*
* Set up the PortA/B/C pins for UART operation.
*/
eppc->pio_papar |= portAmask;
eppc->pio_padir &= ~portAmask;
eppc->pio_paodr &= ~portAmask;
eppc->pio_pcdir &= portCmask;
eppc->pio_pcpar &= portCmask;
eppc->pio_pcso |= portCmask;
eppc->pip_pbpar |= portBmask;
eppc->pip_pbdir |= portBmask;
/*
* SDMA & LCD bus request level 5
* (Section 16.10.2.1)
*/
eppc->dma_sdcr = 1;
/*
* 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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?