| [1] | 1 | /* | 
|---|
 | 2 |  * printk.c - Kernel Log & debug messages API implementation. | 
|---|
 | 3 |  *  | 
|---|
 | 4 |  * authors  Alain Greiner (2016) | 
|---|
 | 5 |  * | 
|---|
 | 6 |  * Copyright (c) UPMC Sorbonne Universites | 
|---|
 | 7 |  * | 
|---|
 | 8 |  * This file is part of ALMOS-MKH.. | 
|---|
 | 9 |  * | 
|---|
 | 10 |  * ALMOS-MKH. is free software; you can redistribute it and/or modify it | 
|---|
 | 11 |  * under the terms of the GNU General Public License as published by | 
|---|
 | 12 |  * the Free Software Foundation; version 2.0 of the License. | 
|---|
 | 13 |  * | 
|---|
 | 14 |  * ALMOS-MKH. is distributed in the hope that it will be useful, but | 
|---|
 | 15 |  * WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
 | 16 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|---|
 | 17 |  * General Public License for more details. | 
|---|
 | 18 |  * | 
|---|
 | 19 |  * You should have received a copy of the GNU General Public License | 
|---|
 | 20 |  * along with ALMOS-MKH.; if not, write to the Free Software Foundation, | 
|---|
 | 21 |  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 
|---|
 | 22 |  */ | 
|---|
 | 23 |  | 
|---|
 | 24 | #include <hal_types.h> | 
|---|
 | 25 | #include <hal_irqmask.h> | 
|---|
| [5] | 26 | #include <hal_special.h> | 
|---|
| [1] | 27 | #include <dev_txt.h> | 
|---|
 | 28 | #include <remote_spinlock.h> | 
|---|
 | 29 | #include <cluster.h> | 
|---|
| [14] | 30 | #include <chdev.h> | 
|---|
| [5] | 31 | #include <printk.h> | 
|---|
| [1] | 32 |  | 
|---|
 | 33 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [14] | 34 | //      Extern variables | 
|---|
 | 35 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 36 |  | 
|---|
| [188] | 37 | extern chdev_directory_t  chdev_dir;  // defined in chdev.h / allocated in kernel_init.c | 
|---|
| [14] | 38 |  | 
|---|
| [23] | 39 | ///////////////////////////////////// | 
|---|
 | 40 | uint32_t snprintf( char     * string, | 
|---|
 | 41 |                    uint32_t   length, | 
|---|
 | 42 |                    char     * format, ... ) | 
|---|
 | 43 | { | 
|---|
 | 44 |  | 
|---|
 | 45 | #define TO_STREAM(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0); | 
|---|
 | 46 |  | 
|---|
 | 47 |     va_list    args;      // printf arguments | 
|---|
 | 48 |     uint32_t   ps;        // write pointer to the string buffer | 
|---|
 | 49 |  | 
|---|
 | 50 |     ps = 0;    | 
|---|
 | 51 |     va_start( args , format ); | 
|---|
 | 52 |  | 
|---|
 | 53 | xprintf_text: | 
|---|
 | 54 |  | 
|---|
 | 55 |     while ( *format != 0 )  | 
|---|
 | 56 |     { | 
|---|
 | 57 |  | 
|---|
 | 58 |         if (*format == '%')   // copy argument to string | 
|---|
 | 59 |         { | 
|---|
 | 60 |             format++; | 
|---|
 | 61 |             goto xprintf_arguments; | 
|---|
 | 62 |         } | 
|---|
 | 63 |         else                  // copy one char to string | 
|---|
 | 64 |         { | 
|---|
 | 65 |             TO_STREAM( *format ); | 
|---|
 | 66 |             format++; | 
|---|
 | 67 |         } | 
|---|
 | 68 |     } | 
|---|
 | 69 |  | 
|---|
 | 70 |     va_end( args ); | 
|---|
 | 71 |      | 
|---|
 | 72 |     // add terminating NUL chracter | 
|---|
 | 73 |     TO_STREAM( 0 ); | 
|---|
 | 74 |     return ps; | 
|---|
 | 75 |  | 
|---|
 | 76 | xprintf_arguments: | 
|---|
 | 77 |  | 
|---|
 | 78 |     { | 
|---|
 | 79 |         char              buf[30];    // buffer to display one number | 
|---|
 | 80 |         char *            pbuf;       // pointer on first char to display | 
|---|
 | 81 |         uint32_t          len = 0;    // number of char to display | 
|---|
 | 82 |         static const char HexaTab[] = "0123456789ABCDEF"; | 
|---|
 | 83 |         uint32_t          i; | 
|---|
 | 84 |          | 
|---|
 | 85 |         // Ignore fields width and precision  | 
|---|
 | 86 |         for ( ; (*format >= '0' && *format <= '9') || (*format == '.') ; format++ ); | 
|---|
 | 87 |  | 
|---|
 | 88 |         switch (*format)  | 
|---|
 | 89 |         { | 
|---|
 | 90 |             case ('c'):             // char conversion  | 
|---|
 | 91 |             { | 
|---|
 | 92 |                 int val = va_arg( args, int ); | 
|---|
 | 93 |                 buf[0] = val; | 
|---|
 | 94 |                 pbuf   = buf; | 
|---|
 | 95 |                 len    = 1; | 
|---|
 | 96 |                 break; | 
|---|
 | 97 |             } | 
|---|
 | 98 |             case ('d'):             // decimal signed integer | 
|---|
 | 99 |             { | 
|---|
 | 100 |                 int val = va_arg( args, int ); | 
|---|
 | 101 |                 if (val < 0)  | 
|---|
 | 102 |                 { | 
|---|
 | 103 |                     TO_STREAM( '-' ); | 
|---|
 | 104 |                     val = -val; | 
|---|
 | 105 |                 } | 
|---|
 | 106 |                 for(i = 0; i < 10; i++)  | 
|---|
 | 107 |                 { | 
|---|
 | 108 |  | 
|---|
 | 109 |                     buf[9 - i] = HexaTab[val % 10]; | 
|---|
 | 110 |                     if (!(val /= 10)) break; | 
|---|
 | 111 |                 } | 
|---|
 | 112 |                 len =  i + 1; | 
|---|
 | 113 |                 pbuf = &buf[9 - i]; | 
|---|
 | 114 |                 break; | 
|---|
 | 115 |             } | 
|---|
 | 116 |             case ('u'):             // decimal unsigned integer | 
|---|
 | 117 |             { | 
|---|
 | 118 |                 uint32_t val = va_arg( args, uint32_t ); | 
|---|
 | 119 |                 for(i = 0; i < 10; i++)  | 
|---|
 | 120 |                 { | 
|---|
 | 121 |                     buf[9 - i] = HexaTab[val % 10]; | 
|---|
 | 122 |                     if (!(val /= 10)) break; | 
|---|
 | 123 |                 } | 
|---|
 | 124 |                 len =  i + 1; | 
|---|
 | 125 |                 pbuf = &buf[9 - i]; | 
|---|
 | 126 |                 break; | 
|---|
 | 127 |             } | 
|---|
 | 128 |             case ('x'):             // 32 bits hexadecimal  | 
|---|
 | 129 |             case ('l'):             // 64 bits hexadecimal  | 
|---|
 | 130 |             { | 
|---|
 | 131 |                 uint32_t       imax; | 
|---|
 | 132 |                 uint64_t val; | 
|---|
 | 133 |                  | 
|---|
 | 134 |                 if ( *format == 'l' )   // 64 bits | 
|---|
 | 135 |                 { | 
|---|
 | 136 |                     val = va_arg( args, uint64_t); | 
|---|
 | 137 |                     imax = 16; | 
|---|
 | 138 |                 } | 
|---|
 | 139 |                 else                    // 32 bits | 
|---|
 | 140 |                 { | 
|---|
 | 141 |                     val = va_arg( args, uint32_t); | 
|---|
 | 142 |                     imax = 8; | 
|---|
 | 143 |                 } | 
|---|
 | 144 |                  | 
|---|
 | 145 |                 TO_STREAM( '0' ); | 
|---|
 | 146 |                 TO_STREAM( 'x' ); | 
|---|
 | 147 |                  | 
|---|
 | 148 |                 for(i = 0; i < imax; i++)  | 
|---|
 | 149 |                 { | 
|---|
 | 150 |                     buf[(imax-1) - i] = HexaTab[val % 16]; | 
|---|
 | 151 |                     if (!(val /= 16))  break; | 
|---|
 | 152 |                 } | 
|---|
 | 153 |                 len =  i + 1; | 
|---|
 | 154 |                 pbuf = &buf[(imax-1) - i]; | 
|---|
 | 155 |                 break; | 
|---|
 | 156 |             } | 
|---|
 | 157 |             case ('s'):             /* string */ | 
|---|
 | 158 |             { | 
|---|
 | 159 |                 char* str = va_arg( args, char* ); | 
|---|
 | 160 |                 while (str[len]) { len++; } | 
|---|
 | 161 |                 pbuf = str; | 
|---|
 | 162 |                 break; | 
|---|
 | 163 |             } | 
|---|
 | 164 |             default:       // unsupported argument type | 
|---|
 | 165 |             { | 
|---|
 | 166 |                 return -1; | 
|---|
 | 167 |             } | 
|---|
 | 168 |         }  // end switch on  argument type | 
|---|
 | 169 |  | 
|---|
 | 170 |         format++; | 
|---|
 | 171 |  | 
|---|
 | 172 |         // copy argument to string | 
|---|
 | 173 |         for( i = 0 ; i < len ; i++ ) | 
|---|
 | 174 |         { | 
|---|
 | 175 |             TO_STREAM( pbuf[i] ); | 
|---|
 | 176 |         } | 
|---|
 | 177 |          | 
|---|
 | 178 |         goto xprintf_text; | 
|---|
 | 179 |     } | 
|---|
 | 180 | } // end xprintf() | 
|---|
 | 181 |  | 
|---|
| [14] | 182 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [5] | 183 | // This static function is called by kernel_printf() to display a string on the | 
|---|
 | 184 | // TXT channel defined by the <channel> argument.  | 
|---|
 | 185 | // The access mode is defined by the <busy> argument: | 
|---|
 | 186 | // - if <busy> is true, it uses the dev_txt_sync_write() function, that takes the | 
|---|
 | 187 | //   TXT lock, and call directly the relevant TXT driver, without descheduling. | 
|---|
 | 188 | // - if <busy is false, it uses the dev_txt_write() function, that register the | 
|---|
 | 189 | //   write buffer in the relevant TXT chdev queue, and uses a descheduling policy. | 
|---|
| [1] | 190 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [5] | 191 | // @ channel  : TXT channel. | 
|---|
| [23] | 192 | // @ busy     : TXT device acces mode (busy waiting if non zero). | 
|---|
| [5] | 193 | // @ buf      : buffer containing the characters. | 
|---|
 | 194 | // @ nc       : number of characters. | 
|---|
 | 195 | // return 0 if success / return -1 if TTY0 busy after 10000 retries. | 
|---|
 | 196 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 197 | static error_t txt_write( uint32_t  channel, | 
|---|
 | 198 |                           uint32_t  busy, | 
|---|
 | 199 |                           char    * buffer, | 
|---|
 | 200 |                           uint32_t  count ) | 
|---|
 | 201 | { | 
|---|
 | 202 |     if( busy ) return dev_txt_sync_write( channel , buffer , count ); | 
|---|
 | 203 |     else       return dev_txt_write( channel , buffer , count ); | 
|---|
 | 204 | }   | 
|---|
 | 205 |  | 
|---|
 | 206 | ////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 207 | // This static function is called by printk() and user_printk() to build | 
|---|
 | 208 | // a formated string. | 
|---|
 | 209 | ////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 210 | // @ channel   : channel index. | 
|---|
| [23] | 211 | // @ busy      : TXT device access mode (busy waiting if non zero). | 
|---|
| [5] | 212 | // @ format    : printf like format. | 
|---|
 | 213 | // @ args      : format arguments. | 
|---|
 | 214 | ////////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [1] | 215 | static void kernel_printf( uint32_t   channel, | 
|---|
| [5] | 216 |                            uint32_t   busy, | 
|---|
| [1] | 217 |                            char     * format,  | 
|---|
 | 218 |                            va_list  * args )  | 
|---|
 | 219 | { | 
|---|
 | 220 |  | 
|---|
 | 221 | printf_text: | 
|---|
 | 222 |  | 
|---|
 | 223 |     while (*format)  | 
|---|
 | 224 |     { | 
|---|
 | 225 |         uint32_t i; | 
|---|
 | 226 |         for (i = 0 ; format[i] && (format[i] != '%') ; i++); | 
|---|
 | 227 |         if (i)  | 
|---|
 | 228 |         { | 
|---|
| [5] | 229 |             txt_write( channel, busy, format, i ); | 
|---|
| [1] | 230 |             format += i; | 
|---|
 | 231 |         } | 
|---|
 | 232 |         if (*format == '%')  | 
|---|
 | 233 |         { | 
|---|
 | 234 |             format++; | 
|---|
 | 235 |             goto printf_arguments; | 
|---|
 | 236 |         } | 
|---|
 | 237 |     } | 
|---|
 | 238 |  | 
|---|
 | 239 |     return; | 
|---|
 | 240 |  | 
|---|
 | 241 | printf_arguments: | 
|---|
 | 242 |  | 
|---|
 | 243 |     { | 
|---|
 | 244 |         char      buf[20]; | 
|---|
 | 245 |         char    * pbuf = NULL; | 
|---|
 | 246 |         uint32_t  len  = 0; | 
|---|
 | 247 |         static const char HexaTab[] = "0123456789ABCDEF"; | 
|---|
 | 248 |         uint32_t i; | 
|---|
 | 249 |  | 
|---|
 | 250 |         switch (*format++)  | 
|---|
 | 251 |         { | 
|---|
 | 252 |             case ('c'):             /* char conversion */ | 
|---|
 | 253 |             { | 
|---|
 | 254 |                 int val = va_arg( *args , int ); | 
|---|
 | 255 |                 len = 1; | 
|---|
 | 256 |                 buf[0] = val; | 
|---|
 | 257 |                 pbuf = &buf[0]; | 
|---|
 | 258 |                 break; | 
|---|
 | 259 |             } | 
|---|
 | 260 |             case ('d'):             /* 32 bits decimal signed  */ | 
|---|
 | 261 |             { | 
|---|
 | 262 |                 int val = va_arg( *args , int ); | 
|---|
 | 263 |                 if (val < 0)  | 
|---|
 | 264 |                 { | 
|---|
 | 265 |                     val = -val; | 
|---|
| [5] | 266 |                     txt_write( channel, busy, "-" , 1 ); | 
|---|
| [1] | 267 |                 } | 
|---|
 | 268 |                 for(i = 0; i < 10; i++)  | 
|---|
 | 269 |                 { | 
|---|
 | 270 |                     buf[9 - i] = HexaTab[val % 10]; | 
|---|
 | 271 |                     if (!(val /= 10)) break; | 
|---|
 | 272 |                 } | 
|---|
 | 273 |                 len =  i + 1; | 
|---|
 | 274 |                 pbuf = &buf[9 - i]; | 
|---|
 | 275 |                 break; | 
|---|
 | 276 |             } | 
|---|
 | 277 |             case ('u'):             /* 32 bits decimal unsigned  */ | 
|---|
 | 278 |             { | 
|---|
 | 279 |                 uint32_t val = va_arg( *args , uint32_t ); | 
|---|
 | 280 |                 for(i = 0; i < 10; i++)  | 
|---|
 | 281 |                 { | 
|---|
 | 282 |                     buf[9 - i] = HexaTab[val % 10]; | 
|---|
 | 283 |                     if (!(val /= 10)) break; | 
|---|
 | 284 |                 } | 
|---|
 | 285 |                 len =  i + 1; | 
|---|
 | 286 |                 pbuf = &buf[9 - i]; | 
|---|
 | 287 |                 break; | 
|---|
 | 288 |             } | 
|---|
 | 289 |             case ('x'):             /* 32 bits hexadecimal unsigned */ | 
|---|
 | 290 |             { | 
|---|
 | 291 |                 uint32_t val = va_arg( *args , uint32_t ); | 
|---|
| [5] | 292 |                 txt_write( channel, busy, "0x" , 2 ); | 
|---|
| [1] | 293 |                 for(i = 0; i < 8; i++)  | 
|---|
 | 294 |                 { | 
|---|
| [5] | 295 |                     buf[7 - i] = HexaTab[val & 0xF]; | 
|---|
| [1] | 296 |                     if (!(val = (val>>4)))  break; | 
|---|
 | 297 |                 } | 
|---|
 | 298 |                 len =  i + 1; | 
|---|
 | 299 |                 pbuf = &buf[7 - i]; | 
|---|
 | 300 |                 break; | 
|---|
 | 301 |             } | 
|---|
| [5] | 302 |             case ('X'):             /* 32 bits hexadecimal unsigned  on 10 char */ | 
|---|
| [1] | 303 |             { | 
|---|
 | 304 |                 uint32_t val = va_arg( *args , uint32_t ); | 
|---|
| [5] | 305 |                 txt_write( channel, busy, "0x" , 2 ); | 
|---|
| [1] | 306 |                 for(i = 0; i < 8; i++)  | 
|---|
 | 307 |                 { | 
|---|
| [5] | 308 |                     buf[7 - i] = HexaTab[val & 0xF]; | 
|---|
| [1] | 309 |                     val = (val>>4); | 
|---|
 | 310 |                 } | 
|---|
 | 311 |                 len =  8; | 
|---|
 | 312 |                 pbuf = buf; | 
|---|
 | 313 |                 break; | 
|---|
 | 314 |             } | 
|---|
 | 315 |             case ('l'):            /* 64 bits hexadecimal unsigned */ | 
|---|
 | 316 |             { | 
|---|
 | 317 |                 uint64_t val = va_arg( *args , uint64_t ); | 
|---|
| [5] | 318 |                 txt_write( channel, busy, "0x" , 2 ); | 
|---|
| [1] | 319 |                 for(i = 0; i < 16; i++)  | 
|---|
 | 320 |                 { | 
|---|
| [5] | 321 |                     buf[15 - i] = HexaTab[val & 0xF]; | 
|---|
 | 322 |                     if (!(val = (val>>4)))  break; | 
|---|
| [1] | 323 |                 } | 
|---|
 | 324 |                 len =  i + 1; | 
|---|
 | 325 |                 pbuf = &buf[15 - i]; | 
|---|
 | 326 |                 break; | 
|---|
 | 327 |             } | 
|---|
| [5] | 328 |             case ('L'):           /* 64 bits hexadecimal unsigned on 18 char */  | 
|---|
 | 329 |             { | 
|---|
 | 330 |                 uint64_t val = va_arg( *args , uint64_t ); | 
|---|
 | 331 |                 txt_write( channel, busy, "0x" , 2 ); | 
|---|
 | 332 |                 for(i = 0; i < 16; i++)  | 
|---|
 | 333 |                 { | 
|---|
 | 334 |                     buf[15 - i] = HexaTab[val & 0xF]; | 
|---|
 | 335 |                     val = (val>>4); | 
|---|
 | 336 |                 } | 
|---|
 | 337 |                 len =  16; | 
|---|
 | 338 |                 pbuf = buf; | 
|---|
 | 339 |                 break; | 
|---|
 | 340 |             } | 
|---|
| [1] | 341 |             case ('s'):             /* string */ | 
|---|
 | 342 |             { | 
|---|
 | 343 |                 char* str = va_arg( *args , char* ); | 
|---|
 | 344 |                 while (str[len])  | 
|---|
 | 345 |                 { | 
|---|
 | 346 |                     len++; | 
|---|
 | 347 |                 } | 
|---|
 | 348 |                 pbuf = str; | 
|---|
 | 349 |                 break; | 
|---|
 | 350 |             } | 
|---|
 | 351 |             default: | 
|---|
 | 352 |             { | 
|---|
| [5] | 353 |                 txt_write( channel , busy, | 
|---|
 | 354 |                            "\n[PANIC] in kernel_printf() : illegal format\n", 45 ); | 
|---|
| [1] | 355 |             } | 
|---|
 | 356 |         } | 
|---|
 | 357 |  | 
|---|
| [5] | 358 |         if( pbuf != NULL ) txt_write( channel, busy, pbuf, len ); | 
|---|
| [1] | 359 |          | 
|---|
 | 360 |         goto printf_text; | 
|---|
 | 361 |     } | 
|---|
 | 362 |  | 
|---|
 | 363 | }  // end kernel_printf() | 
|---|
 | 364 |  | 
|---|
| [14] | 365 | ///////////////////////////////// | 
|---|
 | 366 | void printk( char * format , ...) | 
|---|
| [1] | 367 | { | 
|---|
 | 368 |     va_list       args; | 
|---|
| [14] | 369 |     uint32_t      save_sr; | 
|---|
| [1] | 370 |  | 
|---|
| [188] | 371 |     // get pointers on TXT0 chdev | 
|---|
 | 372 |     xptr_t    txt0_xp  = chdev_dir.txt[0]; | 
|---|
 | 373 |     cxy_t     txt0_cxy = GET_CXY( txt0_xp ); | 
|---|
 | 374 |     chdev_t * txt0_ptr = GET_PTR( txt0_xp ); | 
|---|
 | 375 |  | 
|---|
| [14] | 376 |     // get extended pointer on remote TXT0 chdev lock | 
|---|
| [188] | 377 |     xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock ); | 
|---|
| [14] | 378 |  | 
|---|
 | 379 |     // get TXT0 lock in busy waiting mode | 
|---|
| [188] | 380 |     remote_spinlock_lock_busy( lock_xp , &save_sr ); | 
|---|
| [14] | 381 |  | 
|---|
| [103] | 382 |     // call kernel_printf on TXT0, in busy waiting mode | 
|---|
| [1] | 383 |     va_start( args , format ); | 
|---|
| [5] | 384 |     kernel_printf( 0 , 1 , format , &args ); | 
|---|
| [1] | 385 |     va_end( args ); | 
|---|
| [14] | 386 |  | 
|---|
 | 387 |     // release lock | 
|---|
| [188] | 388 |     remote_spinlock_unlock_busy( lock_xp , save_sr ); | 
|---|
| [1] | 389 | } | 
|---|
 | 390 |  | 
|---|
| [103] | 391 | //////////////////////////////////////// | 
|---|
 | 392 | void nolock_printk( char * format , ...) | 
|---|
| [1] | 393 | { | 
|---|
 | 394 |     va_list   args; | 
|---|
 | 395 |  | 
|---|
| [103] | 396 |     // call kernel_printf on TXT0, in busy waiting mode | 
|---|
| [1] | 397 |     va_start( args , format ); | 
|---|
| [103] | 398 |     kernel_printf( 0 , 1 , format , &args ); | 
|---|
| [1] | 399 |     va_end( args ); | 
|---|
 | 400 | } | 
|---|
 | 401 |  | 
|---|
| [5] | 402 | /////////////////////////////////////////// | 
|---|
 | 403 | inline void assert( bool_t       condition, | 
|---|
 | 404 |                     const char * function_name, | 
|---|
 | 405 |                     char       * string ) | 
|---|
 | 406 | { | 
|---|
 | 407 |     if( condition == false ) | 
|---|
 | 408 |     { | 
|---|
 | 409 |         printk("\n[PANIC] in %s : %s\n" , function_name , string ); | 
|---|
 | 410 |         hal_core_sleep(); | 
|---|
 | 411 |     } | 
|---|
 | 412 | } | 
|---|
| [1] | 413 |  | 
|---|
| [188] | 414 | ////////////////////////////////////////////////// | 
|---|
 | 415 | inline void nolock_assert( bool_t       condition, | 
|---|
 | 416 |                            const char * function_name, | 
|---|
 | 417 |                            char       * string ) | 
|---|
 | 418 | { | 
|---|
 | 419 |     if( condition == false ) | 
|---|
 | 420 |     { | 
|---|
 | 421 |         nolock_printk("\n[PANIC] in %s : %s\n" , function_name , string ); | 
|---|
 | 422 |         hal_core_sleep(); | 
|---|
 | 423 |     } | 
|---|
 | 424 | } | 
|---|
| [23] | 425 |  | 
|---|
| [188] | 426 |  | 
|---|
 | 427 |  | 
|---|
| [1] | 428 | // Local Variables: | 
|---|
 | 429 | // tab-width: 4 | 
|---|
 | 430 | // c-basic-offset: 4 | 
|---|
 | 431 | // c-file-offsets:((innamespace . 0)(inline-open . 0)) | 
|---|
 | 432 | // indent-tabs-mode: nil | 
|---|
 | 433 | // End: | 
|---|
 | 434 | // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 | 
|---|
 | 435 |  | 
|---|