UART driver and Example code for JellyBean.
This commit is contained in:
committed by
Piotr Esden-Tempski
parent
2f425af647
commit
f8542c09a6
@@ -35,7 +35,7 @@ CFLAGS = -O2 -g3 \
|
||||
-mfloat-abi=hard -mfpu=fpv4-sp-d16 -DLPC43XX
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
OBJS = gpio.o scu.o i2c.o ssp.o
|
||||
OBJS = gpio.o vector.o scu.o i2c.o ssp.o nvic.o systick.o uart.o
|
||||
|
||||
VPATH += ../cm3
|
||||
|
||||
|
||||
264
lib/lpc43xx/uart.c
Normal file
264
lib/lpc43xx/uart.c
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/lpc43xx/uart.h>
|
||||
#include <libopencm3/lpc43xx/cgu.h>
|
||||
|
||||
#define UART_SRC_32K 0x00
|
||||
#define UART_SRC_IRC 0x01
|
||||
#define UART_SRC_ENET_RX 0x02
|
||||
#define UART_SRC_ENET_TX 0x03
|
||||
#define UART_SRC_GP_CLKIN 0x04
|
||||
#define UART_SRC_XTAL 0x06
|
||||
#define UART_SRC_PLL0USB 0x07
|
||||
#define UART_SRC_PLL0AUDIO 0x08
|
||||
#define UART_SRC_PLL1 0x09
|
||||
#define UART_SRC_IDIVA 0x0C
|
||||
#define UART_SRC_IDIVB 0x0D
|
||||
#define UART_SRC_IDIVC 0x0E
|
||||
#define UART_SRC_IDIVD 0x0F
|
||||
#define UART_SRC_IDIVE 0x10
|
||||
|
||||
#define UART_CGU_AUTOBLOCK_CLOCK_BIT 11
|
||||
#define UART_CGU_BASE_CLK_SEL_SHIFT 24 /* clock source selection (5 bits) */
|
||||
|
||||
u32 dummy_read;
|
||||
|
||||
/*
|
||||
* UART Init function
|
||||
*/
|
||||
void uart_init(uart_num_t uart_num,
|
||||
uart_databit_t data_nb_bits,
|
||||
uart_stopbit_t data_nb_stop,
|
||||
uart_parity_t data_parity,
|
||||
u16 uart_divisor,
|
||||
u8 uart_divaddval,
|
||||
u8 uart_mulval)
|
||||
{
|
||||
u32 lcr_config;
|
||||
u32 uart_port;
|
||||
|
||||
uart_port = uart_num;
|
||||
|
||||
switch(uart_num)
|
||||
{
|
||||
case UART0_NUM:
|
||||
/* use PLL1 as clock source for UART0 */
|
||||
CGU_BASE_UART0_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT);
|
||||
break;
|
||||
|
||||
case UART1_NUM:
|
||||
/* use PLL1 as clock source for UART1 */
|
||||
CGU_BASE_UART1_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT);
|
||||
break;
|
||||
|
||||
case UART2_NUM:
|
||||
/* use PLL1 as clock source for UART2 */
|
||||
CGU_BASE_UART2_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT);
|
||||
break;
|
||||
|
||||
case UART3_NUM:
|
||||
/* use PLL1 as clock source for UART3 */
|
||||
CGU_BASE_UART3_CLK = (CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT) | (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT);
|
||||
break;
|
||||
|
||||
default:
|
||||
return; /* error */
|
||||
}
|
||||
|
||||
/* FIFOs RX/TX Enabled and Reset RX/TX FIFO (DMA Mode is also cleared) */
|
||||
UART_FCR(uart_port) = ( UART_FCR_FIFO_EN | UART_FCR_RX_RS | UART_FCR_TX_RS);
|
||||
/* Disable FIFO */
|
||||
UART_FCR(uart_port) = 0;
|
||||
|
||||
// Dummy read (to clear existing data)
|
||||
while( UART_LSR(uart_port) & UART_LSR_RDR )
|
||||
{
|
||||
dummy_read = UART_RBR(uart_port);
|
||||
}
|
||||
|
||||
/* Wait end of TX & disable TX */
|
||||
if(uart_num == UART1_NUM)
|
||||
{
|
||||
UART_TER_UART1(uart_port) = UART1_TER_TXEN;
|
||||
|
||||
/* Wait for current transmit complete */
|
||||
while (!(UART_LSR(uart_port) & UART_LSR_THRE));
|
||||
|
||||
/* Disable Tx */
|
||||
UART_TER_UART1(uart_port) = 0;
|
||||
}else
|
||||
{
|
||||
UART_TER(uart_port) = UART0_2_3_TER_TXEN;
|
||||
|
||||
/* Wait for current transmit complete */
|
||||
while (!(UART_LSR(uart_port) & UART_LSR_THRE));
|
||||
|
||||
/* Disable Tx */
|
||||
UART_TER(uart_port) = 0;
|
||||
}
|
||||
|
||||
/* Disable interrupt */
|
||||
UART_IER(uart_port) = 0;
|
||||
|
||||
/* Set LCR to default state */
|
||||
UART_LCR(uart_port) = 0;
|
||||
|
||||
/* Set ACR to default state */
|
||||
UART_ACR(uart_port) = 0;
|
||||
|
||||
/* Dummy Read to Clear Status */
|
||||
dummy_read = UART_LSR(uart_port);
|
||||
|
||||
/*
|
||||
Table 835. USART Fractional Divider Register:
|
||||
UARTbaudrate = PCLK / ( 16* (((256*DLM)+ DLL)*(1+(DivAddVal/MulVal))) )
|
||||
The value of MULVAL and DIVADDVAL should comply to the following conditions:
|
||||
1. 1 <= MULVAL <= 15
|
||||
2. 0 <= DIVADDVAL <= 14
|
||||
3. DIVADDVAL < MULVAL
|
||||
*/
|
||||
|
||||
/* Set DLAB Bit */
|
||||
UART_LCR(uart_port) |= UART_LCR_DLAB_EN;
|
||||
UART_DLM(uart_port) = UART_LOAD_DLM(uart_divisor);
|
||||
UART_DLL(uart_port) = UART_LOAD_DLL(uart_divisor);
|
||||
/* Clear DLAB Bit */
|
||||
UART_LCR(uart_port) &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
|
||||
UART_FDR(uart_port) = (UART_FDR_MULVAL(uart_mulval) | UART_FDR_DIVADDVAL(uart_divaddval)) & UART_FDR_BITMASK;
|
||||
|
||||
/* Read LCR config & Force Enable of Divisor Latches Access */
|
||||
lcr_config = (UART_LCR(uart_port) & UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
|
||||
lcr_config |= data_nb_bits; /* Set Nb Data Bits */
|
||||
lcr_config |= data_nb_stop; /* Set Nb Stop Bits */
|
||||
lcr_config |= data_parity; /* Set Data Parity */
|
||||
|
||||
/* Write LCR (only 8bits) */
|
||||
UART_LCR(uart_port) = (lcr_config & UART_LCR_BITMASK);
|
||||
|
||||
/* Enable TX */
|
||||
if(uart_num == UART1_NUM)
|
||||
{
|
||||
UART_TER_UART1(uart_port) = UART1_TER_TXEN;
|
||||
}else
|
||||
{
|
||||
UART_TER(uart_port) = UART0_2_3_TER_TXEN;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This Function return if data are received or not received.
|
||||
*/
|
||||
uart_rx_data_ready_t uart_rx_data_ready(uart_num_t uart_num)
|
||||
{
|
||||
u32 uart_port;
|
||||
u8 uart_status;
|
||||
uart_rx_data_ready_t data_ready;
|
||||
|
||||
uart_port = uart_num;
|
||||
|
||||
uart_status = UART_LSR(uart_port) & 0xFF;
|
||||
|
||||
/* Check Error */
|
||||
if( (uart_status & UART_LSR_ERROR_MASK) == 0)
|
||||
{
|
||||
/* No errors check if data is ready */
|
||||
if((uart_status & UART_LSR_RDR) == 0)
|
||||
{
|
||||
data_ready = UART_RX_NO_DATA;
|
||||
}else
|
||||
{
|
||||
data_ready = UART_RX_DATA_READY;
|
||||
}
|
||||
}else
|
||||
{
|
||||
/* UART Error */
|
||||
data_ready = UART_RX_DATA_ERROR;
|
||||
}
|
||||
|
||||
return data_ready;
|
||||
}
|
||||
|
||||
/*
|
||||
* This Function Wait until Data RX Ready, and return Data Read from UART.
|
||||
*/
|
||||
u8 uart_read(uart_num_t uart_num)
|
||||
{
|
||||
u32 uart_port;
|
||||
u8 uart_val;
|
||||
|
||||
uart_port = uart_num;
|
||||
|
||||
/* Wait Until Data Received (Rx Data Not Ready) */
|
||||
while( (UART_LSR(uart_port) & UART_LSR_RDR) == 0);
|
||||
|
||||
uart_val = (UART_RBR(uart_port) & UART_RBR_MASKBIT);
|
||||
|
||||
return uart_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* This Function Wait until Data RX Ready, and return Data Read from UART.
|
||||
*/
|
||||
u8 uart_read_timeout(uart_num_t uart_num, u32 rx_timeout_nb_cycles, uart_error_t* error)
|
||||
{
|
||||
u32 uart_port;
|
||||
u8 uart_val;
|
||||
u32 counter;
|
||||
|
||||
uart_port = uart_num;
|
||||
|
||||
/* Wait Until Data Received (Rx Data Not Ready) */
|
||||
counter = 0;
|
||||
while( (UART_LSR(uart_port) & UART_LSR_RDR) == 0)
|
||||
{
|
||||
if(rx_timeout_nb_cycles>0)
|
||||
{
|
||||
counter++;
|
||||
if(counter>=rx_timeout_nb_cycles)
|
||||
{
|
||||
*error = UART_TIMEOUT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uart_val = (UART_RBR(uart_port) & UART_RBR_MASKBIT);
|
||||
|
||||
/* Clear error */
|
||||
*error = UART_NO_ERROR;
|
||||
|
||||
return uart_val;
|
||||
}
|
||||
|
||||
/* This Function Wait Data TX Ready, and Write Data to UART
|
||||
if rx_timeout_nb_cycles = 0 Infinite wait
|
||||
*/
|
||||
void uart_write(uart_num_t uart_num, u8 data)
|
||||
{
|
||||
u32 uart_port;
|
||||
|
||||
uart_port = uart_num;
|
||||
|
||||
/* Wait Until FIFO not full */
|
||||
while( (UART_LSR(uart_port) & UART_LSR_THRE) == 0);
|
||||
|
||||
UART_THR(uart_port) = data;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user