in lib/cmsis/CMSIS/Pack/Example/CMSIS_Driver/USART_LPC18xx.c [1244:1670]
static int32_t USART_Control (uint32_t control,
uint32_t arg,
USART_RESOURCES *usart) {
uint32_t val, mode;
uint32_t syncctrl, hden, icr, scictrl, lcr, mcr;
if ((usart->info->flags & USART_FLAG_POWERED) == 0) {
// USART not powered
return ARM_DRIVER_ERROR;
}
syncctrl = 0;
hden = 0;
icr = 0;
scictrl = 0;
lcr = 0;
switch (control & ARM_USART_CONTROL_Msk) {
case ARM_USART_MODE_ASYNCHRONOUS:
mode = ARM_USART_MODE_ASYNCHRONOUS;
break;
case ARM_USART_MODE_SYNCHRONOUS_MASTER:
if (usart->capabilities.synchronous_master) {
// Enable synchronous master (SCLK out) mode
syncctrl = USART_SYNCCTRL_SYNC | USART_SYNCCTRL_CSRC;
} else return ARM_USART_ERROR_MODE;
mode = ARM_USART_MODE_SYNCHRONOUS_MASTER;
break;
case ARM_USART_MODE_SYNCHRONOUS_SLAVE:
if (usart->capabilities.synchronous_slave) {
// Enable synchronous slave (SCLK in) mode
syncctrl = USART_SYNCCTRL_SYNC;
} else return ARM_USART_ERROR_MODE;
mode = ARM_USART_MODE_SYNCHRONOUS_SLAVE;
break;
case ARM_USART_MODE_SINGLE_WIRE:
// Enable Half duplex
hden = USART_HDEN_HDEN;
mode = ARM_USART_MODE_SINGLE_WIRE;
break;
case ARM_USART_MODE_IRDA:
if (usart->capabilities.irda) {
// Enable IrDA mode
icr = USART_ICR_IRDAEN;
} else return ARM_USART_ERROR_MODE;
mode = ARM_USART_MODE_IRDA;
break;
case ARM_USART_MODE_SMART_CARD:
if (usart->capabilities.smart_card) {
// Enable Smart card mode
scictrl = USART_SCICTRL_SCIEN;
} else return ARM_USART_ERROR_MODE;
mode = ARM_USART_MODE_SMART_CARD;
break;
// Default TX value
case ARM_USART_SET_DEFAULT_TX_VALUE:
usart->info->xfer.tx_def_val = arg;
return ARM_DRIVER_OK;
// IrDA pulse
case ARM_USART_SET_IRDA_PULSE:
if (usart->capabilities.irda) {
if (arg == 0) {
usart->reg->ICR &= ~(USART_ICR_FIXPULSEEN);
} else {
val = 1000000000 / (GetClockFreq (((*usart->clk.base_clk >> 24) & 0x1F)));
icr = usart->reg->ICR & ~USART_ICR_PULSEDIV_MSK;
if (arg <= (2 * val)) icr |= (0 << USART_ICR_PULSEDIV_POS);
else if (arg <= (4 * val)) icr |= (1 << USART_ICR_PULSEDIV_POS);
else if (arg <= (8 * val)) icr |= (2 << USART_ICR_PULSEDIV_POS);
else if (arg <= (6 * val)) icr |= (3 << USART_ICR_PULSEDIV_POS);
else if (arg <= (2 * val)) icr |= (4 << USART_ICR_PULSEDIV_POS);
else if (arg <= (64 * val)) icr |= (5 << USART_ICR_PULSEDIV_POS);
else if (arg <= (128 * val)) icr |= (6 << USART_ICR_PULSEDIV_POS);
else if (arg <= (256 * val)) icr |= (7 << USART_ICR_PULSEDIV_POS);
else return ARM_DRIVER_ERROR;
usart->reg->ICR = icr | USART_ICR_FIXPULSEEN;
}
} else return ARM_DRIVER_ERROR;
return ARM_DRIVER_OK;
// SmartCard guard time
case ARM_USART_SET_SMART_CARD_GUARD_TIME:
if (usart->capabilities.smart_card) {
if (arg > 0xFF) return ARM_DRIVER_ERROR;
usart->reg->SCICTRL &= ~USART_SCICTRL_GUARDTIME_MSK;
usart->reg->SCICTRL |= (arg << USART_SCICTRL_GUARDTIME_POS);
} else return ARM_DRIVER_ERROR;
return ARM_DRIVER_OK;
// SmartCard clock
case ARM_USART_SET_SMART_CARD_CLOCK:
if (usart->capabilities.smart_card == 0) return ARM_DRIVER_ERROR;
if (arg == 0) return ARM_DRIVER_OK;
if (usart->capabilities.smart_card_clock) {
if ((usart->info->baudrate * 372) != arg)
return ARM_DRIVER_ERROR;
} else return ARM_DRIVER_ERROR;
return ARM_DRIVER_OK;
// SmartCard NACK
case ARM_USART_CONTROL_SMART_CARD_NACK:
if (usart->capabilities.smart_card) {
if (arg) usart->reg->SCICTRL &= ~USART_SCICTRL_NACKDIS;
else usart->reg->SCICTRL |= USART_SCICTRL_NACKDIS;
} else return ARM_DRIVER_ERROR;
return ARM_DRIVER_OK;
// Control TX
case ARM_USART_CONTROL_TX:
if (arg) {
if (usart->info->mode != ARM_USART_MODE_SMART_CARD) {
// USART TX pin function selected
SCU_PinConfigure(usart->pins.tx->port, usart->pins.tx->num,
SCU_PIN_CFG_PULLUP_DIS | SCU_PIN_CFG_INPUT_FILTER_DIS |
SCU_PIN_CFG_MODE(usart->pins.tx->config_val));
}
usart->info->flags |= USART_FLAG_TX_ENABLED;
usart->reg->TER |= USART_TER_TXEN;
} else {
usart->info->flags &= ~USART_FLAG_TX_ENABLED;
usart->reg->TER &= ~USART_TER_TXEN;
if (usart->info->mode != ARM_USART_MODE_SMART_CARD) {
// GPIO pin function selected
SCU_PinConfigure(usart->pins.tx->port, usart->pins.tx->num,
SCU_PIN_CFG_PULLUP_DIS | SCU_PIN_CFG_INPUT_FILTER_DIS |
SCU_PIN_CFG_MODE(SCU_CFG_MODE_FUNC0));
}
}
return ARM_DRIVER_OK;
// Control RX
case ARM_USART_CONTROL_RX:
// RX Line interrupt enable (overrun, framing, parity error, break)
if (arg) {
if ((usart->info->mode != ARM_USART_MODE_SMART_CARD) &&
(usart->info->mode != ARM_USART_MODE_SINGLE_WIRE )) {
// USART RX pin function selected
SCU_PinConfigure(usart->pins.rx->port, usart->pins.rx->num,
SCU_PIN_CFG_INPUT_BUFFER_EN | SCU_PIN_CFG_INPUT_FILTER_DIS |
SCU_PIN_CFG_PULLUP_DIS | SCU_PIN_CFG_MODE(usart->pins.rx->config_val));
}
usart->info->flags |= USART_FLAG_RX_ENABLED;
usart->reg->RS485CTRL &= ~USART_RS485CTRL_RXDIS;
usart->reg->IER |= USART_IER_RXIE;
} else {
usart->info->flags &= ~USART_FLAG_RX_ENABLED;
usart->reg->RS485CTRL |= USART_RS485CTRL_RXDIS;
usart->reg->IER &= ~USART_IER_RXIE;
if ((usart->info->mode != ARM_USART_MODE_SMART_CARD) &&
(usart->info->mode != ARM_USART_MODE_SINGLE_WIRE )) {
// GPIO pin function selected
SCU_PinConfigure(usart->pins.rx->port, usart->pins.rx->num,
SCU_PIN_CFG_PULLUP_DIS | SCU_PIN_CFG_INPUT_FILTER_DIS |
SCU_PIN_CFG_MODE(SCU_CFG_MODE_FUNC0));
}
}
return ARM_DRIVER_OK;
// Control break
case ARM_USART_CONTROL_BREAK:
if (arg) usart->reg->LCR |= USART_LCR_BC;
else usart->reg->LCR &= ~USART_LCR_BC;
return ARM_DRIVER_OK;
// Abort Send
case ARM_USART_ABORT_SEND:
// Disable transmit holding register empty interrupt
usart->reg->IER &= ~USART_IER_THREIE;
// Set trigger level
val = (usart->trig_lvl & USART_FCR_RXTRIGLVL_MSK) |
USART_FCR_FIFOEN;
if (usart->dma_rx || usart->dma_tx)
val |= USART_FCR_DMAMODE;
// Transmit FIFO reset
val |= USART_FCR_TXFIFORES;
usart->reg->FCR = val;
// If DMA mode - disable DMA channel
if ((usart->dma_tx) && (usart->info->flags & USART_FLAG_SEND_ACTIVE)) {
GPDMA_ChannelDisable (usart->dma_tx->channel);
}
// Clear Send active flag
usart->info->flags &= ~USART_FLAG_SEND_ACTIVE;
return ARM_DRIVER_OK;
// Abort receive
case ARM_USART_ABORT_RECEIVE:
// Disable receive data available interrupt
usart->reg->IER &= ~USART_IER_RBRIE;
// Set trigger level
val = (usart->trig_lvl & USART_FCR_RXTRIGLVL_MSK) |
USART_FCR_FIFOEN;
if (usart->dma_rx || usart->dma_tx)
val |= USART_FCR_DMAMODE;
// Transmit FIFO reset
val |= USART_FCR_RXFIFORES;
usart->reg->FCR = val;
// If DMA mode - disable DMA channel
if ((usart->dma_rx) && (usart->info->status.rx_busy)) {
GPDMA_ChannelDisable (usart->dma_tx->channel);
}
// Clear RX busy status
usart->info->status.rx_busy = 0;
return ARM_DRIVER_OK;
// Abort transfer
case ARM_USART_ABORT_TRANSFER:
// Disable transmit holding register empty and
// receive data available interrupts
usart->reg->IER &= ~(USART_IER_THREIE | USART_IER_RBRIE);
// If DMA mode - disable DMA channel
if ((usart->dma_tx) && (usart->info->flags & USART_FLAG_SEND_ACTIVE)) {
GPDMA_ChannelDisable (usart->dma_tx->channel);
}
if ((usart->dma_rx) && (usart->info->status.rx_busy)) {
GPDMA_ChannelDisable (usart->dma_tx->channel);
}
// Set trigger level
val = (usart->trig_lvl & USART_FCR_RXTRIGLVL_MSK) |
USART_FCR_FIFOEN;
if (usart->dma_rx || usart->dma_tx)
val |= USART_FCR_DMAMODE;
// Transmit FIFO reset
val |= USART_FCR_TXFIFORES | USART_FCR_RXFIFORES;
usart->reg->FCR = val;
// Clear busy statuses
usart->info->status.rx_busy = 0;
usart->info->flags &= ~USART_FLAG_SEND_ACTIVE;
return ARM_DRIVER_OK;
// Unsupported command
default: return ARM_DRIVER_ERROR_UNSUPPORTED;
}
// Check if Receiver/Transmitter is busy
if ( usart->info->status.rx_busy ||
(usart->info->flags & USART_FLAG_SEND_ACTIVE)) {
return ARM_DRIVER_ERROR_BUSY;
}
// USART Data bits
switch (control & ARM_USART_DATA_BITS_Msk) {
case ARM_USART_DATA_BITS_5: lcr |= (0 << USART_LCR_WLS_POS); break;
case ARM_USART_DATA_BITS_6: lcr |= (1 << USART_LCR_WLS_POS); break;
case ARM_USART_DATA_BITS_7: lcr |= (2 << USART_LCR_WLS_POS); break;
case ARM_USART_DATA_BITS_8: lcr |= (3 << USART_LCR_WLS_POS); break;
default: return ARM_USART_ERROR_DATA_BITS;
}
// USART Parity
switch (control & ARM_USART_PARITY_Msk) {
case ARM_USART_PARITY_NONE: break;
case ARM_USART_PARITY_EVEN: lcr |= (1 << USART_LCR_PS_POS) |
USART_LCR_PE; break;
case ARM_USART_PARITY_ODD: lcr |= USART_LCR_PE; break;
}
// USART Stop bits
switch (control & ARM_USART_STOP_BITS_Msk) {
case ARM_USART_STOP_BITS_1: break;
case ARM_USART_STOP_BITS_2: lcr |= USART_LCR_SBS; break;
default: return ARM_USART_ERROR_STOP_BITS;
}
// USART Flow control (RTS and CTS lines are only available on USART1)
if (usart->uart_reg) {
mcr = usart->uart_reg->MCR & ~(UART_MCR_RTSEN | UART_MCR_CTSEN);
switch (control & ARM_USART_FLOW_CONTROL_Msk) {
case ARM_USART_FLOW_CONTROL_NONE:
break;
case ARM_USART_FLOW_CONTROL_RTS:
if (usart->capabilities.flow_control_rts)
mcr |= UART_MCR_RTSEN;
else return ARM_USART_ERROR_FLOW_CONTROL;
break;
case ARM_USART_FLOW_CONTROL_CTS:
if (usart->capabilities.flow_control_cts)
mcr |= UART_MCR_CTSEN;
else return ARM_USART_ERROR_FLOW_CONTROL;
break;
case ARM_USART_FLOW_CONTROL_RTS_CTS:
if (usart->capabilities.flow_control_rts &&
usart->capabilities.flow_control_cts) {
mcr |= (UART_MCR_RTSEN | UART_MCR_CTSEN);
} else return ARM_USART_ERROR_FLOW_CONTROL;
break;
default:
return ARM_USART_ERROR_FLOW_CONTROL;
}
}
// Clock setting for synchronous mode
if ((mode == ARM_USART_MODE_SYNCHRONOUS_MASTER) ||
(mode == ARM_USART_MODE_SYNCHRONOUS_SLAVE )) {
// Only CPOL0 - CPHA1 combination available
// USART clock polarity
if ((control & ARM_USART_CPOL_Msk) != ARM_USART_CPOL0)
return ARM_USART_ERROR_CPOL;
// USART clock phase
if ((control & ARM_USART_CPHA_Msk) != ARM_USART_CPHA1)
return ARM_USART_ERROR_CPHA;
}
// USART Baudrate
if (USART_SetBaudrate (arg, usart) == -1)
return ARM_USART_ERROR_BAUDRATE;
// Configuration is OK - Mode is valid
usart->info->mode = mode;
// Configure TX pin regarding mode and transmitter state
val = SCU_PIN_CFG_INPUT_FILTER_DIS | SCU_PIN_CFG_PULLUP_DIS;
switch (usart->info->mode) {
case ARM_USART_MODE_SMART_CARD:
// Pin function = USART TX
val |= SCU_PIN_CFG_MODE(usart->pins.tx->config_val);
break;
default:
// Synchronous master/slave, asynchronous, single-wire and IrDA mode
if (usart->info->flags & USART_FLAG_TX_ENABLED) {
// Pin function = USART TX
val |= SCU_PIN_CFG_MODE(usart->pins.tx->config_val);
} else {
// Pin function = GPIO
val |= SCU_PIN_CFG_MODE(SCU_CFG_MODE_FUNC0);
}
}
SCU_PinConfigure(usart->pins.tx->port, usart->pins.tx->num, val);
// Configure RX pin regarding mode and receiver state
val = SCU_PIN_CFG_INPUT_FILTER_DIS | SCU_PIN_CFG_PULLUP_DIS;
switch (usart->info->mode) {
case ARM_USART_MODE_SINGLE_WIRE:
case ARM_USART_MODE_SMART_CARD:
// Pin function = GPIO
val |= SCU_PIN_CFG_MODE(SCU_CFG_MODE_FUNC0);
break;
default:
// Synchronous master/slave, asynchronous and IrDA mode
if (usart->info->flags & USART_FLAG_TX_ENABLED) {
// Pin function = USART RX
val |= SCU_PIN_CFG_INPUT_BUFFER_EN |
SCU_PIN_CFG_MODE(usart->pins.tx->config_val);
} else {
// Pin function = GPIO
val |= SCU_PIN_CFG_MODE(SCU_CFG_MODE_FUNC0);
}
break;
}
SCU_PinConfigure(usart->pins.rx->port, usart->pins.rx->num, val);
// Configure CLK pin regarding mode
if (usart->pins.clk) {
val = SCU_PIN_CFG_PULLUP_DIS | SCU_PIN_CFG_INPUT_FILTER_DIS;
switch (usart->info->mode) {
case ARM_USART_MODE_SMART_CARD:
case ARM_USART_MODE_SYNCHRONOUS_MASTER:
// Pin function = USART UCLK (output)
val |= SCU_PIN_CFG_MODE(usart->pins.clk->config_val);
break;
case ARM_USART_MODE_SYNCHRONOUS_SLAVE:
// Pin function = USART UCLK (input)
val |= SCU_PIN_CFG_INPUT_BUFFER_EN |
SCU_PIN_CFG_MODE(usart->pins.clk->config_val);
break;
default:
// Asynchronous, Single-wire and IrDA mode
// Pin function = GPIO
val |= SCU_PIN_CFG_INPUT_BUFFER_EN |
SCU_PIN_CFG_MODE(SCU_CFG_MODE_FUNC0);
}
SCU_PinConfigure(usart->pins.clk->port, usart->pins.clk->num, val);
}
// Configure SYNCCRTL register (only in synchronous mode)
if (usart->capabilities.synchronous_master ||
usart->capabilities.synchronous_slave) {
usart->reg->SYNCCTRL = USART_SYNCCTRL_FES |
USART_SYNCCTRL_SSSDIS |
syncctrl;
}
// Configure HDEN register (only in single wire mode)
if (usart->capabilities.single_wire)
usart->reg->HDEN = hden;
// Configure ICR register (only in IrDA mode)
if (usart->capabilities.irda)
usart->reg->ICR = (usart->reg->ICR & ~USART_ICR_IRDAEN) | icr;
// Configure SCICTRL register (only in Smart Card mode)
if (usart->capabilities.smart_card) {
usart->reg->SCICTRL = (usart->reg->SCICTRL & ~USART_SCICTRL_SCIEN) |
scictrl;
}
// Configure MCR register (modem line for USART1)
if (usart->uart_reg) {
usart->uart_reg->MCR = ((usart->uart_reg->MCR & ~(UART_MCR_RTSEN |
UART_MCR_CTSEN))) | mcr;
}
// Configure Line control register
usart->reg->LCR = ((usart->reg->LCR & (USART_LCR_BC | USART_LCR_DLAB)) | lcr);
// Set configured flag
usart->info->flags |= USART_FLAG_CONFIGURED;
return ARM_DRIVER_OK;
}