mbed library sources: Modified to operate FRDM-KL25Z at 48MHz from internal 32kHz oscillator (nothing else changed).
Fork of mbed-src by
retarget.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 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 <errno.h> 00023 00024 #if defined(__ARMCC_VERSION) 00025 # include <rt_sys.h> 00026 # define PREFIX(x) _sys##x 00027 # define OPEN_MAX _SYS_OPEN 00028 # ifdef __MICROLIB 00029 # pragma import(__use_full_stdio) 00030 # endif 00031 00032 #elif defined(__ICCARM__) 00033 # include <yfuns.h> 00034 # define PREFIX(x) _##x 00035 # define OPEN_MAX 16 00036 00037 # define STDIN_FILENO 0 00038 # define STDOUT_FILENO 1 00039 # define STDERR_FILENO 2 00040 00041 #else 00042 # include <sys/stat.h> 00043 # include <sys/unistd.h> 00044 # include <sys/syslimits.h> 00045 # define PREFIX(x) x 00046 #endif 00047 00048 using namespace mbed; 00049 00050 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000) 00051 // Before version 5.03, we were using a patched version of microlib with proper names 00052 extern const char __stdin_name[] = ":tt"; 00053 extern const char __stdout_name[] = ":tt"; 00054 extern const char __stderr_name[] = ":tt"; 00055 00056 #else 00057 extern const char __stdin_name[] = "/stdin"; 00058 extern const char __stdout_name[] = "/stdout"; 00059 extern const char __stderr_name[] = "/stderr"; 00060 #endif 00061 00062 /* newlib has the filehandle field in the FILE struct as a short, so 00063 * we can't just return a Filehandle* from _open and instead have to 00064 * put it in a filehandles array and return the index into that array 00065 * (or rather index+3, as filehandles 0-2 are stdin/out/err). 00066 */ 00067 static FileHandle *filehandles[OPEN_MAX]; 00068 00069 FileHandle::~FileHandle() { 00070 /* Remove all open filehandles for this */ 00071 for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00072 if (filehandles[fh_i] == this) { 00073 filehandles[fh_i] = NULL; 00074 } 00075 } 00076 } 00077 00078 #if DEVICE_SERIAL 00079 extern int stdio_uart_inited; 00080 extern serial_t stdio_uart; 00081 #endif 00082 00083 static void init_serial() { 00084 #if DEVICE_SERIAL 00085 if (stdio_uart_inited) return; 00086 serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX); 00087 #endif 00088 } 00089 00090 static inline int openmode_to_posix(int openmode) { 00091 int posix = openmode; 00092 #ifdef __ARMCC_VERSION 00093 if (openmode & OPEN_PLUS) { 00094 posix = O_RDWR; 00095 } else if(openmode & OPEN_W) { 00096 posix = O_WRONLY; 00097 } else if(openmode & OPEN_A) { 00098 posix = O_WRONLY|O_APPEND; 00099 } else { 00100 posix = O_RDONLY; 00101 } 00102 /* a, w, a+, w+ all create if file does not already exist */ 00103 if (openmode & (OPEN_A|OPEN_W)) { 00104 posix |= O_CREAT; 00105 } 00106 /* w and w+ truncate */ 00107 if (openmode & OPEN_W) { 00108 posix |= O_TRUNC; 00109 } 00110 #elif defined(__ICCARM__) 00111 switch (openmode & _LLIO_RDWRMASK) { 00112 case _LLIO_RDONLY: posix = O_RDONLY; break; 00113 case _LLIO_WRONLY: posix = O_WRONLY; break; 00114 case _LLIO_RDWR : posix = O_RDWR ; break; 00115 } 00116 if (openmode & _LLIO_CREAT ) posix |= O_CREAT; 00117 if (openmode & _LLIO_APPEND) posix |= O_APPEND; 00118 if (openmode & _LLIO_TRUNC ) posix |= O_TRUNC; 00119 #endif 00120 return posix; 00121 } 00122 00123 extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) { 00124 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000) 00125 // Before version 5.03, we were using a patched version of microlib with proper names 00126 // This is the workaround that the microlib author suggested us 00127 static int n = 0; 00128 if (!std::strcmp(name, ":tt")) return n++; 00129 00130 #else 00131 /* Use the posix convention that stdin,out,err are filehandles 0,1,2. 00132 */ 00133 if (std::strcmp(name, __stdin_name) == 0) { 00134 init_serial(); 00135 return 0; 00136 } else if (std::strcmp(name, __stdout_name) == 0) { 00137 init_serial(); 00138 return 1; 00139 } else if (std::strcmp(name, __stderr_name) == 0) { 00140 init_serial(); 00141 return 2; 00142 } 00143 #endif 00144 00145 // find the first empty slot in filehandles 00146 unsigned int fh_i; 00147 for (fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00148 if (filehandles[fh_i] == NULL) break; 00149 } 00150 if (fh_i >= sizeof(filehandles)/sizeof(*filehandles)) { 00151 return -1; 00152 } 00153 00154 FileHandle *res; 00155 00156 /* FILENAME: ":0x12345678" describes a FileLike* */ 00157 if (name[0] == ':') { 00158 void *p; 00159 sscanf(name, ":%p", &p); 00160 res = (FileHandle*)p; 00161 00162 /* FILENAME: "/file_system/file_name" */ 00163 } else { 00164 FilePath path(name); 00165 00166 if (!path.exists()) 00167 return -1; 00168 else if (path.isFile()) { 00169 res = path.file(); 00170 } else { 00171 FileSystemLike *fs = path.fileSystem(); 00172 if (fs == NULL) return -1; 00173 int posix_mode = openmode_to_posix(openmode); 00174 res = fs->open(path.fileName(), posix_mode); /* NULL if fails */ 00175 } 00176 } 00177 00178 if (res == NULL) return -1; 00179 filehandles[fh_i] = res; 00180 00181 return fh_i + 3; // +3 as filehandles 0-2 are stdin/out/err 00182 } 00183 00184 extern "C" int PREFIX(_close)(FILEHANDLE fh) { 00185 if (fh < 3) return 0; 00186 00187 FileHandle* fhc = filehandles[fh-3]; 00188 filehandles[fh-3] = NULL; 00189 if (fhc == NULL) return -1; 00190 00191 return fhc->close(); 00192 } 00193 00194 #if defined(__ICCARM__) 00195 extern "C" size_t __write (int fh, const unsigned char *buffer, size_t length) { 00196 #else 00197 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode) { 00198 #endif 00199 int n; // n is the number of bytes written 00200 if (fh < 3) { 00201 #if DEVICE_SERIAL 00202 if (!stdio_uart_inited) init_serial(); 00203 for (unsigned int i = 0; i < length; i++) { 00204 serial_putc(&stdio_uart, buffer[i]); 00205 } 00206 #endif 00207 n = length; 00208 } else { 00209 FileHandle* fhc = filehandles[fh-3]; 00210 if (fhc == NULL) return -1; 00211 00212 n = fhc->write(buffer, length); 00213 } 00214 #ifdef __ARMCC_VERSION 00215 return length-n; 00216 #else 00217 return n; 00218 #endif 00219 } 00220 00221 #if defined(__ICCARM__) 00222 extern "C" size_t __read (int fh, unsigned char *buffer, size_t length) { 00223 #else 00224 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode) { 00225 #endif 00226 int n; // n is the number of bytes read 00227 if (fh < 3) { 00228 // only read a character at a time from stdin 00229 #if DEVICE_SERIAL 00230 *buffer = serial_getc(&stdio_uart); 00231 #endif 00232 n = 1; 00233 } else { 00234 FileHandle* fhc = filehandles[fh-3]; 00235 if (fhc == NULL) return -1; 00236 00237 n = fhc->read(buffer, length); 00238 } 00239 #ifdef __ARMCC_VERSION 00240 return length-n; 00241 #else 00242 return n; 00243 #endif 00244 } 00245 00246 #ifdef __ARMCC_VERSION 00247 extern "C" int PREFIX(_istty)(FILEHANDLE fh) 00248 #else 00249 extern "C" int _isatty(FILEHANDLE fh) 00250 #endif 00251 { 00252 /* stdin, stdout and stderr should be tty */ 00253 if (fh < 3) return 1; 00254 00255 FileHandle* fhc = filehandles[fh-3]; 00256 if (fhc == NULL) return -1; 00257 00258 return fhc->isatty(); 00259 } 00260 00261 extern "C" 00262 #if defined(__ARMCC_VERSION) 00263 int _sys_seek(FILEHANDLE fh, long position) 00264 #elif defined(__ICCARM__) 00265 long __lseek(int fh, long offset, int whence) 00266 #else 00267 int _lseek(FILEHANDLE fh, int offset, int whence) 00268 #endif 00269 { 00270 if (fh < 3) return 0; 00271 00272 FileHandle* fhc = filehandles[fh-3]; 00273 if (fhc == NULL) return -1; 00274 00275 #if defined(__ARMCC_VERSION) 00276 return fhc->lseek(position, SEEK_SET); 00277 #else 00278 return fhc->lseek(offset, whence); 00279 #endif 00280 } 00281 00282 #ifdef __ARMCC_VERSION 00283 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) { 00284 if (fh < 3) return 0; 00285 00286 FileHandle* fhc = filehandles[fh-3]; 00287 if (fhc == NULL) return -1; 00288 00289 return fhc->fsync(); 00290 } 00291 00292 extern "C" long PREFIX(_flen)(FILEHANDLE fh) { 00293 if (fh < 3) return 0; 00294 00295 FileHandle* fhc = filehandles[fh-3]; 00296 if (fhc == NULL) return -1; 00297 00298 return fhc->flen(); 00299 } 00300 #endif 00301 00302 00303 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__) 00304 extern "C" int _fstat(int fd, struct stat *st) { 00305 if ((STDOUT_FILENO == fd) || (STDERR_FILENO == fd) || (STDIN_FILENO == fd)) { 00306 st->st_mode = S_IFCHR; 00307 return 0; 00308 } 00309 00310 errno = EBADF; 00311 return -1; 00312 } 00313 #endif 00314 00315 namespace std { 00316 extern "C" int remove(const char *path) { 00317 FilePath fp(path); 00318 FileSystemLike *fs = fp.fileSystem(); 00319 if (fs == NULL) return -1; 00320 00321 return fs->remove(fp.fileName()); 00322 } 00323 00324 extern "C" int rename(const char *oldname, const char *newname) { 00325 return -1; 00326 } 00327 00328 extern "C" char *tmpnam(char *s) { 00329 return NULL; 00330 } 00331 00332 extern "C" FILE *tmpfile() { 00333 return NULL; 00334 } 00335 } // namespace std 00336 00337 #ifdef __ARMCC_VERSION 00338 extern "C" char *_sys_command_string(char *cmd, int len) { 00339 return NULL; 00340 } 00341 #endif 00342 00343 extern "C" DIR *opendir(const char *path) { 00344 /* root dir is FileSystemLike */ 00345 if (path[0] == '/' && path[1] == 0) { 00346 return FileSystemLike::opendir(); 00347 } 00348 00349 FilePath fp(path); 00350 FileSystemLike* fs = fp.fileSystem(); 00351 if (fs == NULL) return NULL; 00352 00353 return fs->opendir(fp.fileName()); 00354 } 00355 00356 extern "C" struct dirent *readdir(DIR *dir) { 00357 return dir->readdir(); 00358 } 00359 00360 extern "C" int closedir(DIR *dir) { 00361 return dir->closedir(); 00362 } 00363 00364 extern "C" void rewinddir(DIR *dir) { 00365 dir->rewinddir(); 00366 } 00367 00368 extern "C" off_t telldir(DIR *dir) { 00369 return dir->telldir(); 00370 } 00371 00372 extern "C" void seekdir(DIR *dir, off_t off) { 00373 dir->seekdir(off); 00374 } 00375 00376 extern "C" int mkdir(const char *path, mode_t mode) { 00377 FilePath fp(path); 00378 FileSystemLike *fs = fp.fileSystem(); 00379 if (fs == NULL) return -1; 00380 00381 return fs->mkdir(fp.fileName(), mode); 00382 } 00383 00384 #if defined(TOOLCHAIN_GCC) 00385 /* prevents the exception handling name demangling code getting pulled in */ 00386 #include "error.h" 00387 namespace __gnu_cxx { 00388 void __verbose_terminate_handler() { 00389 error("Exception"); 00390 } 00391 } 00392 extern "C" WEAK void __cxa_pure_virtual(void); 00393 extern "C" WEAK void __cxa_pure_virtual(void) { 00394 exit(1); 00395 } 00396 00397 #endif 00398 00399 // **************************************************************************** 00400 // mbed_main is a function that is called before main() 00401 00402 extern "C" WEAK void mbed_main(void); 00403 extern "C" WEAK void mbed_main(void) { 00404 } 00405 00406 #if defined(TOOLCHAIN_ARM) 00407 extern "C" int $Super$$main(void); 00408 00409 extern "C" int $Sub$$main(void) { 00410 mbed_main(); 00411 return $Super$$main(); 00412 } 00413 #elif defined(TOOLCHAIN_GCC) 00414 extern "C" int __real_main(void); 00415 00416 extern "C" int __wrap_main(void) { 00417 mbed_main(); 00418 return __real_main(); 00419 } 00420 #elif defined(TOOLCHAIN_IAR) 00421 // IAR doesn't have the $Super/$Sub mechanism of armcc, nor something equivalent 00422 // to ld's --wrap. It does have a --redirect, but that doesn't help, since redirecting 00423 // 'main' to another symbol looses the original 'main' symbol. However, its startup 00424 // code will call a function to setup argc and argv (__iar_argc_argv) if it is defined. 00425 // Since mbed doesn't use argc/argv, we use this function to call our mbed_main. 00426 extern "C" void __iar_argc_argv() { 00427 mbed_main(); 00428 } 00429 #endif 00430 00431 // Provide implementation of _sbrk (low-level dynamic memory allocation 00432 // routine) for GCC_ARM which compares new heap pointer with MSP instead of 00433 // SP. This make it compatible with RTX RTOS thread stacks. 00434 #if defined(TOOLCHAIN_GCC_ARM) 00435 // Linker defined symbol used by _sbrk to indicate where heap should start. 00436 extern "C" int __end__; 00437 00438 // Turn off the errno macro and use actual global variable instead. 00439 #undef errno 00440 extern "C" int errno; 00441 00442 // For ARM7 only 00443 register unsigned char * stack_ptr __asm ("sp"); 00444 00445 // Dynamic memory allocation related syscall. 00446 extern "C" caddr_t _sbrk(int incr) { 00447 static unsigned char* heap = (unsigned char*)&__end__; 00448 unsigned char* prev_heap = heap; 00449 unsigned char* new_heap = heap + incr; 00450 00451 #if defined(TARGET_ARM7) 00452 if (new_heap >= stack_ptr) { 00453 #else 00454 if (new_heap >= (unsigned char*)__get_MSP()) { 00455 #endif 00456 errno = ENOMEM; 00457 return (caddr_t)-1; 00458 } 00459 00460 heap = new_heap; 00461 return (caddr_t) prev_heap; 00462 } 00463 #endif
Generated on Wed Jul 13 2022 19:29:54 by 1.7.2