fix for mbed lib issue 3 (i2c problem) see also https://mbed.org/users/mbed_official/code/mbed/issues/3 affected implementations: LPC812, LPC11U24, LPC1768, LPC2368, LPC4088
Fork of mbed-src by
stdio.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 <errno.h> 00022 00023 #if defined(__ARMCC_VERSION) 00024 # include <rt_sys.h> 00025 # define PREFIX(x) _sys##x 00026 # define OPEN_MAX _SYS_OPEN 00027 # ifdef __MICROLIB 00028 # pragma import(__use_full_stdio) 00029 # endif 00030 00031 #elif defined(__ICCARM__) 00032 # include <yfuns.h> 00033 # define PREFIX(x) _##x 00034 # define OPEN_MAX 16 00035 00036 # define STDIN_FILENO 0 00037 # define STDOUT_FILENO 1 00038 # define STDERR_FILENO 2 00039 00040 #else 00041 # include <sys/stat.h> 00042 # include <sys/unistd.h> 00043 # include <sys/syslimits.h> 00044 # define PREFIX(x) x 00045 #endif 00046 00047 using namespace mbed; 00048 00049 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000) 00050 // Before version 5.03, we were using a patched version of microlib with proper names 00051 extern const char __stdin_name[] = ":tt"; 00052 extern const char __stdout_name[] = ":tt"; 00053 extern const char __stderr_name[] = ":tt"; 00054 00055 #else 00056 extern const char __stdin_name[] = "/stdin"; 00057 extern const char __stdout_name[] = "/stdout"; 00058 extern const char __stderr_name[] = "/stderr"; 00059 #endif 00060 00061 /* newlib has the filehandle field in the FILE struct as a short, so 00062 * we can't just return a Filehandle* from _open and instead have to 00063 * put it in a filehandles array and return the index into that array 00064 * (or rather index+3, as filehandles 0-2 are stdin/out/err). 00065 */ 00066 static FileHandle *filehandles[OPEN_MAX]; 00067 00068 FileHandle::~FileHandle() { 00069 /* Remove all open filehandles for this */ 00070 for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00071 if (filehandles[fh_i] == this) { 00072 filehandles[fh_i] = NULL; 00073 } 00074 } 00075 } 00076 00077 #if DEVICE_SERIAL 00078 extern int stdio_uart_inited; 00079 extern serial_t stdio_uart; 00080 #endif 00081 00082 static void init_serial() { 00083 #if DEVICE_SERIAL 00084 if (stdio_uart_inited) return; 00085 serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX); 00086 #endif 00087 } 00088 00089 static inline int openmode_to_posix(int openmode) { 00090 int posix = openmode; 00091 #ifdef __ARMCC_VERSION 00092 if (openmode & OPEN_PLUS) { 00093 posix = O_RDWR; 00094 } else if(openmode & OPEN_W) { 00095 posix = O_WRONLY; 00096 } else if(openmode & OPEN_A) { 00097 posix = O_WRONLY|O_APPEND; 00098 } else { 00099 posix = O_RDONLY; 00100 } 00101 /* a, w, a+, w+ all create if file does not already exist */ 00102 if (openmode & (OPEN_A|OPEN_W)) { 00103 posix |= O_CREAT; 00104 } 00105 /* w and w+ truncate */ 00106 if (openmode & OPEN_W) { 00107 posix |= O_TRUNC; 00108 } 00109 #elif defined(__ICCARM__) 00110 switch (openmode & _LLIO_RDWRMASK) { 00111 case _LLIO_RDONLY: posix = O_RDONLY; break; 00112 case _LLIO_WRONLY: posix = O_WRONLY; break; 00113 case _LLIO_RDWR : posix = O_RDWR ; break; 00114 } 00115 if (openmode & _LLIO_CREAT ) posix |= O_CREAT; 00116 if (openmode & _LLIO_APPEND) posix |= O_APPEND; 00117 if (openmode & _LLIO_TRUNC ) posix |= O_TRUNC; 00118 #endif 00119 return posix; 00120 } 00121 00122 extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) { 00123 /* Use the posix convention that stdin,out,err are filehandles 0,1,2. 00124 */ 00125 if (std::strcmp(name, __stdin_name) == 0) { 00126 init_serial(); 00127 return 0; 00128 } else if (std::strcmp(name, __stdout_name) == 0) { 00129 init_serial(); 00130 return 1; 00131 } else if (std::strcmp(name, __stderr_name) == 0) { 00132 init_serial(); 00133 return 2; 00134 } 00135 00136 // find the first empty slot in filehandles 00137 unsigned int fh_i; 00138 for (fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) { 00139 if (filehandles[fh_i] == NULL) break; 00140 } 00141 if (fh_i >= sizeof(filehandles)/sizeof(*filehandles)) { 00142 return -1; 00143 } 00144 00145 FileHandle *res; 00146 00147 /* FILENAME: ":0x12345678" describes a FileLike* */ 00148 if (name[0] == ':') { 00149 void *p; 00150 sscanf(name, ":%p", &p); 00151 res = (FileHandle*)p; 00152 00153 /* FILENAME: "/file_system/file_name" */ 00154 } else { 00155 FilePath path(name); 00156 00157 if (path.isFile()) { 00158 res = path.file(); 00159 } else { 00160 FileSystemLike *fs = path.fileSystem(); 00161 if (fs == NULL) return -1; 00162 int posix_mode = openmode_to_posix(openmode); 00163 res = fs->open(path.fileName(), posix_mode); /* NULL if fails */ 00164 } 00165 } 00166 00167 if (res == NULL) return -1; 00168 filehandles[fh_i] = res; 00169 00170 return fh_i + 3; // +3 as filehandles 0-2 are stdin/out/err 00171 } 00172 00173 extern "C" int PREFIX(_close)(FILEHANDLE fh) { 00174 if (fh < 3) return 0; 00175 00176 FileHandle* fhc = filehandles[fh-3]; 00177 filehandles[fh-3] = NULL; 00178 if (fhc == NULL) return -1; 00179 00180 return fhc->close(); 00181 } 00182 00183 #if defined(__ICCARM__) 00184 extern "C" size_t __write (int fh, const unsigned char *buffer, size_t length) { 00185 #else 00186 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode) { 00187 #endif 00188 int n; // n is the number of bytes written 00189 if (fh < 3) { 00190 #if DEVICE_SERIAL 00191 if (!stdio_uart_inited) init_serial(); 00192 for (unsigned int i = 0; i < length; i++) { 00193 serial_putc(&stdio_uart, buffer[i]); 00194 } 00195 #endif 00196 n = length; 00197 } else { 00198 FileHandle* fhc = filehandles[fh-3]; 00199 if (fhc == NULL) return -1; 00200 00201 n = fhc->write(buffer, length); 00202 } 00203 #ifdef __ARMCC_VERSION 00204 return length-n; 00205 #else 00206 return n; 00207 #endif 00208 } 00209 00210 #if defined(__ICCARM__) 00211 extern "C" size_t __read (int fh, unsigned char *buffer, size_t length) { 00212 #else 00213 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode) { 00214 #endif 00215 int n; // n is the number of bytes read 00216 if (fh < 3) { 00217 // only read a character at a time from stdin 00218 #if DEVICE_SERIAL 00219 *buffer = serial_getc(&stdio_uart); 00220 #endif 00221 n = 1; 00222 } else { 00223 FileHandle* fhc = filehandles[fh-3]; 00224 if (fhc == NULL) return -1; 00225 00226 n = fhc->read(buffer, length); 00227 } 00228 #ifdef __ARMCC_VERSION 00229 return length-n; 00230 #else 00231 return n; 00232 #endif 00233 } 00234 00235 #ifdef __ARMCC_VERSION 00236 extern "C" int PREFIX(_istty)(FILEHANDLE fh) 00237 #else 00238 extern "C" int _isatty(FILEHANDLE fh) 00239 #endif 00240 { 00241 /* stdin, stdout and stderr should be tty */ 00242 if (fh < 3) return 1; 00243 00244 FileHandle* fhc = filehandles[fh-3]; 00245 if (fhc == NULL) return -1; 00246 00247 return fhc->isatty(); 00248 } 00249 00250 extern "C" 00251 #if defined(__ARMCC_VERSION) 00252 int _sys_seek(FILEHANDLE fh, long position) 00253 #elif defined(__ICCARM__) 00254 long __lseek(int fh, long offset, int whence) 00255 #else 00256 int _lseek(FILEHANDLE fh, int offset, int whence) 00257 #endif 00258 { 00259 if (fh < 3) return 0; 00260 00261 FileHandle* fhc = filehandles[fh-3]; 00262 if (fhc == NULL) return -1; 00263 00264 #if defined(__ARMCC_VERSION) 00265 return fhc->lseek(position, SEEK_SET); 00266 #else 00267 return fhc->lseek(offset, whence); 00268 #endif 00269 } 00270 00271 #ifdef __ARMCC_VERSION 00272 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) { 00273 if (fh < 3) return 0; 00274 00275 FileHandle* fhc = filehandles[fh-3]; 00276 if (fhc == NULL) return -1; 00277 00278 return fhc->fsync(); 00279 } 00280 00281 extern "C" long PREFIX(_flen)(FILEHANDLE fh) { 00282 if (fh < 3) return 0; 00283 00284 FileHandle* fhc = filehandles[fh-3]; 00285 if (fhc == NULL) return -1; 00286 00287 return fhc->flen(); 00288 } 00289 #endif 00290 00291 00292 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__) 00293 extern "C" int _fstat(int fd, struct stat *st) { 00294 if ((STDOUT_FILENO == fd) || (STDERR_FILENO == fd) || (STDIN_FILENO == fd)) { 00295 st->st_mode = S_IFCHR; 00296 return 0; 00297 } 00298 00299 errno = EBADF; 00300 return -1; 00301 } 00302 #endif 00303 00304 namespace std { 00305 extern "C" int remove(const char *path) { 00306 FilePath fp(path); 00307 FileSystemLike *fs = fp.fileSystem(); 00308 if (fs == NULL) return -1; 00309 00310 return fs->remove(fp.fileName()); 00311 } 00312 00313 extern "C" int rename(const char *oldname, const char *newname) { 00314 return -1; 00315 } 00316 00317 extern "C" char *tmpnam(char *s) { 00318 return NULL; 00319 } 00320 00321 extern "C" FILE *tmpfile() { 00322 return NULL; 00323 } 00324 } // namespace std 00325 00326 #ifdef __ARMCC_VERSION 00327 extern "C" char *_sys_command_string(char *cmd, int len) { 00328 return NULL; 00329 } 00330 #endif 00331 00332 extern "C" DIR *opendir(const char *path) { 00333 /* root dir is FileSystemLike */ 00334 if (path[0] == '/' && path[1] == 0) { 00335 return FileSystemLike::opendir(); 00336 } 00337 00338 FilePath fp(path); 00339 FileSystemLike* fs = fp.fileSystem(); 00340 if (fs == NULL) return NULL; 00341 00342 return fs->opendir(fp.fileName()); 00343 } 00344 00345 extern "C" struct dirent *readdir(DIR *dir) { 00346 return dir->readdir(); 00347 } 00348 00349 extern "C" int closedir(DIR *dir) { 00350 return dir->closedir(); 00351 } 00352 00353 extern "C" void rewinddir(DIR *dir) { 00354 dir->rewinddir(); 00355 } 00356 00357 extern "C" off_t telldir(DIR *dir) { 00358 return dir->telldir(); 00359 } 00360 00361 extern "C" void seekdir(DIR *dir, off_t off) { 00362 dir->seekdir(off); 00363 } 00364 00365 extern "C" int mkdir(const char *path, mode_t mode) { 00366 FilePath fp(path); 00367 FileSystemLike *fs = fp.fileSystem(); 00368 if (fs == NULL) return -1; 00369 00370 return fs->mkdir(fp.fileName(), mode); 00371 } 00372 00373 #if defined(TOOLCHAIN_GCC_CR) || defined(TOOLCHAIN_GCC_CS) || defined(TOOLCHAIN_GCC_ARM) 00374 /* prevents the exception handling name demangling code getting pulled in */ 00375 #include "error.h" 00376 namespace __gnu_cxx { 00377 void __verbose_terminate_handler() { 00378 error("Exception"); 00379 } 00380 } 00381 #endif
Generated on Tue Jul 12 2022 13:47:02 by 1.7.2