1 |
27 |
unneback |
//==========================================================================
|
2 |
|
|
//
|
3 |
|
|
// devs/serial/MCF52xx/MCF5282
|
4 |
|
|
//
|
5 |
|
|
// MCF5272 UART Serial I/O Interface Module (interrupt driven)
|
6 |
|
|
//
|
7 |
|
|
//==========================================================================
|
8 |
|
|
//####ECOSGPLCOPYRIGHTBEGIN####
|
9 |
|
|
// -------------------------------------------
|
10 |
|
|
// This file is part of eCos, the Embedded Configurable Operating System.
|
11 |
|
|
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
|
12 |
|
|
//
|
13 |
|
|
// eCos is free software; you can redistribute it and/or modify it under
|
14 |
|
|
// the terms of the GNU General Public License as published by the Free
|
15 |
|
|
// Software Foundation; either version 2 or (at your option) any later version.
|
16 |
|
|
//
|
17 |
|
|
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
|
18 |
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
19 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
20 |
|
|
// for more details.
|
21 |
|
|
//
|
22 |
|
|
// You should have received a copy of the GNU General Public License along
|
23 |
|
|
// with eCos; if not, write to the Free Software Foundation, Inc.,
|
24 |
|
|
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
25 |
|
|
//
|
26 |
|
|
// As a special exception, if other files instantiate templates or use macros
|
27 |
|
|
// or inline functions from this file, or you compile this file and link it
|
28 |
|
|
// with other works to produce a work based on this file, this file does not
|
29 |
|
|
// by itself cause the resulting work to be covered by the GNU General Public
|
30 |
|
|
// License. However the source code for this file must still be made available
|
31 |
|
|
// in accordance with section (3) of the GNU General Public License.
|
32 |
|
|
//
|
33 |
|
|
// This exception does not invalidate any other reasons why a work based on
|
34 |
|
|
// this file might be covered by the GNU General Public License.
|
35 |
|
|
//
|
36 |
|
|
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
|
37 |
|
|
// at http://sources.redhat.com/ecos/ecos-license/
|
38 |
|
|
// -------------------------------------------
|
39 |
|
|
//####ECOSGPLCOPYRIGHTEND####
|
40 |
|
|
//==========================================================================
|
41 |
|
|
|
42 |
|
|
#include <cyg/io/io.h>
|
43 |
|
|
#include <cyg/io/devtab.h>
|
44 |
|
|
#include <cyg/io/serial.h>
|
45 |
|
|
#include <cyg/infra/diag.h>
|
46 |
|
|
#include <cyg/hal/hal_intr.h>
|
47 |
|
|
#include <cyg/hal/hal_memmap.h>
|
48 |
|
|
#include <cyg/infra/cyg_type.h>
|
49 |
|
|
#include <cyg/hal/hal_arch.h>
|
50 |
|
|
#include <cyg/hal/drv_api.h>
|
51 |
|
|
#include <pkgconf/hal.h>
|
52 |
|
|
#include <pkgconf/system.h>
|
53 |
|
|
#include <pkgconf/io_serial.h>
|
54 |
|
|
#include <pkgconf/io.h>
|
55 |
|
|
#include <pkgconf/io_serial_mcf5272_uart.h>
|
56 |
|
|
#include <cyg/io/ser_mcf5272_uart.h>
|
57 |
|
|
|
58 |
|
|
|
59 |
|
|
/* The UART priority level */
|
60 |
|
|
#define MCF5272_UART_PRIORITY_LEVEL 2
|
61 |
|
|
|
62 |
|
|
|
63 |
|
|
/* Autobaud states */
|
64 |
|
|
typedef enum autobaud_states_t
|
65 |
|
|
{
|
66 |
|
|
AB_IDLE = 0, /* Normal state. Autobaud process hasn't been initiated yet. */
|
67 |
|
|
AB_BEGIN_BREAK, /* Detected a start of the break */
|
68 |
|
|
AB_BEGIN, /* Detected the end of the break and has set up the autobaud.*/
|
69 |
|
|
|
70 |
|
|
}autobaud_states_t;
|
71 |
|
|
|
72 |
|
|
#define FIELD_OFFSET(type,field) (cyg_uint32)(&(((type*)0)->field))
|
73 |
|
|
|
74 |
|
|
typedef struct MCF5272_uart_info_t
|
75 |
|
|
{
|
76 |
|
|
|
77 |
|
|
volatile mcf5272_sim_uart_t* base; // Base address of the UART registers
|
78 |
|
|
uint32 uart_vector; // UART interrupt vector number
|
79 |
|
|
|
80 |
|
|
cyg_interrupt serial_interrupt; // Interrupt context
|
81 |
|
|
cyg_handle_t serial_interrupt_handle; // Interrupt handle
|
82 |
|
|
|
83 |
|
|
volatile uint8 imr_mirror; // Interrupt mask register mirror
|
84 |
|
|
|
85 |
|
|
cyg_serial_info_t config; // The channel configuration
|
86 |
|
|
|
87 |
|
|
autobaud_states_t autobaud_state; // The autobaud state
|
88 |
|
|
|
89 |
|
|
|
90 |
|
|
} MCF5272_uart_info_t;
|
91 |
|
|
|
92 |
|
|
/* Function prtoftyps for the MCF5272 UART ISR and DSR. */
|
93 |
|
|
static cyg_uint32 MCF5272_uart_ISR(cyg_vector_t vector, cyg_addrword_t data);
|
94 |
|
|
static void MCF5272_uart_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
|
95 |
|
|
|
96 |
|
|
|
97 |
|
|
/* Function prototypes for the serial functions. */
|
98 |
|
|
static bool MCF5272_uart_init(struct cyg_devtab_entry * tab);
|
99 |
|
|
static Cyg_ErrNo MCF5272_uart_lookup(struct cyg_devtab_entry **tab,
|
100 |
|
|
struct cyg_devtab_entry *sub_tab,
|
101 |
|
|
const char *name);
|
102 |
|
|
static bool MCF5272_uart_putc(serial_channel *chan, unsigned char c);
|
103 |
|
|
static unsigned char MCF5272_uart_getc(serial_channel *chan);
|
104 |
|
|
Cyg_ErrNo MCF5272_uart_set_config(serial_channel *chan, cyg_uint32 key,
|
105 |
|
|
const void *xbuf, cyg_uint32 *len);
|
106 |
|
|
static void MCF5272_uart_start_xmit(serial_channel *chan);
|
107 |
|
|
static void MCF5272_uart_stop_xmit(serial_channel * chan);
|
108 |
|
|
|
109 |
|
|
|
110 |
|
|
/* Declare the serial functions that are called by the common serial driver layer. */
|
111 |
|
|
static SERIAL_FUNS
|
112 |
|
|
(
|
113 |
|
|
MCF5272_uart_funs,
|
114 |
|
|
MCF5272_uart_putc,
|
115 |
|
|
MCF5272_uart_getc,
|
116 |
|
|
MCF5272_uart_set_config,
|
117 |
|
|
MCF5272_uart_start_xmit,
|
118 |
|
|
MCF5272_uart_stop_xmit
|
119 |
|
|
);
|
120 |
|
|
|
121 |
|
|
|
122 |
|
|
/* Definition for channel 0 UART configuration. */
|
123 |
|
|
/************************************************/
|
124 |
|
|
#ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL0
|
125 |
|
|
|
126 |
|
|
/* Data structure contains
|
127 |
|
|
channel informtion.
|
128 |
|
|
*/
|
129 |
|
|
static MCF5272_uart_info_t MCF5272_uart_channel_info_0;
|
130 |
|
|
|
131 |
|
|
/* If the channel buffer size is zero, do not include interrupt UART processing */
|
132 |
|
|
#if CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0_BUFSIZE > 0
|
133 |
|
|
|
134 |
|
|
/* Allocated receive and transmit buffer. The size of the buffer is */
|
135 |
|
|
/* configured by the configtool. */
|
136 |
|
|
|
137 |
|
|
static unsigned char MCF5272_uart_out_buf0[CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0_BUFSIZE];
|
138 |
|
|
static unsigned char MCF5272_uart_in_buf0[CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0_BUFSIZE];
|
139 |
|
|
|
140 |
|
|
/* Channel function table. We register the UART functions here so */
|
141 |
|
|
/* that uppper serial drivers can call the serial driver's routines. */
|
142 |
|
|
|
143 |
|
|
static SERIAL_CHANNEL_USING_INTERRUPTS(
|
144 |
|
|
MCF5272_uart_channel_0,
|
145 |
|
|
MCF5272_uart_funs,
|
146 |
|
|
MCF5272_uart_channel_info_0,
|
147 |
|
|
CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0_BAUD),
|
148 |
|
|
CYG_SERIAL_STOP_DEFAULT,
|
149 |
|
|
CYG_SERIAL_PARITY_DEFAULT,
|
150 |
|
|
CYG_SERIAL_WORD_LENGTH_DEFAULT,
|
151 |
|
|
CYG_SERIAL_FLAGS_DEFAULT,
|
152 |
|
|
MCF5272_uart_out_buf0, sizeof(MCF5272_uart_out_buf0),
|
153 |
|
|
MCF5272_uart_in_buf0, sizeof(MCF5272_uart_in_buf0)
|
154 |
|
|
);
|
155 |
|
|
#else
|
156 |
|
|
/* Don't use interrupt processing for the UART. */
|
157 |
|
|
static SERIAL_CHANNEL(
|
158 |
|
|
MCF5272_uart_channel_0,
|
159 |
|
|
MCF5272_uart_funs,
|
160 |
|
|
MCF5272_uart_channel_info_0,
|
161 |
|
|
CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0_BAUD),
|
162 |
|
|
CYG_SERIAL_STOP_DEFAULT,
|
163 |
|
|
CYG_SERIAL_PARITY_DEFAULT,
|
164 |
|
|
CYG_SERIAL_WORD_LENGTH_DEFAULT,
|
165 |
|
|
CYG_SERIAL_FLAGS_DEFAULT
|
166 |
|
|
);
|
167 |
|
|
#endif
|
168 |
|
|
|
169 |
|
|
DEVTAB_ENTRY(
|
170 |
|
|
MCF5272_uart_io0,
|
171 |
|
|
CYGDAT_IO_SERIAL_MCF5272_UART_CHANNEL0_NAME,
|
172 |
|
|
0, // Does not depend on a lower level interface
|
173 |
|
|
&cyg_io_serial_devio, // The table of I/O functions.
|
174 |
|
|
MCF5272_uart_init, // UART initialization function.
|
175 |
|
|
MCF5272_uart_lookup, // The UART lookup function. This function typically sets
|
176 |
|
|
// up the device for actual use, turing on interrupts, configuring the port, etc.
|
177 |
|
|
&MCF5272_uart_channel_0
|
178 |
|
|
);
|
179 |
|
|
#endif // CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0
|
180 |
|
|
|
181 |
|
|
/* Definition for channel 1 UART configuration. */
|
182 |
|
|
/************************************************/
|
183 |
|
|
|
184 |
|
|
#ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL1
|
185 |
|
|
|
186 |
|
|
|
187 |
|
|
/* Data structure contains
|
188 |
|
|
channel informtion.
|
189 |
|
|
*/
|
190 |
|
|
static MCF5272_uart_info_t MCF5272_uart_channel_info_1;
|
191 |
|
|
|
192 |
|
|
/* If the channel buffer size is zero, do not include interrupt UART processing */
|
193 |
|
|
#if CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL1_BUFSIZE > 0
|
194 |
|
|
|
195 |
|
|
/* Allocated receive and transmit buffer. The size of the buffer is */
|
196 |
|
|
/* configured by the configtool. */
|
197 |
|
|
|
198 |
|
|
static unsigned char MCF5272_uart_out_buf1[CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL1_BUFSIZE];
|
199 |
|
|
static unsigned char MCF5272_uart_in_buf1[CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL1_BUFSIZE];
|
200 |
|
|
|
201 |
|
|
/* Channel function table. We register the UART functions here so */
|
202 |
|
|
/* that uppper serial drivers can call the serial driver's routines. */
|
203 |
|
|
|
204 |
|
|
static SERIAL_CHANNEL_USING_INTERRUPTS(
|
205 |
|
|
MCF5272_uart_channel_1,
|
206 |
|
|
MCF5272_uart_funs,
|
207 |
|
|
MCF5272_uart_channel_info_1,
|
208 |
|
|
CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL1_BAUD),
|
209 |
|
|
CYG_SERIAL_STOP_DEFAULT,
|
210 |
|
|
CYG_SERIAL_PARITY_DEFAULT,
|
211 |
|
|
CYG_SERIAL_WORD_LENGTH_DEFAULT,
|
212 |
|
|
CYG_SERIAL_FLAGS_DEFAULT,
|
213 |
|
|
MCF5272_uart_out_buf1, sizeof(MCF5272_uart_out_buf1),
|
214 |
|
|
MCF5272_uart_in_buf1, sizeof(MCF5272_uart_in_buf1)
|
215 |
|
|
);
|
216 |
|
|
|
217 |
|
|
#else
|
218 |
|
|
static SERIAL_CHANNEL(MCF5272_uart_channel_1,
|
219 |
|
|
MCF5272_uart_funs,
|
220 |
|
|
MCF5272_uart_channel_info_1,
|
221 |
|
|
CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL0_BAUD),
|
222 |
|
|
CYG_SERIAL_STOP_DEFAULT,
|
223 |
|
|
CYG_SERIAL_PARITY_DEFAULT,
|
224 |
|
|
CYG_SERIAL_WORD_LENGTH_DEFAULT,
|
225 |
|
|
CYG_SERIAL_FLAGS_DEFAULT
|
226 |
|
|
);
|
227 |
|
|
#endif
|
228 |
|
|
DEVTAB_ENTRY(
|
229 |
|
|
MCF5272_uart_io1,
|
230 |
|
|
CYGDAT_IO_SERIAL_MCF5272_UART_CHANNEL1_NAME,
|
231 |
|
|
0, // Does not depend on a lower level interface
|
232 |
|
|
&cyg_io_serial_devio, // The table of I/O functions.
|
233 |
|
|
MCF5272_uart_init, // UART initialization function.
|
234 |
|
|
MCF5272_uart_lookup, // The UART lookup function. This function typically sets
|
235 |
|
|
// up the device for actual use, turing on interrupts, configuring the port, etc.
|
236 |
|
|
&MCF5272_uart_channel_1
|
237 |
|
|
);
|
238 |
|
|
#endif // CYGNUM_IO_SERIAL_MCF5272_UART_CHANNEL1
|
239 |
|
|
|
240 |
|
|
|
241 |
|
|
|
242 |
|
|
/* Definition of macros that access the UART's SIM registers */
|
243 |
|
|
/* Read from a register */
|
244 |
|
|
|
245 |
|
|
#define MCF5272_UART_WRITE(_addr_,_value_) \
|
246 |
|
|
*((volatile CYG_BYTE*)&(_addr_)) = (CYG_BYTE)(_value_)
|
247 |
|
|
/* Write to a register */
|
248 |
|
|
#define MCF5272_UART_READ(_addr_) \
|
249 |
|
|
*(volatile CYG_BYTE*)&(_addr_)
|
250 |
|
|
|
251 |
|
|
|
252 |
|
|
/* Function Prototypes */
|
253 |
|
|
/* =================== */
|
254 |
|
|
/* Internal function to actually configure the hardware to desired baud rate, etc. */
|
255 |
|
|
static bool MCF5272_uart_config_port(serial_channel*, cyg_serial_info_t*);
|
256 |
|
|
static void MCF5272_uart_start_xmit(serial_channel*);
|
257 |
|
|
|
258 |
|
|
|
259 |
|
|
/* Baudrate conversion table. */
|
260 |
|
|
static unsigned long baud_rates_table[]=
|
261 |
|
|
{
|
262 |
|
|
0,
|
263 |
|
|
50, // CYGNUM_SERIAL_BAUD_50 = 1
|
264 |
|
|
75, // CYGNUM_SERIAL_BAUD_75
|
265 |
|
|
110, // CYGNUM_SERIAL_BAUD_110
|
266 |
|
|
134, // CYGNUM_SERIAL_BAUD_134_5
|
267 |
|
|
150, // CYGNUM_SERIAL_BAUD_150
|
268 |
|
|
200, // CYGNUM_SERIAL_BAUD_200
|
269 |
|
|
300, // CYGNUM_SERIAL_BAUD_300
|
270 |
|
|
600, // CYGNUM_SERIAL_BAUD_600
|
271 |
|
|
1200, // CYGNUM_SERIAL_BAUD_1200
|
272 |
|
|
1800, // CYGNUM_SERIAL_BAUD_1800
|
273 |
|
|
2400, // CYGNUM_SERIAL_BAUD_2400
|
274 |
|
|
3600, // CYGNUM_SERIAL_BAUD_3600
|
275 |
|
|
4800, // CYGNUM_SERIAL_BAUD_4800
|
276 |
|
|
7200, // CYGNUM_SERIAL_BAUD_7200
|
277 |
|
|
9600, // CYGNUM_SERIAL_BAUD_9600
|
278 |
|
|
14400, // CYGNUM_SERIAL_BAUD_14400
|
279 |
|
|
19200, // CYGNUM_SERIAL_BAUD_19200
|
280 |
|
|
38400, // CYGNUM_SERIAL_BAUD_38400
|
281 |
|
|
57600, // CYGNUM_SERIAL_BAUD_57600
|
282 |
|
|
115200, // CYGNUM_SERIAL_BAUD_115200
|
283 |
|
|
230400 // CYGNUM_SERIAL_BAUD_230400
|
284 |
|
|
};
|
285 |
|
|
|
286 |
|
|
/* The table contains divers to divide the clock to configre a */
|
287 |
|
|
/* approppriate for the UART. */
|
288 |
|
|
|
289 |
|
|
static unsigned long dividers_table[]=
|
290 |
|
|
{
|
291 |
|
|
0,
|
292 |
|
|
46080, // 50
|
293 |
|
|
30720, // 75
|
294 |
|
|
20945, // 110
|
295 |
|
|
17130, // 134_5
|
296 |
|
|
15360, // 150
|
297 |
|
|
11520, // 200
|
298 |
|
|
7680, // 300
|
299 |
|
|
3840, // 600
|
300 |
|
|
1920, // 1200
|
301 |
|
|
1280, // 1800
|
302 |
|
|
960, // 2400
|
303 |
|
|
640, // 3600
|
304 |
|
|
480, // 4800
|
305 |
|
|
320, // 7200
|
306 |
|
|
240, // 9600
|
307 |
|
|
160, // 14400
|
308 |
|
|
120, // 19200
|
309 |
|
|
60, // 38400
|
310 |
|
|
40, // 57600
|
311 |
|
|
20, // 115200
|
312 |
|
|
10 // 230400
|
313 |
|
|
};
|
314 |
|
|
|
315 |
|
|
/*******************************************************************************
|
316 |
|
|
MCF5272_uart_init() - This routine is called during bootstrap to set up the
|
317 |
|
|
UART driver.
|
318 |
|
|
|
319 |
|
|
INPUT:
|
320 |
|
|
Pointer to the the device table.
|
321 |
|
|
|
322 |
|
|
RETURN:
|
323 |
|
|
Returns true if the initialization is successful. Otherwise, it retuns false
|
324 |
|
|
*/
|
325 |
|
|
static bool MCF5272_uart_init(struct cyg_devtab_entry * tab)
|
326 |
|
|
{
|
327 |
|
|
serial_channel *chan = (serial_channel *)tab->priv;
|
328 |
|
|
MCF5272_uart_info_t *MCF5272_uart_chan = (MCF5272_uart_info_t *)chan->dev_priv;
|
329 |
|
|
|
330 |
|
|
#ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL0
|
331 |
|
|
|
332 |
|
|
/* Instantiation of the UART channel 0 data strucutre. This data */
|
333 |
|
|
/* structure contains channel information. */
|
334 |
|
|
|
335 |
|
|
if (strcmp(tab->name, CYGDAT_IO_SERIAL_MCF5272_UART_CHANNEL0_NAME) == 0)
|
336 |
|
|
{
|
337 |
|
|
|
338 |
|
|
/* Initiliaze the UART information data to all zeros. */
|
339 |
|
|
|
340 |
|
|
memset(MCF5272_uart_chan, sizeof(MCF5272_uart_info_t), 0);
|
341 |
|
|
|
342 |
|
|
/* Set the base address of the UART registers to differentiate */
|
343 |
|
|
/* itself from the different regusters for the other UART port. */
|
344 |
|
|
|
345 |
|
|
MCF5272_uart_chan->base = (mcf5272_sim_uart_t*)&MCF5272_SIM->uart[0];
|
346 |
|
|
|
347 |
|
|
/* Set the UART interrupt vector number. */
|
348 |
|
|
|
349 |
|
|
MCF5272_uart_chan->uart_vector = CYGNUM_HAL_VECTOR_UART1;
|
350 |
|
|
|
351 |
|
|
/* Set the autobaud state to idle. */
|
352 |
|
|
|
353 |
|
|
MCF5272_uart_chan->autobaud_state = AB_IDLE;
|
354 |
|
|
|
355 |
|
|
/* Initilize the UART 0 output pins */
|
356 |
|
|
|
357 |
|
|
MCF5272_SIM->gpio.pbcnt = MCF5272_GPIO_PBCNT_URT0_EN |
|
358 |
|
|
((MCF5272_SIM->gpio.pbcnt) & ~MCF5272_GPIO_PBCNT_URT0_MSK);
|
359 |
|
|
}
|
360 |
|
|
#endif
|
361 |
|
|
|
362 |
|
|
#ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL1
|
363 |
|
|
|
364 |
|
|
/* Instantiation of the UART channel 1 data strucutre. This data structure contains
|
365 |
|
|
channel information.
|
366 |
|
|
*/
|
367 |
|
|
if (strcmp(tab->name, CYGDAT_IO_SERIAL_MCF5272_UART_CHANNEL1_NAME) == 0)
|
368 |
|
|
{
|
369 |
|
|
|
370 |
|
|
/* Initiliaze the UART information data to all zeros. */
|
371 |
|
|
|
372 |
|
|
memset(MCF5272_uart_chan, sizeof(MCF5272_uart_info_t), 0);
|
373 |
|
|
|
374 |
|
|
/* Set the base address of the UART registers to differentiate */
|
375 |
|
|
/* itself from the different regusters for the other UART port. */
|
376 |
|
|
|
377 |
|
|
MCF5272_uart_chan->base = (mcf5272_sim_uart_t*)&MCF5272_SIM->uart[1];
|
378 |
|
|
|
379 |
|
|
/* Set the UART interrupt vector number. */
|
380 |
|
|
|
381 |
|
|
MCF5272_uart_chan->uart_vector = CYGNUM_HAL_VECTOR_UART2;
|
382 |
|
|
|
383 |
|
|
/* Set the autobaud state to idle. */
|
384 |
|
|
|
385 |
|
|
MCF5272_uart_chan->autobaud_state = AB_IDLE;
|
386 |
|
|
|
387 |
|
|
/* Initilize the UART 1 output pins */
|
388 |
|
|
|
389 |
|
|
MCF5272_SIM->gpio.pdcnt = MCF5272_GPIO_PDCNT_URT1_EN |
|
390 |
|
|
((MCF5272_SIM->gpio.pdcnt) & ~MCF5272_GPIO_PDCNT_URT1_MSK);
|
391 |
|
|
|
392 |
|
|
}
|
393 |
|
|
#endif
|
394 |
|
|
|
395 |
|
|
|
396 |
|
|
if (chan->out_cbuf.len > 0) {
|
397 |
|
|
|
398 |
|
|
/* If the the buffer is greater than zero, then the driver will */
|
399 |
|
|
/* use interrupt driven I/O. Hence, the driver creates an */
|
400 |
|
|
/* interrupt context for the UART device. */
|
401 |
|
|
|
402 |
|
|
cyg_drv_interrupt_create(MCF5272_uart_chan->uart_vector,
|
403 |
|
|
MCF5272_UART_PRIORITY_LEVEL, // Priority - Level 2
|
404 |
|
|
(cyg_addrword_t)chan, // Data item passed to interrupt handler
|
405 |
|
|
MCF5272_uart_ISR,
|
406 |
|
|
MCF5272_uart_DSR,
|
407 |
|
|
&MCF5272_uart_chan->serial_interrupt_handle,
|
408 |
|
|
&MCF5272_uart_chan->serial_interrupt);
|
409 |
|
|
|
410 |
|
|
cyg_drv_interrupt_attach(MCF5272_uart_chan->serial_interrupt_handle);
|
411 |
|
|
|
412 |
|
|
(chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices
|
413 |
|
|
}
|
414 |
|
|
|
415 |
|
|
// Configure Serial device.
|
416 |
|
|
return(MCF5272_uart_config_port(chan, &chan->config));
|
417 |
|
|
}
|
418 |
|
|
|
419 |
|
|
/******************************************************************************************************
|
420 |
|
|
MCF5272_uart_config_port() - Configure the UART port.
|
421 |
|
|
|
422 |
|
|
Internal function to actually configure the hardware to desired baud rate, etc.
|
423 |
|
|
|
424 |
|
|
INPUT:
|
425 |
|
|
chan - The channel information
|
426 |
|
|
new_confg - The port configuration which include the desired baud rate, etc.
|
427 |
|
|
|
428 |
|
|
RETURN:
|
429 |
|
|
Returns true if the port configuration is successful. Otherwise, it retuns false
|
430 |
|
|
|
431 |
|
|
*/
|
432 |
|
|
static bool MCF5272_uart_config_port(serial_channel *chan,
|
433 |
|
|
cyg_serial_info_t *new_config)
|
434 |
|
|
{
|
435 |
|
|
MCF5272_uart_info_t * port = (MCF5272_uart_info_t *) chan->dev_priv;
|
436 |
|
|
uint8 mode_reg = 0;
|
437 |
|
|
uint32 ubgs;
|
438 |
|
|
unsigned int baud_divisor;
|
439 |
|
|
|
440 |
|
|
|
441 |
|
|
/* Get the divisor from the baudrate table which will use to */
|
442 |
|
|
/* configure the port's baud rate. */
|
443 |
|
|
|
444 |
|
|
baud_divisor = baud_rates_table[new_config->baud];
|
445 |
|
|
|
446 |
|
|
/* If the divisor is zeor, we dont' configure the port. */
|
447 |
|
|
|
448 |
|
|
if (baud_divisor == 0) return false;
|
449 |
|
|
|
450 |
|
|
/* Save the configuration value for later use. */
|
451 |
|
|
|
452 |
|
|
port->config = *new_config;
|
453 |
|
|
|
454 |
|
|
/* We first write the reset values into the device and then configure */
|
455 |
|
|
/* the device the we way we want to use it. */
|
456 |
|
|
|
457 |
|
|
/* Reset Transmitter */
|
458 |
|
|
|
459 |
|
|
MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_TX);
|
460 |
|
|
|
461 |
|
|
/* Reset Receiver */
|
462 |
|
|
|
463 |
|
|
MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_RX);
|
464 |
|
|
|
465 |
|
|
/* Reset Mode Register */
|
466 |
|
|
|
467 |
|
|
MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_MR);
|
468 |
|
|
|
469 |
|
|
/* Translate the parity configuration to UART mode bits. */
|
470 |
|
|
|
471 |
|
|
switch(port->config.parity)
|
472 |
|
|
{
|
473 |
|
|
default:
|
474 |
|
|
case CYGNUM_SERIAL_PARITY_NONE:
|
475 |
|
|
mode_reg = 0 | MCF5272_UART_UMR1_PM_NONE;
|
476 |
|
|
break;
|
477 |
|
|
case CYGNUM_SERIAL_PARITY_EVEN:
|
478 |
|
|
mode_reg = 0 | MCF5272_UART_UMR1_PM_EVEN;
|
479 |
|
|
break;
|
480 |
|
|
case CYGNUM_SERIAL_PARITY_ODD:
|
481 |
|
|
mode_reg = 0 | MCF5272_UART_UMR1_PM_ODD;
|
482 |
|
|
break;
|
483 |
|
|
case CYGNUM_SERIAL_PARITY_MARK:
|
484 |
|
|
mode_reg = 0 | MCF5272_UART_UMR1_PM_FORCE_HI;
|
485 |
|
|
break;
|
486 |
|
|
case CYGNUM_SERIAL_PARITY_SPACE:
|
487 |
|
|
mode_reg = 0 | MCF5272_UART_UMR1_PM_FORCE_LO;
|
488 |
|
|
break;
|
489 |
|
|
}
|
490 |
|
|
|
491 |
|
|
/* Translate the number of bits per character configuration to UART mode bits. */
|
492 |
|
|
|
493 |
|
|
switch(port->config.word_length)
|
494 |
|
|
{
|
495 |
|
|
|
496 |
|
|
case CYGNUM_SERIAL_WORD_LENGTH_5:
|
497 |
|
|
mode_reg |= MCF5272_UART_UMR1_BC_5;
|
498 |
|
|
break;
|
499 |
|
|
case CYGNUM_SERIAL_WORD_LENGTH_6:
|
500 |
|
|
mode_reg |= MCF5272_UART_UMR1_BC_6;
|
501 |
|
|
break;
|
502 |
|
|
case CYGNUM_SERIAL_WORD_LENGTH_7:
|
503 |
|
|
mode_reg |= MCF5272_UART_UMR1_BC_7;
|
504 |
|
|
break;
|
505 |
|
|
default:
|
506 |
|
|
case CYGNUM_SERIAL_WORD_LENGTH_8:
|
507 |
|
|
mode_reg |= MCF5272_UART_UMR1_BC_8;
|
508 |
|
|
break;
|
509 |
|
|
}
|
510 |
|
|
|
511 |
|
|
/* Configure the parity and the bits per character */
|
512 |
|
|
|
513 |
|
|
MCF5272_UART_WRITE(port->base->umr, mode_reg);
|
514 |
|
|
|
515 |
|
|
/* Translate the stop bit length to UART mode bits. */
|
516 |
|
|
|
517 |
|
|
switch(port->config.stop)
|
518 |
|
|
{
|
519 |
|
|
default:
|
520 |
|
|
case CYGNUM_SERIAL_STOP_1:
|
521 |
|
|
mode_reg = MCF5272_UART_UMR2_STOP_BITS_1;
|
522 |
|
|
break;
|
523 |
|
|
case CYGNUM_SERIAL_STOP_1_5:
|
524 |
|
|
mode_reg = MCF5272_UART_UMR2_STOP_BITS_15;
|
525 |
|
|
break;
|
526 |
|
|
case CYGNUM_SERIAL_STOP_2:
|
527 |
|
|
mode_reg = MCF5272_UART_UMR2_STOP_BITS_2;
|
528 |
|
|
break;
|
529 |
|
|
}
|
530 |
|
|
|
531 |
|
|
/* No echo or loopback */
|
532 |
|
|
|
533 |
|
|
MCF5272_UART_WRITE(port->base->umr, 0 | MCF5272_UART_UMR2_CM_NORMAL | mode_reg);
|
534 |
|
|
|
535 |
|
|
/* Set Rx and Tx baud by timer */
|
536 |
|
|
|
537 |
|
|
MCF5272_UART_WRITE(port->base->ucr, 0 | MCF5272_UART_UCSR_RCS(0xD) |
|
538 |
|
|
MCF5272_UART_UCSR_TCS(0xD));
|
539 |
|
|
|
540 |
|
|
/* Mask all USART interrupts */
|
541 |
|
|
|
542 |
|
|
MCF5272_UART_WRITE(port->base->uisr_uimr, 0);
|
543 |
|
|
|
544 |
|
|
/* Calculate baud settings */
|
545 |
|
|
|
546 |
|
|
ubgs = (uint16)((CYGHWR_HAL_SYSTEM_CLOCK_MHZ*1000000)/
|
547 |
|
|
(baud_divisor * 32));
|
548 |
|
|
|
549 |
|
|
/* Program the baud settings to the device. */
|
550 |
|
|
|
551 |
|
|
MCF5272_UART_WRITE(port->base->udu, (uint8)((ubgs & 0xFF00) >> 8));
|
552 |
|
|
MCF5272_UART_WRITE(port->base->udl, (uint8)(ubgs & 0x00FF));
|
553 |
|
|
|
554 |
|
|
/* Enable receiver and transmitter */
|
555 |
|
|
|
556 |
|
|
MCF5272_UART_WRITE(port->base->ucr, 0 | MCF5272_UART_UCR_TXRXEN);
|
557 |
|
|
|
558 |
|
|
/* Enable both transmit and receive interrupt. */
|
559 |
|
|
|
560 |
|
|
port->imr_mirror = MCF5272_UART_UIMR_TXRDY | MCF5272_UART_UIMR_FFULL |
|
561 |
|
|
MCF5272_UART_UIMR_DB;
|
562 |
|
|
MCF5272_UART_WRITE(port->base->uisr_uimr, port->imr_mirror);
|
563 |
|
|
|
564 |
|
|
return true; /* Returns true to indicate a successful configuration */
|
565 |
|
|
|
566 |
|
|
}
|
567 |
|
|
|
568 |
|
|
/*******************************************************************************
|
569 |
|
|
MCF5272_uart_lookup() - This routine is called when the device is "looked" up
|
570 |
|
|
(i.e. attached)
|
571 |
|
|
|
572 |
|
|
INPUT:
|
573 |
|
|
tab - pointer to a pointer of the device table
|
574 |
|
|
sub_tab - Pointer to the sub device table.
|
575 |
|
|
name - name of the device
|
576 |
|
|
|
577 |
|
|
RETURN:
|
578 |
|
|
always return ENOERR
|
579 |
|
|
|
580 |
|
|
*/
|
581 |
|
|
static Cyg_ErrNo MCF5272_uart_lookup(struct cyg_devtab_entry **tab,
|
582 |
|
|
struct cyg_devtab_entry *sub_tab,
|
583 |
|
|
const char *name)
|
584 |
|
|
{
|
585 |
|
|
serial_channel *chan = (serial_channel *)(*tab)->priv;
|
586 |
|
|
(chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices
|
587 |
|
|
return ENOERR;
|
588 |
|
|
}
|
589 |
|
|
|
590 |
|
|
/*******************************************************************************
|
591 |
|
|
MCF5272_uart_putc() - Send a character to the device output buffer.
|
592 |
|
|
|
593 |
|
|
INPUT:
|
594 |
|
|
chan - pointer to the serial private data.
|
595 |
|
|
c - the character to output
|
596 |
|
|
|
597 |
|
|
RETURN:
|
598 |
|
|
'true' if character is sent to device, return 'false' when we've
|
599 |
|
|
ran out of buffer space in the device itself.
|
600 |
|
|
|
601 |
|
|
*/
|
602 |
|
|
|
603 |
|
|
static bool MCF5272_uart_putc(serial_channel *chan, unsigned char c)
|
604 |
|
|
{
|
605 |
|
|
CYG_INTERRUPT_STATE int_state;
|
606 |
|
|
MCF5272_uart_info_t *port = (MCF5272_uart_info_t *)chan->dev_priv;
|
607 |
|
|
|
608 |
|
|
/* Make sure the transmitter is not full. If it is full, return false. */
|
609 |
|
|
if (!(MCF5272_UART_READ(port->base->usr_ucsr) & MCF5272_UART_USR_TXRDY))
|
610 |
|
|
return false;
|
611 |
|
|
|
612 |
|
|
/* Enable transmit interrupt. */
|
613 |
|
|
HAL_DISABLE_INTERRUPTS(int_state);
|
614 |
|
|
port->imr_mirror |= MCF5272_UART_UIMR_TXRDY;
|
615 |
|
|
MCF5272_UART_WRITE(port->base->uisr_uimr, port->imr_mirror);
|
616 |
|
|
HAL_RESTORE_INTERRUPTS(int_state);
|
617 |
|
|
|
618 |
|
|
/* Enable the UART transmit. */
|
619 |
|
|
MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_TXRXEN);
|
620 |
|
|
|
621 |
|
|
/* Send the character */
|
622 |
|
|
MCF5272_UART_WRITE(port->base->urb_utb, c);
|
623 |
|
|
|
624 |
|
|
return true ;
|
625 |
|
|
}
|
626 |
|
|
|
627 |
|
|
|
628 |
|
|
/******************************************************************************************************
|
629 |
|
|
MCF5272_uart_getc() - Fetch a character from the device input bufferand return it to the alling
|
630 |
|
|
routine. Wait until there is a character ready.
|
631 |
|
|
|
632 |
|
|
INPUT:
|
633 |
|
|
chan - pointer to the serial private data.
|
634 |
|
|
|
635 |
|
|
RETURN:
|
636 |
|
|
the character read from the UART.
|
637 |
|
|
|
638 |
|
|
*/
|
639 |
|
|
static unsigned char MCF5272_uart_getc(serial_channel *chan)
|
640 |
|
|
{
|
641 |
|
|
MCF5272_uart_info_t * port = (MCF5272_uart_info_t *)chan->dev_priv;
|
642 |
|
|
|
643 |
|
|
/* Wait until character has been received */
|
644 |
|
|
|
645 |
|
|
while (!(MCF5272_UART_READ(port->base->usr_ucsr) & MCF5272_UART_USR_RXRDY))
|
646 |
|
|
{
|
647 |
|
|
diag_printf("ready poll");
|
648 |
|
|
}
|
649 |
|
|
|
650 |
|
|
/* Read the character from the FIFO queue. */
|
651 |
|
|
|
652 |
|
|
return MCF5272_UART_READ(port->base->urf);
|
653 |
|
|
|
654 |
|
|
}
|
655 |
|
|
|
656 |
|
|
|
657 |
|
|
/*******************************************************************************
|
658 |
|
|
MCF5272_uart_set_config() - Set up the device characteristics; baud rate, etc.
|
659 |
|
|
|
660 |
|
|
INPUT:
|
661 |
|
|
chan - pointer to the serial private data.
|
662 |
|
|
key - configuration key (command).
|
663 |
|
|
xbuf - pointer to the configuration buffer
|
664 |
|
|
len - the length of the configuration buffer
|
665 |
|
|
|
666 |
|
|
RETURN:
|
667 |
|
|
NOERR - If the configuration is successful
|
668 |
|
|
EINVAL - If the argument is invalid
|
669 |
|
|
|
670 |
|
|
*/
|
671 |
|
|
|
672 |
|
|
Cyg_ErrNo MCF5272_uart_set_config(serial_channel *chan, cyg_uint32 key,
|
673 |
|
|
const void *xbuf, cyg_uint32 *len)
|
674 |
|
|
{
|
675 |
|
|
cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
|
676 |
|
|
MCF5272_uart_info_t * port = (MCF5272_uart_info_t *) chan->dev_priv;
|
677 |
|
|
|
678 |
|
|
|
679 |
|
|
switch (key) {
|
680 |
|
|
case CYG_IO_SET_CONFIG_SERIAL_INFO:
|
681 |
|
|
{
|
682 |
|
|
/* Set serial configuration. */
|
683 |
|
|
if ( *len < sizeof(cyg_serial_info_t) ) {
|
684 |
|
|
return EINVAL;
|
685 |
|
|
}
|
686 |
|
|
*len = sizeof(cyg_serial_info_t);
|
687 |
|
|
|
688 |
|
|
if (!MCF5272_uart_config_port(chan, config))
|
689 |
|
|
return EINVAL;
|
690 |
|
|
}
|
691 |
|
|
break;
|
692 |
|
|
|
693 |
|
|
case CYG_IO_GET_CONFIG_SERIAL_INFO:
|
694 |
|
|
// Retrieve UART configuration
|
695 |
|
|
*config = port->config;
|
696 |
|
|
break;
|
697 |
|
|
|
698 |
|
|
default:
|
699 |
|
|
return EINVAL;
|
700 |
|
|
}
|
701 |
|
|
return ENOERR;
|
702 |
|
|
}
|
703 |
|
|
|
704 |
|
|
|
705 |
|
|
/*******************************************************************************
|
706 |
|
|
MCF5272_uart_start_xmit() - Enable the transmitter on the device.
|
707 |
|
|
|
708 |
|
|
INPUT:
|
709 |
|
|
chan - pointer to the serial private data.
|
710 |
|
|
|
711 |
|
|
*/
|
712 |
|
|
static void MCF5272_uart_start_xmit(serial_channel *chan)
|
713 |
|
|
{
|
714 |
|
|
CYG_INTERRUPT_STATE int_state;
|
715 |
|
|
MCF5272_uart_info_t * port = (MCF5272_uart_info_t *) chan->dev_priv;
|
716 |
|
|
|
717 |
|
|
/* Enable the UART transmit. */
|
718 |
|
|
MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_TXEN);
|
719 |
|
|
|
720 |
|
|
/* Enable transmit interrupt */
|
721 |
|
|
HAL_DISABLE_INTERRUPTS(int_state);
|
722 |
|
|
port->imr_mirror |= MCF5272_UART_UIMR_TXRDY;
|
723 |
|
|
MCF5272_UART_WRITE(port->base->uisr_uimr, port->imr_mirror);
|
724 |
|
|
HAL_RESTORE_INTERRUPTS(int_state);
|
725 |
|
|
|
726 |
|
|
|
727 |
|
|
}
|
728 |
|
|
|
729 |
|
|
|
730 |
|
|
/******************************************************************************************************
|
731 |
|
|
MCF5272_uart_stop_xmit() - Disable the transmitter on the device
|
732 |
|
|
|
733 |
|
|
INPUT:
|
734 |
|
|
chan - pointer to the serial private data.
|
735 |
|
|
|
736 |
|
|
*/
|
737 |
|
|
static void MCF5272_uart_stop_xmit(serial_channel * chan)
|
738 |
|
|
{
|
739 |
|
|
CYG_INTERRUPT_STATE int_state;
|
740 |
|
|
MCF5272_uart_info_t * port = (MCF5272_uart_info_t *) chan->dev_priv;
|
741 |
|
|
|
742 |
|
|
/* Disable transmit interrupt */
|
743 |
|
|
HAL_DISABLE_INTERRUPTS(int_state);
|
744 |
|
|
port->imr_mirror &= ~MCF5272_UART_UIMR_TXRDY;
|
745 |
|
|
MCF5272_UART_WRITE(port->base->uisr_uimr, port->imr_mirror);
|
746 |
|
|
HAL_RESTORE_INTERRUPTS(int_state);
|
747 |
|
|
|
748 |
|
|
/* Disable the UART transmit.
|
749 |
|
|
!!!!!!!!!!!!!
|
750 |
|
|
!!!WARNING!!!
|
751 |
|
|
!!!!!!!!!!!!!
|
752 |
|
|
If the transmit the disabe
|
753 |
|
|
the diag_printf routines will poll forever to transmit the
|
754 |
|
|
a character. Hence, don't ever disable the transmit if
|
755 |
|
|
we want it to work with diag_printf.
|
756 |
|
|
*/
|
757 |
|
|
//MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_TXDE);
|
758 |
|
|
|
759 |
|
|
|
760 |
|
|
}
|
761 |
|
|
|
762 |
|
|
|
763 |
|
|
/******************************************************************************************************
|
764 |
|
|
MCF5272_uart_ISR() - UART I/O interrupt interrupt service routine (ISR).
|
765 |
|
|
|
766 |
|
|
INPUT:
|
767 |
|
|
vector - the interrupt vector number
|
768 |
|
|
data - user parameter.
|
769 |
|
|
|
770 |
|
|
|
771 |
|
|
RETURN:
|
772 |
|
|
returns CYG_ISR_CALL_DSR to call the DSR.
|
773 |
|
|
|
774 |
|
|
*/
|
775 |
|
|
static cyg_uint32 MCF5272_uart_ISR(cyg_vector_t vector, cyg_addrword_t data)
|
776 |
|
|
{
|
777 |
|
|
serial_channel *chan = (serial_channel *) data;
|
778 |
|
|
MCF5272_uart_info_t * port = (MCF5272_uart_info_t *) chan->dev_priv;
|
779 |
|
|
|
780 |
|
|
|
781 |
|
|
/* Write the value in the interrupt status register back
|
782 |
|
|
to the mask register to disable the interrupt temporarily.
|
783 |
|
|
*/
|
784 |
|
|
|
785 |
|
|
MCF5272_UART_WRITE(port->base->uisr_uimr, 0);
|
786 |
|
|
|
787 |
|
|
return CYG_ISR_CALL_DSR; // Cause DSR to run
|
788 |
|
|
}
|
789 |
|
|
|
790 |
|
|
|
791 |
|
|
|
792 |
|
|
/******************************************************************************************************
|
793 |
|
|
MCF5272_uart_DSR() - Defered Service Routine (DSR) - This routine processes the interrupt
|
794 |
|
|
from the device.
|
795 |
|
|
|
796 |
|
|
INPUT:
|
797 |
|
|
vector - The interrupt vector number
|
798 |
|
|
count - The nunber of DSR requests.
|
799 |
|
|
data - Device specific information
|
800 |
|
|
|
801 |
|
|
*/
|
802 |
|
|
|
803 |
|
|
static void MCF5272_uart_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
|
804 |
|
|
{
|
805 |
|
|
serial_channel *chan = (serial_channel *)data;
|
806 |
|
|
MCF5272_uart_info_t *port = (MCF5272_uart_info_t *)chan->dev_priv;
|
807 |
|
|
volatile u8_t isr;
|
808 |
|
|
|
809 |
|
|
|
810 |
|
|
/* Retrieve the interrupt status bits. We use these status bits to figure out
|
811 |
|
|
what process shouled we perform: read from the UART or inform of a completion
|
812 |
|
|
of a data transmission.
|
813 |
|
|
*/
|
814 |
|
|
|
815 |
|
|
/* Retrieve the interrupt status register so
|
816 |
|
|
* the DSR can look it up.
|
817 |
|
|
*/
|
818 |
|
|
|
819 |
|
|
|
820 |
|
|
while((isr = (MCF5272_UART_READ(port->base->uisr_uimr) & port->imr_mirror)))
|
821 |
|
|
{
|
822 |
|
|
switch (port->autobaud_state)
|
823 |
|
|
{
|
824 |
|
|
default:
|
825 |
|
|
case AB_IDLE:
|
826 |
|
|
if (isr & MCF5272_UART_UISR_DB)
|
827 |
|
|
{
|
828 |
|
|
/* Detected the begin of a break, set the state to AB_BEGIN_BREAK
|
829 |
|
|
*/
|
830 |
|
|
port->autobaud_state = AB_BEGIN_BREAK;
|
831 |
|
|
|
832 |
|
|
/* Reset the Delta Break bit in the UISR */
|
833 |
|
|
MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_BKCHGINT);
|
834 |
|
|
|
835 |
|
|
}
|
836 |
|
|
break;
|
837 |
|
|
case AB_BEGIN_BREAK:
|
838 |
|
|
if (isr & MCF5272_UART_UISR_DB)
|
839 |
|
|
{
|
840 |
|
|
/* Detected the end of a break, set the state to AB_BEGIN, and
|
841 |
|
|
setup autobaud detection.
|
842 |
|
|
*/
|
843 |
|
|
port->autobaud_state = AB_BEGIN;
|
844 |
|
|
|
845 |
|
|
/* Reset the Delta Break bit in the UISR and Enable autobaud */
|
846 |
|
|
MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_RESET_BKCHGINT |
|
847 |
|
|
MCF5272_UART_UCR_ENAB);
|
848 |
|
|
|
849 |
|
|
/* Enable autobaud completion interrupt */
|
850 |
|
|
port->imr_mirror |= MCF5272_UART_UIMR_ABC;
|
851 |
|
|
/* Disable the delta break interrupt so we can't receive
|
852 |
|
|
anymore break interrupt.
|
853 |
|
|
*/
|
854 |
|
|
port->imr_mirror &= ~MCF5272_UART_UIMR_DB;
|
855 |
|
|
|
856 |
|
|
}
|
857 |
|
|
break;
|
858 |
|
|
|
859 |
|
|
case AB_BEGIN:
|
860 |
|
|
if (isr & MCF5272_UART_UISR_ABC)
|
861 |
|
|
{
|
862 |
|
|
int count;
|
863 |
|
|
// Retrieve the baudrate that we're using now.
|
864 |
|
|
u16_t divider = (port->base->uabu << 8) + port->base->uabl;
|
865 |
|
|
// Search in the list to find a match.
|
866 |
|
|
for (count = sizeof(dividers_table)/sizeof(unsigned long) - 1;
|
867 |
|
|
count >= 0;
|
868 |
|
|
count--)
|
869 |
|
|
{
|
870 |
|
|
if (divider < dividers_table[count]) break;
|
871 |
|
|
}
|
872 |
|
|
|
873 |
|
|
// Set the baud.
|
874 |
|
|
port->config.baud = count;
|
875 |
|
|
|
876 |
|
|
/* Autobaud completion */
|
877 |
|
|
port->autobaud_state = AB_IDLE;
|
878 |
|
|
|
879 |
|
|
/* Disable autobaud */
|
880 |
|
|
MCF5272_UART_WRITE(port->base->ucr, MCF5272_UART_UCR_NONE);
|
881 |
|
|
|
882 |
|
|
/* Ignore autobaud completion interrupt. */
|
883 |
|
|
port->imr_mirror &= ~MCF5272_UART_UIMR_ABC;
|
884 |
|
|
|
885 |
|
|
/* Reenable begin break change and receive interrupt. */
|
886 |
|
|
port->imr_mirror |= MCF5272_UART_UIMR_DB;
|
887 |
|
|
|
888 |
|
|
}
|
889 |
|
|
break;
|
890 |
|
|
|
891 |
|
|
}
|
892 |
|
|
|
893 |
|
|
|
894 |
|
|
/* Receive character interrupt */
|
895 |
|
|
if ((isr & MCF5272_UART_UISR_RXRDY))
|
896 |
|
|
/* Ignore all receive interrupt when we're autobauding. */
|
897 |
|
|
{
|
898 |
|
|
// Read all the characters in the fifo.
|
899 |
|
|
while ((MCF5272_UART_READ(port->base->uisr_uimr) & MCF5272_UART_UISR_RXRDY))
|
900 |
|
|
{
|
901 |
|
|
char c;
|
902 |
|
|
/* Read the character from the UART. */
|
903 |
|
|
c = MCF5272_UART_READ(port->base->urb_utb);
|
904 |
|
|
/* Pass the read character to the upper layer. */
|
905 |
|
|
(chan->callbacks->rcv_char)(chan, c);
|
906 |
|
|
}
|
907 |
|
|
}
|
908 |
|
|
|
909 |
|
|
/* Transmit complete interrupt */
|
910 |
|
|
|
911 |
|
|
if ((isr & MCF5272_UART_UISR_TXRDY))
|
912 |
|
|
{
|
913 |
|
|
|
914 |
|
|
/* Transmit holding register is empty */
|
915 |
|
|
(chan->callbacks->xmt_char)(chan);
|
916 |
|
|
|
917 |
|
|
}
|
918 |
|
|
|
919 |
|
|
}
|
920 |
|
|
|
921 |
|
|
/* Unmask all the DUART interrupts that were masked in the ISR, so */
|
922 |
|
|
/* that we can receive the next interrupt. */
|
923 |
|
|
|
924 |
|
|
MCF5272_UART_WRITE(port->base->uisr_uimr, port->imr_mirror);
|
925 |
|
|
|
926 |
|
|
}
|
927 |
|
|
|
928 |
|
|
#ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL0
|
929 |
|
|
unsigned long MCF5272_uart_get_channel_0_baud_rate()
|
930 |
|
|
{
|
931 |
|
|
/* return the baud rate for the first serial port */
|
932 |
|
|
|
933 |
|
|
return baud_rates_table[MCF5272_uart_channel_info_0.config.baud];
|
934 |
|
|
}
|
935 |
|
|
#endif
|
936 |
|
|
|
937 |
|
|
#ifdef CYGPKG_IO_SERIAL_MCF5272_UART_CHANNEL1
|
938 |
|
|
unsigned long MCF5272_uart_get_channel_1_baud_rate()
|
939 |
|
|
{
|
940 |
|
|
/* return the baud rate for the second serial port */
|
941 |
|
|
|
942 |
|
|
return baud_rates_table[MCF5272_uart_channel_info_1.config.baud];
|
943 |
|
|
}
|
944 |
|
|
#endif
|
945 |
|
|
|
946 |
|
|
|