From f8542c09a6d9ce6c458e2e404882fa66bc017aaf Mon Sep 17 00:00:00 2001 From: TitanMKD Date: Sun, 1 Jul 2012 11:34:38 +0200 Subject: [PATCH] UART driver and Example code for JellyBean. --- include/libopencm3/lpc43xx/uart.h | 341 ++++++++++++++++++++++++++++++ lib/lpc43xx/Makefile | 2 +- lib/lpc43xx/uart.c | 264 +++++++++++++++++++++++ 3 files changed, 606 insertions(+), 1 deletion(-) create mode 100644 include/libopencm3/lpc43xx/uart.h create mode 100644 lib/lpc43xx/uart.c diff --git a/include/libopencm3/lpc43xx/uart.h b/include/libopencm3/lpc43xx/uart.h new file mode 100644 index 00000000..7e640f55 --- /dev/null +++ b/include/libopencm3/lpc43xx/uart.h @@ -0,0 +1,341 @@ +/* +* This file is part of the libopencm3 project. +* +* Copyright (C) 2012 Benjamin Vernoux +* +* 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 . +*/ + +#ifndef LPC43XX_UART_H +#define LPC43XX_UART_H + +#include +#include + +/* --- Convenience macros -------------------------------------------------- */ + +/* UART port base addresses (for convenience) */ +#define UART0 USART0_BASE /* APB0 */ +#define UART1 UART1_BASE /* APB0 */ +#define UART2 USART2_BASE /* APB2 */ +#define UART3 USART3_BASE /* APB2 */ + +/* --- UART registers ------------------------------------------------------- */ + +/* Receiver Buffer Register (DLAB=0) Read Only */ +#define UART_RBR(port) MMIO32(port + 0x000) /* 8bits */ + +/* Transmitter Holding Register (DLAB=0) Write Only */ +#define UART_THR(port) MMIO32(port + 0x000) /* 8bits */ + +/* Divisor Latch LSB Register (DLAB=1) */ +#define UART_DLL(port) MMIO32(port + 0x000) /* 8bits */ + +/* Divisor Latch MSB Register (DLAB=1) */ +#define UART_DLM(port) MMIO32(port + 0x004) /* 8bits */ + +/* Interrupt Enable Register (DLAB=0) */ +#define UART_IER(port) MMIO32(port + 0x004) + +/* Interrupt ID Register Read Only */ +#define UART_IIR(port) MMIO32(port + 0x008) + +/* FIFO Control Register Write Only */ +#define UART_FCR(port) MMIO32(port + 0x008) + +/* Line Control Register */ +#define UART_LCR(port) MMIO32(port + 0x00C) + +/* MCR only for UART1 */ + +/* Line Status Register */ +#define UART_LSR(port) MMIO32(port + 0x014) + +/* Auto Baud Control Register */ +#define UART_ACR(port) MMIO32(port + 0x020) + +/* IrDA Control Register only for UART0/2/3 */ +//#define UART_ICR(port) MMIO32(port + 0x024) + +/* Fractional Divider Register */ +#define UART_FDR(port) MMIO32(port + 0x028) + +/* Oversampling Register only for UART0/2/3 */ +// #define UART_OSR(port) MMIO32(port + 0x02C) + +/* Transmit Enable Register Only for UART1 */ +#define UART_TER_UART1(port) MMIO32(port + 0x030) + +/* Half-Duplex enable Register only for UART0/2/3 */ +// #define UART_HDEN(port) MMIO32(port + 0x040) + +/* Smart card Interface Register Only for UART0/2/3 */ +//#define UART_SCICTRL(port) MMIO32(port + 0x048) + +/* RS-485/EIA-485 Control Register */ +#define UART_RS485CTRL(port) MMIO32(port + 0x04C) + +/* RS-485/EIA-485 Address Match Register */ +#define UART_RS485ADRMATCH(port) MMIO32(port + 0x050) + +/* RS-485/EIA-485 Direction Control Delay Register */ +#define UART_RS485DLY(port) MMIO32(port + 0x054) + +/* Synchronous Mode Control Register only for UART0/2/3 */ +//#define UART_SYNCCTRL(port) MMIO32(port + 0x058) + +/* Transmit Enable Register Only for UART0/2/3 */ +#define UART_TER(port) MMIO32(port + 0x05C) + +/* --------------------- BIT DEFINITIONS -------------------------------------- */ +/*********************************************************************** +* Macro defines for Macro defines for UARTn Receiver Buffer Register +**********************************************************************/ +#define UART_RBR_MASKBIT ((u8)0xFF) /* UART Received Buffer mask bit (8 bits) */ + +/*********************************************************************** +* Macro defines for Macro defines for UARTn Transmit Holding Register +**********************************************************************/ +#define UART_THR_MASKBIT ((u8)0xFF) /* UART Transmit Holding mask bit (8 bits) */ + +/*********************************************************************** +* Macro defines for Macro defines for UARTn Divisor Latch LSB register +**********************************************************************/ +#define UART_LOAD_DLL(div) ((div) & 0xFF) /* Macro for loading least significant halfs of divisors */ +#define UART_DLL_MASKBIT ((u8)0xFF) /* Divisor latch LSB bit mask */ + +/*********************************************************************** +* Macro defines for Macro defines for UARTn Divisor Latch MSB register +**********************************************************************/ +#define UART_DLM_MASKBIT ((u8)0xFF) /* Divisor latch MSB bit mask */ +#define UART_LOAD_DLM(div) (((div) >> 8) & 0xFF) /* Macro for loading most significant halfs of divisors */ + +/*********************************************************************** +* Macro defines for Macro defines for UART interrupt enable register +**********************************************************************/ +#define UART_IER_RBRINT_EN ((u32)(BIT0)) /* RBR Interrupt enable*/ +#define UART_IER_THREINT_EN ((u32)(BIT1)) /* THR Interrupt enable*/ +#define UART_IER_RLSINT_EN ((u32)(BIT2)) /* RX line status interrupt enable*/ +#define UART1_IER_MSINT_EN ((u32)(BIT3)) /* Modem status interrupt enable */ +#define UART1_IER_CTSINT_EN ((u32)(BIT7)) /* CTS1 signal transition interrupt enable */ +#define UART_IER_ABEOINT_EN ((u32)(BIT8)) /* Enables the end of auto-baud interrupt */ +#define UART_IER_ABTOINT_EN ((u32)(BIT9)) /* Enables the auto-baud time-out interrupt */ +#define UART_IER_BITMASK ((u32)(0x307)) /* UART interrupt enable register bit mask */ +#define UART1_IER_BITMASK ((u32)(0x38F)) /* UART1 interrupt enable register bit mask */ + +/********************************************************************** +* Macro defines for Macro defines for UART interrupt identification register +**********************************************************************/ +#define UART_IIR_INTSTAT_PEND ((u32)(BIT0)) /* Interrupt Status - Active low */ +#define UART_IIR_INTID_RDA ((u32)(2<<1)) /* Interrupt identification: Receive data available*/ +#define UART_IIR_INTID_RLS ((u32)(3<<1)) /* Interrupt identification: Receive line status*/ +#define UART_IIR_INTID_CTI ((u32)(6<<1)) /* Interrupt identification: Character time-out indicator*/ +#define UART_IIR_INTID_THRE ((u32)(BIT1)) /* Interrupt identification: THRE interrupt*/ +#define UART1_IIR_INTID_MODEM ((u32)(0<<1)) /* Interrupt identification: Modem interrupt*/ +#define UART_IIR_INTID_MASK ((u32)(7<<1)) /* Interrupt identification: Interrupt ID mask */ +#define UART_IIR_FIFO_EN ((u32)(3<<6)) /* These bits are equivalent to UnFCR[0] */ +#define UART_IIR_ABEO_INT ((u32)(BIT8)) /* End of auto-baud interrupt */ +#define UART_IIR_ABTO_INT ((u32)(BIT9)) /* Auto-baud time-out interrupt */ +#define UART_IIR_BITMASK ((u32)(0x3CF)) /* UART interrupt identification register bit mask */ + +/********************************************************************** +* Macro defines for Macro defines for UART FIFO control register +**********************************************************************/ +#define UART_FCR_FIFO_EN ((u8)(BIT0)) /* UART FIFO enable */ +#define UART_FCR_RX_RS ((u8)(BIT1)) /* UART FIFO RX reset */ +#define UART_FCR_TX_RS ((u8)(BIT2)) /* UART FIFO TX reset */ +#define UART_FCR_DMAMODE_SEL ((u8)(BIT3)) /* UART DMA mode selection */ +#define UART_FCR_TRG_LEV0 ((u8)(0)) /* UART FIFO trigger level 0: 1 character */ +#define UART_FCR_TRG_LEV1 ((u8)(BIT6)) /* UART FIFO trigger level 1: 4 character */ +#define UART_FCR_TRG_LEV2 ((u8)(2<<6)) /* UART FIFO trigger level 2: 8 character */ +#define UART_FCR_TRG_LEV3 ((u8)(3<<6)) /* UART FIFO trigger level 3: 14 character */ +#define UART_FCR_BITMASK ((u8)(0xCF)) /* UART FIFO control bit mask */ +#define UART_TX_FIFO_SIZE (16) + +/********************************************************************** +* Macro defines for Macro defines for UART line control register +**********************************************************************/ +#define UART_LCR_WLEN5 ((u8)(0)) /* UART 5 bit data mode */ +#define UART_LCR_WLEN6 ((u8)(1)) /* UART 6 bit data mode */ +#define UART_LCR_WLEN7 ((u8)(2)) /* UART 7 bit data mode */ +#define UART_LCR_WLEN8 ((u8)(3)) /* UART 8 bit data mode */ +#define UART_LCR_ONE_STOPBIT ((u8)(0)) /* UART One Stop Bits */ +#define UART_LCR_TWO_STOPBIT ((u8)(BIT2)) /* UART Two Stop Bits */ +#define UART_LCR_NO_PARITY ((u8)(0)) /* UART Parity Disabled / No Parity */ +#define UART_LCR_PARITY_EN ((u8)(BIT3)) /* UART Parity Enable */ +#define UART_LCR_PARITY_ODD ((u8)(0)) /* UART Odd Parity Select */ +#define UART_LCR_PARITY_EVEN ((u8)(BIT4)) /* UART Even Parity Select */ +#define UART_LCR_PARITY_SP_1 ((u8)(0x20)) /* UART force 1 stick parity */ +#define UART_LCR_PARITY_SP_0 ((u8)(0x30)) /* UART force 0 stick parity */ +#define UART_LCR_BREAK_EN ((u8)(BIT6)) /* UART Transmission Break enable */ +#define UART_LCR_DLAB_EN ((u8)(BIT7)) /* UART Divisor Latches Access bit enable */ +#define UART_LCR_BITMASK ((u8)(0xFF)) /* UART line control bit mask */ + +/********************************************************************** +* Macro defines for Macro defines for UART line status register +**********************************************************************/ +#define UART_LSR_RDR ((u8)(BIT0)) /* Line status register: Receive data ready */ +#define UART_LSR_OE ((u8)(BIT1)) /* Line status register: Overrun error */ +#define UART_LSR_PE ((u8)(BIT2)) /* Line status register: Parity error */ +#define UART_LSR_FE ((u8)(BIT3)) /* Line status register: Framing error */ +#define UART_LSR_BI ((u8)(BIT4)) /* Line status register: Break interrupt */ +#define UART_LSR_THRE ((u8)(BIT5)) /* Line status register: Transmit holding register empty */ +#define UART_LSR_TEMT ((u8)(BIT6)) /* Line status register: Transmitter empty */ +#define UART_LSR_RXFE ((u8)(BIT7)) /* Error in RX FIFO */ +#define UART_LSR_BITMASK ((u8)(0xFF)) /* UART Line status bit mask */ +#define UART_LSR_ERROR_MASK (UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI|UART_LSR_RXFE) + +/********************************************************************** +* Macro defines for Macro defines for UART Scratch Pad Register +**********************************************************************/ +#define UART_SCR_BIMASK ((u8)(0xFF)) /* UART Scratch Pad bit mask */ + +/*********************************************************************** +* Macro defines for Macro defines for UART Auto baudrate control register +**********************************************************************/ +#define UART_ACR_START ((u32)(BIT0)) /* UART Auto-baud start */ +#define UART_ACR_MODE ((u32)(BIT1)) /* UART Auto baudrate Mode 1 */ +#define UART_ACR_AUTO_RESTART ((u32)(BIT2)) /* UART Auto baudrate restart */ +#define UART_ACR_ABEOINT_CLR ((u32)(BIT8)) /* UART End of auto-baud interrupt clear */ +#define UART_ACR_ABTOINT_CLR ((u32)(BIT9)) /* UART Auto-baud time-out interrupt clear */ +#define UART_ACR_BITMASK ((u32)(0x307)) /* UART Auto Baudrate register bit mask */ + +/********************************************************************* +* Macro defines for Macro defines for UART IrDA control register +**********************************************************************/ +#define UART_ICR_IRDAEN ((u32)(BIT0)) /* IrDA mode enable */ +#define UART_ICR_IRDAINV ((u32)(BIT1)) /* IrDA serial input inverted */ +#define UART_ICR_FIXPULSE_EN ((u32)(BIT2)) /* IrDA fixed pulse width mode */ +#define UART_ICR_PULSEDIV(n) ((u32)((n&0x07)<<3)) /* PulseDiv - Configures the pulse when FixPulseEn = 1 */ +#define UART_ICR_BITMASK ((u32)(0x3F)) /* UART IRDA bit mask */ + +/********************************************************************** +* Macro defines for Macro defines for UART half duplex register +**********************************************************************/ +#define UART_HDEN_HDEN ((u32)(BIT0)) /* enable half-duplex mode*/ + +/********************************************************************** +* Macro defines for Macro defines for UART smart card interface control register +**********************************************************************/ +#define UART_SCICTRL_SCIEN ((u32)(BIT0)) /* enable asynchronous half-duplex smart card interface*/ +#define UART_SCICTRL_NACKDIS ((u32)(BIT1)) /* NACK response is inhibited*/ +#define UART_SCICTRL_PROTSEL_T1 ((u32)(BIT2)) /* ISO7816-3 protocol T1 is selected*/ +#define UART_SCICTRL_TXRETRY(n) ((u32)((n&0x07)<<5)) /* number of retransmission*/ +#define UART_SCICTRL_GUARDTIME(n) ((u32)((n&0xFF)<<8)) /* Extra guard time*/ + +/********************************************************************* +* Macro defines for Macro defines for UART synchronous control register +**********************************************************************/ +#define UART_SYNCCTRL_SYNC ((u32)(BIT0)) /* enable synchronous mode*/ +#define UART_SYNCCTRL_CSRC_MASTER ((u32)(BIT1)) /* synchronous master mode*/ +#define UART_SYNCCTRL_FES ((u32)(BIT2)) /* sample on falling edge*/ +#define UART_SYNCCTRL_TSBYPASS ((u32)(BIT3)) /* to be defined*/ +#define UART_SYNCCTRL_CSCEN ((u32)(BIT4)) /* continuous running clock enable (master mode only) */ +#define UART_SYNCCTRL_NOSTARTSTOP ((u32)(BIT5)) /* Do not send start/stop bit */ +#define UART_SYNCCTRL_CCCLR ((u32)(BIT6)) /* stop continuous clock */ + +/********************************************************************* +* Macro defines for Macro defines for UART Fractional divider register +**********************************************************************/ +#define UART_FDR_DIVADDVAL(n) ((u32)(n&0x0F)) /* Baud-rate generation pre-scaler divisor */ +#define UART_FDR_MULVAL(n) ((u32)((n<<4)&0xF0)) /* Baud-rate pre-scaler multiplier value */ +#define UART_FDR_BITMASK ((u32)(0xFF)) /* UART Fractional Divider register bit mask */ + +/********************************************************************* +* Macro defines for Macro defines for UART Tx Enable register +**********************************************************************/ +#define UART1_TER_TXEN ((u8)(BIT7)) /* Transmit enable bit */ +#define UART1_TER_BITMASK ((u8)(0x80)) /* UART Transmit Enable Register bit mask */ + +#define UART0_2_3_TER_TXEN ((u8)(BIT0)) /* Transmit enable bit */ +#define UART0_2_3_TER_BITMASK ((u8)(0x01)) /* UART Transmit Enable Register bit mask */ + +/********************************************************************** +* Macro defines for Macro defines for UART FIFO Level register +**********************************************************************/ +#define UART_FIFOLVL_RX(n) ((u32)(n&0x0F)) /* Reflects the current level of the UART receiver FIFO */ +#define UART_FIFOLVL_TX(n) ((u32)((n>>8)&0x0F)) /* Reflects the current level of the UART transmitter FIFO */ +#define UART_FIFOLVL_BITMASK ((u32)(0x0F0F)) /* UART FIFO Level Register bit mask */ + +/********************************************************************* +* UART enum +**********************************************************************/ + +/* +* UART Databit type definitions +*/ +typedef enum { + UART_DATABIT_5 = UART_LCR_WLEN5, /* UART 5 bit data mode */ + UART_DATABIT_6 = UART_LCR_WLEN6, /* UART 6 bit data mode */ + UART_DATABIT_7 = UART_LCR_WLEN7, /* UART 7 bit data mode */ + UART_DATABIT_8 = UART_LCR_WLEN8 /* UART 8 bit data mode */ +} uart_databit_t; + +/* +* UART Stop bit type definitions +*/ +typedef enum { + UART_STOPBIT_1 = UART_LCR_ONE_STOPBIT, /* UART 1 Stop Bits Select */ + UART_STOPBIT_2 = UART_LCR_TWO_STOPBIT /* UART 2 Stop Bits Select */ +} uart_stopbit_t; + +/* +* UART Parity type definitions +*/ +typedef enum { + UART_PARITY_NONE = UART_LCR_NO_PARITY, /* No parity */ + UART_PARITY_ODD = (UART_LCR_PARITY_ODD | UART_LCR_PARITY_EN), /* Odd parity */ + UART_PARITY_EVEN = (UART_LCR_PARITY_EVEN | UART_LCR_PARITY_EN), /* Even parity */ + UART_PARITY_SP_1 = (UART_LCR_PARITY_SP_1 | UART_LCR_PARITY_EN), /* Forced 1 stick parity */ + UART_PARITY_SP_0 = (UART_LCR_PARITY_SP_0 | UART_LCR_PARITY_EN) /* Forced 0 stick parity */ +} uart_parity_t; + +typedef enum { + UART0_NUM = UART0, + UART1_NUM = UART1, + UART2_NUM = UART2, + UART3_NUM = UART3 +} uart_num_t; + +typedef enum { + UART_NO_ERROR = 0, + UART_TIMEOUT_ERROR = 1 +} uart_error_t; + +typedef enum { + UART_RX_NO_DATA = 0, + UART_RX_DATA_READY = 1, + UART_RX_DATA_ERROR = 2 +} uart_rx_data_ready_t; + +/* function prototypes */ + +/* Init UART and set PLL1 as clock source (PCLK) */ +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); + +uart_rx_data_ready_t uart_rx_data_ready(uart_num_t uart_num); + +u8 uart_read(uart_num_t uart_num); + +u8 uart_read_timeout(uart_num_t uart_num, u32 rx_timeout_nb_cycles, uart_error_t* error); + +void uart_write(uart_num_t uart_num, u8 data); + +#endif diff --git a/lib/lpc43xx/Makefile b/lib/lpc43xx/Makefile index b35156c7..17c1ded0 100644 --- a/lib/lpc43xx/Makefile +++ b/lib/lpc43xx/Makefile @@ -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 diff --git a/lib/lpc43xx/uart.c b/lib/lpc43xx/uart.c new file mode 100644 index 00000000..30d09186 --- /dev/null +++ b/lib/lpc43xx/uart.c @@ -0,0 +1,264 @@ +/* +* This file is part of the libopencm3 project. +* +* Copyright (C) 2012 Benjamin Vernoux +* +* 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 . +*/ + +#include +#include + +#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<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; +} +