1 |
30 |
unneback |
/*
|
2 |
|
|
* M68340/349 uart management tools
|
3 |
|
|
*
|
4 |
|
|
* Author:
|
5 |
|
|
* Geoffroy Montel
|
6 |
|
|
* France Telecom - CNET/DSM/TAM/CAT
|
7 |
|
|
* 4, rue du Clos Courtel
|
8 |
|
|
* 35512 CESSON-SEVIGNE
|
9 |
|
|
* FRANCE
|
10 |
|
|
*
|
11 |
|
|
* e-mail: g_montel@yahoo.com
|
12 |
|
|
*
|
13 |
|
|
* COPYRIGHT (c) 1989-1999.
|
14 |
|
|
* On-Line Applications Research Corporation (OAR).
|
15 |
|
|
*
|
16 |
|
|
* The license and distribution terms for this file may be
|
17 |
|
|
* found in the file LICENSE in this distribution or at
|
18 |
|
|
*
|
19 |
|
|
* http://www.OARcorp.com/rtems/license.html.
|
20 |
|
|
*
|
21 |
|
|
* $Id: m340uart.c,v 1.2 2001-09-27 12:00:07 chris Exp $
|
22 |
|
|
*/
|
23 |
|
|
|
24 |
|
|
#include <termios.h>
|
25 |
|
|
#include <bsp.h>
|
26 |
|
|
#include <rtems/libio.h>
|
27 |
|
|
#include <m68340.h>
|
28 |
|
|
#include <m340uart.h>
|
29 |
|
|
#include <stdarg.h>
|
30 |
|
|
|
31 |
|
|
/* this table shows compatible speed configurations for the MC68340:
|
32 |
|
|
the first row shows baud rates for baud speed set 1
|
33 |
|
|
the second row shows baud rates for baud speed set 2
|
34 |
|
|
look at Motorola's MC68340 Integrated Processor User's Manual
|
35 |
|
|
page 7-30 for more infos */
|
36 |
|
|
|
37 |
|
|
float m340_Baud_Rates_Table[16][2] = {\
|
38 |
|
|
{ 50, 75 }, \
|
39 |
|
|
{ 110, 110 }, \
|
40 |
|
|
{ 134.5, 134.5 }, \
|
41 |
|
|
{ 200, 150 }, \
|
42 |
|
|
{ 300, 300 }, \
|
43 |
|
|
{ 600, 600 }, \
|
44 |
|
|
{ 1200, 1200 }, \
|
45 |
|
|
{ 1050, 2000 }, \
|
46 |
|
|
{ 2400, 2400 }, \
|
47 |
|
|
{ 4800, 4800 }, \
|
48 |
|
|
{ 7200, 1800 }, \
|
49 |
|
|
{ 9600, 9600 }, \
|
50 |
|
|
{ 38400, 19200 }, \
|
51 |
|
|
{ 76800, 38400 }, \
|
52 |
|
|
{ SCLK/16, SCLK/16}, \
|
53 |
|
|
{ SCLK, SCLK }, \
|
54 |
|
|
};
|
55 |
|
|
|
56 |
|
|
/* config on both 340 channels */
|
57 |
|
|
uart_channel_config m340_uart_config[UART_NUMBER_OF_CHANNELS];
|
58 |
|
|
|
59 |
|
|
/*
|
60 |
|
|
* Init UART table
|
61 |
|
|
*/
|
62 |
|
|
|
63 |
|
|
#define NOT_IMPLEMENTED_YET 0
|
64 |
|
|
|
65 |
|
|
/******************************************************
|
66 |
|
|
Name: Init_UART_Table
|
67 |
|
|
Input parameters: -
|
68 |
|
|
Output parameters: -
|
69 |
|
|
Description: Init the m340_uart_config
|
70 |
|
|
THIS SHOULD NOT BE HERE!
|
71 |
|
|
Its aim was to let the user configure
|
72 |
|
|
UARTs for each application.
|
73 |
|
|
As we can't pass args to the console
|
74 |
|
|
driver initialisation routine at the
|
75 |
|
|
moment, this was not done.
|
76 |
|
|
ATTENTION: TERMIOS init presupposes that the channel
|
77 |
|
|
baud rates is 9600/9600.
|
78 |
|
|
-> risks when using IOCTL
|
79 |
|
|
*****************************************************/
|
80 |
|
|
void Init_UART_Table(void)
|
81 |
|
|
{
|
82 |
|
|
m340_uart_config[UART_CHANNEL_A].enable = TRUE;
|
83 |
|
|
strcpy(m340_uart_config[UART_CHANNEL_A].name, UART_CONSOLE_NAME);
|
84 |
|
|
m340_uart_config[UART_CHANNEL_A].parity_mode = m340_No_Parity;
|
85 |
|
|
m340_uart_config[UART_CHANNEL_A].bits_per_char = m340_8bpc;
|
86 |
|
|
m340_uart_config[UART_CHANNEL_A].rx_baudrate = 9600;
|
87 |
|
|
m340_uart_config[UART_CHANNEL_A].tx_baudrate = 9600;
|
88 |
|
|
m340_uart_config[UART_CHANNEL_A].rx_mode = UART_CRR;
|
89 |
|
|
m340_uart_config[UART_CHANNEL_A].mode = UART_POLLING;
|
90 |
|
|
|
91 |
|
|
m340_uart_config[UART_CHANNEL_A].termios.enable = TRUE;
|
92 |
|
|
m340_uart_config[UART_CHANNEL_A].termios.rx_buffer_size = NOT_IMPLEMENTED_YET;
|
93 |
|
|
m340_uart_config[UART_CHANNEL_A].termios.tx_buffer_size = NOT_IMPLEMENTED_YET;
|
94 |
|
|
|
95 |
|
|
m340_uart_config[UART_CHANNEL_B].enable = FALSE;
|
96 |
|
|
strcpy(m340_uart_config[UART_CHANNEL_B].name, UART_RAW_IO_NAME);
|
97 |
|
|
m340_uart_config[UART_CHANNEL_B].parity_mode = m340_No_Parity;
|
98 |
|
|
m340_uart_config[UART_CHANNEL_B].bits_per_char = m340_8bpc;
|
99 |
|
|
m340_uart_config[UART_CHANNEL_B].rx_baudrate = 38400;
|
100 |
|
|
m340_uart_config[UART_CHANNEL_B].tx_baudrate = 38400;
|
101 |
|
|
m340_uart_config[UART_CHANNEL_B].rx_mode = UART_CRR;
|
102 |
|
|
m340_uart_config[UART_CHANNEL_B].mode = UART_INTERRUPTS;
|
103 |
|
|
|
104 |
|
|
m340_uart_config[UART_CHANNEL_B].termios.enable = TRUE;
|
105 |
|
|
m340_uart_config[UART_CHANNEL_B].termios.rx_buffer_size = NOT_IMPLEMENTED_YET;
|
106 |
|
|
m340_uart_config[UART_CHANNEL_B].termios.tx_buffer_size = NOT_IMPLEMENTED_YET;
|
107 |
|
|
}
|
108 |
|
|
|
109 |
|
|
/******************************************************
|
110 |
|
|
Name: Find_Right_m340_UART_Channel_Config
|
111 |
|
|
Input parameters: Send/Receive baud rates for a
|
112 |
|
|
given channel
|
113 |
|
|
Output parameters: UART compatible configs for this
|
114 |
|
|
channel
|
115 |
|
|
Description: returns which uart configurations fit
|
116 |
|
|
Receiver Baud Rate and Transmitter Baud
|
117 |
|
|
Rate for a given channel
|
118 |
|
|
For instance, according to the
|
119 |
|
|
m340_Baud_Rates_Table:
|
120 |
|
|
- Output Speed = 50, Input Speed = 75
|
121 |
|
|
is not a correct config, because
|
122 |
|
|
50 bauds implies set 1 and 75 bauds
|
123 |
|
|
implies set 2
|
124 |
|
|
- Output Speed = 9600, Input Speed = 9600
|
125 |
|
|
two correct configs for this:
|
126 |
|
|
RCS=11, TCS=11, Set=1 or 2
|
127 |
|
|
*****************************************************/
|
128 |
|
|
t_baud_speed_table
|
129 |
|
|
Find_Right_m340_UART_Channel_Config(float ReceiverBaudRate, float TransmitterBaudRate)
|
130 |
|
|
{
|
131 |
|
|
t_baud_speed_table return_value;
|
132 |
|
|
|
133 |
|
|
struct {
|
134 |
|
|
int cs;
|
135 |
|
|
int set;
|
136 |
|
|
} Receiver[2], Transmitter[2];
|
137 |
|
|
|
138 |
|
|
int Receiver_nb_of_config = 0;
|
139 |
|
|
int Transmitter_nb_of_config = 0;
|
140 |
|
|
|
141 |
|
|
int i,j;
|
142 |
|
|
|
143 |
|
|
/* Receiver and Transmitter baud rates must be compatible, ie in the same set */
|
144 |
|
|
|
145 |
|
|
/* search for configurations for ReceiverBaudRate - there can't be more than two (only two sets) */
|
146 |
|
|
for (i=0;i<16;i++)
|
147 |
|
|
for (j=0;j<2;j++)
|
148 |
|
|
if (m340_Baud_Rates_Table[i][j]==ReceiverBaudRate) {
|
149 |
|
|
Receiver[Receiver_nb_of_config].cs=i;
|
150 |
|
|
Receiver[Receiver_nb_of_config].set=j;
|
151 |
|
|
Receiver_nb_of_config++;
|
152 |
|
|
}
|
153 |
|
|
|
154 |
|
|
/* search for configurations for TransmitterBaudRate - there can't be more than two (only two sets) */
|
155 |
|
|
for (i=0;i<16;i++)
|
156 |
|
|
for (j=0;j<2;j++)
|
157 |
|
|
if (m340_Baud_Rates_Table[i][j]==TransmitterBaudRate) {
|
158 |
|
|
Transmitter[Transmitter_nb_of_config].cs=i;
|
159 |
|
|
Transmitter[Transmitter_nb_of_config].set=j;
|
160 |
|
|
Transmitter_nb_of_config++;
|
161 |
|
|
}
|
162 |
|
|
|
163 |
|
|
/* now check if there's a compatible config */
|
164 |
|
|
return_value.nb=0;
|
165 |
|
|
|
166 |
|
|
for (i=0; i<Receiver_nb_of_config; i++)
|
167 |
|
|
for (j=0;j<Transmitter_nb_of_config;j++)
|
168 |
|
|
if (Receiver[i].set == Transmitter[j].set) {
|
169 |
|
|
return_value.baud_speed_table[return_value.nb].set = Receiver[i].set + 1; /* we want set 1 or set 2, not 0 or 1 */
|
170 |
|
|
return_value.baud_speed_table[return_value.nb].rcs = Receiver[i].cs;
|
171 |
|
|
return_value.baud_speed_table[return_value.nb].tcs = Transmitter[j].cs;
|
172 |
|
|
return_value.nb++;
|
173 |
|
|
}
|
174 |
|
|
|
175 |
|
|
return return_value;
|
176 |
|
|
}
|
177 |
|
|
|
178 |
|
|
/******************************************************
|
179 |
|
|
Name: Find_Right_m340_UART_Config
|
180 |
|
|
Input parameters: Send/Receive baud rates for both
|
181 |
|
|
channels
|
182 |
|
|
Output parameters: UART compatible configs for
|
183 |
|
|
BOTH channels
|
184 |
|
|
Description: returns which uart configurations fit
|
185 |
|
|
Receiver Baud Rate and Transmitter Baud
|
186 |
|
|
Rate for both channels
|
187 |
|
|
For instance, if we want 9600/38400 on
|
188 |
|
|
channel A and 9600/19200 on channel B,
|
189 |
|
|
this is not a good m340 uart config
|
190 |
|
|
(channel A needs set 1 and channel B
|
191 |
|
|
needs set 2)
|
192 |
|
|
*****************************************************/
|
193 |
|
|
t_baud_speed_table
|
194 |
|
|
Find_Right_m340_UART_Config(float ChannelA_ReceiverBaudRate, float ChannelA_TransmitterBaudRate, rtems_unsigned8 enableA,
|
195 |
|
|
float ChannelB_ReceiverBaudRate, float ChannelB_TransmitterBaudRate, rtems_unsigned8 enableB)
|
196 |
|
|
{
|
197 |
|
|
t_baud_speed_table tableA, tableB;
|
198 |
|
|
t_baud_speed_table return_value, tmp;
|
199 |
|
|
int i,j;
|
200 |
|
|
|
201 |
|
|
return_value.nb=0;
|
202 |
|
|
|
203 |
|
|
if (enableA && enableB) {
|
204 |
|
|
tableA = Find_Right_m340_UART_Channel_Config(ChannelA_ReceiverBaudRate, ChannelA_TransmitterBaudRate);
|
205 |
|
|
tableB = Find_Right_m340_UART_Channel_Config(ChannelB_ReceiverBaudRate, ChannelB_TransmitterBaudRate);
|
206 |
|
|
|
207 |
|
|
for (i=0;i<tableA.nb;i++)
|
208 |
|
|
for (j=0;j<tableB.nb;j++)
|
209 |
|
|
if (tableA.baud_speed_table[i].set==tableB.baud_speed_table[j].set) {
|
210 |
|
|
return_value.baud_speed_table[UART_CHANNEL_A].set=tableA.baud_speed_table[i].set;
|
211 |
|
|
return_value.baud_speed_table[UART_CHANNEL_A].rcs=tableA.baud_speed_table[i].rcs;
|
212 |
|
|
return_value.baud_speed_table[UART_CHANNEL_A].tcs=tableA.baud_speed_table[i].tcs;
|
213 |
|
|
return_value.baud_speed_table[UART_CHANNEL_B].set=tableB.baud_speed_table[j].set;
|
214 |
|
|
return_value.baud_speed_table[UART_CHANNEL_B].rcs=tableB.baud_speed_table[j].rcs;
|
215 |
|
|
return_value.baud_speed_table[UART_CHANNEL_B].tcs=tableB.baud_speed_table[j].tcs;
|
216 |
|
|
return_value.nb=2;
|
217 |
|
|
break;
|
218 |
|
|
}
|
219 |
|
|
return return_value;
|
220 |
|
|
}
|
221 |
|
|
|
222 |
|
|
if (enableA) {
|
223 |
|
|
return_value = Find_Right_m340_UART_Channel_Config(ChannelA_ReceiverBaudRate, ChannelA_TransmitterBaudRate);
|
224 |
|
|
return return_value;
|
225 |
|
|
}
|
226 |
|
|
|
227 |
|
|
if (enableB) {
|
228 |
|
|
tmp = Find_Right_m340_UART_Channel_Config(ChannelB_ReceiverBaudRate, ChannelB_TransmitterBaudRate);
|
229 |
|
|
if (tmp.nb!=0) {
|
230 |
|
|
return_value.nb = 2;
|
231 |
|
|
return_value.baud_speed_table[1].set = tmp.baud_speed_table[0].set;
|
232 |
|
|
return_value.baud_speed_table[1].rcs = tmp.baud_speed_table[0].rcs;
|
233 |
|
|
return_value.baud_speed_table[1].tcs = tmp.baud_speed_table[0].tcs;
|
234 |
|
|
}
|
235 |
|
|
}
|
236 |
|
|
return return_value;
|
237 |
|
|
}
|
238 |
|
|
|
239 |
|
|
/******************************************************
|
240 |
|
|
Name: termios_baud_rates_equivalence
|
241 |
|
|
Input parameters: Termios coded speed
|
242 |
|
|
Output parameters: explicit speed
|
243 |
|
|
Description: ioctl calls return termios coded speed
|
244 |
|
|
we need to know real speed in order
|
245 |
|
|
to use the functions above
|
246 |
|
|
*****************************************************/
|
247 |
|
|
float termios_baud_rates_equivalence ( int speed )
|
248 |
|
|
{
|
249 |
|
|
switch (speed) {
|
250 |
|
|
default: return 0; break;
|
251 |
|
|
case B50: return 50; break;
|
252 |
|
|
case B75: return 75; break;
|
253 |
|
|
case B110: return 110; break;
|
254 |
|
|
case B134: return 134; break;
|
255 |
|
|
case B150: return 150; break;
|
256 |
|
|
case B200: return 200; break;
|
257 |
|
|
case B300: return 300; break;
|
258 |
|
|
case B600: return 600; break;
|
259 |
|
|
case B1200: return 1200; break;
|
260 |
|
|
case B1800: return 1800; break;
|
261 |
|
|
case B2400: return 2400; break;
|
262 |
|
|
case B4800: return 4800; break;
|
263 |
|
|
case B9600: return 9600; break;
|
264 |
|
|
case B19200: return 19200; break;
|
265 |
|
|
case B38400: return 38400; break;
|
266 |
|
|
case B57600: return 57600; break;
|
267 |
|
|
case B115200: return 115200; break;
|
268 |
|
|
case B230400: return 230400; break;
|
269 |
|
|
case B460800: return 460800; break;
|
270 |
|
|
}
|
271 |
|
|
return 0;
|
272 |
|
|
}
|
273 |
|
|
|
274 |
|
|
/****************************************************************************************************/
|
275 |
|
|
|
276 |
|
|
/*
|
277 |
|
|
* very low level fmted output
|
278 |
|
|
*/
|
279 |
|
|
|
280 |
|
|
extern void dbug_out_char( int minor, int ch );
|
281 |
|
|
extern int dbug_in_char( int minor );
|
282 |
|
|
extern int dbug_char_present( int minor );
|
283 |
|
|
|
284 |
|
|
/******************************************************
|
285 |
|
|
Name: dbugRead
|
286 |
|
|
Input parameters: channel
|
287 |
|
|
Output parameters: char read
|
288 |
|
|
Description: polled read
|
289 |
|
|
*****************************************************/
|
290 |
|
|
int dbugRead (int minor)
|
291 |
|
|
{
|
292 |
|
|
if (dbug_char_present(minor) == 0)
|
293 |
|
|
return -1;
|
294 |
|
|
return dbug_in_char(minor);
|
295 |
|
|
}
|
296 |
|
|
|
297 |
|
|
/******************************************************
|
298 |
|
|
Name: dbugWrite
|
299 |
|
|
Input parameters: channel, buffer and its length
|
300 |
|
|
Output parameters: always successfull
|
301 |
|
|
Description: polled write
|
302 |
|
|
*****************************************************/
|
303 |
|
|
int dbugWrite (int minor, const char *buf, int len)
|
304 |
|
|
{
|
305 |
|
|
static char txBuf;
|
306 |
|
|
|
307 |
|
|
while (len--) {
|
308 |
|
|
txBuf = *buf++;
|
309 |
|
|
dbug_out_char( minor, (int)txBuf );
|
310 |
|
|
}
|
311 |
|
|
return 0;
|
312 |
|
|
}
|
313 |
|
|
|
314 |
|
|
static void fmt_num( int minor, unsigned long, unsigned );
|
315 |
|
|
static void fmt_str( int minor, const char* );
|
316 |
|
|
|
317 |
|
|
/******************************************************
|
318 |
|
|
Name: RAW_GETC
|
319 |
|
|
Input parameters: channel, buffer and its length
|
320 |
|
|
Output parameters:
|
321 |
|
|
Description: a light blocking "getc"
|
322 |
|
|
*****************************************************/
|
323 |
|
|
char RAW_GETC(int minor)
|
324 |
|
|
{
|
325 |
|
|
while (!dbug_char_present(minor)) continue;
|
326 |
|
|
return dbug_in_char(minor);
|
327 |
|
|
}
|
328 |
|
|
|
329 |
|
|
/******************************************************
|
330 |
|
|
Name: RAW_FMT
|
331 |
|
|
Input parameters: channel, buffer and its length
|
332 |
|
|
Output parameters: always successfull
|
333 |
|
|
Description: a light polled "printf"
|
334 |
|
|
useful when there's a serious pb and
|
335 |
|
|
there are no more interrupts
|
336 |
|
|
*****************************************************/
|
337 |
|
|
void RAW_FMT( int minor, const char* fmt, ... )
|
338 |
|
|
{
|
339 |
|
|
int ch;
|
340 |
|
|
va_list va;
|
341 |
|
|
|
342 |
|
|
va_start( va, fmt );
|
343 |
|
|
|
344 |
|
|
while( (ch = *fmt++) )
|
345 |
|
|
if( ch != '%' || (ch = *fmt++) == '%' )
|
346 |
|
|
{
|
347 |
|
|
if( ch == '\n' )
|
348 |
|
|
dbug_out_char( minor, '\r' );
|
349 |
|
|
dbug_out_char( minor, ch );
|
350 |
|
|
}
|
351 |
|
|
else switch( ch )
|
352 |
|
|
{
|
353 |
|
|
case 'c':
|
354 |
|
|
dbug_out_char( minor, va_arg( va, int ) );
|
355 |
|
|
continue;
|
356 |
|
|
case 's':
|
357 |
|
|
fmt_str( minor, va_arg( va, char* ) );
|
358 |
|
|
continue;
|
359 |
|
|
case 'd':
|
360 |
|
|
ch = va_arg( va, int );
|
361 |
|
|
if( ch >= 0 )
|
362 |
|
|
fmt_num( minor, ch, 10 );
|
363 |
|
|
else
|
364 |
|
|
{
|
365 |
|
|
dbug_out_char( minor, '-' );
|
366 |
|
|
fmt_num( minor, -ch, 10 );
|
367 |
|
|
}
|
368 |
|
|
continue;
|
369 |
|
|
case 'u':
|
370 |
|
|
fmt_num( minor, va_arg( va, unsigned ), 10 );
|
371 |
|
|
continue;
|
372 |
|
|
case 'o':
|
373 |
|
|
fmt_num( minor, va_arg( va, unsigned ), 8 );
|
374 |
|
|
continue;
|
375 |
|
|
case 'x':
|
376 |
|
|
case 'p':
|
377 |
|
|
fmt_num( minor, va_arg( va, unsigned ), 16 );
|
378 |
|
|
continue;
|
379 |
|
|
default: continue;
|
380 |
|
|
return;
|
381 |
|
|
}
|
382 |
|
|
va_end( va );
|
383 |
|
|
}
|
384 |
|
|
|
385 |
|
|
static void fmt_num( int minor, unsigned long num, unsigned base )
|
386 |
|
|
{
|
387 |
|
|
char buf[33];
|
388 |
|
|
int ib = sizeof(buf);
|
389 |
|
|
|
390 |
|
|
buf[--ib] = 0;
|
391 |
|
|
do
|
392 |
|
|
{
|
393 |
|
|
buf[--ib] = "0123456789ABCDEF"[num%base];
|
394 |
|
|
num /= base;
|
395 |
|
|
}
|
396 |
|
|
while( num != 0 );
|
397 |
|
|
|
398 |
|
|
fmt_str( minor, buf+ib );
|
399 |
|
|
}
|
400 |
|
|
|
401 |
|
|
static void fmt_str( int minor, const char* str )
|
402 |
|
|
{
|
403 |
|
|
if( str )
|
404 |
|
|
while( *str )
|
405 |
|
|
dbug_out_char( minor, *str++ );
|
406 |
|
|
}
|
407 |
|
|
|
408 |
|
|
|