Modification of Mbed-dev library for LQFP48 package microcontrollers: STM32F103C8 (STM32F103C8T6) and STM32F103CB (STM32F103CBT6) (Bluepill boards, Maple mini etc. )

Fork of mbed-STM32F103C8_org by Nothing Special

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mbed_retarget.cpp Source File

mbed_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/platform.h"
00017 #include "drivers/FilePath.h"
00018 #include "hal/serial_api.h"
00019 #include "platform/mbed_toolchain.h"
00020 #include "platform/mbed_semihost_api.h"
00021 #include "platform/mbed_interface.h"
00022 #include "platform/SingletonPtr.h"
00023 #include "platform/PlatformMutex.h"
00024 #include "platform/mbed_error.h"
00025 #include "platform/mbed_stats.h"
00026 #if MBED_CONF_FILESYSTEM_PRESENT
00027 #include "filesystem/FileSystem.h"
00028 #include "filesystem/File.h"
00029 #include "filesystem/Dir.h"
00030 #endif
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #if DEVICE_STDIO_MESSAGES
00034 #include <stdio.h>
00035 #endif
00036 #include <errno.h>
00037 #include "platform/mbed_retarget.h"
00038 
00039 
00040 #if defined(__ARMCC_VERSION)
00041 #   include <rt_sys.h>
00042 #   define PREFIX(x)    _sys##x
00043 #   define OPEN_MAX     _SYS_OPEN
00044 #   ifdef __MICROLIB
00045 #       pragma import(__use_full_stdio)
00046 #   endif
00047 
00048 #elif defined(__ICCARM__)
00049 #   include <yfuns.h>
00050 #   define PREFIX(x)        _##x
00051 #   define OPEN_MAX         16
00052 
00053 #   define STDIN_FILENO     0
00054 #   define STDOUT_FILENO    1
00055 #   define STDERR_FILENO    2
00056 
00057 #else
00058 #   include <sys/stat.h>
00059 #   include <sys/syslimits.h>
00060 #   define PREFIX(x)    x
00061 #endif
00062 
00063 #define FILE_HANDLE_RESERVED    0xFFFFFFFF
00064 
00065 using namespace mbed;
00066 
00067 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
00068 // Before version 5.03, we were using a patched version of microlib with proper names
00069 extern const char __stdin_name[]  = ":tt";
00070 extern const char __stdout_name[] = ":tt";
00071 extern const char __stderr_name[] = ":tt";
00072 
00073 #else
00074 extern const char __stdin_name[]  = "/stdin";
00075 extern const char __stdout_name[] = "/stdout";
00076 extern const char __stderr_name[] = "/stderr";
00077 #endif
00078 
00079 // Heap limits - only used if set
00080 unsigned char *mbed_heap_start = 0;
00081 uint32_t mbed_heap_size = 0;
00082 
00083 /* newlib has the filehandle field in the FILE struct as a short, so
00084  * we can't just return a Filehandle* from _open and instead have to
00085  * put it in a filehandles array and return the index into that array
00086  * (or rather index+3, as filehandles 0-2 are stdin/out/err).
00087  */
00088 static FileLike *filehandles[OPEN_MAX];
00089 static SingletonPtr<PlatformMutex>  filehandle_mutex;
00090 
00091 namespace mbed {
00092 void remove_filehandle(FileLike *file) {
00093     filehandle_mutex->lock();
00094     /* Remove all open filehandles for this */
00095     for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) {
00096         if (filehandles[fh_i] == file) {
00097             filehandles[fh_i] = NULL;
00098         }
00099     }
00100     filehandle_mutex->unlock();
00101 }
00102 }
00103 
00104 #if DEVICE_SERIAL
00105 extern int stdio_uart_inited;
00106 extern serial_t stdio_uart;
00107 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
00108 static char stdio_in_prev;
00109 static char stdio_out_prev;
00110 #endif
00111 #endif
00112 
00113 static void init_serial() {
00114 #if DEVICE_SERIAL
00115     if (stdio_uart_inited) return;
00116     serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX);
00117 #if MBED_CONF_PLATFORM_STDIO_BAUD_RATE
00118     serial_baud(&stdio_uart, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
00119 #endif
00120 #endif
00121 }
00122 
00123 static inline int openmode_to_posix(int openmode) {
00124     int posix = openmode;
00125 #ifdef __ARMCC_VERSION
00126     if (openmode & OPEN_PLUS) {
00127         posix = O_RDWR;
00128     } else if(openmode & OPEN_W) {
00129         posix = O_WRONLY;
00130     } else if(openmode & OPEN_A) {
00131         posix = O_WRONLY|O_APPEND;
00132     } else {
00133         posix = O_RDONLY;
00134     }
00135     /* a, w, a+, w+ all create if file does not already exist */
00136     if (openmode & (OPEN_A|OPEN_W)) {
00137         posix |= O_CREAT;
00138     }
00139     /* w and w+ truncate */
00140     if (openmode & OPEN_W) {
00141         posix |= O_TRUNC;
00142     }
00143 #elif defined(__ICCARM__)
00144     switch (openmode & _LLIO_RDWRMASK) {
00145         case _LLIO_RDONLY: posix = O_RDONLY; break;
00146         case _LLIO_WRONLY: posix = O_WRONLY; break;
00147         case _LLIO_RDWR  : posix = O_RDWR  ; break;
00148     }
00149     if (openmode & _LLIO_CREAT ) posix |= O_CREAT;
00150     if (openmode & _LLIO_APPEND) posix |= O_APPEND;
00151     if (openmode & _LLIO_TRUNC ) posix |= O_TRUNC;
00152 #elif defined(TOOLCHAIN_GCC)
00153     posix &= ~O_BINARY;
00154 #endif
00155     return posix;
00156 }
00157 
00158 extern "C" WEAK void mbed_sdk_init(void);
00159 extern "C" WEAK void mbed_sdk_init(void) {
00160 }
00161 
00162 #if MBED_CONF_FILESYSTEM_PRESENT
00163 // Internally used file objects with managed memory on close
00164 class ManagedFile : public File {
00165 public:
00166     virtual int close() {
00167         int err = File::close();
00168         delete this;
00169         return err;
00170     }
00171 };
00172 
00173 class ManagedDir : public Dir {
00174 public:
00175      virtual int close() {
00176         int err = Dir::close();
00177         delete this;
00178         return err;
00179     }
00180 };
00181 #endif
00182 
00183 /* @brief   standard c library fopen() retargeting function.
00184  *
00185  * This function is invoked by the standard c library retargeting to handle fopen()
00186  *
00187  * @return
00188  *  On success, a valid FILEHANDLE is returned.
00189  *  On failure, -1 is returned and errno is set to an appropriate value e.g.
00190  *   EBADF      a bad file descriptor was found (default errno setting)
00191  *   EMFILE     the maximum number of open files was exceeded.
00192  *
00193  * */
00194 extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) {
00195     #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
00196     // Before version 5.03, we were using a patched version of microlib with proper names
00197     // This is the workaround that the microlib author suggested us
00198     static int n = 0;
00199     static int mbed_sdk_inited = 0;
00200     if (!mbed_sdk_inited) {
00201         mbed_sdk_inited = 1;
00202         mbed_sdk_init();
00203     }
00204     if (!std::strcmp(name, ":tt")) return n++;
00205     #else
00206     /* Use the posix convention that stdin,out,err are filehandles 0,1,2.
00207      */
00208     if (std::strcmp(name, __stdin_name) == 0) {
00209         init_serial();
00210         return 0;
00211     } else if (std::strcmp(name, __stdout_name) == 0) {
00212         init_serial();
00213         return 1;
00214     } else if (std::strcmp(name, __stderr_name) == 0) {
00215         init_serial();
00216         return 2;
00217     }
00218     #endif
00219 
00220     /* if something goes wrong and errno is not explicly set, errno will be set to EBADF */
00221     errno = EBADF;
00222 
00223     // find the first empty slot in filehandles
00224     filehandle_mutex->lock();
00225     unsigned int fh_i;
00226     for (fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) {
00227         /* Take a next free filehandle slot available. */
00228         if (filehandles[fh_i] == NULL) break;
00229     }
00230     if (fh_i >= sizeof(filehandles)/sizeof(*filehandles)) {
00231         /* Too many file handles have been opened */
00232         errno = EMFILE;
00233         filehandle_mutex->unlock();
00234         return -1;
00235     }
00236     filehandles[fh_i] = (FileLike*)FILE_HANDLE_RESERVED;
00237     filehandle_mutex->unlock();
00238 
00239     FileLike *res = NULL;
00240 
00241     /* FILENAME: ":0x12345678" describes a FileLike* */
00242     if (name[0] == ':') {
00243         void *p;
00244         sscanf(name, ":%p", &p);
00245         res = (FileLike*)p;
00246 
00247     /* FILENAME: "/file_system/file_name" */
00248     } else {
00249         FilePath path(name);
00250 
00251         if (!path.exists()) {
00252             /* The first part of the filename (between first 2 '/') is not a
00253              * registered mount point in the namespace.
00254              * Free file handle.
00255              */
00256             filehandles[fh_i] = NULL;
00257             errno = ENOENT;
00258             return -1;
00259         } else if (path.isFile()) {
00260             res = path.file();
00261 #if MBED_CONF_FILESYSTEM_PRESENT
00262         } else {
00263             FileSystem *fs = path.fileSystem();
00264             if (fs == NULL) {
00265                 /* The filesystem instance managing the namespace under the mount point
00266                  * has not been found. Free file handle */
00267                 errno = ENOENT;
00268                 filehandles[fh_i] = NULL;
00269                 return -1;
00270             }
00271             int posix_mode = openmode_to_posix(openmode);
00272             File *file = new ManagedFile;
00273             int err = file->open(fs, path.fileName(), posix_mode);
00274             if (err < 0) {
00275                 errno = -err;
00276                 delete file;
00277             } else {
00278                 res = file;
00279             }
00280 #endif
00281         }
00282     }
00283 
00284     if (res == NULL) {
00285         // Free file handle
00286         filehandles[fh_i] = NULL;
00287         return -1;
00288     }
00289     filehandles[fh_i] = res;
00290 
00291     return fh_i + 3; // +3 as filehandles 0-2 are stdin/out/err
00292 }
00293 
00294 extern "C" int PREFIX(_close)(FILEHANDLE fh) {
00295     if (fh < 3) return 0;
00296 
00297     errno = EBADF;
00298     FileLike* fhc = filehandles[fh-3];
00299     filehandles[fh-3] = NULL;
00300     if (fhc == NULL) return -1;
00301 
00302     int err = fhc->close();
00303     if (err < 0) {
00304         errno = -err;
00305         return -1;
00306     } else {
00307         return 0;
00308     }
00309 }
00310 
00311 #if defined(__ICCARM__)
00312 extern "C" size_t    __write (int        fh, const unsigned char *buffer, size_t length) {
00313 #else
00314 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode) {
00315 #endif
00316     int n; // n is the number of bytes written
00317 
00318     errno = EBADF;
00319     if (fh < 3) {
00320 #if DEVICE_SERIAL
00321         if (!stdio_uart_inited) init_serial();
00322 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
00323         for (unsigned int i = 0; i < length; i++) {
00324             if (buffer[i] == '\n' && stdio_out_prev != '\r') {
00325                  serial_putc(&stdio_uart, '\r');
00326             }
00327             serial_putc(&stdio_uart, buffer[i]);
00328             stdio_out_prev = buffer[i];
00329         }
00330 #else
00331         for (unsigned int i = 0; i < length; i++) {
00332             serial_putc(&stdio_uart, buffer[i]);
00333         }
00334 #endif
00335 #endif
00336         n = length;
00337     } else {
00338         FileLike* fhc = filehandles[fh-3];
00339         if (fhc == NULL) return -1;
00340 
00341         n = fhc->write(buffer, length);
00342         if (n < 0) {
00343             errno = -n;
00344         }
00345     }
00346 #ifdef __ARMCC_VERSION
00347     return length-n;
00348 #else
00349     return n;
00350 #endif
00351 }
00352 
00353 #if defined(__ICCARM__)
00354 extern "C" size_t    __read (int        fh, unsigned char *buffer, size_t       length) {
00355 #else
00356 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode) {
00357 #endif
00358     int n; // n is the number of bytes read
00359 
00360     errno = EBADF;
00361     if (fh < 3) {
00362         // only read a character at a time from stdin
00363 #if DEVICE_SERIAL
00364         if (!stdio_uart_inited) init_serial();
00365 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
00366         while (true) {
00367             char c = serial_getc(&stdio_uart);
00368             if ((c == '\r' && stdio_in_prev != '\n') ||
00369                 (c == '\n' && stdio_in_prev != '\r')) {
00370                 stdio_in_prev = c;
00371                 *buffer = '\n';
00372                 break;
00373             } else if ((c == '\r' && stdio_in_prev == '\n') ||
00374                        (c == '\n' && stdio_in_prev == '\r')) {
00375                 stdio_in_prev = c;
00376                 // onto next character
00377                 continue;
00378             } else {
00379                 stdio_in_prev = c;
00380                 *buffer = c;
00381                 break;
00382             }
00383         }
00384 #else
00385         *buffer = serial_getc(&stdio_uart);
00386 #endif
00387 #endif
00388         n = 1;
00389     } else {
00390         FileLike* fhc = filehandles[fh-3];
00391         if (fhc == NULL) return -1;
00392 
00393         n = fhc->read(buffer, length);
00394         if (n < 0) {
00395             errno = -n;
00396         }
00397     }
00398 #ifdef __ARMCC_VERSION
00399     return length-n;
00400 #else
00401     return n;
00402 #endif
00403 }
00404 
00405 #ifdef __ARMCC_VERSION
00406 extern "C" int PREFIX(_istty)(FILEHANDLE fh)
00407 #else
00408 extern "C" int _isatty(FILEHANDLE fh)
00409 #endif
00410 {
00411     errno = EBADF;
00412     /* stdin, stdout and stderr should be tty */
00413     if (fh < 3) return 1;
00414 
00415     FileLike* fhc = filehandles[fh-3];
00416     if (fhc == NULL) return -1;
00417 
00418     int err = fhc->isatty();
00419     if (err < 0) {
00420         errno = -err;
00421         return -1;
00422     } else {
00423         return 0;
00424     }
00425 }
00426 
00427 extern "C"
00428 #if defined(__ARMCC_VERSION)
00429 int _sys_seek(FILEHANDLE fh, long position)
00430 #elif defined(__ICCARM__)
00431 long __lseek(int fh, long offset, int whence)
00432 #else
00433 int _lseek(FILEHANDLE fh, int offset, int whence)
00434 #endif
00435 {
00436     errno = EBADF;
00437     if (fh < 3) return 0;
00438 
00439     FileLike* fhc = filehandles[fh-3];
00440     if (fhc == NULL) return -1;
00441 
00442 #if defined(__ARMCC_VERSION)
00443     return fhc->seek(position, SEEK_SET);
00444 #else
00445     return fhc->seek(offset, whence);
00446 #endif
00447 }
00448 
00449 #ifdef __ARMCC_VERSION
00450 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) {
00451     errno = EBADF;
00452     if (fh < 3) return 0;
00453 
00454     FileLike* fhc = filehandles[fh-3];
00455     if (fhc == NULL) return -1;
00456 
00457     int err = fhc->sync();
00458     if (err < 0) {
00459         errno = -err;
00460         return -1;
00461     } else {
00462         return 0;
00463     }
00464 }
00465 
00466 extern "C" long PREFIX(_flen)(FILEHANDLE fh) {
00467     errno = EBADF;
00468     if (fh < 3) return 0;
00469 
00470     FileLike* fhc = filehandles[fh-3];
00471     if (fhc == NULL) return -1;
00472 
00473     return fhc->size();
00474 }
00475 #endif
00476 
00477 
00478 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__)
00479 extern "C" int _fstat(int fd, struct stat *st) {
00480     if (fd < 3) {
00481         st->st_mode = S_IFCHR;
00482         return  0;
00483     }
00484     errno = EBADF;
00485     return -1;
00486 }
00487 #endif
00488 
00489 namespace std {
00490 extern "C" int remove(const char *path) {
00491 #if MBED_CONF_FILESYSTEM_PRESENT
00492     errno = EBADF;
00493     FilePath fp(path);
00494     FileSystem *fs = fp.fileSystem();
00495     if (fs == NULL) return -1;
00496 
00497     int err = fs->remove(fp.fileName());
00498     if (err < 0) {
00499         errno = -err;
00500         return -1;
00501     } else {
00502         return 0;
00503     }
00504 #else
00505     errno = ENOSYS;
00506     return -1;
00507 #endif
00508 }
00509 
00510 extern "C" int rename(const char *oldname, const char *newname) {
00511 #if MBED_CONF_FILESYSTEM_PRESENT
00512     errno = EBADF;
00513     FilePath fpOld(oldname);
00514     FilePath fpNew(newname);
00515     FileSystem *fsOld = fpOld.fileSystem();
00516     FileSystem *fsNew = fpNew.fileSystem();
00517 
00518     /* rename only if both files are on the same FS */
00519     if (fsOld != fsNew || fsOld == NULL) return -1;
00520 
00521     int err = fsOld->rename(fpOld.fileName(), fpNew.fileName());
00522     if (err < 0) {
00523         errno = -err;
00524         return -1;
00525     } else {
00526         return 0;
00527     }
00528 #else
00529     errno = ENOSYS;
00530     return -1;
00531 #endif
00532 }
00533 
00534 extern "C" char *tmpnam(char *s) {
00535     errno = EBADF;
00536     return NULL;
00537 }
00538 
00539 extern "C" FILE *tmpfile() {
00540     errno = EBADF;
00541     return NULL;
00542 }
00543 } // namespace std
00544 
00545 #ifdef __ARMCC_VERSION
00546 extern "C" char *_sys_command_string(char *cmd, int len) {
00547     return NULL;
00548 }
00549 #endif
00550 
00551 extern "C" DIR *opendir(const char *path) {
00552 #if MBED_CONF_FILESYSTEM_PRESENT
00553     errno = EBADF;
00554 
00555     FilePath fp(path);
00556     FileSystem* fs = fp.fileSystem();
00557     if (fs == NULL) return NULL;
00558 
00559     Dir *dir = new ManagedDir;
00560     int err = dir->open(fs, fp.fileName());
00561     if (err < 0) {
00562         errno = -err;
00563         delete dir;
00564         dir = NULL;
00565     }
00566 
00567     return dir;
00568 #else
00569     errno = ENOSYS;
00570     return 0;
00571 #endif
00572 }
00573 
00574 extern "C" struct dirent *readdir(DIR *dir) {
00575 #if MBED_CONF_FILESYSTEM_PRESENT
00576     static struct dirent ent;
00577     int err = dir->read(&ent);
00578     if (err < 1) {
00579         if (err < 0) {
00580             errno = -err;
00581         }
00582         return NULL;
00583     }
00584 
00585     return &ent;
00586 #else
00587     errno = ENOSYS;
00588     return 0;
00589 #endif
00590 }
00591 
00592 extern "C" int closedir(DIR *dir) {
00593 #if MBED_CONF_FILESYSTEM_PRESENT
00594     int err = dir->close();
00595     if (err < 0) {
00596         errno = -err;
00597         return -1;
00598     } else {
00599         return 0;
00600     }
00601 #else
00602     errno = ENOSYS;
00603     return -1;
00604 #endif
00605 }
00606 
00607 extern "C" void rewinddir(DIR *dir) {
00608 #if MBED_CONF_FILESYSTEM_PRESENT
00609     dir->rewind();
00610 #else
00611     errno = ENOSYS;
00612 #endif
00613 }
00614 
00615 extern "C" off_t telldir(DIR *dir) {
00616 #if MBED_CONF_FILESYSTEM_PRESENT
00617     return dir->tell();
00618 #else
00619     errno = ENOSYS;
00620     return 0;
00621 #endif
00622 }
00623 
00624 extern "C" void seekdir(DIR *dir, off_t off) {
00625 #if MBED_CONF_FILESYSTEM_PRESENT
00626     dir->seek(off);
00627 #else
00628     errno = ENOSYS;
00629 #endif
00630 }
00631 
00632 extern "C" int mkdir(const char *path, mode_t mode) {
00633 #if MBED_CONF_FILESYSTEM_PRESENT
00634     FilePath fp(path);
00635     FileSystem *fs = fp.fileSystem();
00636     if (fs == NULL) return -1;
00637 
00638     int err = fs->mkdir(fp.fileName(), mode);
00639     if (err < 0) {
00640         errno = -err;
00641         return -1;
00642     } else {
00643         return 0;
00644     }
00645 #else
00646     errno = ENOSYS;
00647     return -1;
00648 #endif
00649 }
00650 
00651 extern "C" int stat(const char *path, struct stat *st) {
00652 #if MBED_CONF_FILESYSTEM_PRESENT
00653     FilePath fp(path);
00654     FileSystem *fs = fp.fileSystem();
00655     if (fs == NULL) return -1;
00656 
00657     int err = fs->stat(fp.fileName(), st);
00658     if (err < 0) {
00659         errno = -err;
00660         return -1;
00661     } else {
00662         return 0;
00663     }
00664 #else
00665     errno = ENOSYS;
00666     return -1;
00667 #endif
00668 }
00669 
00670 #if defined(TOOLCHAIN_GCC)
00671 /* prevents the exception handling name demangling code getting pulled in */
00672 #include "mbed_error.h"
00673 namespace __gnu_cxx {
00674     void __verbose_terminate_handler() {
00675         error("Exception");
00676     }
00677 }
00678 extern "C" WEAK void __cxa_pure_virtual(void);
00679 extern "C" WEAK void __cxa_pure_virtual(void) {
00680     exit(1);
00681 }
00682 
00683 #endif
00684 
00685 #if defined(TOOLCHAIN_GCC)
00686 
00687 #ifdef  FEATURE_UVISOR
00688 #include "uvisor-lib/uvisor-lib.h"
00689 #endif/* FEATURE_UVISOR */
00690 
00691 
00692 extern "C" WEAK void software_init_hook_rtos(void)
00693 {
00694     // Do nothing by default.
00695 }
00696 
00697 extern "C" void software_init_hook(void)
00698 {
00699 #ifdef   FEATURE_UVISOR
00700     int return_code;
00701 
00702     return_code = uvisor_lib_init();
00703     if (return_code) {
00704         mbed_die();
00705     }
00706 #endif/* FEATURE_UVISOR */
00707     mbed_sdk_init();
00708     software_init_hook_rtos();
00709 }
00710 #endif
00711 
00712 // ****************************************************************************
00713 // mbed_main is a function that is called before main()
00714 // mbed_sdk_init() is also a function that is called before main(), but unlike
00715 // mbed_main(), it is not meant for user code, but for the SDK itself to perform
00716 // initializations before main() is called.
00717 
00718 extern "C" WEAK void mbed_main(void);
00719 extern "C" WEAK void mbed_main(void) {
00720 }
00721 
00722 #if defined(TOOLCHAIN_ARM)
00723 extern "C" int $Super$$main(void);
00724 
00725 extern "C" int $Sub$$main(void) {
00726     mbed_main();
00727     return $Super$$main();
00728 }
00729 
00730 extern "C" void _platform_post_stackheap_init (void) {
00731     mbed_sdk_init();
00732 }
00733 
00734 #elif defined(TOOLCHAIN_GCC)
00735 extern "C" int __real_main(void);
00736 
00737 extern "C" int __wrap_main(void) {
00738     mbed_main();
00739     return __real_main();
00740 }
00741 #elif defined(TOOLCHAIN_IAR)
00742 // IAR doesn't have the $Super/$Sub mechanism of armcc, nor something equivalent
00743 // to ld's --wrap. It does have a --redirect, but that doesn't help, since redirecting
00744 // 'main' to another symbol looses the original 'main' symbol. However, its startup
00745 // code will call a function to setup argc and argv (__iar_argc_argv) if it is defined.
00746 // Since mbed doesn't use argc/argv, we use this function to call our mbed_main.
00747 extern "C" void __iar_argc_argv() {
00748     mbed_main();
00749 }
00750 #endif
00751 
00752 // Provide implementation of _sbrk (low-level dynamic memory allocation
00753 // routine) for GCC_ARM which compares new heap pointer with MSP instead of
00754 // SP.  This make it compatible with RTX RTOS thread stacks.
00755 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
00756 // Linker defined symbol used by _sbrk to indicate where heap should start.
00757 extern "C" int __end__;
00758 
00759 #if defined(TARGET_CORTEX_A)
00760 extern "C" uint32_t  __HeapLimit;
00761 #endif
00762 
00763 // Turn off the errno macro and use actual global variable instead.
00764 #undef errno
00765 extern "C" int errno;
00766 
00767 // For ARM7 only
00768 register unsigned char * stack_ptr __asm ("sp");
00769 
00770 // Dynamic memory allocation related syscall.
00771 #if defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NUMAKER_PFM_M453)
00772 // Overwrite _sbrk() to support two region model (heap and stack are two distinct regions).
00773 // __wrap__sbrk() is implemented in:
00774 // TARGET_NUMAKER_PFM_NUC472    hal/targets/cmsis/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/retarget.c
00775 // TARGET_NUMAKER_PFM_M453      hal/targets/cmsis/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/TOOLCHAIN_GCC_ARM/retarget.c
00776 extern "C" void *__wrap__sbrk(int incr);
00777 extern "C" caddr_t _sbrk(int incr) {
00778     return (caddr_t) __wrap__sbrk(incr);
00779 }
00780 #else
00781 extern "C" caddr_t _sbrk(int incr) {
00782     static unsigned char* heap = (unsigned char*)&__end__;
00783     unsigned char*        prev_heap = heap;
00784     unsigned char*        new_heap = heap + incr;
00785 
00786 #if defined(TARGET_ARM7)
00787     if (new_heap >= stack_ptr) {
00788 #elif defined(TARGET_CORTEX_A)
00789     if (new_heap >= (unsigned char*)&__HeapLimit) {     /* __HeapLimit is end of heap section */
00790 #else
00791     if (new_heap >= (unsigned char*)__get_MSP()) {
00792 #endif
00793         errno = ENOMEM;
00794         return (caddr_t)-1;
00795     }
00796 
00797     // Additional heap checking if set
00798     if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) {
00799         errno = ENOMEM;
00800         return (caddr_t)-1;
00801     }
00802 
00803     heap = new_heap;
00804     return (caddr_t) prev_heap;
00805 }
00806 #endif
00807 #endif
00808 
00809 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
00810 extern "C" void _exit(int return_code) {
00811 #else
00812 namespace std {
00813 extern "C" void exit(int return_code) {
00814 #endif
00815 
00816 #if DEVICE_STDIO_MESSAGES
00817 #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT
00818     fflush(stdout);
00819     fflush(stderr);
00820 #endif
00821 #endif
00822 
00823 #if DEVICE_SEMIHOST
00824     if (mbed_interface_connected()) {
00825         semihost_exit();
00826     }
00827 #endif
00828     if (return_code) {
00829         mbed_die();
00830     }
00831 
00832     while (1);
00833 }
00834 
00835 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR)
00836 } //namespace std
00837 #endif
00838 
00839 #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC)
00840 
00841 // This series of function disable the registration of global destructors
00842 // in a dynamic table which will be called when the application exit.
00843 // In mbed, program never exit properly, it dies.
00844 // More informations about this topic for ARMCC here:
00845 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html
00846 extern "C" {
00847 int __aeabi_atexit(void *object, void (*dtor)(void* /*this*/), void *handle) {
00848     return 1;
00849 }
00850 
00851 int __cxa_atexit(void (*dtor)(void* /*this*/), void *object, void *handle) {
00852     return 1;
00853 }
00854 
00855 void __cxa_finalize(void *handle) {
00856 }
00857 
00858 } // end of extern "C"
00859 
00860 #endif
00861 
00862 
00863 #if defined(TOOLCHAIN_GCC)
00864 
00865 /*
00866  * Depending on how newlib is  configured, it is often not enough to define
00867  * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the
00868  * behavior regarding the registration of handlers with atexit.
00869  *
00870  * To overcome this limitation, exit and atexit are overriden here.
00871  */
00872 extern "C"{
00873 
00874 /**
00875  * @brief Retarget of exit for GCC.
00876  * @details Unlike the standard version, this function doesn't call any function
00877  * registered with atexit before calling _exit.
00878  */
00879 void __wrap_exit(int return_code) {
00880     _exit(return_code);
00881 }
00882 
00883 /**
00884  * @brief Retarget atexit from GCC.
00885  * @details This function will always fail and never register any handler to be
00886  * called at exit.
00887  */
00888 int __wrap_atexit(void (*func)()) {
00889     return 1;
00890 }
00891 
00892 }
00893 
00894 #endif
00895 
00896 
00897 
00898 namespace mbed {
00899 
00900 void mbed_set_unbuffered_stream(FILE *_file) {
00901 #if defined (__ICCARM__)
00902     char buf[2];
00903     std::setvbuf(_file,buf,_IONBF,NULL);    
00904 #else
00905     setbuf(_file, NULL);
00906 #endif
00907 }
00908 
00909 int mbed_getc(FILE *_file){
00910 #if defined (__ICCARM__)
00911     /*This is only valid for unbuffered streams*/
00912     int res = std::fgetc(_file);
00913     if (res>=0){
00914         _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
00915         _file->_Rend = _file->_Wend;
00916         _file->_Next = _file->_Wend;
00917     }    
00918     return res;
00919 #else    
00920     return std::fgetc(_file);
00921 #endif   
00922 }
00923 
00924 char* mbed_gets(char*s, int size, FILE *_file){
00925 #if defined (__ICCARM__)
00926     /*This is only valid for unbuffered streams*/
00927     char *str = fgets(s,size,_file);
00928     if (str!=NULL){
00929         _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
00930         _file->_Rend = _file->_Wend;
00931         _file->_Next = _file->_Wend;
00932     }
00933     return str;
00934 #else    
00935     return std::fgets(s,size,_file);
00936 #endif
00937 }
00938 
00939 } // namespace mbed
00940 
00941 #if defined (__ICCARM__)
00942 // Stub out locks when an rtos is not present
00943 extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {}
00944 extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {}
00945 extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {}
00946 extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {}
00947 extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {}
00948 extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {}
00949 extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {}
00950 extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {}
00951 #elif defined(__CC_ARM)
00952 // Do nothing
00953 #elif defined (__GNUC__)
00954 struct _reent;
00955 // Stub out locks when an rtos is not present
00956 extern "C" WEAK void __rtos_malloc_lock( struct _reent *_r ) {}
00957 extern "C" WEAK void __rtos_malloc_unlock( struct _reent *_r ) {}
00958 extern "C" WEAK void __rtos_env_lock( struct _reent *_r ) {}
00959 extern "C" WEAK void __rtos_env_unlock( struct _reent *_r ) {}
00960 
00961 extern "C" void __malloc_lock( struct _reent *_r )
00962 {
00963     __rtos_malloc_lock(_r);
00964 }
00965 
00966 extern "C" void __malloc_unlock( struct _reent *_r )
00967 {
00968     __rtos_malloc_unlock(_r);
00969 }
00970 
00971 extern "C" void __env_lock( struct _reent *_r )
00972 {
00973     __rtos_env_lock(_r);
00974 }
00975 
00976 extern "C" void __env_unlock( struct _reent *_r )
00977 {
00978     __rtos_env_unlock(_r);
00979 }
00980 
00981 #define CXA_GUARD_INIT_DONE             (1 << 0)
00982 #define CXA_GUARD_INIT_IN_PROGRESS      (1 << 1)
00983 #define CXA_GUARD_MASK                  (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS)
00984 
00985 extern "C" int __cxa_guard_acquire(int *guard_object_p)
00986 {
00987     uint8_t *guard_object = (uint8_t *)guard_object_p;
00988     if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
00989         return 0;
00990     }
00991     singleton_lock();
00992     if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
00993         singleton_unlock();
00994         return 0;
00995     }
00996     MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK));
00997     *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS;
00998     return 1;
00999 }
01000 
01001 extern "C" void __cxa_guard_release(int *guard_object_p)
01002 {
01003     uint8_t *guard_object = (uint8_t *)guard_object_p;
01004     MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
01005     *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE;
01006     singleton_unlock();
01007 }
01008 
01009 extern "C" void __cxa_guard_abort(int *guard_object_p)
01010 {
01011     uint8_t *guard_object = (uint8_t *)guard_object_p;
01012     MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
01013     *guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS;
01014     singleton_unlock();
01015 }
01016 
01017 #endif
01018 
01019 void *operator new(std::size_t count)
01020 {
01021     void *buffer = malloc(count);
01022     if (NULL == buffer) {
01023         error("Operator new out of memory\r\n");
01024     }
01025     return buffer;
01026 }
01027 
01028 void *operator new[](std::size_t count)
01029 {
01030     void *buffer = malloc(count);
01031     if (NULL == buffer) {
01032         error("Operator new[] out of memory\r\n");
01033     }
01034     return buffer;
01035 }
01036 
01037 void operator delete(void *ptr)
01038 {
01039     if (ptr != NULL) {
01040         free(ptr);
01041     }
01042 }
01043 void operator delete[](void *ptr)
01044 {
01045     if (ptr != NULL) {
01046         free(ptr);
01047     }
01048 }