]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/lpc24xx/var/v2_0/src/hal_diag.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / lpc24xx / var / v2_0 / src / hal_diag.c
1 /*=============================================================================
2 //
3 //      hal_diag.c
4 //
5 //      HAL diagnostic output code
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 // Copyright (C) 2004 eCosCentric Limited 
13 //
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
17 //
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21 // for more details.
22 //
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 //
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
33 //
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
36 // -------------------------------------------
37 //####ECOSGPLCOPYRIGHTEND####
38 //=============================================================================
39 //#####DESCRIPTIONBEGIN####
40 //
41 // Author(s):   jani
42 // Contributors:jskov, gthomas
43 // Date:        2001-07-12
44 // Purpose:     HAL diagnostic output
45 // Description: Implementations of HAL diagnostic output support.
46 //
47 //####DESCRIPTIONEND####
48 //
49 //===========================================================================*/
50
51
52 //===========================================================================
53 //                                INCLUDES
54 //===========================================================================
55 #include <pkgconf/hal.h>
56 #include CYGBLD_HAL_PLATFORM_H
57
58 #include <cyg/infra/cyg_type.h>         // base types
59
60 #include <cyg/hal/hal_arch.h>           // SAVE/RESTORE GP macros
61 #include <cyg/hal/hal_io.h>             // IO macros
62 #include <cyg/hal/hal_if.h>             // interface API
63 #include <cyg/hal/hal_intr.h>           // HAL_ENABLE/MASK/UNMASK_INTERRUPTS
64 #include <cyg/hal/hal_misc.h>           // Helper functions
65 #include <cyg/hal/drv_api.h>            // CYG_ISR_HANDLED
66 #include <cyg/hal/hal_diag.h>
67
68 #include <cyg/hal/var_io.h>             // USART registers
69 #include <cyg/hal/lpc24xx_misc.h>       // peripheral identifiers
70
71
72 //===========================================================================
73 //                                DATA TYPES
74 //===========================================================================-
75 typedef struct 
76 {
77     cyg_uint8* base;     
78     cyg_int32  msec_timeout;     
79     int        isr_vector;
80     int        baud_rate;
81     cyg_uint8  periph_id;
82 } channel_data_t;
83
84
85 //
86 // Diagnostic serial channel data
87 //
88 static channel_data_t lpc2xxx_ser_channels[2] = 
89 {
90     { (cyg_uint8*)CYGARC_HAL_LPC24XX_REG_UART0_BASE, 
91        1000, 
92        CYGNUM_HAL_INTERRUPT_UART0, 
93        CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD,
94        CYNUM_HAL_LPC24XX_PCLK_UART0},
95       
96     { (cyg_uint8*)CYGARC_HAL_LPC24XX_REG_UART1_BASE, 
97        1000, 
98        CYGNUM_HAL_INTERRUPT_UART1, 
99        CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD,
100        CYNUM_HAL_LPC24XX_PCLK_UART1}
101 };
102
103
104 //===========================================================================
105 // Initialize diagnostic serial channel
106 //===========================================================================
107 static void cyg_hal_plf_serial_init_channel(void* __ch_data)
108 {
109     channel_data_t* chan = (channel_data_t*)__ch_data;
110     cyg_uint8* base = chan->base;
111     cyg_uint16 divider = CYG_HAL_ARM_LPC24XX_BAUD_GENERATOR(chan->periph_id, 
112                                                             chan->baud_rate);
113     // Set baudrate
114     HAL_WRITE_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxLCR, 
115                      CYGARC_HAL_LPC24XX_REG_UxLCR_DLAB);
116     HAL_WRITE_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxDLM, divider >> 8);
117     HAL_WRITE_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxDLL, divider & 0xFF);
118
119     // 8-1-no parity.
120     HAL_WRITE_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxLCR, 
121                      CYGARC_HAL_LPC24XX_REG_UxLCR_WORD_LENGTH_8 |
122                      CYGARC_HAL_LPC24XX_REG_UxLCR_STOP_1);
123
124     // Reset and enable FIFO
125     HAL_WRITE_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxFCR, 
126                      CYGARC_HAL_LPC24XX_REG_UxFCR_FIFO_ENA |
127                      CYGARC_HAL_LPC24XX_REG_UxFCR_RX_FIFO_RESET | 
128                      CYGARC_HAL_LPC24XX_REG_UxFCR_TX_FIFO_RESET);
129 }
130
131
132 //===========================================================================
133 // Write single character
134 //===========================================================================
135 void cyg_hal_plf_serial_putc(void *__ch_data, char c)
136 {
137     cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
138     cyg_uint8 stat;
139     CYGARC_HAL_SAVE_GP();
140
141     do {
142         HAL_READ_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxLSR, stat);
143     } while ((stat & CYGARC_HAL_LPC24XX_REG_UxLSR_THRE) == 0);
144
145     HAL_WRITE_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxTHR, c);
146
147     CYGARC_HAL_RESTORE_GP();
148 }
149
150
151 //===========================================================================
152 // Read single character non blocking
153 //===========================================================================
154 static cyg_bool cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
155 {
156     channel_data_t* chan = (channel_data_t*)__ch_data;
157     cyg_uint8* base = chan->base;
158     cyg_uint8 stat;
159
160     HAL_READ_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxLSR, stat);
161     if ((stat & CYGARC_HAL_LPC24XX_REG_UxLSR_RDR) == 0)
162         return false;
163
164     HAL_READ_UINT32(base + CYGARC_HAL_LPC24XX_REG_UxRBR, *ch);
165
166     return true;
167 }
168
169
170 //===========================================================================
171 // Read single character blocking
172 //===========================================================================
173 cyg_uint8 cyg_hal_plf_serial_getc(void* __ch_data)
174 {
175     cyg_uint8 ch;
176     CYGARC_HAL_SAVE_GP();
177
178     while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch));
179
180     CYGARC_HAL_RESTORE_GP();
181     return ch;
182 }
183
184
185 //===========================================================================
186 // Write data buffer via serial line
187 //===========================================================================
188 static void cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, 
189                          cyg_uint32 __len)
190 {
191     CYGARC_HAL_SAVE_GP();
192
193     while(__len-- > 0)
194         cyg_hal_plf_serial_putc(__ch_data, *__buf++);
195
196     CYGARC_HAL_RESTORE_GP();
197 }
198
199
200 //===========================================================================
201 // Read data buffer
202 //===========================================================================
203 static void cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, 
204                                     cyg_uint32 __len)
205 {
206     CYGARC_HAL_SAVE_GP();
207
208     while(__len-- > 0)
209         *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
210
211     CYGARC_HAL_RESTORE_GP();
212 }
213
214
215 //===========================================================================
216 // Read single character with timeout
217 //===========================================================================
218 cyg_bool cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
219 {
220     int delay_count;
221     channel_data_t* chan = (channel_data_t*)__ch_data;
222     cyg_bool res;
223     CYGARC_HAL_SAVE_GP();
224
225     delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
226
227     for(;;) {
228         res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
229         if (res || 0 == delay_count--)
230             break;
231         
232         CYGACC_CALL_IF_DELAY_US(100);
233     }
234
235     CYGARC_HAL_RESTORE_GP();
236     return res;
237 }
238
239
240 //===========================================================================
241 // Control serial channel configuration
242 //===========================================================================
243 static int cyg_hal_plf_serial_control(void *__ch_data, 
244                                       __comm_control_cmd_t __func, ...)
245 {
246     static int irq_state = 0;
247     channel_data_t* chan = (channel_data_t*)__ch_data;
248     cyg_uint8* base = ((channel_data_t*)__ch_data)->base;
249     int ret = 0;
250     va_list ap;
251
252     CYGARC_HAL_SAVE_GP();
253     va_start(ap, __func);
254
255     switch (__func) {
256     case __COMMCTL_GETBAUD:
257         ret = chan->baud_rate;
258         break;
259     case __COMMCTL_SETBAUD:
260         chan->baud_rate = va_arg(ap, cyg_int32);
261         // Should we verify this value here?
262         cyg_hal_plf_serial_init_channel(chan);
263         ret = 0;
264         break;
265     case __COMMCTL_IRQ_ENABLE:
266         irq_state = 1;
267         HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector);
268         HAL_INTERRUPT_UNMASK(chan->isr_vector);
269         HAL_WRITE_UINT32(base+CYGARC_HAL_LPC24XX_REG_UxIER, 
270                          CYGARC_HAL_LPC24XX_REG_UxIER_RXDATA_INT);
271         break;
272     case __COMMCTL_IRQ_DISABLE:
273         ret = irq_state;
274         irq_state = 0;
275         HAL_INTERRUPT_MASK(chan->isr_vector);
276         HAL_WRITE_UINT32(base+CYGARC_HAL_LPC24XX_REG_UxIER, 0);
277         break;
278     case __COMMCTL_DBG_ISR_VECTOR:
279         ret = chan->isr_vector;
280         break;
281     case __COMMCTL_SET_TIMEOUT:
282         ret = chan->msec_timeout;
283         chan->msec_timeout = va_arg(ap, cyg_uint32);
284     default:
285         break;
286     }
287
288     va_end(ap);
289     CYGARC_HAL_RESTORE_GP();
290     return ret;
291 }
292
293
294 //===========================================================================
295 // Serial channel ISR
296 //===========================================================================
297 static int cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, 
298                                   CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
299 {
300     int res = 0;
301     channel_data_t* chan = (channel_data_t*)__ch_data;
302     cyg_uint8 c;
303     cyg_uint8 iir;
304     
305     CYGARC_HAL_SAVE_GP();
306
307     *__ctrlc = 0;
308
309     HAL_READ_UINT32(chan->base + CYGARC_HAL_LPC24XX_REG_UxIIR, iir);
310     
311     if((iir & (CYGARC_HAL_LPC24XX_REG_UxIIR_IIR0 | 
312                CYGARC_HAL_LPC24XX_REG_UxIIR_IIR1 | 
313                CYGARC_HAL_LPC24XX_REG_UxIIR_IIR2)) 
314        == CYGARC_HAL_LPC24XX_REG_UxIIR_IIR2)
315     {
316         // Rx data available or character timeout
317         // Read data in order to clear interrupt
318         HAL_READ_UINT32(chan->base + CYGARC_HAL_LPC24XX_REG_UxRBR, c);
319         if( cyg_hal_is_break( &c , 1 ) ) *__ctrlc = 1;
320
321         res = CYG_ISR_HANDLED;
322     }
323
324     HAL_INTERRUPT_ACKNOWLEDGE(chan->isr_vector);
325
326     CYGARC_HAL_RESTORE_GP();
327     return res;
328 }
329
330
331 //===========================================================================
332 // Initialize serial channel
333 //===========================================================================
334 void cyg_hal_plf_serial_init(void)
335 {
336     hal_virtual_comm_table_t* comm;
337     int cur;
338
339     cur = 
340       CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
341
342     // Init channels
343     cyg_hal_plf_serial_init_channel(&lpc2xxx_ser_channels[0]);
344 #if CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 1
345     cyg_hal_plf_serial_init_channel(&lpc2xxx_ser_channels[1]);
346 #endif
347
348     // Setup procs in the vector table
349
350     // Set channel 0
351     CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
352     comm = CYGACC_CALL_IF_CONSOLE_PROCS();
353     CYGACC_COMM_IF_CH_DATA_SET(*comm, &lpc2xxx_ser_channels[0]);
354     CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
355     CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
356     CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
357     CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
358     CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
359     CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
360     CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
361
362 #if CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS > 1
363     // Set channel 1
364     CYGACC_CALL_IF_SET_CONSOLE_COMM(1);
365     comm = CYGACC_CALL_IF_CONSOLE_PROCS();
366     CYGACC_COMM_IF_CH_DATA_SET(*comm, &lpc2xxx_ser_channels[1]);
367     CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
368     CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
369     CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
370     CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
371     CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
372     CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
373     CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
374 #endif
375
376     // Restore original console
377     CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
378 }
379
380
381 //===========================================================================
382 // Set diagnostic led
383 //===========================================================================
384 void hal_diag_led(int mask)
385 {
386     hal_lpc24xx_set_leds(mask);
387 }
388
389 //-----------------------------------------------------------------------------
390 // End of hal_diag.c