]> rtime.felk.cvut.cz Git - arc.git/blob - common/newlib_port.c
Fixed compile bug for TMS570. Added terminal support for Code Composer.
[arc.git] / common / newlib_port.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 \r
17 #include <unistd.h>\r
18 #include <sys/stat.h>\r
19 #include <sys/types.h>\r
20 #include <errno.h>\r
21 #include <stdlib.h>\r
22 #include <string.h>\r
23 #include <stdio.h>\r
24 #include <stddef.h>\r
25 #include "Std_Types.h"\r
26 #include "Ramlog.h"\r
27 \r
28 #if defined(CFG_ARM_CM3)\r
29 #include "irq_types.h"\r
30 #include "stm32f10x.h"\r
31 #endif\r
32 \r
33 #ifdef USE_TTY_TCF_STREAMS\r
34 #include "streams.h"\r
35 #endif\r
36 \r
37 \r
38 #if defined(CFG_ARM)\r
39 #define open    _open\r
40 #define exit    _exit\r
41 #define fstat   _fstat\r
42 #define getpid  _getpid\r
43 #define kill    _kill\r
44 #define close   _close\r
45 #define isatty  _isatty\r
46 #define sbrk    _sbrk\r
47 #define read    _read\r
48 #define write   _write\r
49 #define lseek   _lseek\r
50 #endif\r
51 \r
52 // Operation on Winidea terminal buffer\r
53 \r
54 \r
55 #define TWBUFF_SIZE 0x100\r
56 #define TRBUFF_SIZE 0x100\r
57 \r
58 \r
59 #define TBUFF_PTR 2\r
60 \r
61 #define TWBUFF_LEN (TWBUFF_SIZE+TBUFF_PTR)\r
62 #define TRBUFF_LEN (TRBUFF_SIZE+TBUFF_PTR)\r
63 #define TWBUFF_TPTR (g_TWBuffer[TWBUFF_SIZE+0])\r
64 #define TWBUFF_CPTR (g_TWBuffer[TWBUFF_SIZE+1])\r
65 #define TWBUFF_INC(n) ((n + 1)&(TWBUFF_SIZE-1))\r
66 #define TWBUFF_FULL() (TWBUFF_TPTR==((TWBUFF_CPTR-1)&(TWBUFF_SIZE-1)))\r
67 \r
68 #ifdef USE_TTY_WINIDEA\r
69 \r
70 #if defined(MC912DG128A)\r
71 static volatile unsigned char g_TWBuffer[TWBUFF_LEN];\r
72 static volatile unsigned char g_TRBuffer[TRBUFF_LEN];\r
73 volatile char g_TConn __attribute__ ((section (".winidea_port")));\r
74 \r
75 #else\r
76 static volatile unsigned char g_TWBuffer[TWBUFF_LEN] __attribute__ ((aligned (0x100))); // Transmit to WinIDEA terminal\r
77 static volatile unsigned char g_TRBuffer[TRBUFF_LEN] __attribute__ ((aligned (0x100)));\r
78 volatile char g_TConn __attribute__ ((section (".winidea_port")));\r
79 \r
80 #endif\r
81 \r
82 #endif\r
83 \r
84 #ifdef USE_TTY_CODE_COMPOSER\r
85 \r
86 #define _DTOPEN    (0xF0)\r
87 #define _DTCLOSE   (0xF1)\r
88 #define _DTREAD    (0xF2)\r
89 #define _DTWRITE   (0xF3)\r
90 #define _DTLSEEK   (0xF4)\r
91 #define _DTUNLINK  (0xF5)\r
92 #define _DTGETENV  (0xF6)\r
93 #define _DTRENAME  (0xF7)\r
94 #define _DTGETTIME (0xF8)\r
95 #define _DTGETCLK  (0xF9)\r
96 #define _DTSYNC    (0xFF)\r
97 \r
98 #define LOADSHORT(x,y,z)  { x[(z)]   = (unsigned short) (y); \\r
99                             x[(z)+1] = (unsigned short) (y) >> 8;  }\r
100 \r
101 #define UNLOADSHORT(x,z) ((short) ( (short) x[(z)] +             \\r
102                                    ((short) x[(z)+1] << 8)))\r
103 \r
104 #define PACKCHAR(val, base, byte) ( (base)[(byte)] = (val) )\r
105 \r
106 #define UNPACKCHAR(base, byte)    ( (base)[byte] )\r
107 \r
108 \r
109 static unsigned char parmbuf[8];\r
110 #define BUFSIZ 512\r
111 #define CC_BUFFER_SIZE ((BUFSIZ)+32)\r
112 volatile unsigned int _CIOBUF_[CC_BUFFER_SIZE] __attribute__ ((section (".cio")));\r
113 static unsigned char CIOTMPBUF[BUFSIZ];\r
114 static uint16 cio_tmp_buf_index = 0;\r
115 \r
116 /***************************************************************************/\r
117 /*                                                                         */\r
118 /*  WRITEMSG()  -  Sends the passed data and parameters on to the host.    */\r
119 /*                                                                         */\r
120 /***************************************************************************/\r
121 void writemsg(unsigned char  command,\r
122               register const unsigned char *parm,\r
123               register const          char *data,\r
124               unsigned int            length)\r
125 {\r
126    volatile unsigned char *p = (volatile unsigned char *)(_CIOBUF_+1);\r
127    unsigned int i;\r
128 \r
129    /***********************************************************************/\r
130    /* THE LENGTH IS WRITTEN AS A TARGET INT                               */\r
131    /***********************************************************************/\r
132    _CIOBUF_[0] = length;\r
133 \r
134    /***********************************************************************/\r
135    /* THE COMMAND IS WRITTEN AS A TARGET BYTE                             */\r
136    /***********************************************************************/\r
137    *p++ = command;\r
138 \r
139    /***********************************************************************/\r
140    /* PACK THE PARAMETERS AND DATA SO THE HOST READS IT AS BYTE STREAM    */\r
141    /***********************************************************************/\r
142    for (i = 0; i < 8; i++)      PACKCHAR(*parm++, p, i);\r
143    for (i = 0; i < length; i++) PACKCHAR(*data++, p, i+8);\r
144 \r
145    /***********************************************************************/\r
146    /* THE BREAKPOINT THAT SIGNALS THE HOST TO DO DATA TRANSFER            */\r
147    /***********************************************************************/\r
148    __asm("       .global C$$IO$$");\r
149    __asm("C$$IO$$: nop");\r
150 }\r
151 \r
152 /***************************************************************************/\r
153 /*                                                                         */\r
154 /*  READMSG()   -  Reads the data and parameters passed from the host.     */\r
155 /*                                                                         */\r
156 /***************************************************************************/\r
157 void readmsg(register unsigned char *parm,\r
158              register char          *data)\r
159 {\r
160    volatile unsigned char *p = (volatile unsigned char *)(_CIOBUF_+1);\r
161    unsigned int   i;\r
162    unsigned int   length;\r
163 \r
164    /***********************************************************************/\r
165    /* THE LENGTH IS READ AS A TARGET INT                                  */\r
166    /***********************************************************************/\r
167    length = _CIOBUF_[0];\r
168 \r
169    /***********************************************************************/\r
170    /* UNPACK THE PARAMETERS AND DATA                                      */\r
171    /***********************************************************************/\r
172    for (i = 0; i < 8; i++) *parm++ = UNPACKCHAR(p, i);\r
173    if (data != NULL)\r
174       for (i = 0; i < length; i++) *data++ = UNPACKCHAR(p, i+8);\r
175 }\r
176 \r
177 /****************************************************************************/\r
178 /* HOSTWRITE()  -  Pass the write command and its arguments to the host.    */\r
179 /****************************************************************************/\r
180 int HOSTwrite(int dev_fd, const char *buf, unsigned count)\r
181 {\r
182    int result;\r
183 \r
184    // WARNING. Can only handle count == 1!\r
185    if (count != 1) _exit(1);\r
186 \r
187    if (count > BUFSIZ) count = BUFSIZ;\r
188 \r
189    if (cio_tmp_buf_index < BUFSIZ) {\r
190            CIOTMPBUF[cio_tmp_buf_index++] = *buf;\r
191 \r
192            if (*buf != 0xA) { // Only flush if newline\r
193                    return 0;\r
194            }\r
195    }\r
196 \r
197 \r
198    LOADSHORT(parmbuf,dev_fd,0);\r
199    LOADSHORT(parmbuf,cio_tmp_buf_index,2);\r
200    writemsg(_DTWRITE,parmbuf,(char *)CIOTMPBUF,cio_tmp_buf_index);\r
201    readmsg(parmbuf,NULL);\r
202 \r
203    result = UNLOADSHORT(parmbuf,0);\r
204 \r
205    cio_tmp_buf_index = 0;\r
206 \r
207    return result;\r
208 }\r
209 \r
210 #endif\r
211 \r
212 #ifdef USE_TTY_TMS570_KEIL\r
213 #include "GLCD.h"\r
214 #endif\r
215 \r
216 #define FILE_RAMLOG             3\r
217 \r
218 /* Location MUST match NoICE configuration */\r
219 #ifdef USE_TTY_NOICE\r
220 static volatile char VUART_TX __attribute__ ((section (".noice_port")));\r
221 static volatile char VUART_RX __attribute__ ((section (".noice_port")));\r
222 volatile unsigned char START_VUART = 0;\r
223 #endif\r
224 \r
225 /*\r
226  * T32 stuff\r
227  */\r
228 \r
229 // This must be in un-cached space....\r
230 #ifdef USE_TTY_T32\r
231 static volatile char t32_outport __attribute__ ((section (".t32_outport")));\r
232 \r
233 void t32_writebyte(char c)\r
234 {\r
235         /* T32 can hang here for several reasons;\r
236          * - term.view e:address.offset(v.address(t32_outport)) e:0\r
237          */\r
238 \r
239         while (t32_outport != 0 ) ; /* wait until port is free */\r
240         t32_outport = c; /* send character */\r
241 }\r
242 #endif\r
243 /*\r
244  * clib support\r
245  */\r
246 \r
247 /* Do nothing */\r
248 int close( int fd ) {\r
249         (void)fd;\r
250         return (-1);\r
251 }\r
252 \r
253 char *__env[1] = { 0 };\r
254 char **environ = __env;\r
255 \r
256 \r
257 #include <errno.h>\r
258 #undef errno\r
259 extern int errno;\r
260 \r
261 \r
262 int execve(const char *path, char * const argv[], char * const envp[] ) {\r
263 //int execve(char *name, char **argv, char **env){\r
264         (void)path;\r
265         (void)argv;\r
266         (void)envp;\r
267         errno=ENOMEM;\r
268         return -1;\r
269 }\r
270 \r
271 pid_t fork() {\r
272   errno=EAGAIN;\r
273   return -1;\r
274 }\r
275 \r
276 #include <sys/stat.h>\r
277 int fstat(int file, struct stat *st) {\r
278         (void)file;\r
279         st->st_mode = S_IFCHR;\r
280         return 0;\r
281 }\r
282 \r
283 /* Returns 1 if connected to a terminal. T32 can be a terminal\r
284  */\r
285 \r
286 int isatty( int fd )\r
287 {\r
288         (void)fd;\r
289         return 1;\r
290 }\r
291 \r
292 /*\r
293 int fstat( int fd,  struct stat *buf )\r
294 {\r
295   buf->st_mode = S_IFCHR;\r
296   buf->st_blksize = 0;\r
297 \r
298   return (0);\r
299 }\r
300 */\r
301 \r
302 /* reposition read/write file offset\r
303  * We can't seek, return error.*/\r
304 off_t lseek( int fd, off_t offset,int whence)\r
305 {\r
306         (void)fd;\r
307         (void)offset;\r
308         (void)whence;\r
309 \r
310         errno = ESPIPE;\r
311         return ((off_t)-1);\r
312 }\r
313 \r
314 int open(const char *name, int flags, int mode){\r
315         (void)name;\r
316         (void)flags;\r
317         (void)mode;\r
318 \r
319 #if defined(USE_RAMLOG)\r
320         if( strcmp(name,"ramlog") == 0 ) {\r
321                 return FILE_RAMLOG;\r
322         }\r
323 #endif\r
324 \r
325     return -1;\r
326 }\r
327 \r
328 int read( int fd, void *buf, size_t nbytes )\r
329 {\r
330         (void)fd;\r
331         (void)buf;\r
332         (void)nbytes;\r
333 #ifdef USE_TTY_WINIDEA\r
334         (void)g_TRBuffer[0];\r
335 #endif\r
336 \r
337 #ifdef USE_TTY_NOICE\r
338         // Not tested at all\r
339     int retval;\r
340     while (VUART_RX != 0)\r
341     {\r
342     }\r
343 \r
344     retval = VUART_RX;\r
345     VUART_RX = 0;\r
346 #endif\r
347 \r
348         /* Only support write for now, return 0 read */\r
349         return 0;\r
350 }\r
351 \r
352 \r
353 int write(  int fd, const void *_buf, size_t nbytes)\r
354 {\r
355         //(void)fd;  // Normally 0- ?, 1-stdout, 2-stderr,\r
356                                 // Added 3-ramlog,\r
357 \r
358 \r
359         if( fd <= STDERR_FILENO ) {\r
360 #ifdef USE_TTY_NOICE\r
361         char *buf1 = (char *)_buf;\r
362         if (START_VUART)\r
363         {\r
364            for (int i = 0; i < nbytes; i++) {\r
365                    char c = buf1[i];\r
366                    if (c == '\n')\r
367                    {\r
368                            while (VUART_TX != 0)\r
369                            {\r
370                            }\r
371 \r
372                            VUART_TX = '\r';\r
373                    }\r
374 \r
375                    while (VUART_TX != 0)\r
376                    {\r
377                    }\r
378 \r
379                    VUART_TX = c;\r
380            }\r
381         }\r
382 #endif\r
383 \r
384 #ifdef USE_TTY_WINIDEA\r
385                 if (g_TConn)\r
386                 {\r
387           char *buf = (char *)_buf;\r
388                   unsigned char nCnt,nLen;\r
389                   for(nCnt=0; nCnt<nbytes; nCnt++)\r
390                         {\r
391                         while(TWBUFF_FULL()) ;\r
392                         nLen=TWBUFF_TPTR;\r
393                         g_TWBuffer[nLen]=buf[nCnt];\r
394                         nLen=TWBUFF_INC(nLen);\r
395                         TWBUFF_TPTR=nLen;\r
396                         }\r
397                 }\r
398 #endif\r
399 \r
400 #ifdef USE_TTY_T32\r
401                 char *buf = (char *)_buf;\r
402                 for (int i = 0; i < nbytes; i++) {\r
403                         if (*(buf + i) == '\n') {\r
404                                 t32_writebyte ('\r');\r
405 //                      t32_writebyte ('\n');\r
406                         }\r
407                         t32_writebyte (*(buf + i));\r
408                 }\r
409 #endif\r
410 \r
411 #ifdef USE_TTY_ARM_ITM\r
412                 char *buf = (char *)_buf;\r
413                 for (int i = 0; i < nbytes; i++) {\r
414                         ITM_SendChar(*(buf + i));\r
415                 }\r
416 #endif\r
417 \r
418 #ifdef USE_TTY_TCF_STREAMS\r
419                 char *buf = (char *)_buf;\r
420                 for (int i = 0; i < nbytes; i++) {\r
421                         TCF_TTY_SendChar(*(buf + i));\r
422                 }\r
423 #endif\r
424 \r
425 #ifdef USE_TTY_CODE_COMPOSER\r
426         HOSTwrite(fd, _buf, nbytes);\r
427 #endif\r
428 \r
429 #ifdef USE_TTY_TMS570_KEIL\r
430         for (int i = 0; i < nbytes; i++) {\r
431                 GLCD_PrintChar((char *)(_buf + i));\r
432         }\r
433 #endif\r
434 \r
435 #if defined(USE_RAMLOG)\r
436                 {\r
437                         char *buf = (char *)_buf;\r
438                         for (int i = 0; i < nbytes; i++) {\r
439                                 ramlog_chr (*(buf + i));\r
440                         }\r
441                 }\r
442 #endif\r
443 \r
444         }\r
445         else\r
446         {\r
447 #if defined(USE_RAMLOG)\r
448                 /* RAMLOG support */\r
449                 if(fd == FILE_RAMLOG) {\r
450                         char *buf = (char *)_buf;\r
451                         for (int i = 0; i < nbytes; i++) {\r
452                                 ramlog_chr (*(buf + i));\r
453                         }\r
454                 }\r
455 #endif\r
456         }\r
457 \r
458         return (nbytes);\r
459 }\r
460 \r
461 int arc_putchar(int fd, int c) {\r
462         char cc = c;\r
463         write( fd,&cc,1);\r
464 \r
465         return 0;\r
466 }\r
467 \r
468 /* If we use malloc and it runs out of memory it calls sbrk()\r
469  */\r
470 \r
471 #if defined(CFG_PPC)\r
472 \r
473 /* linker symbols */\r
474 extern char _heap_start[];  // incomplete array to ensure not placed in small-data\r
475 extern char _heap_end[];\r
476 \r
477 void * sbrk( ptrdiff_t incr )\r
478 {\r
479     char *prevEnd;\r
480     static char *nextAvailMemPtr = _heap_start;\r
481 \r
482     if( nextAvailMemPtr + incr >  _heap_end) {\r
483                 write( 2, "Heap overflow!\n", 15 );\r
484                 abort();\r
485         }\r
486     prevEnd = nextAvailMemPtr;\r
487     nextAvailMemPtr += incr;\r
488     return prevEnd;\r
489 }\r
490 #else\r
491 extern char _end[];\r
492 \r
493 //static char *curbrk = _end;\r
494 \r
495 #ifndef HEAPSIZE\r
496 #define HEAPSIZE 16000\r
497 #endif\r
498 \r
499 /*\r
500  * The heap sadly have alignment that depends on the pagesize that\r
501  * you compile malloc newlib with. From what I can tell from the\r
502  * code that is a pagesize of 4096.\r
503  */\r
504 \r
505 unsigned char _heap[HEAPSIZE] __attribute__((aligned (4)));\r
506 //__attribute__((section(".heap")));\r
507 \r
508 void * sbrk( ptrdiff_t incr )\r
509 {\r
510     static unsigned char *heap_end;\r
511     unsigned char *prev_heap_end;\r
512 \r
513 /* initialize */\r
514     if( heap_end == 0 ){\r
515         heap_end = _heap;\r
516     }\r
517     prev_heap_end = heap_end;\r
518 \r
519         if( heap_end + incr - _heap > HEAPSIZE ) {\r
520         /* heap overflow - announce on stderr */\r
521                 write( 2, "Heap overflow!\n", 15 );\r
522                 abort();\r
523         }\r
524 \r
525    heap_end += incr;\r
526 \r
527    return (caddr_t) prev_heap_end;\r
528 }\r
529 #endif\r
530 \r
531 int stat( const char *file, struct stat *st ) {\r
532 //int stat(char *file, struct stat *st) {\r
533         (void)file;\r
534         st->st_mode = S_IFCHR;\r
535         return 0;\r
536 }\r
537 \r
538 \r
539 pid_t getpid() {\r
540   return 1;\r
541 }\r
542 \r
543 #include <errno.h>\r
544 #undef errno\r
545 extern int errno;\r
546 int kill(int pid, int sig){\r
547         (void)pid;\r
548         (void)sig;\r
549         errno=EINVAL;\r
550         return(-1);\r
551 }\r
552 \r
553 \r
554 /* Should not really be here, but .. */\r
555 \r
556 void _fini( void )\r
557 {\r
558 \r
559 }\r
560 \r
561 \r
562 #if defined(__GNUC__)\r
563 void __init( void )\r
564 {\r
565 }\r
566 #endif\r
567 \r
568 #if defined(CFG_ARM)\r
569 void _exit( int status ) {\r
570 #ifdef USE_TTY_CODE_COMPOSER\r
571         __asm("        .global C$$EXIT");\r
572         __asm("C$$EXIT: nop");\r
573 #endif\r
574         while(1) ;\r
575 }\r
576 #endif\r
577 \r