00001 /* 00002 * Copyright (C) 2005 by egnite Software GmbH. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holders nor the names of 00014 * contributors may be used to endorse or promote products derived 00015 * from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS 00018 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00019 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00020 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE 00021 * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00022 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00023 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00024 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00025 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00026 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00027 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGE. 00029 * 00030 * For additional information see http://www.ethernut.de/ 00031 */ 00032 00033 /* 00034 * $Log: usart0at91.c,v $ 00035 * Revision 1.10 2008/10/05 16:38:06 haraldkipp 00036 * UART driver was broken on SAM7S and SAM7SE. 00037 * 00038 * Revision 1.9 2008/08/11 06:59:13 haraldkipp 00039 * BSD types replaced by stdint types (feature request #1282721). 00040 * 00041 * Revision 1.8 2008/08/06 12:51:01 haraldkipp 00042 * Added support for Ethernut 5 (AT91SAM9XE reference design). 00043 * 00044 * Revision 1.7 2008/07/31 09:43:24 haraldkipp 00045 * Initializing peripheral control registers in a more general way. 00046 * Fixes bug #2032960. 00047 * 00048 * Revision 1.6 2008/04/18 13:24:55 haraldkipp 00049 * Added Szemzo Andras' RS485 patch. 00050 * 00051 * Revision 1.5 2008/02/15 16:59:11 haraldkipp 00052 * Spport for AT91SAM7SE512 added. 00053 * 00054 * Revision 1.4 2007/10/04 20:04:11 olereinhardt 00055 * Support for SAM7S256 added 00056 * 00057 * Revision 1.3 2006/07/05 07:55:23 haraldkipp 00058 * Daidai's support for AT91SAM7X added. 00059 * 00060 * Revision 1.2 2006/01/05 16:46:52 haraldkipp 00061 * Baudrate calculation is now based on NutGetCpuClock(). 00062 * 00063 * Revision 1.1 2005/11/20 14:40:28 haraldkipp 00064 * Added interrupt driven UART driver for AT91. 00065 * 00066 */ 00067 00068 #include <cfg/os.h> 00069 #include <cfg/clock.h> 00070 #include <cfg/arch.h> 00071 00072 #include <string.h> 00073 00074 #include <sys/atom.h> 00075 #include <sys/event.h> 00076 #include <sys/timer.h> 00077 00078 #include <dev/irqreg.h> 00079 #include <dev/usartat91.h> 00080 00081 #ifndef NUT_CPU_FREQ 00082 #ifdef NUT_PLL_CPUCLK 00083 #include <dev/cy2239x.h> 00084 #else /* !NUT_PLL_CPUCLK */ 00085 #define NUT_CPU_FREQ 73728000UL 00086 #endif /* !NUT_PLL_CPUCLK */ 00087 #endif /* !NUT_CPU_FREQ */ 00088 00089 /* 00090 * Local function prototypes. 00091 */ 00092 static uint32_t At91UsartGetSpeed(void); 00093 static int At91UsartSetSpeed(uint32_t rate); 00094 static uint8_t At91UsartGetDataBits(void); 00095 static int At91UsartSetDataBits(uint8_t bits); 00096 static uint8_t At91UsartGetParity(void); 00097 static int At91UsartSetParity(uint8_t mode); 00098 static uint8_t At91UsartGetStopBits(void); 00099 static int At91UsartSetStopBits(uint8_t bits); 00100 static uint32_t At91UsartGetFlowControl(void); 00101 static int At91UsartSetFlowControl(uint32_t flags); 00102 static uint32_t At91UsartGetStatus(void); 00103 static int At91UsartSetStatus(uint32_t flags); 00104 static uint8_t At91UsartGetClockMode(void); 00105 static int At91UsartSetClockMode(uint8_t mode); 00106 static void At91UsartTxStart(void); 00107 static void At91UsartRxStart(void); 00108 static int At91UsartInit(void); 00109 static int At91UsartDeinit(void); 00110 00115 00119 static USARTDCB dcb_usart0 = { 00120 0, /* dcb_modeflags */ 00121 0, /* dcb_statusflags */ 00122 0, /* dcb_rtimeout */ 00123 0, /* dcb_wtimeout */ 00124 {0, 0, 0, 0, 0, 0, 0, 0}, /* dcb_tx_rbf */ 00125 {0, 0, 0, 0, 0, 0, 0, 0}, /* dcb_rx_rbf */ 00126 0, /* dbc_last_eol */ 00127 At91UsartInit, /* dcb_init */ 00128 At91UsartDeinit, /* dcb_deinit */ 00129 At91UsartTxStart, /* dcb_tx_start */ 00130 At91UsartRxStart, /* dcb_rx_start */ 00131 At91UsartSetFlowControl, /* dcb_set_flow_control */ 00132 At91UsartGetFlowControl, /* dcb_get_flow_control */ 00133 At91UsartSetSpeed, /* dcb_set_speed */ 00134 At91UsartGetSpeed, /* dcb_get_speed */ 00135 At91UsartSetDataBits, /* dcb_set_data_bits */ 00136 At91UsartGetDataBits, /* dcb_get_data_bits */ 00137 At91UsartSetParity, /* dcb_set_parity */ 00138 At91UsartGetParity, /* dcb_get_parity */ 00139 At91UsartSetStopBits, /* dcb_set_stop_bits */ 00140 At91UsartGetStopBits, /* dcb_get_stop_bits */ 00141 At91UsartSetStatus, /* dcb_set_status */ 00142 At91UsartGetStatus, /* dcb_get_status */ 00143 At91UsartSetClockMode, /* dcb_set_clock_mode */ 00144 At91UsartGetClockMode, /* dcb_get_clock_mode */ 00145 }; 00146 00162 NUTDEVICE devUsartAt910 = { 00163 0, /* Pointer to next device, dev_next. */ 00164 {'u', 'a', 'r', 't', '0', 0, 0, 0, 0}, /* Unique device name, dev_name. */ 00165 IFTYP_CHAR, /* Type of device, dev_type. */ 00166 0, /* Base address, dev_base (not used). */ 00167 0, /* First interrupt number, dev_irq (not used). */ 00168 0, /* Interface control block, dev_icb (not used). */ 00169 &dcb_usart0, /* Driver control block, dev_dcb. */ 00170 UsartInit, /* Driver initialization routine, dev_init. */ 00171 UsartIOCtl, /* Driver specific control function, dev_ioctl. */ 00172 UsartRead, /* Read from device, dev_read. */ 00173 UsartWrite, /* Write to device, dev_write. */ 00174 UsartOpen, /* Open a device or file, dev_open. */ 00175 UsartClose, /* Close a device or file, dev_close. */ 00176 UsartSize /* Request file size, dev_size. */ 00177 }; 00178 00182 00183 #if defined(MCU_AT91SAM9260) || defined(MCU_AT91SAM9XE512) 00184 #define US_PIOB_PINS_A (_BV(PB4_TXD0_A) | _BV(PB5_RXD0_A)) 00185 #define US_PIOB_PINS US_PIOB_PINS_A 00186 #endif 00187 00188 #if defined(MCU_AT91SAM7X256) 00189 #ifdef AT91_UART0_RS485 00190 #define US_PIOA_PINS_A (_BV(PA0_RXD0_A) | _BV(PA1_TXD0_A) | _BV(PA3_RTS0_A)) 00191 #define AT91_UART_RS485_MODE 00192 #else /* AT91_UART0_RS485 */ 00193 #define US_PIOA_PINS_A (_BV(PA0_RXD0_A) | _BV(PA1_TXD0_A)) 00194 #undef AT91_UART_RS485_MODE 00195 #endif /* AT91_UART0_RS485 */ 00196 #define US_PIOA_PINS US_PIOA_PINS_A 00197 #endif 00198 00199 #if defined(MCU_AT91SAM7S256) || defined(MCU_AT91SAM7SE512) 00200 #define US_PIOA_PINS_A (_BV(PA5_RXD0_A) | _BV(PA6_TXD0_A)) 00201 #define US_PIOA_PINS US_PIOA_PINS_A 00202 #endif 00203 00204 #if defined(MCU_AT91R40008) 00205 #define US_PIO_PINS (_BV(P15_RXD0) | _BV(P14_TXD0)) 00206 #endif 00207 00208 #define USARTn_BASE USART0_BASE 00209 #define US_ID US0_ID 00210 #define SIG_UART sig_UART0 00211 #define dcb_usart dcb_usart0 00212 00213 #include "usartat91.c"