1 | #include <errno.h>
|
2 | #include <sys/stat.h>
|
3 | #include <sys/times.h>
|
4 | #include <sys/unistd.h>
|
5 | #include <stdint.h>
|
6 |
|
7 | #include <stm32f4xx_usart.h>
|
8 |
|
9 | #ifndef UNUSED
|
10 | #define UNUSED(x) (void)x
|
11 | #endif
|
12 |
|
13 | #ifndef STDOUT_USART
|
14 | #define STDOUT_USART 1
|
15 | #endif
|
16 |
|
17 | #ifndef STDERR_USART
|
18 | #define STDERR_USART 2
|
19 | #endif
|
20 |
|
21 | #ifndef STDIN_USART
|
22 | #define STDIN_USART 1
|
23 | #endif
|
24 |
|
25 | #undef errno
|
26 | extern int errno;
|
27 |
|
28 | /*
|
29 | * A pointer to a list of environment variables and their values.
|
30 | * For a minimal environment, this empty list is adequate.
|
31 | */
|
32 | char *__env[1] = { 0 };
|
33 | char **environ = __env;
|
34 |
|
35 | int _write(int file, char *ptr, int len);
|
36 |
|
37 | void _exit(int status) {
|
38 | UNUSED(status);
|
39 |
|
40 | _write(1, "exit", 4);
|
41 | while (1) {
|
42 | ;
|
43 | }
|
44 | }
|
45 |
|
46 | int _close(int file) {
|
47 | UNUSED(file);
|
48 |
|
49 | return -1;
|
50 | }
|
51 |
|
52 | /*
|
53 | * Transfer control to a new process. Minimal implementation (for a system
|
54 | * without processes)
|
55 | */
|
56 | int _execve(char *name, char **argv, char **env) {
|
57 | UNUSED(name);
|
58 | UNUSED(argv);
|
59 | UNUSED(env);
|
60 |
|
61 | errno = ENOMEM;
|
62 | return -1;
|
63 | }
|
64 |
|
65 | /*
|
66 | * Create a new process. Minimal implementation (for a system without processes)
|
67 | */
|
68 | int _fork() {
|
69 | errno = EAGAIN;
|
70 | return -1;
|
71 | }
|
72 | /*
|
73 | * Status of an open file. Minimal implementation.
|
74 | */
|
75 | int _fstat(int file, struct stat *st) {
|
76 | UNUSED(file);
|
77 |
|
78 | st->st_mode = S_IFCHR;
|
79 | return 0;
|
80 | }
|
81 |
|
82 | /*
|
83 | * Process-ID; this is sometimes used to generate strings unlikely to conflict
|
84 | * with other processes. Minimal implementation, for a system without processes.
|
85 | */
|
86 | int _getpid() {
|
87 | return 1;
|
88 | }
|
89 |
|
90 | /*
|
91 | * Query whether output stream is a terminal. For consistency with the other
|
92 | * minimal implementation.
|
93 | */
|
94 | int _isatty(int file) {
|
95 | UNUSED(file);
|
96 |
|
97 | switch (file) {
|
98 | case STDOUT_FILENO:
|
99 | case STDERR_FILENO:
|
100 | case STDIN_FILENO:
|
101 | return 1;
|
102 | default:
|
103 | //errno = ENOTTY;
|
104 | errno = EBADF;
|
105 | return 0;
|
106 | }
|
107 | }
|
108 |
|
109 | /*
|
110 | * Send a signal. Minimal implementation.
|
111 | */
|
112 | int _kill(int pid, int sig) {
|
113 | UNUSED(pid);
|
114 | UNUSED(sig);
|
115 |
|
116 | errno = EINVAL;
|
117 | return (-1);
|
118 | }
|
119 |
|
120 | /*
|
121 | * Establish a new name for an existing file. Minimal implementation.
|
122 | */
|
123 | int _link(char *old, char *new) {
|
124 | UNUSED(old);
|
125 | UNUSED(new);
|
126 |
|
127 | errno = EMLINK;
|
128 | return -1;
|
129 | }
|
130 |
|
131 | /*
|
132 | * Set position in a file. Minimal implementation.
|
133 | */
|
134 | int _lseek(int file, int ptr, int dir) {
|
135 | UNUSED(file);
|
136 | UNUSED(ptr);
|
137 | UNUSED(dir);
|
138 |
|
139 | return 0;
|
140 | }
|
141 |
|
142 | /*
|
143 | * Increase program data space. Malloc and related functions depend on this.
|
144 | */
|
145 | caddr_t _sbrk(int incr) {
|
146 |
|
147 | extern char _ebss; // Defined by the linker
|
148 | static char *heap_end;
|
149 | char *prev_heap_end;
|
150 |
|
151 | if (heap_end == 0) {
|
152 | heap_end = &_ebss;
|
153 | }
|
154 | prev_heap_end = heap_end;
|
155 |
|
156 | /** FIX **/
|
157 | char * stack = (char*) __get_MSP();
|
158 | if (heap_end + incr > stack){
|
159 | _write (STDERR_FILENO, "Heap and stack collision\n", 25);
|
160 | errno = ENOMEM;
|
161 | return (caddr_t) - 1;
|
162 | //abort ();
|
163 | }
|
164 |
|
165 | heap_end += incr;
|
166 | return (caddr_t) prev_heap_end;
|
167 |
|
168 | }
|
169 |
|
170 | /*
|
171 | * Read a character to a file. `libc' subroutines will use this system routine
|
172 | * for input from all files, including stdin.
|
173 | * Returns -1 on error or blocks until the number of characters have been read.
|
174 | */
|
175 | int _read(int file, char *ptr, int len) {
|
176 | int n;
|
177 | int num = 0;
|
178 | switch (file) {
|
179 | case STDIN_FILENO:
|
180 | for (n = 0; n < len; n++) {
|
181 | #if STDIN_USART == 1
|
182 | while ((USART1->SR & USART_FLAG_RXNE) == (uint16_t)RESET) {}
|
183 | char c = (char)(USART1->DR & (uint16_t)0x01FF);
|
184 | #elif STDIN_USART == 2
|
185 | // while ((USART2->ISR & USART_FLAG_RXNE) == (uint16_t) RESET) {}
|
186 | // char c = (char) (USART2->TDR & (uint16_t) 0x01FF);
|
187 | #elif STDIN_USART == 3
|
188 | // while ((USART3->ISR & USART_FLAG_RXNE) == (uint16_t)RESET) {}
|
189 | // char c = (char)(USART3->TDR & (uint16_t)0x01FF);
|
190 | #endif
|
191 | *ptr++ = c;
|
192 | num++;
|
193 | }
|
194 | break;
|
195 | default:
|
196 | errno = EBADF;
|
197 | return -1;
|
198 | }
|
199 | return num;
|
200 | }
|
201 |
|
202 | /*
|
203 | * Status of a file (by name). Minimal implementation.
|
204 | * int _EXFUN(stat,( const char *__path, struct stat *__sbuf ));
|
205 | */
|
206 | int _stat(const char *filepath, struct stat *st) {
|
207 | UNUSED(filepath);
|
208 |
|
209 | st->st_mode = S_IFCHR;
|
210 | return 0;
|
211 | }
|
212 |
|
213 | /*
|
214 | * Timing information for current process. Minimal implementation.
|
215 | */
|
216 | clock_t _times(struct tms *buf) {
|
217 | UNUSED(buf);
|
218 |
|
219 | return -1;
|
220 | }
|
221 |
|
222 | /*
|
223 | * Remove a file's directory entry. Minimal implementation.
|
224 | */
|
225 | int _unlink(char *name) {
|
226 | UNUSED(name);
|
227 |
|
228 | errno = ENOENT;
|
229 | return -1;
|
230 | }
|
231 |
|
232 | /*
|
233 | * Wait for a child process. Minimal implementation.
|
234 | */
|
235 | int _wait(int *status) {
|
236 | UNUSED(status);
|
237 |
|
238 | errno = ECHILD;
|
239 | return -1;
|
240 | }
|
241 |
|
242 | /*
|
243 | * Write a character to a file. `libc' subroutines will use this system routine
|
244 | * for output to all files, including stdout.
|
245 | * Returns -1 on error or number of bytes sent.
|
246 | */
|
247 | int _write(int file, char *ptr, int len) {
|
248 | int n;
|
249 |
|
250 | switch (file) {
|
251 | case STDOUT_FILENO: /*stdout*/
|
252 | for (n = 0; n < len; n++) {
|
253 | while ((USART1->SR & USART_FLAG_TXE) == (uint16_t)RESET) {
|
254 | //USART1->DR = (*ptr++ & (uint16_t)0x01FF);
|
255 | }
|
256 | USART1->DR = (*ptr++ & (uint16_t)0x01FF);
|
257 | }
|
258 | break;
|
259 | case STDERR_FILENO: /* stderr */
|
260 | for (n = 0; n < len; n++) {
|
261 |
|
262 | }
|
263 | break;
|
264 | default:
|
265 | errno = EBADF;
|
266 | return -1;
|
267 | }
|
268 | return len;
|
269 | }
|