PokittoLib is the library needed for programming the Pokitto DIY game console (www.pokitto.com)
Dependents: YATTT sd_map_test cPong SnowDemo ... more
retarget.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "platform.h" 00017 #include "FileHandle.h" 00018 #include "FileSystemLike.h" 00019 #include "FilePath.h" 00020 #include "serial_api.h" 00021 #include "toolchain.h" 00022 #include "semihost_api.h" 00023 #include "mbed_interface.h" 00024 #if DEVICE_STDIO_MESSAGES 00025 #include <stdio.h> 00026 #endif 00027 #include <errno.h> 00028 00029 #if defined(__ARMCC_VERSION) 00030 # include <rt_sys.h> 00031 # define PREFIX(x) _sys##x 00032 # define OPEN_MAX _SYS_OPEN 00033 # ifdef __MICROLIB 00034 //# pragma import(__use_full_stdio) 00035 __asm(".global __use_full_stdio"); 00036 # endif 00037 00038 #elif defined(__ICCARM__) 00039 # include <yfuns.h> 00040 # define PREFIX(x) _##x 00041 # define OPEN_MAX 16 00042 00043 # define STDIN_FILENO 0 00044 # define STDOUT_FILENO 1 00045 # define STDERR_FILENO 2 00046 00047 #else 00048 # include <sys/stat.h> 00049 # include <sys/unistd.h> 00050 # include <sys/syslimits.h> 00051 # define PREFIX(x) x 00052 #endif 00053 00054 using namespace mbed; 00055 00056 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000) 00057 // Before version 5.03, we were using a patched version of microlib with proper names 00058 extern const char __stdin_name[] = ":tt"; 00059 extern const char __stdout_name[] = ":tt"; 00060 extern const char __stderr_name[] = ":tt"; 00061 00062 #else 00063 extern const char __stdin_name[] = "/stdin"; 00064 extern const char __stdout_name[] = "/stdout"; 00065 extern const char __stderr_name[] = "/stderr"; 00066 #endif 00067 00068 /* newlib has the filehandle field in the FILE struct as a short, so 00069 * we can't just return a Filehandle* from _open and instead have to 00070 * put it in a filehandles array and return the index into that array 00071 * (or rather index+3, as filehandles 0-2 are stdin/out/err). 00072 */ 00073 static FileHandle *filehandles[OPEN_MAX]; 00074 00075 FileHandle::~FileHandle() { 00076 /* Remove all open filehandles for this */ 00077 for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00078 if (filehandles[fh_i] == this) { 00079 filehandles[fh_i] = NULL; 00080 } 00081 } 00082 } 00083 00084 #if DEVICE_SERIAL 00085 extern int stdio_uart_inited; 00086 extern serial_t stdio_uart; 00087 #endif 00088 00089 static void init_serial() { 00090 #if DEVICE_SERIAL 00091 if (stdio_uart_inited) return; 00092 serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX); 00093 #endif 00094 } 00095 00096 static inline int openmode_to_posix(int openmode) { 00097 int posix = openmode; 00098 #ifdef __ARMCC_VERSION 00099 if (openmode & OPEN_PLUS) { 00100 posix = O_RDWR; 00101 } else if(openmode & OPEN_W) { 00102 posix = O_WRONLY; 00103 } else if(openmode & OPEN_A) { 00104 posix = O_WRONLY|O_APPEND; 00105 } else { 00106 posix = O_RDONLY; 00107 } 00108 /* a, w, a+, w+ all create if file does not already exist */ 00109 if (openmode & (OPEN_A|OPEN_W)) { 00110 posix |= O_CREAT; 00111 } 00112 /* w and w+ truncate */ 00113 if (openmode & OPEN_W) { 00114 posix |= O_TRUNC; 00115 } 00116 #elif defined(__ICCARM__) 00117 switch (openmode & _LLIO_RDWRMASK) { 00118 case _LLIO_RDONLY: posix = O_RDONLY; break; 00119 case _LLIO_WRONLY: posix = O_WRONLY; break; 00120 case _LLIO_RDWR : posix = O_RDWR ; break; 00121 } 00122 if (openmode & _LLIO_CREAT ) posix |= O_CREAT; 00123 if (openmode & _LLIO_APPEND) posix |= O_APPEND; 00124 if (openmode & _LLIO_TRUNC ) posix |= O_TRUNC; 00125 #endif 00126 return posix; 00127 } 00128 00129 extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) { 00130 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000) 00131 // Before version 5.03, we were using a patched version of microlib with proper names 00132 // This is the workaround that the microlib author suggested us 00133 static int n = 0; 00134 if (!std::strcmp(name, ":tt")) return n++; 00135 00136 #else 00137 /* Use the posix convention that stdin,out,err are filehandles 0,1,2. 00138 */ 00139 if (std::strcmp(name, __stdin_name) == 0) { 00140 init_serial(); 00141 return 0; 00142 } else if (std::strcmp(name, __stdout_name) == 0) { 00143 init_serial(); 00144 return 1; 00145 } else if (std::strcmp(name, __stderr_name) == 0) { 00146 init_serial(); 00147 return 2; 00148 } 00149 #endif 00150 00151 // find the first empty slot in filehandles 00152 unsigned int fh_i; 00153 for (fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00154 if (filehandles[fh_i] == NULL) break; 00155 } 00156 if (fh_i >= sizeof(filehandles)/sizeof(*filehandles)) { 00157 return -1; 00158 } 00159 00160 FileHandle *res; 00161 00162 /* FILENAME: ":0x12345678" describes a FileLike* */ 00163 if (name[0] == ':') { 00164 void *p; 00165 sscanf(name, ":%p", &p); 00166 res = (FileHandle*)p; 00167 00168 /* FILENAME: "/file_system/file_name" */ 00169 } else { 00170 FilePath path(name); 00171 00172 if (!path.exists()) 00173 return -1; 00174 else if (path.isFile()) { 00175 res = path.file(); 00176 } else { 00177 FileSystemLike *fs = path.fileSystem(); 00178 if (fs == NULL) return -1; 00179 int posix_mode = openmode_to_posix(openmode); 00180 res = fs->open(path.fileName(), posix_mode); /* NULL if fails */ 00181 } 00182 } 00183 00184 if (res == NULL) return -1; 00185 filehandles[fh_i] = res; 00186 00187 return fh_i + 3; // +3 as filehandles 0-2 are stdin/out/err 00188 } 00189 00190 extern "C" int PREFIX(_close)(FILEHANDLE fh) { 00191 if (fh < 3) return 0; 00192 00193 FileHandle* fhc = filehandles[fh-3]; 00194 filehandles[fh-3] = NULL; 00195 if (fhc == NULL) return -1; 00196 00197 return fhc->close(); 00198 } 00199 00200 #if defined(__ICCARM__) 00201 extern "C" size_t __write (int fh, const unsigned char *buffer, size_t length) { 00202 #else 00203 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode) { 00204 #endif 00205 int n; // n is the number of bytes written 00206 if (fh < 3) { 00207 #if DEVICE_SERIAL 00208 if (!stdio_uart_inited) init_serial(); 00209 for (unsigned int i = 0; i < length; i++) { 00210 serial_putc(&stdio_uart, buffer[i]); 00211 } 00212 #endif 00213 n = length; 00214 } else { 00215 FileHandle* fhc = filehandles[fh-3]; 00216 if (fhc == NULL) return -1; 00217 00218 n = fhc->write(buffer, length); 00219 } 00220 #ifdef __ARMCC_VERSION 00221 return length-n; 00222 #else 00223 return n; 00224 #endif 00225 } 00226 00227 #if defined(__ICCARM__) 00228 extern "C" size_t __read (int fh, unsigned char *buffer, size_t length) { 00229 #else 00230 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode) { 00231 #endif 00232 int n; // n is the number of bytes read 00233 if (fh < 3) { 00234 // only read a character at a time from stdin 00235 #if DEVICE_SERIAL 00236 if (!stdio_uart_inited) init_serial(); 00237 *buffer = serial_getc(&stdio_uart); 00238 #endif 00239 n = 1; 00240 } else { 00241 FileHandle* fhc = filehandles[fh-3]; 00242 if (fhc == NULL) return -1; 00243 00244 n = fhc->read(buffer, length); 00245 } 00246 #ifdef __ARMCC_VERSION 00247 return length-n; 00248 #else 00249 return n; 00250 #endif 00251 } 00252 00253 #ifdef __ARMCC_VERSION 00254 extern "C" int PREFIX(_istty)(FILEHANDLE fh) 00255 #else 00256 extern "C" int _isatty(FILEHANDLE fh) 00257 #endif 00258 { 00259 /* stdin, stdout and stderr should be tty */ 00260 if (fh < 3) return 1; 00261 00262 FileHandle* fhc = filehandles[fh-3]; 00263 if (fhc == NULL) return -1; 00264 00265 return fhc->isatty(); 00266 } 00267 00268 extern "C" 00269 #if defined(__ARMCC_VERSION) 00270 int _sys_seek(FILEHANDLE fh, long position) 00271 #elif defined(__ICCARM__) 00272 long __lseek(int fh, long offset, int whence) 00273 #else 00274 int _lseek(FILEHANDLE fh, int offset, int whence) 00275 #endif 00276 { 00277 if (fh < 3) return 0; 00278 00279 FileHandle* fhc = filehandles[fh-3]; 00280 if (fhc == NULL) return -1; 00281 00282 #if defined(__ARMCC_VERSION) 00283 return fhc->lseek(position, SEEK_SET); 00284 #else 00285 return fhc->lseek(offset, whence); 00286 #endif 00287 } 00288 00289 #ifdef __ARMCC_VERSION 00290 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) { 00291 if (fh < 3) return 0; 00292 00293 FileHandle* fhc = filehandles[fh-3]; 00294 if (fhc == NULL) return -1; 00295 00296 return fhc->fsync(); 00297 } 00298 00299 extern "C" long PREFIX(_flen)(FILEHANDLE fh) { 00300 if (fh < 3) return 0; 00301 00302 FileHandle* fhc = filehandles[fh-3]; 00303 if (fhc == NULL) return -1; 00304 00305 return fhc->flen(); 00306 } 00307 #endif 00308 00309 00310 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__) 00311 extern "C" int _fstat(int fd, struct stat *st) { 00312 if ((STDOUT_FILENO == fd) || (STDERR_FILENO == fd) || (STDIN_FILENO == fd)) { 00313 st->st_mode = S_IFCHR; 00314 return 0; 00315 } 00316 00317 errno = EBADF; 00318 return -1; 00319 } 00320 #endif 00321 00322 namespace std { 00323 extern "C" int remove(const char *path) { 00324 FilePath fp(path); 00325 FileSystemLike *fs = fp.fileSystem(); 00326 if (fs == NULL) return -1; 00327 00328 return fs->remove(fp.fileName()); 00329 } 00330 00331 extern "C" int rename(const char *oldname, const char *newname) { 00332 FilePath fpOld(oldname); 00333 FilePath fpNew(newname); 00334 FileSystemLike *fsOld = fpOld.fileSystem(); 00335 FileSystemLike *fsNew = fpNew.fileSystem(); 00336 00337 /* rename only if both files are on the same FS */ 00338 if (fsOld != fsNew || fsOld == NULL) return -1; 00339 00340 return fsOld->rename(fpOld.fileName(), fpNew.fileName()); 00341 } 00342 00343 extern "C" char *tmpnam(char *s) { 00344 return NULL; 00345 } 00346 00347 extern "C" FILE *tmpfile() { 00348 return NULL; 00349 } 00350 } // namespace std 00351 00352 #ifdef __ARMCC_VERSION 00353 extern "C" char *_sys_command_string(char *cmd, int len) { 00354 return NULL; 00355 } 00356 #endif 00357 00358 extern "C" DIR *opendir(const char *path) { 00359 /* root dir is FileSystemLike */ 00360 if (path[0] == '/' && path[1] == 0) { 00361 return FileSystemLike::opendir(); 00362 } 00363 00364 FilePath fp(path); 00365 FileSystemLike* fs = fp.fileSystem(); 00366 if (fs == NULL) return NULL; 00367 00368 return fs->opendir(fp.fileName()); 00369 } 00370 00371 extern "C" struct dirent *readdir(DIR *dir) { 00372 return dir->readdir(); 00373 } 00374 00375 extern "C" int closedir(DIR *dir) { 00376 return dir->closedir(); 00377 } 00378 00379 extern "C" void rewinddir(DIR *dir) { 00380 dir->rewinddir(); 00381 } 00382 00383 extern "C" off_t telldir(DIR *dir) { 00384 return dir->telldir(); 00385 } 00386 00387 extern "C" void seekdir(DIR *dir, off_t off) { 00388 dir->seekdir(off); 00389 } 00390 00391 extern "C" int mkdir(const char *path, mode_t mode) { 00392 FilePath fp(path); 00393 FileSystemLike *fs = fp.fileSystem(); 00394 if (fs == NULL) return -1; 00395 00396 return fs->mkdir(fp.fileName(), mode); 00397 } 00398 00399 #if defined(TOOLCHAIN_GCC) 00400 /* prevents the exception handling name demangling code getting pulled in */ 00401 #include "mbed_error.h" 00402 namespace __gnu_cxx { 00403 void __verbose_terminate_handler() { 00404 error("Exception"); 00405 } 00406 } 00407 extern "C" WEAK void __cxa_pure_virtual(void); 00408 extern "C" WEAK void __cxa_pure_virtual(void) { 00409 exit(1); 00410 } 00411 00412 #endif 00413 00414 // **************************************************************************** 00415 // mbed_main is a function that is called before main() 00416 // mbed_sdk_init() is also a function that is called before main(), but unlike 00417 // mbed_main(), it is not meant for user code, but for the SDK itself to perform 00418 // initializations before main() is called. 00419 00420 extern "C" WEAK void mbed_main(void); 00421 extern "C" WEAK void mbed_main(void) { 00422 } 00423 00424 extern "C" WEAK void mbed_sdk_init(void); 00425 extern "C" WEAK void mbed_sdk_init(void) { 00426 } 00427 00428 #if defined(TOOLCHAIN_ARM) 00429 extern "C" int $Super$$main(void); 00430 00431 extern "C" int $Sub$$main(void) { 00432 mbed_sdk_init(); 00433 mbed_main(); 00434 return $Super$$main(); 00435 } 00436 #elif defined(TOOLCHAIN_GCC) 00437 extern "C" int __real_main(void); 00438 00439 extern "C" int __wrap_main(void) { 00440 mbed_sdk_init(); 00441 mbed_main(); 00442 return __real_main(); 00443 } 00444 #elif defined(TOOLCHAIN_IAR) 00445 // IAR doesn't have the $Super/$Sub mechanism of armcc, nor something equivalent 00446 // to ld's --wrap. It does have a --redirect, but that doesn't help, since redirecting 00447 // 'main' to another symbol looses the original 'main' symbol. However, its startup 00448 // code will call a function to setup argc and argv (__iar_argc_argv) if it is defined. 00449 // Since mbed doesn't use argc/argv, we use this function to call our mbed_main. 00450 extern "C" void __iar_argc_argv() { 00451 mbed_sdk_init(); 00452 mbed_main(); 00453 } 00454 #endif 00455 00456 // Provide implementation of _sbrk (low-level dynamic memory allocation 00457 // routine) for GCC_ARM which compares new heap pointer with MSP instead of 00458 // SP. This make it compatible with RTX RTOS thread stacks. 00459 #if defined(TOOLCHAIN_GCC_ARM) 00460 // Linker defined symbol used by _sbrk to indicate where heap should start. 00461 extern "C" int __end__; 00462 00463 #if defined(TARGET_CORTEX_A) 00464 extern "C" uint32_t __HeapLimit; 00465 #endif 00466 00467 // Turn off the errno macro and use actual global variable instead. 00468 #undef errno 00469 extern "C" int errno; 00470 00471 // For ARM7 only 00472 register unsigned char * stack_ptr __asm ("sp"); 00473 00474 // Dynamic memory allocation related syscall. 00475 extern "C" caddr_t _sbrk(int incr) { 00476 static unsigned char* heap = (unsigned char*)&__end__; 00477 unsigned char* prev_heap = heap; 00478 unsigned char* new_heap = heap + incr; 00479 00480 #if defined(TARGET_ARM7) 00481 if (new_heap >= stack_ptr) { 00482 #elif defined(TARGET_CORTEX_A) 00483 if (new_heap >= (unsigned char*)&__HeapLimit) { /* __HeapLimit is end of heap section */ 00484 #else 00485 if (new_heap >= (unsigned char*)__get_MSP()) { 00486 #endif 00487 errno = ENOMEM; 00488 return (caddr_t)-1; 00489 } 00490 00491 heap = new_heap; 00492 return (caddr_t) prev_heap; 00493 } 00494 #endif 00495 00496 00497 #ifdef TOOLCHAIN_GCC_CW 00498 // TODO: Ideally, we would like to define directly "_ExitProcess" 00499 extern "C" void mbed_exit(int return_code) { 00500 #elif defined TOOLCHAIN_GCC_ARM 00501 extern "C" void _exit(int return_code) { 00502 #else 00503 namespace std { 00504 extern "C" void exit(int return_code) { 00505 #endif 00506 00507 #if DEVICE_STDIO_MESSAGES 00508 fflush(stdout); 00509 fflush(stderr); 00510 #endif 00511 00512 #if DEVICE_SEMIHOST 00513 if (mbed_interface_connected()) { 00514 semihost_exit(); 00515 } 00516 #endif 00517 if (return_code) { 00518 mbed_die(); 00519 } 00520 00521 while (1); 00522 } 00523 00524 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CW) 00525 } //namespace std 00526 #endif 00527 00528 00529 namespace mbed { 00530 00531 void mbed_set_unbuffered_stream(FILE *_file) { 00532 #if defined (__ICCARM__) 00533 char buf[2]; 00534 std::setvbuf(_file,buf,_IONBF,NULL); 00535 #else 00536 setbuf(_file, NULL); 00537 #endif 00538 } 00539 00540 int mbed_getc(FILE *_file){ 00541 #if defined (__ICCARM__) 00542 /*This is only valid for unbuffered streams*/ 00543 int res = std::fgetc(_file); 00544 if (res>=0){ 00545 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ 00546 _file->_Rend = _file->_Wend; 00547 _file->_Next = _file->_Wend; 00548 } 00549 return res; 00550 #else 00551 return std::fgetc(_file); 00552 #endif 00553 } 00554 00555 char* mbed_gets(char*s, int size, FILE *_file){ 00556 #if defined (__ICCARM__) 00557 /*This is only valid for unbuffered streams*/ 00558 char *str = fgets(s,size,_file); 00559 if (str!=NULL){ 00560 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */ 00561 _file->_Rend = _file->_Wend; 00562 _file->_Next = _file->_Wend; 00563 } 00564 return str; 00565 #else 00566 return std::fgets(s,size,_file); 00567 #endif 00568 } 00569 00570 } // namespace mbed
Generated on Tue Jul 12 2022 11:20:39 by 1.7.2