source: soft/giet_vm/giet_common/tty0.c @ 737

Last change on this file since 737 was 709, checked in by alain, 9 years ago

Major release: Change the task model to implement the POSIX threads API.

  • The shell "exec" and "kill" commands can be used to activate/de-activate the applications.
  • The "pause", "resume", and "context" commands can be used to stop, restart, a single thtead or to display the thread context.

This version has been tested on the following multi-threaded applications,
that have been modified to use the POSIX threads:

  • classif
  • convol
  • transpose
  • gameoflife
  • raycast
File size: 9.8 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : tty0.c
3// Date     : 02/12/2014
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The tty0.c and tty0.h files are part of the GIET-VM nano-kernel.
8///////////////////////////////////////////////////////////////////////////////////
9
10#include <hard_config.h>
11#include <tty0.h>
12#include <stdarg.h>
13#include <tty_driver.h>
14#include <ctx_handler.h>
15#include <utils.h>
16#include <kernel_locks.h>
17
18/////////////////////////////////////////////////////////////////////////////
19// The global variable tty0_boot_mode define the type of lock used,
20// and must be defined in both kernel_init.c and boot.c files.
21// - the boot code must use a spin_lock because the kernel heap is not set.
22// - the kernel code can use a sqt_lock when the kernel heap is set.
23/////////////////////////////////////////////////////////////////////////////
24
25extern unsigned int  _tty0_boot_mode;
26
27__attribute__((section(".kdata")))
28sqt_lock_t           _tty0_sqt_lock  __attribute__((aligned(64))); 
29
30__attribute__((section(".kdata")))
31spin_lock_t          _tty0_spin_lock  __attribute__((aligned(64)));
32
33/////////////////////////////////////////////////////
34unsigned int _tty_channel_write( unsigned int channel,
35                                 char*        buffer,
36                                 unsigned int nbytes )
37{
38    unsigned int n;
39    unsigned int k;
40
41    for ( n = 0 ; n < nbytes ; n++ ) 
42    {
43        // test TTY_TX buffer full
44        if ( (_tty_get_register( channel , TTY_STATUS ) & 0x2) ) // buffer full
45        {
46            // retry if full
47            for( k = 0 ; k < 10000 ; k++ )
48            {
49                if ( (_tty_get_register( channel , TTY_STATUS ) & 0x2) == 0) break;
50            }
51            // return error if full after 10000 retry
52            return 1;
53        }
54
55        // write one byte
56        if (buffer[n] == '\n') _tty_set_register( channel, TTY_WRITE, (unsigned int)'\r' );
57        _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[n] );
58    }
59    return 0;
60}
61
62//////////////////////////
63void _puts( char* string ) 
64{
65    unsigned int n = 0;
66
67    while ( string[n] > 0 ) n++;
68
69    _tty_channel_write( 0, string, n );
70}
71
72
73//////////////////////////////
74void _putx( unsigned int val )
75{
76    static const char HexaTab[] = "0123456789ABCDEF";
77    char buf[10];
78    unsigned int c;
79
80    buf[0] = '0';
81    buf[1] = 'x';
82
83    for (c = 0; c < 8; c++) 
84    { 
85        buf[9 - c] = HexaTab[val & 0xF];
86        val = val >> 4;
87    }
88    _tty_channel_write( 0, buf, 10 );
89}
90
91////////////////////////////////////
92void _putl( unsigned long long val )
93{
94    static const char HexaTab[] = "0123456789ABCDEF";
95    char buf[18];
96    unsigned int c;
97
98    buf[0] = '0';
99    buf[1] = 'x';
100
101    for (c = 0; c < 16; c++) 
102    { 
103        buf[17 - c] = HexaTab[(unsigned int)val & 0xF];
104        val = val >> 4;
105    }
106    _tty_channel_write( 0, buf, 18 );
107}
108
109//////////////////////////////
110void _putd( unsigned int val ) 
111{
112    static const char DecTab[] = "0123456789";
113    char buf[10];
114    unsigned int i;
115    unsigned int first = 0;
116
117    for (i = 0; i < 10; i++) 
118    {
119        if ((val != 0) || (i == 0)) 
120        {
121            buf[9 - i] = DecTab[val % 10];
122            first = 9 - i;
123        }
124        else 
125        {
126            break;
127        }
128        val /= 10;
129    }
130    _tty_channel_write( 0, &buf[first], 10 - first );
131}
132
133/////////////////////////
134void _getc( char*  byte )
135{
136    // test status register
137    while ( _tty_get_register( 0 , TTY_STATUS ) == 0 );
138
139    // read one byte
140    *byte = (char)_tty_get_register( 0 , TTY_READ );
141}
142
143//////////////////////////////////////////////////////////
144static void _kernel_printf( unsigned int channel,
145                            char *       format, 
146                            va_list*     args ) 
147{
148
149printf_text:
150
151    while (*format) 
152    {
153        unsigned int i;
154        for (i = 0 ; format[i] && (format[i] != '%') ; i++);
155        if (i) 
156        {
157            if ( _tty_channel_write( channel, format, i ) ) goto return_error;
158            format += i;
159        }
160        if (*format == '%') 
161        {
162            format++;
163            goto printf_arguments;
164        }
165    }
166
167    return;
168
169printf_arguments:
170
171    {
172        char buf[20];
173        char * pbuf;
174        unsigned int len = 0;
175        static const char HexaTab[] = "0123456789ABCDEF";
176        unsigned int i;
177
178        switch (*format++) 
179        {
180            case ('c'):             /* char conversion */
181            {
182                int val = va_arg( *args , int );
183                len = 1;
184                buf[0] = val;
185                pbuf = &buf[0];
186                break;
187            }
188            case ('d'):             /* 32 bits decimal signed  */
189            {
190                int val = va_arg( *args , int );
191                if (val < 0) 
192                {
193                    val = -val;
194                    if ( _tty_channel_write( channel, "-" , 1 ) ) goto return_error;
195                }
196                for(i = 0; i < 10; i++) 
197                {
198                    buf[9 - i] = HexaTab[val % 10];
199                    if (!(val /= 10)) break;
200                }
201                len =  i + 1;
202                pbuf = &buf[9 - i];
203                break;
204            }
205            case ('u'):             /* 32 bits decimal unsigned  */
206            {
207                unsigned int val = va_arg( *args , unsigned int );
208                for(i = 0; i < 10; i++) 
209                {
210                    buf[9 - i] = HexaTab[val % 10];
211                    if (!(val /= 10)) break;
212                }
213                len =  i + 1;
214                pbuf = &buf[9 - i];
215                break;
216            }
217            case ('x'):             /* 32 bits hexadecimal unsigned */
218            {
219                unsigned int val = va_arg( *args , unsigned int );
220                if ( _tty_channel_write( channel, "0x" , 2 ) ) goto return_error;
221                for(i = 0; i < 8; i++) 
222                {
223                    buf[7 - i] = HexaTab[val % 16];
224                    if (!(val = (val>>4)))  break;
225                }
226                len =  i + 1;
227                pbuf = &buf[7 - i];
228                break;
229            }
230            case ('X'):             /* 32 bits hexadecimal unsigned  on 10 char*/
231            {
232                unsigned int val = va_arg( *args , unsigned int );
233                if ( _tty_channel_write( channel, "0x" , 2 ) ) goto return_error;
234                for(i = 0; i < 8; i++) 
235                {
236                    buf[7 - i] = HexaTab[val % 16];
237                    val = (val>>4);
238                }
239                len =  8;
240                pbuf = buf;
241                break;
242            }
243            case ('l'):            /* 64 bits hexadecimal unsigned */
244            {
245                unsigned long long val = va_arg( *args , unsigned long long );
246                if ( _tty_channel_write( channel, "0x" , 2 ) ) goto return_error;
247                for(i = 0; i < 16; i++) 
248                {
249                    buf[15 - i] = HexaTab[val % 16];
250                    if (!(val /= 16))  break;
251                }
252                len =  i + 1;
253                pbuf = &buf[15 - i];
254                break;
255            }
256            case ('s'):             /* string */
257            {
258                char* str = va_arg( *args , char* );
259                while (str[len]) 
260                {
261                    len++;
262                }
263                pbuf = str;
264                break;
265            }
266            default:
267                goto return_error;
268        }
269
270        if ( _tty_channel_write( channel, pbuf, len ) ) goto return_error;
271       
272        goto printf_text;
273    }
274
275return_error:
276
277    {
278        // try to print an error message and exit...
279        unsigned int procid     = _get_procid();
280        unsigned int x          = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
281        unsigned int y          = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
282        unsigned int lpid       = procid & ((1<<P_WIDTH)-1);
283        _puts("\n\n[GIET ERROR] in _printf() for processor[");
284        _putd( x ); 
285        _puts(",");
286        _putd( y );
287        _puts(",");
288        _putd( lpid );
289        _puts("]\n");
290        _exit();
291    }
292}  // end _kernel_printf()
293
294///////////////////////////////////////
295void _nolock_printf( char* format, ...)
296{
297    va_list   args;
298
299    // call kernel_printf
300    va_start( args , format );
301    _kernel_printf( 0, format , &args );
302    va_end( args );
303}
304
305////////////////////////////////
306void _printf( char* format, ...)
307{
308    va_list       args;
309    unsigned int  save_sr;
310
311    // get TTY0 lock
312    _it_disable( &save_sr );
313    if ( _tty0_boot_mode ) _spin_lock_acquire( &_tty0_spin_lock );
314    else                   _sqt_lock_acquire( &_tty0_sqt_lock );
315
316    // call kernel_printf
317    va_start( args , format );
318    _kernel_printf( 0, format , &args );
319    va_end( args );
320
321    // release TTY0 lock
322    if ( _tty0_boot_mode ) _spin_lock_release( &_tty0_spin_lock );
323    else                   _sqt_lock_release( &_tty0_sqt_lock );
324    _it_restore( &save_sr );
325}
326
327/////////////////////////////////////
328void _user_printf( char* format, ...)
329{
330    va_list   args;
331
332    // get calling thread TYY channel
333    unsigned int channel = _get_context_slot( CTX_TTY_ID );
334    if( channel >= NB_TTY_CHANNELS ) 
335    {
336        _puts("\n[GIET ERROR] in _user_printf() : no TTY allocated for thread ");
337        _putx( _get_thread_trdid() );
338        _puts("\n");
339        _exit();
340    }
341
342    // call kernel_printf
343    va_start( args , format );
344    _kernel_printf( channel, format , &args );
345    va_end( args );
346}
347
348
349
350// Local Variables:
351// tab-width: 4
352// c-basic-offset: 4
353// c-file-offsets:((innamespace . 0)(inline-open . 0))
354// indent-tabs-mode: nil
355// End:
356// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
357
Note: See TracBrowser for help on using the repository browser.