From 4eee8434e151fd542232fcee346d8c7e13fe92c3 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Sat, 21 Nov 2009 15:45:32 +0000 Subject: 2009-11-21 Fernando Nicodemos * Makefile.am, preinstall.am, at91rm9200/include/at91rm9200.h: Add initial support for USART on at91rm9200. * at91rm9200/include/at91rm9200_usart.h, at91rm9200/usart/usart.c: New files. --- c/src/lib/libcpu/arm/ChangeLog | 7 + c/src/lib/libcpu/arm/Makefile.am | 11 +- .../lib/libcpu/arm/at91rm9200/include/at91rm9200.h | 24 +- .../arm/at91rm9200/include/at91rm9200_usart.h | 148 +++++++++++ c/src/lib/libcpu/arm/at91rm9200/usart/usart.c | 274 +++++++++++++++++++++ c/src/lib/libcpu/arm/preinstall.am | 4 + 6 files changed, 462 insertions(+), 6 deletions(-) create mode 100644 c/src/lib/libcpu/arm/at91rm9200/include/at91rm9200_usart.h create mode 100644 c/src/lib/libcpu/arm/at91rm9200/usart/usart.c (limited to 'c') diff --git a/c/src/lib/libcpu/arm/ChangeLog b/c/src/lib/libcpu/arm/ChangeLog index 68c8a15f43..536c2344a8 100644 --- a/c/src/lib/libcpu/arm/ChangeLog +++ b/c/src/lib/libcpu/arm/ChangeLog @@ -1,3 +1,10 @@ +2009-11-21 Fernando Nicodemos + + * Makefile.am, preinstall.am, at91rm9200/include/at91rm9200.h: Add + initial support for USART on at91rm9200. + * at91rm9200/include/at91rm9200_usart.h, at91rm9200/usart/usart.c: + New files. + 2009-09-17 Joel Sherrill * pxa255/ffuart/ffuart.c: Add BSP_poll_char. diff --git a/c/src/lib/libcpu/arm/Makefile.am b/c/src/lib/libcpu/arm/Makefile.am index 317942fd22..b7b5ec0b47 100644 --- a/c/src/lib/libcpu/arm/Makefile.am +++ b/c/src/lib/libcpu/arm/Makefile.am @@ -26,7 +26,7 @@ endif if pxa255 include_HEADERS = pxa255/include/pxa255.h pxa255/include/ffuart.h -##pxa255/clock +## pxa255/clock noinst_PROGRAMS += pxa255/clock.rel pxa255_clock_rel_SOURCES = pxa255/clock/clock.c pxa255_clock_rel_CPPFLAGS = $(AM_CPPFLAGS) @@ -63,7 +63,8 @@ endif if at91rm9200 include_HEADERS = at91rm9200/include/at91rm9200.h at91rm9200/include/at91rm9200_dbgu.h \ at91rm9200/include/at91rm9200_emac.h at91rm9200/include/at91rm9200_gpio.h \ - at91rm9200/include/at91rm9200_mem.h at91rm9200/include/at91rm9200_pmc.h at91rm9200/include/bits.h + at91rm9200/include/at91rm9200_mem.h at91rm9200/include/at91rm9200_pmc.h \ + at91rm9200/include/bits.h at91rm9200/include/at91rm9200_usart.h ## at91rm9200/clock noinst_PROGRAMS += at91rm9200/clock.rel @@ -77,6 +78,12 @@ at91rm9200_dbgu_rel_SOURCES = at91rm9200/dbgu/dbgu.c at91rm9200_dbgu_rel_CPPFLAGS = $(AM_CPPFLAGS) at91rm9200_dbgu_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) +## at91rm9200/usart +noinst_PROGRAMS += at91rm9200/usart.rel +at91rm9200_usart_rel_SOURCES = at91rm9200/usart/usart.c +at91rm9200_usart_rel_CPPFLAGS = $(AM_CPPFLAGS) +at91rm9200_usart_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) + ## at91rm9200/timer noinst_PROGRAMS += at91rm9200/timer.rel at91rm9200_timer_rel_SOURCES = at91rm9200/timer/timer.c diff --git a/c/src/lib/libcpu/arm/at91rm9200/include/at91rm9200.h b/c/src/lib/libcpu/arm/at91rm9200/include/at91rm9200.h index ab80442631..99346dbaa0 100644 --- a/c/src/lib/libcpu/arm/at91rm9200/include/at91rm9200.h +++ b/c/src/lib/libcpu/arm/at91rm9200/include/at91rm9200.h @@ -1,16 +1,21 @@ /* - * Atmel AT91RM9200 Register definitions + * Atmel AT91RM9200 Register definitions, used in KIT637_V6 (CSB637) * * Copyright (c) 2003 by Cogent Computer Systems * Written by Mike Kelly - * + * + * Modified by Fernando Nicodemos + * from NCB - Sistemas Embarcados Ltda. (Brazil) + * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * * http://www.rtems.com/license/LICENSE. * * $Id$ - */ +*/ + + #ifndef __AT91RM9200_H__ #define __AT91RM9200_H__ @@ -103,7 +108,7 @@ typedef volatile unsigned long vulong; #define AIC_SMR_SRC_EDGE_HI (3 << 5) /**************************************************************************/ -/* Debug Unit */ +/* Debug Unit */ /**************************************************************************/ #define DBGU_BASE 0xFFFFF200 #define DBGU_REG(_x_) *(vulong *)(DBGU_BASE + _x_) @@ -122,6 +127,17 @@ typedef volatile unsigned long vulong; #define DBGU_C2R 0x44 /* Chip ID2 Register */ #define DBGU_FNTR 0x48 /* Force NTRST Register */ +/**************************************************************************/ +/* USART 0-3 */ +/**************************************************************************/ +#define USART0_BASE 0xFFFC0000 +#define USART1_BASE 0xFFFC4000 +#define USART2_BASE 0xFFFC8000 +#define USART3_BASE 0xFFFCC000 +/**** The USART3_BASE at the AT91RM9200 Manual is wrong ****/ +/**** Manual revision: Rev. 1768H-ATARM–16-Jun-09 ****/ +//#define USART3_BASE 0xFFECC000 + /****************/ /* System Timer */ /****************/ diff --git a/c/src/lib/libcpu/arm/at91rm9200/include/at91rm9200_usart.h b/c/src/lib/libcpu/arm/at91rm9200/include/at91rm9200_usart.h new file mode 100644 index 0000000000..defb9e74e6 --- /dev/null +++ b/c/src/lib/libcpu/arm/at91rm9200/include/at91rm9200_usart.h @@ -0,0 +1,148 @@ +/* + * Atmel AT91RM9200_USART Register definitions, used in KIT637_V6 (CSB637) + * + * Copyright (c) 2003 by Cogent Computer Systems + * Written by Mike Kelly + * + * Modified by Fernando Nicodemos + * from NCB - Sistemas Embarcados Ltda. (Brazil) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ +*/ + +#ifndef __AT91RM9200_USART_H__ +#define __AT91RM9200_USART_H__ + +#include + +/* Register Offsets */ +#define US_CR 0x00 /* Control Register */ +#define US_MR 0x04 /* Mode Register */ +#define US_IER 0x08 /* Interrupt Enable Register */ +#define US_IDR 0x0C /* Interrupt Disable Register */ +#define US_IMR 0x10 /* Interrupt Mask Register */ +#define US_SR 0x14 /* Channel Status Register */ +#define US_RHR 0x18 /* Receiver Holding Register */ +#define US_THR 0x1C /* Transmitter Holding Register */ +#define US_BRGR 0x20 /* Baud Rate Generator Register */ +#define US_RTOR 0x24 /* Receiver Time-out Register */ +#define US_TTGR 0x28 /* Transmitter Timeguard Register */ +#define US_C1R 0x40 /* Chip ID1 Register - FI DI Ratio Register */ +#define US_C2R 0x44 /* Chip ID2 Register - Number of Erros Register */ +#define US_FNTR 0x48 /* Force NTRST Register */ +#define US_IF 0x4C /* IrDA Filter Register */ + +/* Bit Defines */ +/* Control Register, US_CR, Offset 0x00 */ +#define US_CR_RSTRX BIT2 /* 1 = Reset and disable receiver */ +#define US_CR_RSTTX BIT3 /* 1 = Reset and disable transmitter */ +#define US_CR_RXEN BIT4 /* 1 = Receiver enable */ +#define US_CR_RXDIS BIT5 /* 1 = Receiver disable */ +#define US_CR_TXEN BIT6 /* 1 = Transmitter enable */ +#define US_CR_TXDIS BIT7 /* 1 = Transmitter disable */ +#define US_CR_RSTSTA BIT8 /* 1 = Reset PARE, FRAME and OVRE in DBGU_SR. */ +#define US_CR_STTBRK BIT9 /* 1 = Start transmission of a Break */ +#define US_CR_STPBRK BIT10 /* 1 = Stop transmission of a Break */ +#define US_CR_STTTO BIT11 /* 1 = Start Time-out */ +#define US_CR_SENDA BIT12 /* 1 = Send Address - MDROP mode only */ +#define US_CR_RSTIT BIT13 /* 1 = Reset Iteration */ +#define US_CR_RSTNACK BIT14 /* 1 = Reset Non Acknowledge */ +#define US_CR_RETTO BIT15 /* 1 = Restart Time-out */ +#define US_CR_DTREN BIT16 /* 1 = Data Terminal Ready Enable - AT91RM9200 only */ +#define US_CR_DTRDIS BIT17 /* 1 = Data Terminal Ready Disable - AT91RM9200 only */ +#define US_CR_RTSEN BIT18 /* 1 = Request To Send Enable */ +#define US_CR_RTSDIS BIT19 /* 1 = Request To Send Disable */ + + +/* Mode Register. US_MR. Offset 0x04 */ +#define US_MR_USMODE (0xF << 0) /* Mode of the USART */ +#define US_MR_USMODE_NORMAL 0 +#define US_MR_USMODE_RS485 1 +#define US_MR_USMODE_HWHS 2 +#define US_MR_USMODE_MODEM 3 +#define US_MR_USMODE_ISO7816_T0 4 +#define US_MR_USMODE_ISO7816_T1 6 +#define US_MR_USMODE_IRDA 8 +#define US_MR_USCLKS (3 << 4) /* Clock Selection */ +#define US_MR_USCLKS_MCK (0 << 4) +#define US_MR_USCLKS_MCK_DIV8 (1 << 4) +#define US_MR_USCLKS_SCK (3 << 4) +#define US_MR_CHRL (3 << 6) /* Character Length */ +#define US_MR_CHRL_5 (0 << 6) +#define US_MR_CHRL_6 (1 << 6) +#define US_MR_CHRL_7 (2 << 6) +#define US_MR_CHRL_8 (3 << 6) +#define US_MR_SYNC (1 << 8) /* Synchronous Mode Select */ +#define US_MR_PAR (7 << 9) /* Parity Type */ +#define US_MR_PAR_EVEN (0 << 9) /* Even Parity */ +#define US_MR_PAR_ODD (1 << 9) /* Odd Parity */ +#define US_MR_PAR_SPACE (2 << 9) /* Parity forced to 0 (Space) */ +#define US_MR_PAR_MARK (3 << 9) /* Parity forced to 1 (Mark) */ +#define US_MR_PAR_NONE (4 << 9) /* No Parity */ +#define US_MR_PAR_MDROP (6 << 9) /* Multi-drop mode */ +#define US_MR_NBSTOP (3 << 12) /* Number of Stop Bits */ +#define US_MR_NBSTOP_1 (0 << 12) +#define US_MR_NBSTOP_1_5 (1 << 12) +#define US_MR_NBSTOP_2 (2 << 12) +#define US_MR_CHMODE (3 << 14) /* Channel Mode */ +#define US_MR_CHMODE_NORM (0 << 14) /* Normal Mode */ +#define US_MR_CHMODE_AUTO (1 << 14) /* Auto Echo: RXD drives TXD */ +#define US_MR_CHMODE_LOC (2 << 14) /* Local Loopback: TXD drives RXD */ +#define US_MR_CHMODE_REM (3 << 14) /* Remote Loopback: RXD pin connected to TXD pin. */ +#define US_MR_MSBF (1 << 16) /* Bit Order */ +#define US_MR_MODE9 (1 << 17) /* 9-bit Character Length */ +#define US_MR_CLKO (1 << 18) /* Clock Output Select */ +#define US_MR_OVER (1 << 19) /* Oversampling Mode */ +#define US_MR_INACK (1 << 20) /* Inhibit Non Acknowledge */ +#define US_MR_DSNACK (1 << 21) /* Disable Successive NACK */ +#define US_MR_MAX_ITER (7 << 24) /* Max Iterations */ +#define US_MR_FILTER (1 << 28) /* Infrared Receive Line Filter */ + +/* Interrupt Enable Register, US_IER, Offset 0x08 */ +/* Interrupt Disable Register, US_IDR, Offset 0x0C */ +/* Interrupt Mask Register, US_IMR, Offset 0x10 */ +/* Channel Status Register, US_SR, Offset 0x14 */ +#define US_IER_RXRDY BIT0 /* RXRDY Interrupt */ +#define US_IER_TXRDY BIT1 /* TXRDY Interrupt */ +#define US_IER_RXBRK BIT2 /* End of Receive Transfer Interrupt */ +#define US_IER_ENDRX BIT3 /* End of Receiver Transfer */ +//#define US_IER_ENDTX BIT4 /* End of Transmit Interrupt */ +#define US_IER_OVRE BIT5 /* Overrun Interrupt */ +#define US_IER_FRAME BIT6 /* Framing Error Interrupt */ +#define US_IER_PARE BIT7 /* Parity Error */ +#define US_IER_TIMEOUT BIT8 /* Receiver Time-out */ +#define US_IER_TXEMPTY BIT9 /* Transmitter Empty */ +#define US_IER_ITERATION BIT10 /* Max number of Repetitions Reached */ +#define US_IER_TXBUFE BIT11 /* Transmission Buffer Empty */ +#define US_IER_RXBUFF BIT12 /* Reception Buffer Full */ +#define US_IER_NACK BIT13 /* Non Acknowledge */ +#define US_IER_RIIC BIT16 /* Ring Indicator Input Change [AT91RM9200 only] */ +#define US_IER_DSRIC BIT17 /* Data Set Ready Input Change [AT91RM9200 only] */ +#define US_IER_DCDIC BIT18 /* Data Carrier Detect Input Change [AT91RM9200 only] */ +#define US_IER_CTSIC BIT19 /* Clear to Send Input Change */ +#define US_IER_ALL 0xC0001AFB /* all assigned bits */ + +/* FORCE_NTRST Register, US_FNTR, Offset 0x48 */ +#define US_FNTR_NTRST BIT0 /* 1 = Force NTRST low in JTAG */ + +typedef struct { + volatile uint32_t cr; + volatile uint32_t mr; + volatile uint32_t ier; + volatile uint32_t idr; + volatile uint32_t imr; + volatile uint32_t sr; + volatile uint32_t rhr; + volatile uint32_t thr; + volatile uint32_t brgr; + volatile uint32_t _res0[7]; + volatile uint32_t cidr; + volatile uint32_t exid; + volatile uint32_t fnr; +} at91rm9200_usart_regs_t; + +#endif /* __AT91RM9200_USART_H__ */ diff --git a/c/src/lib/libcpu/arm/at91rm9200/usart/usart.c b/c/src/lib/libcpu/arm/at91rm9200/usart/usart.c new file mode 100644 index 0000000000..c26cccc1f9 --- /dev/null +++ b/c/src/lib/libcpu/arm/at91rm9200/usart/usart.c @@ -0,0 +1,274 @@ +/* + * Driver for AT91RM9200 USART ports + * + * COPYRIGHT (c) 2006-2009. + * NCB - Sistemas Embarcados Ltda. (Brazil) + * Fernando Nicodemos + * + * and + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* static function prototypes */ +static int usart_first_open(int major, int minor, void *arg); +static int usart_last_close(int major, int minor, void *arg); +static int usart_read_polled(int minor); +static int usart_write_polled_support(int minor, const char *buf, int len); +static void usart_init(int minor); +static void usart_write_polled(int minor, char c); +static int usart_set_attributes(int minor, const struct termios *t); +at91rm9200_usart_regs_t *usart_get_base(int minor); + +/* Pointers to functions for handling the UART polled. */ +console_fns usart_polling_fns = { + libchip_serial_default_probe, /* deviceProbe */ + usart_first_open, /* deviceFirstOpen */ + usart_last_close, /* deviceLastClose */ + usart_read_polled, /* deviceRead */ + usart_write_polled_support, /* deviceWrite */ + usart_init, /* deviceInitialize */ + usart_write_polled, /* deviceWritePolled */ + usart_set_attributes, /* deviceSetAttributes */ + FALSE /* TRUE if interrupt driven, FALSE if not. */ +}; + +at91rm9200_usart_regs_t *usart_get_base(int minor) +{ + console_tbl *console_entry; + at91rm9200_usart_regs_t *port; + + console_entry = BSP_get_uart_from_minor(minor); + + if (console_entry == NULL) + return 0; + + port = (at91rm9200_usart_regs_t *) console_entry->ulCtrlPort1; + //printk( "minor=%d entry=%p port=%p\n", minor, console_entry, port ); + + return port; +} + +/* + * Functions called via callbacks (i.e. the ones in uart_fns + */ + +/* + * This is called the first time each device is opened. Since + * the driver is polled, we don't have to do anything. If the driver + * were interrupt driven, we'd enable interrupts here. + */ +static int usart_first_open(int major, int minor, void *arg) +{ + at91rm9200_usart_regs_t *usart; + + usart = usart_get_base(minor); + if ( !usart ) + return -1; + + /* XXX port isn't being initialized or enabled */ + + /* XXX I hope this is enough */ + usart->cr = (US_CR_RXEN | US_CR_TXEN); + return 0; +} + +/* + * This is called the last time each device is closed. Since + * the driver is polled, we don't have to do anything. If the driver + * were interrupt driven, we'd disable interrupts here. + */ +static int usart_last_close(int major, int minor, void *arg) +{ + at91rm9200_usart_regs_t *usart; + + usart = usart_get_base(minor); + if ( !usart ) + return -1; + + return 0; +} + +/* + * Read one character from UART. + * + * return -1 if there's no data, otherwise return + * the character in lowest 8 bits of returned int. + */ +static int usart_read_polled(int minor) +{ + at91rm9200_usart_regs_t *usart; + + usart = usart_get_base(minor); + if ( !usart ) + return -1; + + /* if nothing ready return -1 */ + if ( (usart->sr & US_IER_RXBUFF) == 0 ) + return -1; + + return usart->thr; +} + + +/* + * Write character out + */ +static void usart_write_polled(int minor, char c) +{ + at91rm9200_usart_regs_t *usart; + + usart = usart_get_base(minor); + if ( !usart ) + return; + + /* delay until TX empty */ + while ( (usart->sr & US_IER_TXEMPTY) == 0 ) + ; + + usart->thr = c; +} + +/* + * Write buffer to UART + * + * return 1 on success, -1 on error + */ +static int usart_write_polled_support(int minor, const char *buf, int len) +{ + at91rm9200_usart_regs_t *usart; + int nwrite=0; + + /* + * Verify the minor number + */ + usart = usart_get_base(minor); + if ( !usart ) + return -1; + + /* + * poll each byte in the string out of the port. + */ + while (nwrite < len) { + usart_write_polled(minor, *buf++); + nwrite++; + } + + /* + * return the number of bytes written. + */ + return nwrite; + + return 1; +} + + +/* Set up the UART. */ +static void usart_init(int minor) +{ + at91rm9200_usart_regs_t *usart; + + usart = usart_get_base(minor); + if ( !usart ) + return; + +} + + +/* This is for setting baud rate, bits, etc. */ +static int usart_set_attributes(int minor, const struct termios *t) +{ + uint32_t brgr; + uint32_t mode, baud, baud_requested; + at91rm9200_usart_regs_t *usart; + + usart = usart_get_base(minor); + if ( !usart ) + return -1; + + /* Get current mode register */ + mode = usart->mr & ~(US_MR_USMODE | US_MR_USCLKS | US_MR_CHRL + | US_MR_PAR | US_MR_NBSTOP); + + /* Byte size */ + switch (t->c_cflag & CSIZE){ + case CS5: + mode |= US_MR_CHRL_5; + break; + case CS6: + mode |= US_MR_CHRL_6; + break; + case CS7: + mode |= US_MR_CHRL_7; + break; + default: + mode |= US_MR_CHRL_8; + break; + } + + /* Stop bits */ + if (t->c_cflag & CSTOPB){ + mode |= US_MR_NBSTOP_2; /* 2 stop bits */ + } else + mode |= US_MR_NBSTOP_1; /* 1 stop bits */ + + /* Parity */ + if (t->c_cflag & PARENB){ + /* Mark or Space parity */ + if (t->c_cflag & PARODD){ + mode |= US_MR_PAR_ODD; + } else + mode |= US_MR_PAR_EVEN; + } else + mode |= US_MR_PAR_NONE; + + baud_requested = t->c_cflag & CBAUD; + + /* If not, set the dbgu console baud as USART baud default */ + if (!baud_requested) + baud_requested = BSP_get_baud(); + + baud = rtems_termios_baud_to_number(baud_requested); + + brgr = (at91rm9200_get_mck() / 16) / baud; + + if (brgr > 65535){ /* BRGR is 16-bit, so switch to slower clock */ + brgr /= 8; + mode |= US_MR_USCLKS_MCK_DIV8; + } + + usart->mr = mode; + usart->brgr = brgr; +} + +/* + * The following functions are not used by TERMIOS, but other RTEMS + * functions use them instead. + */ + +/* + * Read from UART. This is used in the exit code, and can't + * rely on interrupts. + */ +int usart_poll_read(int minor) +{ + return usart_read_polled(minor); +} diff --git a/c/src/lib/libcpu/arm/preinstall.am b/c/src/lib/libcpu/arm/preinstall.am index 3d156cad74..4ae225666a 100644 --- a/c/src/lib/libcpu/arm/preinstall.am +++ b/c/src/lib/libcpu/arm/preinstall.am @@ -70,6 +70,10 @@ $(PROJECT_INCLUDE)/bits.h: at91rm9200/include/bits.h $(PROJECT_INCLUDE)/$(dirsta $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bits.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bits.h +$(PROJECT_INCLUDE)/at91rm9200_usart.h: at91rm9200/include/at91rm9200_usart.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/at91rm9200_usart.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/at91rm9200_usart.h + $(PROJECT_INCLUDE)/irq.h: at91rm9200/irq/irq.h $(PROJECT_INCLUDE)/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/irq.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/irq.h -- cgit v1.2.3