Test code for Grove Node BLE
Dependencies: BLE_API nRF51822
Fork of BLE_LoopbackUART 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 if (!stdio_uart_inited) init_serial(); 00231 *buffer = serial_getc(&stdio_uart); 00232 #endif 00233 n = 1; 00234 } else { 00235 FileHandle* fhc = filehandles[fh-3]; 00236 if (fhc == NULL) return -1; 00237 00238 n = fhc->read(buffer, length); 00239 } 00240 #ifdef __ARMCC_VERSION 00241 return length-n; 00242 #else 00243 return n; 00244 #endif 00245 } 00246 00247 #ifdef __ARMCC_VERSION 00248 extern "C" int PREFIX(_istty)(FILEHANDLE fh) 00249 #else 00250 extern "C" int _isatty(FILEHANDLE fh) 00251 #endif 00252 { 00253 /* stdin, stdout and stderr should be tty */ 00254 if (fh < 3) return 1; 00255 00256 FileHandle* fhc = filehandles[fh-3]; 00257 if (fhc == NULL) return -1; 00258 00259 return fhc->isatty(); 00260 } 00261 00262 extern "C" 00263 #if defined(__ARMCC_VERSION) 00264 int _sys_seek(FILEHANDLE fh, long position) 00265 #elif defined(__ICCARM__) 00266 long __lseek(int fh, long offset, int whence) 00267 #else 00268 int _lseek(FILEHANDLE fh, int offset, int whence) 00269 #endif 00270 { 00271 if (fh < 3) return 0; 00272 00273 FileHandle* fhc = filehandles[fh-3]; 00274 if (fhc == NULL) return -1; 00275 00276 #if defined(__ARMCC_VERSION) 00277 return fhc->lseek(position, SEEK_SET); 00278 #else 00279 return fhc->lseek(offset, whence); 00280 #endif 00281 } 00282 00283 #ifdef __ARMCC_VERSION 00284 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) { 00285 if (fh < 3) return 0; 00286 00287 FileHandle* fhc = filehandles[fh-3]; 00288 if (fhc == NULL) return -1; 00289 00290 return fhc->fsync(); 00291 } 00292 00293 extern "C" long PREFIX(_flen)(FILEHANDLE fh) { 00294 if (fh < 3) return 0; 00295 00296 FileHandle* fhc = filehandles[fh-3]; 00297 if (fhc == NULL) return -1; 00298 00299 return fhc->flen(); 00300 } 00301 #endif 00302 00303 00304 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__) 00305 extern "C" int _fstat(int fd, struct stat *st) { 00306 if ((STDOUT_FILENO == fd) || (STDERR_FILENO == fd) || (STDIN_FILENO == fd)) { 00307 st->st_mode = S_IFCHR; 00308 return 0; 00309 } 00310 00311 errno = EBADF; 00312 return -1; 00313 } 00314 #endif 00315 00316 namespace std { 00317 extern "C" int remove(const char *path) { 00318 FilePath fp(path); 00319 FileSystemLike *fs = fp.fileSystem(); 00320 if (fs == NULL) return -1; 00321 00322 return fs->remove(fp.fileName()); 00323 } 00324 00325 extern "C" int rename(const char *oldname, const char *newname) { 00326 FilePath fpOld(oldname); 00327 FilePath fpNew(newname); 00328 FileSystemLike *fsOld = fpOld.fileSystem(); 00329 FileSystemLike *fsNew = fpNew.fileSystem(); 00330 00331 /* rename only if both files are on the same FS */ 00332 if (fsOld != fsNew || fsOld == NULL) return -1; 00333 00334 return fsOld->rename(fpOld.fileName(), fpNew.fileName()); 00335 } 00336 00337 extern "C" char *tmpnam(char *s) { 00338 return NULL; 00339 } 00340 00341 extern "C" FILE *tmpfile() { 00342 return NULL; 00343 } 00344 } // namespace std 00345 00346 #ifdef __ARMCC_VERSION 00347 extern "C" char *_sys_command_string(char *cmd, int len) { 00348 return NULL; 00349 } 00350 #endif 00351 00352 extern "C" DIR *opendir(const char *path) { 00353 /* root dir is FileSystemLike */ 00354 if (path[0] == '/' && path[1] == 0) { 00355 return FileSystemLike::opendir(); 00356 } 00357 00358 FilePath fp(path); 00359 FileSystemLike* fs = fp.fileSystem(); 00360 if (fs == NULL) return NULL; 00361 00362 return fs->opendir(fp.fileName()); 00363 } 00364 00365 extern "C" struct dirent *readdir(DIR *dir) { 00366 return dir->readdir(); 00367 } 00368 00369 extern "C" int closedir(DIR *dir) { 00370 return dir->closedir(); 00371 } 00372 00373 extern "C" void rewinddir(DIR *dir) { 00374 dir->rewinddir(); 00375 } 00376 00377 extern "C" off_t telldir(DIR *dir) { 00378 return dir->telldir(); 00379 } 00380 00381 extern "C" void seekdir(DIR *dir, off_t off) { 00382 dir->seekdir(off); 00383 } 00384 00385 extern "C" int mkdir(const char *path, mode_t mode) { 00386 FilePath fp(path); 00387 FileSystemLike *fs = fp.fileSystem(); 00388 if (fs == NULL) return -1; 00389 00390 return fs->mkdir(fp.fileName(), mode); 00391 } 00392 00393 #if defined(TOOLCHAIN_GCC) 00394 /* prevents the exception handling name demangling code getting pulled in */ 00395 #include "mbed_error.h" 00396 namespace __gnu_cxx { 00397 void __verbose_terminate_handler() { 00398 error("Exception"); 00399 } 00400 } 00401 extern "C" WEAK void __cxa_pure_virtual(void); 00402 extern "C" WEAK void __cxa_pure_virtual(void) { 00403 exit(1); 00404 } 00405 00406 #endif 00407 00408 // **************************************************************************** 00409 // mbed_main is a function that is called before main() 00410 // mbed_sdk_init() is also a function that is called before main(), but unlike 00411 // mbed_main(), it is not meant for user code, but for the SDK itself to perform 00412 // initializations before main() is called. 00413 00414 extern "C" WEAK void mbed_main(void); 00415 extern "C" WEAK void mbed_main(void) { 00416 } 00417 00418 extern "C" WEAK void mbed_sdk_init(void); 00419 extern "C" WEAK void mbed_sdk_init(void) { 00420 } 00421 00422 #if defined(TOOLCHAIN_ARM) 00423 extern "C" int $Super$$main(void); 00424 00425 extern "C" int $Sub$$main(void) { 00426 mbed_sdk_init(); 00427 mbed_main(); 00428 return $Super$$main(); 00429 } 00430 #elif defined(TOOLCHAIN_GCC) 00431 extern "C" int __real_main(void); 00432 00433 extern "C" int __wrap_main(void) { 00434 mbed_sdk_init(); 00435 mbed_main(); 00436 return __real_main(); 00437 } 00438 #elif defined(TOOLCHAIN_IAR) 00439 // IAR doesn't have the $Super/$Sub mechanism of armcc, nor something equivalent 00440 // to ld's --wrap. It does have a --redirect, but that doesn't help, since redirecting 00441 // 'main' to another symbol looses the original 'main' symbol. However, its startup 00442 // code will call a function to setup argc and argv (__iar_argc_argv) if it is defined. 00443 // Since mbed doesn't use argc/argv, we use this function to call our mbed_main. 00444 extern "C" void __iar_argc_argv() { 00445 mbed_sdk_init(); 00446 mbed_main(); 00447 } 00448 #endif 00449 00450 // Provide implementation of _sbrk (low-level dynamic memory allocation 00451 // routine) for GCC_ARM which compares new heap pointer with MSP instead of 00452 // SP. This make it compatible with RTX RTOS thread stacks. 00453 #if defined(TOOLCHAIN_GCC_ARM) 00454 // Linker defined symbol used by _sbrk to indicate where heap should start. 00455 extern "C" int __end__; 00456 00457 // Turn off the errno macro and use actual global variable instead. 00458 #undef errno 00459 extern "C" int errno; 00460 00461 // For ARM7 only 00462 register unsigned char * stack_ptr __asm ("sp"); 00463 00464 // Dynamic memory allocation related syscall. 00465 extern "C" caddr_t _sbrk(int incr) { 00466 static unsigned char* heap = (unsigned char*)&__end__; 00467 unsigned char* prev_heap = heap; 00468 unsigned char* new_heap = heap + incr; 00469 00470 #if defined(TARGET_ARM7) 00471 if (new_heap >= stack_ptr) { 00472 #else 00473 if (new_heap >= (unsigned char*)__get_MSP()) { 00474 #endif 00475 errno = ENOMEM; 00476 return (caddr_t)-1; 00477 } 00478 00479 heap = new_heap; 00480 return (caddr_t) prev_heap; 00481 } 00482 #endif
Generated on Tue Jul 12 2022 21:43:25 by 1.7.2