Exemplo n.º 1
0
static int32_t USART_Control (uint32_t control, uint32_t arg,
                              USART_RESOURCES *usart)
{
    uint32_t mode;

    if ((usart->info->flags & USART_FLAG_POWERED) == 0)
        // USART not powered
        return ARM_DRIVER_ERROR;

    switch (control & ARM_USART_CONTROL_Msk)
    {
    // Control TX
    case ARM_USART_CONTROL_TX:
        if (arg)
        {
            usart->info->flags |= USART_FLAG_TX_ENABLED;
            usart->reg->CR |= UART_CR_TXE;
            usart->reg->IMSC |= UART_IMSC_TXIM;
        }
        else
        {
            usart->info->flags &= ~USART_FLAG_TX_ENABLED;
            usart->reg->CR &= ~UART_CR_TXE;
            usart->reg->IMSC &= ~UART_IMSC_TXIM;
            usart->reg->ICR |= UART_ICR_TXIC;
        }

        return ARM_DRIVER_OK;
    // Control RX
    case ARM_USART_CONTROL_RX:
        if (arg)
        {
            usart->info->flags |= USART_FLAG_RX_ENABLED;
            usart->reg->CR |= UART_CR_RXE;
            // RX Line interrupt enable (overrun, framing, parity error, break)
            usart->reg->IMSC |= (UART_IMSC_RXIM | UART_IMSC_FEIM |
                                 UART_IMSC_PEIM | UART_IMSC_BEIM | UART_IMSC_OEIM);
        }
        else
        {
            usart->info->flags &= ~USART_FLAG_RX_ENABLED;
            usart->reg->CR &= ~UART_CR_RXE;
            usart->reg->IMSC &= ~(UART_IMSC_RXIM | UART_IMSC_FEIM |
                                  UART_IMSC_PEIM | UART_IMSC_BEIM | UART_IMSC_OEIM);
            usart->reg->ICR |= (UART_ICR_RXIC | UART_ICR_FEIC |
                                UART_ICR_PEIC | UART_ICR_BEIC | UART_ICR_OEIC);
        }

        return ARM_DRIVER_OK;
    // Control break
    case ARM_USART_CONTROL_BREAK:
        if (arg)
        {
            if (usart->info->flags & USART_FLAG_SEND_ACTIVE)
                return ARM_DRIVER_ERROR_BUSY;

            usart->reg->LCR_H |= UART_LCR_H_BRK;

            // Set Send active flag
            usart->info->flags |= USART_FLAG_SEND_ACTIVE;
        }
        else
        {
            usart->reg->LCR_H &= ~UART_LCR_H_BRK;

            // Clear Send active flag
            usart->info->flags &= ~USART_FLAG_SEND_ACTIVE;
        }

        return ARM_DRIVER_OK;
    // Abort Send
    case ARM_USART_ABORT_SEND:
        // Disable transmit interrupt
        usart->reg->IMSC &= ~UART_IMSC_TXIM;
        usart->reg->ICR |= UART_ICR_TXIC;

        // Clear Send active flag
        usart->info->flags &= ~USART_FLAG_SEND_ACTIVE;

        return ARM_DRIVER_OK;
    // Abort receive
    case ARM_USART_ABORT_RECEIVE:
        // Disable receive interrupt
        usart->reg->IMSC &= ~(UART_IMSC_RXIM | UART_IMSC_FEIM |
                              UART_IMSC_PEIM | UART_IMSC_BEIM | UART_IMSC_OEIM);
        usart->reg->ICR |= (UART_ICR_RXIC | UART_ICR_FEIC |
                            UART_ICR_PEIC | UART_ICR_BEIC | UART_ICR_OEIC);

        // Clear RX busy status
        usart->info->status.rx_busy = 0;

        return ARM_DRIVER_OK;
    // Abort transfer
    case ARM_USART_ABORT_TRANSFER:
        // Disable transmit and receive interrupts
        usart->reg->IMSC &= ~(UART_IMSC_RXIM | UART_IMSC_TXIM |
                              UART_IMSC_FEIM | UART_IMSC_PEIM | UART_IMSC_BEIM | UART_IMSC_OEIM);
        usart->reg->ICR |= (UART_ICR_RXIC | UART_ICR_TXIC |
                            UART_ICR_FEIC | UART_ICR_PEIC | UART_ICR_BEIC | UART_ICR_OEIC);

        // Clear busy statuses
        usart->info->status.rx_busy = 0;
        usart->info->flags &= ~USART_FLAG_SEND_ACTIVE;

        return ARM_DRIVER_OK;
    }

    switch (control & ARM_USART_CONTROL_Msk)
    {
    case ARM_USART_MODE_ASYNCHRONOUS:
        mode = ARM_USART_MODE_ASYNCHRONOUS;

        break;
    case ARM_USART_MODE_IRDA:
        if (usart->capabilities.irda)
            // Enable IrDA mode
            usart->reg->CR |= UART_CR_SIREN;
        else
            return ARM_USART_ERROR_MODE;

        mode = ARM_USART_MODE_IRDA;

        break;
    // IrDA pulse
    case ARM_USART_SET_IRDA_PULSE:
        if (usart->capabilities.irda)
            usart->reg->ILPR = RTE_HCLK / usart->clk.div / NomClkIrDA;
        else
            return ARM_DRIVER_ERROR;

        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:
        usart->reg->LCR_H &= ~UART_LCR_H_WLEN_Msk;
        usart->reg->LCR_H |= (UART_LCR_H_WLEN_5_BITS << UART_LCR_H_WLEN_Pos);

        break;
    case ARM_USART_DATA_BITS_6:
        usart->reg->LCR_H &= ~UART_LCR_H_WLEN_Msk;
        usart->reg->LCR_H |= (UART_LCR_H_WLEN_6_BITS << UART_LCR_H_WLEN_Pos);

        break;
    case ARM_USART_DATA_BITS_7:
        usart->reg->LCR_H &= ~UART_LCR_H_WLEN_Msk;
        usart->reg->LCR_H |= (UART_LCR_H_WLEN_7_BITS << UART_LCR_H_WLEN_Pos);

        break;
    case ARM_USART_DATA_BITS_8:
        usart->reg->LCR_H &= ~UART_LCR_H_WLEN_Msk;
        usart->reg->LCR_H |= (UART_LCR_H_WLEN_8_BITS << UART_LCR_H_WLEN_Pos);

        break;
    default:
        return ARM_USART_ERROR_DATA_BITS;
    }

    // USART Parity
    switch (control & ARM_USART_PARITY_Msk)
    {
    case ARM_USART_PARITY_NONE:
        usart->reg->LCR_H &= ~UART_LCR_H_PEN;

        break;
    case ARM_USART_PARITY_EVEN:
        usart->reg->LCR_H |= UART_LCR_H_PEN;
        usart->reg->LCR_H &= ~UART_LCR_H_EPS;

        break;
    case ARM_USART_PARITY_ODD:
        usart->reg->LCR_H |= (UART_LCR_H_PEN | UART_LCR_H_EPS);
    }

    // USART Stop bits
    switch (control & ARM_USART_STOP_BITS_Msk)
    {
    case ARM_USART_STOP_BITS_1:
        usart->reg->LCR_H &= ~UART_LCR_H_STP2;

        break;
    case ARM_USART_STOP_BITS_2:
        usart->reg->LCR_H |= UART_LCR_H_STP2;

        break;
    default:
        return ARM_USART_ERROR_STOP_BITS;
    }

    usart->reg->CR &= ~(UART_CR_RTSEN | UART_CR_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)
            usart->reg->CR |= UART_CR_RTSEN;
        else
            return ARM_USART_ERROR_FLOW_CONTROL;

        break;
    case ARM_USART_FLOW_CONTROL_CTS:
        if (usart->capabilities.flow_control_cts)
            usart->reg->CR |= UART_CR_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)
            usart->reg->CR |= (UART_CR_RTSEN | UART_CR_CTSEN);
        else
            return ARM_USART_ERROR_FLOW_CONTROL;

        break;
    default:
        return ARM_USART_ERROR_FLOW_CONTROL;
    }

    // USART Baudrate
    USART_SetBaudrate (arg, usart);

    // Configuration is OK - Mode is valid
    usart->info->mode = mode;

    // Set configured flag
    usart->info->flags |= USART_FLAG_CONFIGURED;

    return ARM_DRIVER_OK;
}
Exemplo n.º 2
0
Arquivo: main.c Projeto: gstroe/Arm
/**
 * \brief Configures USART in LON mode
 */
static void _ConfigureUsart( void )
{
	/* Initialization for Sending/Receiving A LON Frame */

	uint32_t mode;
	Usart *pUsart = USART;

	/* 1. Write TXEN and RXEN in US_CR to enable both the transmitter and the
	      receiver.                                                           */
	/* Enable receiver & transmitter */
	USART_SetTransmitterEnabled(pUsart, 1);
	USART_SetReceiverEnabled(pUsart, 1);

	/* 2. Write USART_MODE in US_MR to select the LON mode configuration.     */
	/* Enable the peripheral clock in the PMC */
	PMC_EnablePeripheral(ID_USART);

	mode = US_MR_USART_MODE_LON | US_MR_USCLKS_MCK
					| US_MR_CHRL_8_BIT | US_MR_PAR_NO | US_MR_NBSTOP_1_BIT
					| US_MR_CHMODE_NORMAL
					//| US_MR_CHMODE_LOCAL_LOOPBACK //US_MR_CHMODE_NORMAL
					| US_MR_MAN;

	pUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX
					| US_CR_RXDIS | US_CR_TXDIS | US_CR_RSTSTA;
	pUsart->US_IDR = 0xFFFFFFFF;

	pUsart->US_MR = mode;

	/* 3. Write CD and FP in US_BRGR to configure the baud rate.              */
	USART_SetBaudrate(pUsart, 0, BAUDRATE, BOARD_MCK);

	/* 4. Write COMMT, COLDET, TCOL, CDTAIL, RDMNBM and DMAM in US_LONMR to
	      configure the LON operating mode.                                   */
	pUsart->US_LONMR = US_LONMR_COMMT /* LON comm_type = 2 mode */
					| US_LONMR_COLDET /* LON collision detection feature enabled */
					| US_LONMR_DMAM   /* The LON data length register US_LONDL is written by the DMA */
					| US_LONMR_LCDS   /* LON collision detection source is internal. */
					| US_LONMR_EOFS(1);

	/* 5. Write BETA2, BETA1TX, BETA1RX, PCYCLE, PSNB, NPS, IDTTX and ITDRX
	      respectively in US_FIDI, US_LONB1TX, US_LONB1RX, US_TTGR, US_LONPRIO,
	      US_LONIDTTX and US_LONIDTRX to set the LON network configuration.   */
	pUsart->US_FIDI    = 5; /* LON BETA2 length */
	pUsart->US_LONB1TX = 5; /* LON Beta1 Tx     */
	pUsart->US_LONB1RX = 5; /* LON Beta1 Rx     */
	pUsart->US_TTGR    = US_TTGR_PCYCLE(5);  /* package cycle timer value */
	pUsart->US_LONPRIO = US_LONPRIO_PSNB(5)  /* Number of priority slots  */
						| US_LONPRIO_NPS(5); /* Node priority slot        */

	/* Set LON Indeterminate Time after Transmission or Reception
	 * (comm_type = 1 mode only) */
	if (0 == (pUsart->US_LONMR & US_LONMR_COMMT)) {
		pUsart->US_IDTTX   = US_IDTTX_IDTTX(3);
		pUsart->US_IDTRX   = US_IDTRX_IDTRX(3);
	}

	/* (TX) 6. Write TX_PL in US_MAN to select the preamble pattern to use.   */
	/* (RX) 6. Write RXIDLEV and RX_PL in US_MAN to indicate the receiver line
	           value and select the preamble pattern to use.                  */
	// preamble pattern
	pUsart->US_MAN = US_MAN_TX_PL(5) | US_MAN_TX_PP_ALL_ONE
					| US_MAN_RX_PL(5) | US_MAN_RX_PP_ALL_ONE
					| US_MAN_ONE | US_MAN_DRIFT;

	pUsart->US_LONPR = US_LONPR_LONPL(5);

	/* proceed by a software reset of the transmitter and the receiver and
	followed by a transmitter/receiver enable to avoid unpredictable behavior */
	pUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX;
	pUsart->US_CR = US_CR_RXEN | US_CR_TXEN;
}