]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_R4F_RZ_T_GCC_IAR_ARM/System/GCC/src/syscalls.c
d4eabd0e8e23404fa5acec0245e862589e952310
[freertos] / FreeRTOS / Demo / CORTEX_R4F_RZ_T_GCC_IAR_ARM / System / GCC / src / syscalls.c
1 /* Support files for GNU libc.  Files in the system namespace go here.
2    Files in the C namespace (ie those that do not start with an
3    underscore) go in .c.  */
4
5 #include <_ansi.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <sys/fcntl.h>
9 #include <stdio.h>
10 #include <time.h>
11 #include <sys/time.h>
12 #include <sys/times.h>
13 #include <errno.h>
14 #include <reent.h>
15 #include <signal.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <sys/wait.h>
19 #include "r_typedefs.h"
20 #include "siochar.h"
21 #include "swi.h"
22
23
24 #ifndef NULL
25 #define NULL (0)
26 #endif
27
28 /* Forward prototypes.  */
29 int     _system     _PARAMS ((const char *));
30 int     _rename     _PARAMS ((const char *, const char *));
31 int     _isatty         _PARAMS ((int));
32 clock_t _times          _PARAMS ((struct tms *));
33 int     _gettimeofday   _PARAMS ((struct timeval *, void *));
34 void    _raise          _PARAMS ((void));
35 int     _unlink         _PARAMS ((const char *));
36 int     _link           _PARAMS ((void));
37 int     _stat           _PARAMS ((const char *, struct stat *));
38 int     _fstat          _PARAMS ((int, struct stat *));
39 caddr_t _sbrk           _PARAMS ((int));
40 int     _getpid         _PARAMS ((int));
41 int     _kill           _PARAMS ((int, int));
42 void    _exit           _PARAMS ((int));
43 int     _close          _PARAMS ((int));
44 int     _swiclose       _PARAMS ((int));
45 int     _open           _PARAMS ((const char *, int, ...));
46 int     _swiopen        _PARAMS ((const char *, int));
47 int     _write          _PARAMS ((int, const char *, unsigned int));
48
49 int     _swiwrite       _PARAMS ((int, char *, int));
50 int     _lseek          _PARAMS ((int, int, int));
51 int     _swilseek       _PARAMS ((int, int, int));
52 int     _read           _PARAMS ((int, char *, unsigned int));
53
54 int     _swiread        _PARAMS ((int, char *, int));
55 void    initialise_monitor_handles _PARAMS ((void));
56
57 static int      wrap            _PARAMS ((int));
58 static int      error           _PARAMS ((int));
59 static int      get_errno       _PARAMS ((void));
60 static int      remap_handle    _PARAMS ((int));
61
62 #ifdef ARM_RDI_MONITOR
63 static int      do_AngelSWI     _PARAMS ((int, void *));
64 #endif
65
66 static int      findslot        _PARAMS ((int));
67
68 /* Register name faking - works in collusion with the linker.  */
69 register char * stack_ptr __asm ("sp");
70
71
72 /* following is copied from libc/stdio/local.h to check std streams */
73 extern void   _EXFUN(__sinit,(struct _reent *));
74 #define CHECK_INIT(ptr) \
75         do                                              \
76             {                                           \
77               if ((ptr) && !(ptr)->__sdidinit)          \
78             __sinit (ptr);                              \
79             }                                           \
80           while (0)
81
82 /* Adjust our internal handles to stay away from std* handles.  */
83 #define FILE_HANDLE_OFFSET (0x20)
84
85 static int monitor_stdin;
86 static int monitor_stdout;
87 static int monitor_stderr;
88
89 /* Struct used to keep track of the file position, just so we
90    can implement fseek(fh,x,SEEK_CUR).  */
91 typedef struct
92 {
93   int handle;
94   int pos;
95 }
96 poslog;
97
98 #define MAX_OPEN_FILES (20)
99 static poslog openfiles [MAX_OPEN_FILES];
100
101 static int
102 findslot (int fh)
103 {
104   int i;
105   for (i = 0; i < MAX_OPEN_FILES; i ++)
106     if (openfiles[i].handle == fh)
107     {
108         break;
109     }
110   return (i);
111 }
112
113 #ifdef ARM_RDI_MONITOR
114
115 static inline int
116 do_AngelSWI (int reason, void * arg)
117 {
118   int value;
119   asm volatile ("mov r0, %1; mov r1, %2; " AngelSWIInsn " %a3; mov %0, r0"
120        : "=r" (value) /* Outputs */
121        : "r" (reason), "r" (arg), "i" (AngelSWI) /* Inputs */
122        : "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc"
123                 /* Clobbers r0 and r1, and lr if in supervisor mode */);
124                 /* Accordingly to page 13-77 of ARM DUI 0040D other registers
125                    can also be clobbered.  Some memory positions may also be
126                    changed by a system call, so they should not be kept in
127                    registers. Note: we are assuming the manual is right and
128                    Angel is respecting the APCS.  */
129   return value;
130 }
131 #endif /* ARM_RDI_MONITOR */
132
133 /* Function to convert std(in|out|err) handles to internal versions.  */
134 static int
135 remap_handle (int fh)
136 {
137     CHECK_INIT(_REENT);
138
139     if (STDIN_FILENO == fh)
140     {
141         return (monitor_stdin);
142     }
143     if (STDOUT_FILENO == fh)
144     {
145         return (monitor_stdout);
146     }
147     if (STDERR_FILENO == fh)
148     {
149         return (monitor_stderr);
150     }
151
152   return (fh - FILE_HANDLE_OFFSET);
153 }
154
155 void
156 initialise_monitor_handles (void)
157 {
158   int i;
159   
160 #ifdef ARM_RDI_MONITOR
161   int volatile block[3];
162   
163   block[0] = (int) ":tt";
164   block[2] = 3;     /* length of filename */
165   block[1] = 0;     /* mode "r" */
166   monitor_stdin = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
167
168   block[0] = (int) ":tt";
169   block[2] = 3;     /* length of filename */
170   block[1] = 4;     /* mode "w" */
171   monitor_stdout = monitor_stderr = do_AngelSWI (AngelSWI_Reason_Open, (void *) block);
172 #else
173   int fh;
174   const char * pname;
175
176   pname = ":tt";
177   __asm ("mov r0,%2; mov r1, #0; swi %a1; mov %0, r0"
178        : "=r"(fh)
179        : "i" (SWI_Open),"r"(pname)
180        : "r0","r1");
181   monitor_stdin = fh;
182
183   pname = ":tt";
184   __asm ("mov r0,%2; mov r1, #4; swi %a1; mov %0, r0"
185        : "=r"(fh)
186        : "i" (SWI_Open),"r"(pname)
187        : "r0","r1");
188   monitor_stdout = (monitor_stderr = fh);
189 #endif
190
191     for (i = 0; i < MAX_OPEN_FILES; i ++)
192     {
193         openfiles[i].handle = (-1);
194     }
195
196     openfiles[0].handle = monitor_stdin;
197     openfiles[0].pos = 0;
198     openfiles[1].handle = monitor_stdout;
199     openfiles[1].pos = 0;
200 }
201
202 static int
203 get_errno (void)
204 {
205 #ifdef ARM_RDI_MONITOR
206   return do_AngelSWI (AngelSWI_Reason_Errno, NULL);
207 #else
208   __asm ("swi %a0" :: "i" (SWI_GetErrno));
209   return (0);
210 #endif
211 }
212
213 static int
214 error (int result)
215 {
216   errno = get_errno ();
217   return (result);
218 }
219
220 static int
221 wrap (int result)
222 {
223     if ((-1) == result)
224     {
225         return (error(-1));
226     }
227     return (result);
228 }
229
230 /* Returns # chars not! written.  */
231 int
232 _swiread (int file,
233           char * ptr,
234           int len)
235 {
236   int fh = remap_handle (file);
237 #ifdef ARM_RDI_MONITOR
238   int block[3];
239   
240   block[0] = fh;
241   block[1] = (int) ptr;
242   block[2] = len;
243   
244   return do_AngelSWI (AngelSWI_Reason_Read, block);
245 #else
246   __asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0"
247        : /* No outputs */
248        : "i"(SWI_Read), "r"(fh), "r"(ptr), "r"(len)
249        : "r0","r1","r2");
250   return (0);
251 #endif
252 }
253
254 /******************************************************************************
255 * Function Name: _read
256 * Description  : GNU interface to low-level I/O read
257 * Arguments    : int file_no
258 *              : const char *buffer
259 *              : unsigned int n
260 * Return Value : none
261 ******************************************************************************/
262 int _read(int file_no , char *buffer , unsigned int n)
263 {
264     return (sio_read(file_no , buffer , n));
265 }
266
267 int
268 _swilseek (int file,
269            int ptr,
270            int dir)
271 {
272   int res;
273   int fh = remap_handle (file);
274   int slot = findslot (fh);
275 #ifdef ARM_RDI_MONITOR
276   int block[2];
277 #endif
278
279   if (SEEK_CUR == dir)
280     {
281         if (MAX_OPEN_FILES == slot)
282         {
283             return (-1);
284         }
285         ptr = (openfiles[slot].pos + ptr);
286         dir = SEEK_SET;
287     }
288   
289 #ifdef ARM_RDI_MONITOR
290   if (dir == SEEK_END)
291     {
292       block[0] = fh;
293       ptr += do_AngelSWI (AngelSWI_Reason_FLen, block);
294     }
295   
296   /* This code only does absolute seeks.  */
297   block[0] = remap_handle (file);
298   block[1] = ptr;
299   res = do_AngelSWI (AngelSWI_Reason_Seek, block);
300 #else
301   if (SEEK_END == dir)
302     {
303       __asm ("mov r0, %2; swi %a1; mov %0, r0"
304            : "=r" (res)
305            : "i" (SWI_Flen), "r" (fh)
306            : "r0");
307       ptr += res;
308     }
309
310   /* This code only does absolute seeks.  */
311   __asm ("mov r0, %2; mov r1, %3; swi %a1; mov %0, r0"
312        : "=r" (res)
313        : "i" (SWI_Seek), "r" (fh), "r" (ptr)
314        : "r0", "r1");
315 #endif
316
317     if ((MAX_OPEN_FILES != slot) && (0 == res))
318     {
319         openfiles[slot].pos = ptr;
320     }
321
322   /* This is expected to return the position in the file.  */
323     return ((0 == res) ? ptr : (-1));
324 }
325
326 int
327 _lseek (int file,
328         int ptr,
329         int dir)
330 {
331   return (wrap (_swilseek (file, ptr, dir)));
332 }
333
334 /* Returns #chars not! written.  */
335 int
336 _swiwrite (
337            int    file,
338            char * ptr,
339            int    len)
340 {
341   int fh = remap_handle (file);
342 #ifdef ARM_RDI_MONITOR
343   int block[3];
344   
345   block[0] = fh;
346   block[1] = (int) ptr;
347   block[2] = len;
348   
349   return do_AngelSWI (AngelSWI_Reason_Write, block);
350 #else
351   __asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0"
352        : /* No outputs */
353        : "i"(SWI_Write), "r"(fh), "r"(ptr), "r"(len)
354        : "r0","r1","r2");
355   return (0);
356 #endif
357 }
358
359 /******************************************************************************
360 * Function Name: _write
361 * Description  : GNU interface to low-level I/O write
362 * Arguments    : int file_no
363 *              : const char *buffer
364 *              : unsigned int n
365 * Return Value : none
366 ******************************************************************************/
367 int _write(int file_no , const char *buffer , unsigned int n)
368 {
369     return (sio_write(file_no , buffer , n));
370 }
371
372 int
373 _swiopen (const char * path,
374           int          flags)
375 {
376   int aflags = 0, fh;
377 #ifdef ARM_RDI_MONITOR
378   int block[3];
379 #endif
380   
381   int i = findslot (-1);
382   
383   if (MAX_OPEN_FILES == i)
384     {
385         return (-1);
386     }
387
388   /* The flags are Unix-style, so we need to convert them.  */
389 #ifdef O_BINARY
390   if (flags & O_BINARY)
391     {
392         aflags |= 1;
393     }
394 #endif
395
396   if (flags & O_RDWR)
397     {
398         aflags |= 2;
399     }
400
401   if (flags & O_CREAT)
402     {
403         aflags |= 4;
404     }
405
406   if (flags & O_TRUNC)
407     {
408         aflags |= 4;
409     }
410
411   if (flags & O_APPEND)
412     {
413       aflags &= (~4);     /* Can't ask for w AND a; means just 'a'.  */
414       aflags |= 8;
415     }
416   
417 #ifdef ARM_RDI_MONITOR
418   block[0] = (int) path;
419   block[2] = strlen (path);
420   block[1] = aflags;
421   
422   fh = do_AngelSWI (AngelSWI_Reason_Open, block);
423   
424 #else
425   __asm ("mov r0,%2; mov r1, %3; swi %a1; mov %0, r0"
426        : "=r"(fh)
427        : "i" (SWI_Open),"r"(path),"r"(aflags)
428        : "r0","r1");
429 #endif
430   
431   if (fh >= 0)
432     {
433       openfiles[i].handle = fh;
434       openfiles[i].pos = 0;
435     }
436
437   return ((fh >= 0) ? (fh + FILE_HANDLE_OFFSET) : error (fh));
438 }
439
440 int
441 _open (const char * path,
442        int          flags,
443        ...)
444 {
445   return (wrap (_swiopen (path, flags)));
446 }
447
448 int
449 _swiclose (int file)
450 {
451   int myhan = remap_handle (file);
452   int slot = findslot (myhan);
453   
454   if (MAX_OPEN_FILES != slot)
455     {
456         openfiles[slot].handle = (-1);
457     }
458
459 #ifdef ARM_RDI_MONITOR
460   return do_AngelSWI (AngelSWI_Reason_Close, & myhan);
461 #else
462   __asm ("mov r0, %1; swi %a0" :: "i" (SWI_Close),"r"(myhan):"r0");
463   return (0);
464 #endif
465 }
466
467 int
468 _close (int file)
469 {
470   return (wrap (_swiclose (file)));
471 }
472
473 int
474 _kill (int pid, int sig)
475 {
476   (void)pid; (void)sig;
477 #ifdef ARM_RDI_MONITOR
478   /* Note: The pid argument is thrown away.  */
479   switch (sig) {
480           case SIGABRT:
481                   return do_AngelSWI (AngelSWI_Reason_ReportException,
482                                   (void *) ADP_Stopped_RunTimeError);
483           default:
484                   return do_AngelSWI (AngelSWI_Reason_ReportException,
485                                   (void *) ADP_Stopped_ApplicationExit);
486   }
487 #else
488   __asm ("swi %a0" :: "i" (SWI_Exit));
489   return (0);
490 #endif
491 }
492
493 void
494 _exit (int status)
495 {
496   /* There is only one SWI for both _exit and _kill. For _exit, call
497      the SWI with the second argument set to -1, an invalid value for
498      signum, so that the SWI handler can distinguish the two calls.
499      Note: The RDI implementation of _kill throws away both its
500      arguments.  */
501   _kill(status, -1);
502   while(1)\r
503   {\r
504       /* exit occurred */\r
505   };
506 }
507
508 int
509 _getpid (int n)
510 {
511   (void)(n);
512   return (1);
513 }
514
515 caddr_t
516 _sbrk (int incr)
517 {
518   extern char   end __asm ("end");      /* Defined by the linker.  */
519   static char * pheap_end;
520   char *        prev_heap_end;
521
522     if (NULL == pheap_end)
523     {
524         pheap_end = (&end);
525     }
526   
527   prev_heap_end = pheap_end;
528   
529   if ((pheap_end + incr) > stack_ptr)
530     {
531       /* Some of the libstdc++-v3 tests rely upon detecting
532          out of memory errors, so do not abort here.  */
533 #if 0
534       extern void abort (void);
535
536       _write (1, "_sbrk: Heap and stack collision\n", 32);
537       
538       abort ();
539 #else
540       errno = ENOMEM;
541       return ((caddr_t) (-1));
542 #endif
543     }
544   
545   pheap_end += incr;
546
547   return ((caddr_t) prev_heap_end);
548 }
549
550 int
551 _fstat (int file, struct stat * st)
552 {
553   (void)file;
554   memset (st, 0, sizeof (* st));
555   st->st_mode = S_IFCHR;
556   st->st_blksize = 1024;
557   return (0);
558 }
559
560 int _stat (const char *fname, struct stat *st)
561 {
562   int file;
563
564   /* The best we can do is try to open the file read-only.  If it exists,
565      then we can guess a few things about it.  */
566   if ((file = _open (fname, O_RDONLY)) < 0)
567     {
568         return (-1);
569     }
570
571   memset (st, 0, sizeof (* st));
572   st->st_mode = (S_IFREG | S_IREAD);
573   st->st_blksize = 1024;
574   _swiclose (file); /* Not interested in the error.  */
575   return (0);
576 }
577
578 int
579 _link (void)
580 {
581   return (-1);
582 }
583
584 int
585 _unlink (const char *path)
586 {
587 #ifdef ARM_RDI_MONITOR
588   int block[2];
589   block[0] = path;
590   block[1] = strlen(path);
591   return wrap (do_AngelSWI (AngelSWI_Reason_Remove, block)) ? -1 : 0;
592 #else  
593   return -1;
594 #endif
595 }
596
597 void
598 _raise (void)
599 {
600   return;
601 }
602
603 int
604 _gettimeofday (struct timeval * tp, void * tzvp)
605 {
606   struct timezone * ptzp = tzvp;
607   if (tp)
608     {
609     /* Ask the host for the seconds since the Unix epoch.  */
610 #ifdef ARM_RDI_MONITOR
611       tp->tv_sec = do_AngelSWI (AngelSWI_Reason_Time,NULL);
612 #else
613       {
614         int value;
615         __asm ("swi %a1; mov %0, r0" : "=r" (value): "i" (SWI_Time) : "r0");
616         tp->tv_sec = value;
617       }
618 #endif
619       tp->tv_usec = 0;
620     }
621
622   /* Return fixed data for the time-zone.  */
623   if (ptzp)
624     {
625       ptzp->tz_minuteswest = 0;
626       ptzp->tz_dsttime = 0;
627     }
628
629   return (0);
630 }
631
632 /* Return a clock that ticks at 100Hz.  */
633 clock_t 
634 _times (struct tms * tp)
635 {
636   clock_t timeval;
637
638 #ifdef ARM_RDI_MONITOR
639   timeval = do_AngelSWI (AngelSWI_Reason_Clock,NULL);
640 #else
641   __asm ("swi %a1; mov %0, r0" : "=r" (timeval): "i" (SWI_Clock) : "r0");
642 #endif
643
644   if (tp)
645     {
646       tp->tms_utime  = timeval; /* user time */
647       tp->tms_stime  = 0;       /* system time */
648       tp->tms_cutime = 0;       /* user time, children */
649       tp->tms_cstime = 0;       /* system time, children */
650     }
651   
652   return (timeval);
653 };
654
655
656 int
657 _isatty (int fd)
658 {
659 #ifdef ARM_RDI_MONITOR
660   int fh = remap_handle (fd);
661   return wrap (do_AngelSWI (AngelSWI_Reason_IsTTY, &fh));
662 #else
663   return ((fd <= 2) ? 1 : 0);  /* one of stdin, stdout, stderr */
664 #endif
665 }
666
667 int
668 _system (const char *s)
669 {
670 #ifdef ARM_RDI_MONITOR
671   int block[2];
672   int e;
673
674   /* Hmmm.  The ARM debug interface specification doesn't say whether
675      SYS_SYSTEM does the right thing with a null argument, or assign any
676      meaning to its return value.  Try to do something reasonable....  */
677   if (!s)
678     return 1;  /* maybe there is a shell available? we can hope. :-P */
679   block[0] = s;
680   block[1] = strlen (s);
681   e = wrap (do_AngelSWI (AngelSWI_Reason_System, block));
682   if ((e >= 0) && (e < 256))
683     {
684       /* We have to convert e, an exit status to the encoded status of
685          the command.  To avoid hard coding the exit status, we simply
686          loop until we find the right position.  */
687       int exit_code;
688
689       for (exit_code = e; e && WEXITSTATUS (e) != exit_code; e <<= 1)
690         continue;
691     }
692   return e;
693 #else
694   if (NULL == s)
695     {
696         return (0);
697     }
698   errno = ENOSYS;
699   return (-1);
700 #endif
701 }
702
703 int
704 _rename (const char * oldpath, const char * newpath)
705 {
706 #ifdef ARM_RDI_MONITOR
707   int block[4];
708   block[0] = oldpath;
709   block[1] = strlen(oldpath);
710   block[2] = newpath;
711   block[3] = strlen(newpath);
712   return wrap (do_AngelSWI (AngelSWI_Reason_Rename, block)) ? -1 : 0;
713 #else  
714   errno = ENOSYS;
715   return (-1);
716 #endif
717 }