mbed-os

Fork of mbed-os by erkin yucel

Committer:
xuaner
Date:
Thu Jul 20 14:26:57 2017 +0000
Revision:
1:3deb71413561
Parent:
0:f269e3021894
mbed_os

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 /* mbed Microcontroller Library
elessair 0:f269e3021894 2 * Copyright (c) 2006-2015 ARM Limited
elessair 0:f269e3021894 3 *
elessair 0:f269e3021894 4 * Licensed under the Apache License, Version 2.0 (the "License");
elessair 0:f269e3021894 5 * you may not use this file except in compliance with the License.
elessair 0:f269e3021894 6 * You may obtain a copy of the License at
elessair 0:f269e3021894 7 *
elessair 0:f269e3021894 8 * http://www.apache.org/licenses/LICENSE-2.0
elessair 0:f269e3021894 9 *
elessair 0:f269e3021894 10 * Unless required by applicable law or agreed to in writing, software
elessair 0:f269e3021894 11 * distributed under the License is distributed on an "AS IS" BASIS,
elessair 0:f269e3021894 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
elessair 0:f269e3021894 13 * See the License for the specific language governing permissions and
elessair 0:f269e3021894 14 * limitations under the License.
elessair 0:f269e3021894 15 */
elessair 0:f269e3021894 16 #include "platform/platform.h"
elessair 0:f269e3021894 17 #include "drivers/FileHandle.h"
elessair 0:f269e3021894 18 #include "drivers/FileSystemLike.h"
elessair 0:f269e3021894 19 #include "drivers/FilePath.h"
elessair 0:f269e3021894 20 #include "hal/serial_api.h"
elessair 0:f269e3021894 21 #include "platform/toolchain.h"
elessair 0:f269e3021894 22 #include "platform/semihost_api.h"
elessair 0:f269e3021894 23 #include "platform/mbed_interface.h"
elessair 0:f269e3021894 24 #include "platform/SingletonPtr.h"
elessair 0:f269e3021894 25 #include "platform/PlatformMutex.h"
elessair 0:f269e3021894 26 #include "platform/mbed_error.h"
elessair 0:f269e3021894 27 #include "platform/mbed_stats.h"
elessair 0:f269e3021894 28 #include <stdlib.h>
elessair 0:f269e3021894 29 #include <string.h>
elessair 0:f269e3021894 30 #if DEVICE_STDIO_MESSAGES
elessair 0:f269e3021894 31 #include <stdio.h>
elessair 0:f269e3021894 32 #endif
elessair 0:f269e3021894 33 #include <errno.h>
elessair 0:f269e3021894 34
elessair 0:f269e3021894 35 #if defined(__ARMCC_VERSION)
elessair 0:f269e3021894 36 # include <rt_sys.h>
elessair 0:f269e3021894 37 # define PREFIX(x) _sys##x
elessair 0:f269e3021894 38 # define OPEN_MAX _SYS_OPEN
elessair 0:f269e3021894 39 # ifdef __MICROLIB
elessair 0:f269e3021894 40 # pragma import(__use_full_stdio)
elessair 0:f269e3021894 41 # endif
elessair 0:f269e3021894 42
elessair 0:f269e3021894 43 #elif defined(__ICCARM__)
elessair 0:f269e3021894 44 # include <yfuns.h>
elessair 0:f269e3021894 45 # define PREFIX(x) _##x
elessair 0:f269e3021894 46 # define OPEN_MAX 16
elessair 0:f269e3021894 47
elessair 0:f269e3021894 48 # define STDIN_FILENO 0
elessair 0:f269e3021894 49 # define STDOUT_FILENO 1
elessair 0:f269e3021894 50 # define STDERR_FILENO 2
elessair 0:f269e3021894 51
elessair 0:f269e3021894 52 #else
elessair 0:f269e3021894 53 # include <sys/stat.h>
elessair 0:f269e3021894 54 # include <sys/unistd.h>
elessair 0:f269e3021894 55 # include <sys/syslimits.h>
elessair 0:f269e3021894 56 # define PREFIX(x) x
elessair 0:f269e3021894 57 #endif
elessair 0:f269e3021894 58
elessair 0:f269e3021894 59 #define FILE_HANDLE_RESERVED 0xFFFFFFFF
elessair 0:f269e3021894 60
elessair 0:f269e3021894 61 using namespace mbed;
elessair 0:f269e3021894 62
elessair 0:f269e3021894 63 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
elessair 0:f269e3021894 64 // Before version 5.03, we were using a patched version of microlib with proper names
elessair 0:f269e3021894 65 extern const char __stdin_name[] = ":tt";
elessair 0:f269e3021894 66 extern const char __stdout_name[] = ":tt";
elessair 0:f269e3021894 67 extern const char __stderr_name[] = ":tt";
elessair 0:f269e3021894 68
elessair 0:f269e3021894 69 #else
elessair 0:f269e3021894 70 extern const char __stdin_name[] = "/stdin";
elessair 0:f269e3021894 71 extern const char __stdout_name[] = "/stdout";
elessair 0:f269e3021894 72 extern const char __stderr_name[] = "/stderr";
elessair 0:f269e3021894 73 #endif
elessair 0:f269e3021894 74
elessair 0:f269e3021894 75 // Heap limits - only used if set
elessair 0:f269e3021894 76 unsigned char *mbed_heap_start = 0;
elessair 0:f269e3021894 77 uint32_t mbed_heap_size = 0;
elessair 0:f269e3021894 78
elessair 0:f269e3021894 79 /* newlib has the filehandle field in the FILE struct as a short, so
elessair 0:f269e3021894 80 * we can't just return a Filehandle* from _open and instead have to
elessair 0:f269e3021894 81 * put it in a filehandles array and return the index into that array
elessair 0:f269e3021894 82 * (or rather index+3, as filehandles 0-2 are stdin/out/err).
elessair 0:f269e3021894 83 */
elessair 0:f269e3021894 84 static FileHandle *filehandles[OPEN_MAX];
elessair 0:f269e3021894 85 static SingletonPtr<PlatformMutex> filehandle_mutex;
elessair 0:f269e3021894 86
elessair 0:f269e3021894 87 FileHandle::~FileHandle() {
elessair 0:f269e3021894 88 filehandle_mutex->lock();
elessair 0:f269e3021894 89 /* Remove all open filehandles for this */
elessair 0:f269e3021894 90 for (unsigned int fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) {
elessair 0:f269e3021894 91 if (filehandles[fh_i] == this) {
elessair 0:f269e3021894 92 filehandles[fh_i] = NULL;
elessair 0:f269e3021894 93 }
elessair 0:f269e3021894 94 }
elessair 0:f269e3021894 95 filehandle_mutex->unlock();
elessair 0:f269e3021894 96 }
elessair 0:f269e3021894 97
elessair 0:f269e3021894 98 #if DEVICE_SERIAL
elessair 0:f269e3021894 99 extern int stdio_uart_inited;
elessair 0:f269e3021894 100 extern serial_t stdio_uart;
elessair 0:f269e3021894 101 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
elessair 0:f269e3021894 102 static char stdio_in_prev;
elessair 0:f269e3021894 103 static char stdio_out_prev;
elessair 0:f269e3021894 104 #endif
elessair 0:f269e3021894 105 #endif
elessair 0:f269e3021894 106
elessair 0:f269e3021894 107 static void init_serial() {
elessair 0:f269e3021894 108 #if DEVICE_SERIAL
elessair 0:f269e3021894 109 if (stdio_uart_inited) return;
elessair 0:f269e3021894 110 serial_init(&stdio_uart, STDIO_UART_TX, STDIO_UART_RX);
elessair 0:f269e3021894 111 #if MBED_CONF_PLATFORM_STDIO_BAUD_RATE
elessair 0:f269e3021894 112 serial_baud(&stdio_uart, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
elessair 0:f269e3021894 113 #endif
elessair 0:f269e3021894 114 #endif
elessair 0:f269e3021894 115 }
elessair 0:f269e3021894 116
elessair 0:f269e3021894 117 static inline int openmode_to_posix(int openmode) {
elessair 0:f269e3021894 118 int posix = openmode;
elessair 0:f269e3021894 119 #ifdef __ARMCC_VERSION
elessair 0:f269e3021894 120 if (openmode & OPEN_PLUS) {
elessair 0:f269e3021894 121 posix = O_RDWR;
elessair 0:f269e3021894 122 } else if(openmode & OPEN_W) {
elessair 0:f269e3021894 123 posix = O_WRONLY;
elessair 0:f269e3021894 124 } else if(openmode & OPEN_A) {
elessair 0:f269e3021894 125 posix = O_WRONLY|O_APPEND;
elessair 0:f269e3021894 126 } else {
elessair 0:f269e3021894 127 posix = O_RDONLY;
elessair 0:f269e3021894 128 }
elessair 0:f269e3021894 129 /* a, w, a+, w+ all create if file does not already exist */
elessair 0:f269e3021894 130 if (openmode & (OPEN_A|OPEN_W)) {
elessair 0:f269e3021894 131 posix |= O_CREAT;
elessair 0:f269e3021894 132 }
elessair 0:f269e3021894 133 /* w and w+ truncate */
elessair 0:f269e3021894 134 if (openmode & OPEN_W) {
elessair 0:f269e3021894 135 posix |= O_TRUNC;
elessair 0:f269e3021894 136 }
elessair 0:f269e3021894 137 #elif defined(__ICCARM__)
elessair 0:f269e3021894 138 switch (openmode & _LLIO_RDWRMASK) {
elessair 0:f269e3021894 139 case _LLIO_RDONLY: posix = O_RDONLY; break;
elessair 0:f269e3021894 140 case _LLIO_WRONLY: posix = O_WRONLY; break;
elessair 0:f269e3021894 141 case _LLIO_RDWR : posix = O_RDWR ; break;
elessair 0:f269e3021894 142 }
elessair 0:f269e3021894 143 if (openmode & _LLIO_CREAT ) posix |= O_CREAT;
elessair 0:f269e3021894 144 if (openmode & _LLIO_APPEND) posix |= O_APPEND;
elessair 0:f269e3021894 145 if (openmode & _LLIO_TRUNC ) posix |= O_TRUNC;
elessair 0:f269e3021894 146 #elif defined(TOOLCHAIN_GCC)
elessair 0:f269e3021894 147 posix &= ~O_BINARY;
elessair 0:f269e3021894 148 #endif
elessair 0:f269e3021894 149 return posix;
elessair 0:f269e3021894 150 }
elessair 0:f269e3021894 151
elessair 0:f269e3021894 152 extern "C" WEAK void mbed_sdk_init(void);
elessair 0:f269e3021894 153 extern "C" WEAK void mbed_sdk_init(void) {
elessair 0:f269e3021894 154 }
elessair 0:f269e3021894 155
elessair 0:f269e3021894 156 extern "C" FILEHANDLE PREFIX(_open)(const char* name, int openmode) {
elessair 0:f269e3021894 157 #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
elessair 0:f269e3021894 158 // Before version 5.03, we were using a patched version of microlib with proper names
elessair 0:f269e3021894 159 // This is the workaround that the microlib author suggested us
elessair 0:f269e3021894 160 static int n = 0;
elessair 0:f269e3021894 161 static int mbed_sdk_inited = 0;
elessair 0:f269e3021894 162 if (!mbed_sdk_inited) {
elessair 0:f269e3021894 163 mbed_sdk_inited = 1;
elessair 0:f269e3021894 164 mbed_sdk_init();
elessair 0:f269e3021894 165 }
elessair 0:f269e3021894 166 if (!std::strcmp(name, ":tt")) return n++;
elessair 0:f269e3021894 167 #else
elessair 0:f269e3021894 168 /* Use the posix convention that stdin,out,err are filehandles 0,1,2.
elessair 0:f269e3021894 169 */
elessair 0:f269e3021894 170 if (std::strcmp(name, __stdin_name) == 0) {
elessair 0:f269e3021894 171 init_serial();
elessair 0:f269e3021894 172 return 0;
elessair 0:f269e3021894 173 } else if (std::strcmp(name, __stdout_name) == 0) {
elessair 0:f269e3021894 174 init_serial();
elessair 0:f269e3021894 175 return 1;
elessair 0:f269e3021894 176 } else if (std::strcmp(name, __stderr_name) == 0) {
elessair 0:f269e3021894 177 init_serial();
elessair 0:f269e3021894 178 return 2;
elessair 0:f269e3021894 179 }
elessair 0:f269e3021894 180 #endif
elessair 0:f269e3021894 181
elessair 0:f269e3021894 182 // find the first empty slot in filehandles
elessair 0:f269e3021894 183 filehandle_mutex->lock();
elessair 0:f269e3021894 184 unsigned int fh_i;
elessair 0:f269e3021894 185 for (fh_i = 0; fh_i < sizeof(filehandles)/sizeof(*filehandles); fh_i++) {
elessair 0:f269e3021894 186 if (filehandles[fh_i] == NULL) break;
elessair 0:f269e3021894 187 }
elessair 0:f269e3021894 188 if (fh_i >= sizeof(filehandles)/sizeof(*filehandles)) {
elessair 0:f269e3021894 189 filehandle_mutex->unlock();
elessair 0:f269e3021894 190 return -1;
elessair 0:f269e3021894 191 }
elessair 0:f269e3021894 192 filehandles[fh_i] = (FileHandle*)FILE_HANDLE_RESERVED;
elessair 0:f269e3021894 193 filehandle_mutex->unlock();
elessair 0:f269e3021894 194
elessair 0:f269e3021894 195 FileHandle *res;
elessair 0:f269e3021894 196
elessair 0:f269e3021894 197 /* FILENAME: ":0x12345678" describes a FileLike* */
elessair 0:f269e3021894 198 if (name[0] == ':') {
elessair 0:f269e3021894 199 void *p;
elessair 0:f269e3021894 200 sscanf(name, ":%p", &p);
elessair 0:f269e3021894 201 res = (FileHandle*)p;
elessair 0:f269e3021894 202
elessair 0:f269e3021894 203 /* FILENAME: "/file_system/file_name" */
elessair 0:f269e3021894 204 } else {
elessair 0:f269e3021894 205 FilePath path(name);
elessair 0:f269e3021894 206
elessair 0:f269e3021894 207 if (!path.exists()) {
elessair 0:f269e3021894 208 // Free file handle
elessair 0:f269e3021894 209 filehandles[fh_i] = NULL;
elessair 0:f269e3021894 210 return -1;
elessair 0:f269e3021894 211 } else if (path.isFile()) {
elessair 0:f269e3021894 212 res = path.file();
elessair 0:f269e3021894 213 } else {
elessair 0:f269e3021894 214 FileSystemLike *fs = path.fileSystem();
elessair 0:f269e3021894 215 if (fs == NULL) {
elessair 0:f269e3021894 216 // Free file handle
elessair 0:f269e3021894 217 filehandles[fh_i] = NULL;
elessair 0:f269e3021894 218 return -1;
elessair 0:f269e3021894 219 }
elessair 0:f269e3021894 220 int posix_mode = openmode_to_posix(openmode);
elessair 0:f269e3021894 221 res = fs->open(path.fileName(), posix_mode); /* NULL if fails */
elessair 0:f269e3021894 222 }
elessair 0:f269e3021894 223 }
elessair 0:f269e3021894 224
elessair 0:f269e3021894 225 if (res == NULL) {
elessair 0:f269e3021894 226 // Free file handle
elessair 0:f269e3021894 227 filehandles[fh_i] = NULL;
elessair 0:f269e3021894 228 return -1;
elessair 0:f269e3021894 229 }
elessair 0:f269e3021894 230 filehandles[fh_i] = res;
elessair 0:f269e3021894 231
elessair 0:f269e3021894 232 return fh_i + 3; // +3 as filehandles 0-2 are stdin/out/err
elessair 0:f269e3021894 233 }
elessair 0:f269e3021894 234
elessair 0:f269e3021894 235 extern "C" int PREFIX(_close)(FILEHANDLE fh) {
elessair 0:f269e3021894 236 if (fh < 3) return 0;
elessair 0:f269e3021894 237
elessair 0:f269e3021894 238 FileHandle* fhc = filehandles[fh-3];
elessair 0:f269e3021894 239 filehandles[fh-3] = NULL;
elessair 0:f269e3021894 240 if (fhc == NULL) return -1;
elessair 0:f269e3021894 241
elessair 0:f269e3021894 242 return fhc->close();
elessair 0:f269e3021894 243 }
elessair 0:f269e3021894 244
elessair 0:f269e3021894 245 #if defined(__ICCARM__)
elessair 0:f269e3021894 246 extern "C" size_t __write (int fh, const unsigned char *buffer, size_t length) {
elessair 0:f269e3021894 247 #else
elessair 0:f269e3021894 248 extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode) {
elessair 0:f269e3021894 249 #endif
elessair 0:f269e3021894 250 int n; // n is the number of bytes written
elessair 0:f269e3021894 251 if (fh < 3) {
elessair 0:f269e3021894 252 #if DEVICE_SERIAL
elessair 0:f269e3021894 253 if (!stdio_uart_inited) init_serial();
elessair 0:f269e3021894 254 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
elessair 0:f269e3021894 255 for (unsigned int i = 0; i < length; i++) {
elessair 0:f269e3021894 256 if (buffer[i] == '\n' && stdio_out_prev != '\r') {
elessair 0:f269e3021894 257 serial_putc(&stdio_uart, '\r');
elessair 0:f269e3021894 258 }
elessair 0:f269e3021894 259 serial_putc(&stdio_uart, buffer[i]);
elessair 0:f269e3021894 260 stdio_out_prev = buffer[i];
elessair 0:f269e3021894 261 }
elessair 0:f269e3021894 262 #else
elessair 0:f269e3021894 263 for (unsigned int i = 0; i < length; i++) {
elessair 0:f269e3021894 264 serial_putc(&stdio_uart, buffer[i]);
elessair 0:f269e3021894 265 }
elessair 0:f269e3021894 266 #endif
elessair 0:f269e3021894 267 #endif
elessair 0:f269e3021894 268 n = length;
elessair 0:f269e3021894 269 } else {
elessair 0:f269e3021894 270 FileHandle* fhc = filehandles[fh-3];
elessair 0:f269e3021894 271 if (fhc == NULL) return -1;
elessair 0:f269e3021894 272
elessair 0:f269e3021894 273 n = fhc->write(buffer, length);
elessair 0:f269e3021894 274 }
elessair 0:f269e3021894 275 #ifdef __ARMCC_VERSION
elessair 0:f269e3021894 276 return length-n;
elessair 0:f269e3021894 277 #else
elessair 0:f269e3021894 278 return n;
elessair 0:f269e3021894 279 #endif
elessair 0:f269e3021894 280 }
elessair 0:f269e3021894 281
elessair 0:f269e3021894 282 #if defined(__ICCARM__)
elessair 0:f269e3021894 283 extern "C" size_t __read (int fh, unsigned char *buffer, size_t length) {
elessair 0:f269e3021894 284 #else
elessair 0:f269e3021894 285 extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode) {
elessair 0:f269e3021894 286 #endif
elessair 0:f269e3021894 287 int n; // n is the number of bytes read
elessair 0:f269e3021894 288 if (fh < 3) {
elessair 0:f269e3021894 289 // only read a character at a time from stdin
elessair 0:f269e3021894 290 #if DEVICE_SERIAL
elessair 0:f269e3021894 291 if (!stdio_uart_inited) init_serial();
elessair 0:f269e3021894 292 #if MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
elessair 0:f269e3021894 293 while (true) {
elessair 0:f269e3021894 294 char c = serial_getc(&stdio_uart);
elessair 0:f269e3021894 295 if ((c == '\r' && stdio_in_prev != '\n') ||
elessair 0:f269e3021894 296 (c == '\n' && stdio_in_prev != '\r')) {
elessair 0:f269e3021894 297 stdio_in_prev = c;
elessair 0:f269e3021894 298 *buffer = '\n';
elessair 0:f269e3021894 299 break;
elessair 0:f269e3021894 300 } else if ((c == '\r' && stdio_in_prev == '\n') ||
elessair 0:f269e3021894 301 (c == '\n' && stdio_in_prev == '\r')) {
elessair 0:f269e3021894 302 stdio_in_prev = c;
elessair 0:f269e3021894 303 // onto next character
elessair 0:f269e3021894 304 continue;
elessair 0:f269e3021894 305 } else {
elessair 0:f269e3021894 306 stdio_in_prev = c;
elessair 0:f269e3021894 307 *buffer = c;
elessair 0:f269e3021894 308 break;
elessair 0:f269e3021894 309 }
elessair 0:f269e3021894 310 }
elessair 0:f269e3021894 311 #else
elessair 0:f269e3021894 312 *buffer = serial_getc(&stdio_uart);
elessair 0:f269e3021894 313 #endif
elessair 0:f269e3021894 314 #endif
elessair 0:f269e3021894 315 n = 1;
elessair 0:f269e3021894 316 } else {
elessair 0:f269e3021894 317 FileHandle* fhc = filehandles[fh-3];
elessair 0:f269e3021894 318 if (fhc == NULL) return -1;
elessair 0:f269e3021894 319
elessair 0:f269e3021894 320 n = fhc->read(buffer, length);
elessair 0:f269e3021894 321 }
elessair 0:f269e3021894 322 #ifdef __ARMCC_VERSION
elessair 0:f269e3021894 323 return length-n;
elessair 0:f269e3021894 324 #else
elessair 0:f269e3021894 325 return n;
elessair 0:f269e3021894 326 #endif
elessair 0:f269e3021894 327 }
elessair 0:f269e3021894 328
elessair 0:f269e3021894 329 #ifdef __ARMCC_VERSION
elessair 0:f269e3021894 330 extern "C" int PREFIX(_istty)(FILEHANDLE fh)
elessair 0:f269e3021894 331 #else
elessair 0:f269e3021894 332 extern "C" int _isatty(FILEHANDLE fh)
elessair 0:f269e3021894 333 #endif
elessair 0:f269e3021894 334 {
elessair 0:f269e3021894 335 /* stdin, stdout and stderr should be tty */
elessair 0:f269e3021894 336 if (fh < 3) return 1;
elessair 0:f269e3021894 337
elessair 0:f269e3021894 338 FileHandle* fhc = filehandles[fh-3];
elessair 0:f269e3021894 339 if (fhc == NULL) return -1;
elessair 0:f269e3021894 340
elessair 0:f269e3021894 341 return fhc->isatty();
elessair 0:f269e3021894 342 }
elessair 0:f269e3021894 343
elessair 0:f269e3021894 344 extern "C"
elessair 0:f269e3021894 345 #if defined(__ARMCC_VERSION)
elessair 0:f269e3021894 346 int _sys_seek(FILEHANDLE fh, long position)
elessair 0:f269e3021894 347 #elif defined(__ICCARM__)
elessair 0:f269e3021894 348 long __lseek(int fh, long offset, int whence)
elessair 0:f269e3021894 349 #else
elessair 0:f269e3021894 350 int _lseek(FILEHANDLE fh, int offset, int whence)
elessair 0:f269e3021894 351 #endif
elessair 0:f269e3021894 352 {
elessair 0:f269e3021894 353 if (fh < 3) return 0;
elessair 0:f269e3021894 354
elessair 0:f269e3021894 355 FileHandle* fhc = filehandles[fh-3];
elessair 0:f269e3021894 356 if (fhc == NULL) return -1;
elessair 0:f269e3021894 357
elessair 0:f269e3021894 358 #if defined(__ARMCC_VERSION)
elessair 0:f269e3021894 359 return fhc->lseek(position, SEEK_SET);
elessair 0:f269e3021894 360 #else
elessair 0:f269e3021894 361 return fhc->lseek(offset, whence);
elessair 0:f269e3021894 362 #endif
elessair 0:f269e3021894 363 }
elessair 0:f269e3021894 364
elessair 0:f269e3021894 365 #ifdef __ARMCC_VERSION
elessair 0:f269e3021894 366 extern "C" int PREFIX(_ensure)(FILEHANDLE fh) {
elessair 0:f269e3021894 367 if (fh < 3) return 0;
elessair 0:f269e3021894 368
elessair 0:f269e3021894 369 FileHandle* fhc = filehandles[fh-3];
elessair 0:f269e3021894 370 if (fhc == NULL) return -1;
elessair 0:f269e3021894 371
elessair 0:f269e3021894 372 return fhc->fsync();
elessair 0:f269e3021894 373 }
elessair 0:f269e3021894 374
elessair 0:f269e3021894 375 extern "C" long PREFIX(_flen)(FILEHANDLE fh) {
elessair 0:f269e3021894 376 if (fh < 3) return 0;
elessair 0:f269e3021894 377
elessair 0:f269e3021894 378 FileHandle* fhc = filehandles[fh-3];
elessair 0:f269e3021894 379 if (fhc == NULL) return -1;
elessair 0:f269e3021894 380
elessair 0:f269e3021894 381 return fhc->flen();
elessair 0:f269e3021894 382 }
elessair 0:f269e3021894 383 #endif
elessair 0:f269e3021894 384
elessair 0:f269e3021894 385
elessair 0:f269e3021894 386 #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__)
elessair 0:f269e3021894 387 extern "C" int _fstat(int fd, struct stat *st) {
elessair 0:f269e3021894 388 if ((STDOUT_FILENO == fd) || (STDERR_FILENO == fd) || (STDIN_FILENO == fd)) {
elessair 0:f269e3021894 389 st->st_mode = S_IFCHR;
elessair 0:f269e3021894 390 return 0;
elessair 0:f269e3021894 391 }
elessair 0:f269e3021894 392
elessair 0:f269e3021894 393 errno = EBADF;
elessair 0:f269e3021894 394 return -1;
elessair 0:f269e3021894 395 }
elessair 0:f269e3021894 396 #endif
elessair 0:f269e3021894 397
elessair 0:f269e3021894 398 namespace std {
elessair 0:f269e3021894 399 extern "C" int remove(const char *path) {
elessair 0:f269e3021894 400 FilePath fp(path);
elessair 0:f269e3021894 401 FileSystemLike *fs = fp.fileSystem();
elessair 0:f269e3021894 402 if (fs == NULL) return -1;
elessair 0:f269e3021894 403
elessair 0:f269e3021894 404 return fs->remove(fp.fileName());
elessair 0:f269e3021894 405 }
elessair 0:f269e3021894 406
elessair 0:f269e3021894 407 extern "C" int rename(const char *oldname, const char *newname) {
elessair 0:f269e3021894 408 FilePath fpOld(oldname);
elessair 0:f269e3021894 409 FilePath fpNew(newname);
elessair 0:f269e3021894 410 FileSystemLike *fsOld = fpOld.fileSystem();
elessair 0:f269e3021894 411 FileSystemLike *fsNew = fpNew.fileSystem();
elessair 0:f269e3021894 412
elessair 0:f269e3021894 413 /* rename only if both files are on the same FS */
elessair 0:f269e3021894 414 if (fsOld != fsNew || fsOld == NULL) return -1;
elessair 0:f269e3021894 415
elessair 0:f269e3021894 416 return fsOld->rename(fpOld.fileName(), fpNew.fileName());
elessair 0:f269e3021894 417 }
elessair 0:f269e3021894 418
elessair 0:f269e3021894 419 extern "C" char *tmpnam(char *s) {
elessair 0:f269e3021894 420 return NULL;
elessair 0:f269e3021894 421 }
elessair 0:f269e3021894 422
elessair 0:f269e3021894 423 extern "C" FILE *tmpfile() {
elessair 0:f269e3021894 424 return NULL;
elessair 0:f269e3021894 425 }
elessair 0:f269e3021894 426 } // namespace std
elessair 0:f269e3021894 427
elessair 0:f269e3021894 428 #ifdef __ARMCC_VERSION
elessair 0:f269e3021894 429 extern "C" char *_sys_command_string(char *cmd, int len) {
elessair 0:f269e3021894 430 return NULL;
elessair 0:f269e3021894 431 }
elessair 0:f269e3021894 432 #endif
elessair 0:f269e3021894 433
elessair 0:f269e3021894 434 extern "C" DIR *opendir(const char *path) {
elessair 0:f269e3021894 435 /* root dir is FileSystemLike */
elessair 0:f269e3021894 436 if (path[0] == '/' && path[1] == 0) {
elessair 0:f269e3021894 437 return FileSystemLike::opendir();
elessair 0:f269e3021894 438 }
elessair 0:f269e3021894 439
elessair 0:f269e3021894 440 FilePath fp(path);
elessair 0:f269e3021894 441 FileSystemLike* fs = fp.fileSystem();
elessair 0:f269e3021894 442 if (fs == NULL) return NULL;
elessair 0:f269e3021894 443
elessair 0:f269e3021894 444 return fs->opendir(fp.fileName());
elessair 0:f269e3021894 445 }
elessair 0:f269e3021894 446
elessair 0:f269e3021894 447 extern "C" struct dirent *readdir(DIR *dir) {
elessair 0:f269e3021894 448 return dir->readdir();
elessair 0:f269e3021894 449 }
elessair 0:f269e3021894 450
elessair 0:f269e3021894 451 extern "C" int closedir(DIR *dir) {
elessair 0:f269e3021894 452 return dir->closedir();
elessair 0:f269e3021894 453 }
elessair 0:f269e3021894 454
elessair 0:f269e3021894 455 extern "C" void rewinddir(DIR *dir) {
elessair 0:f269e3021894 456 dir->rewinddir();
elessair 0:f269e3021894 457 }
elessair 0:f269e3021894 458
elessair 0:f269e3021894 459 extern "C" off_t telldir(DIR *dir) {
elessair 0:f269e3021894 460 return dir->telldir();
elessair 0:f269e3021894 461 }
elessair 0:f269e3021894 462
elessair 0:f269e3021894 463 extern "C" void seekdir(DIR *dir, off_t off) {
elessair 0:f269e3021894 464 dir->seekdir(off);
elessair 0:f269e3021894 465 }
elessair 0:f269e3021894 466
elessair 0:f269e3021894 467 extern "C" int mkdir(const char *path, mode_t mode) {
elessair 0:f269e3021894 468 FilePath fp(path);
elessair 0:f269e3021894 469 FileSystemLike *fs = fp.fileSystem();
elessair 0:f269e3021894 470 if (fs == NULL) return -1;
elessair 0:f269e3021894 471
elessair 0:f269e3021894 472 return fs->mkdir(fp.fileName(), mode);
elessair 0:f269e3021894 473 }
elessair 0:f269e3021894 474
elessair 0:f269e3021894 475 #if defined(TOOLCHAIN_GCC)
elessair 0:f269e3021894 476 /* prevents the exception handling name demangling code getting pulled in */
elessair 0:f269e3021894 477 #include "mbed_error.h"
elessair 0:f269e3021894 478 namespace __gnu_cxx {
elessair 0:f269e3021894 479 void __verbose_terminate_handler() {
elessair 0:f269e3021894 480 error("Exception");
elessair 0:f269e3021894 481 }
elessair 0:f269e3021894 482 }
elessair 0:f269e3021894 483 extern "C" WEAK void __cxa_pure_virtual(void);
elessair 0:f269e3021894 484 extern "C" WEAK void __cxa_pure_virtual(void) {
elessair 0:f269e3021894 485 exit(1);
elessair 0:f269e3021894 486 }
elessair 0:f269e3021894 487
elessair 0:f269e3021894 488 #endif
elessair 0:f269e3021894 489
elessair 0:f269e3021894 490 #if defined(TOOLCHAIN_GCC)
elessair 0:f269e3021894 491
elessair 0:f269e3021894 492 #ifdef FEATURE_UVISOR
elessair 0:f269e3021894 493 #include "uvisor-lib/uvisor-lib.h"
elessair 0:f269e3021894 494 #endif/* FEATURE_UVISOR */
elessair 0:f269e3021894 495
elessair 0:f269e3021894 496
elessair 0:f269e3021894 497 extern "C" WEAK void software_init_hook_rtos(void)
elessair 0:f269e3021894 498 {
elessair 0:f269e3021894 499 // Do nothing by default.
elessair 0:f269e3021894 500 }
elessair 0:f269e3021894 501
elessair 0:f269e3021894 502 extern "C" void software_init_hook(void)
elessair 0:f269e3021894 503 {
elessair 0:f269e3021894 504 #ifdef FEATURE_UVISOR
elessair 0:f269e3021894 505 int return_code;
elessair 0:f269e3021894 506
elessair 0:f269e3021894 507 return_code = uvisor_lib_init();
elessair 0:f269e3021894 508 if (return_code) {
elessair 0:f269e3021894 509 mbed_die();
elessair 0:f269e3021894 510 }
elessair 0:f269e3021894 511 #endif/* FEATURE_UVISOR */
elessair 0:f269e3021894 512 mbed_sdk_init();
elessair 0:f269e3021894 513 software_init_hook_rtos();
elessair 0:f269e3021894 514 }
elessair 0:f269e3021894 515 #endif
elessair 0:f269e3021894 516
elessair 0:f269e3021894 517 // ****************************************************************************
elessair 0:f269e3021894 518 // mbed_main is a function that is called before main()
elessair 0:f269e3021894 519 // mbed_sdk_init() is also a function that is called before main(), but unlike
elessair 0:f269e3021894 520 // mbed_main(), it is not meant for user code, but for the SDK itself to perform
elessair 0:f269e3021894 521 // initializations before main() is called.
elessair 0:f269e3021894 522
elessair 0:f269e3021894 523 extern "C" WEAK void mbed_main(void);
elessair 0:f269e3021894 524 extern "C" WEAK void mbed_main(void) {
elessair 0:f269e3021894 525 }
elessair 0:f269e3021894 526
elessair 0:f269e3021894 527 #if defined(TOOLCHAIN_ARM)
elessair 0:f269e3021894 528 extern "C" int $Super$$main(void);
elessair 0:f269e3021894 529
elessair 0:f269e3021894 530 extern "C" int $Sub$$main(void) {
elessair 0:f269e3021894 531 mbed_main();
elessair 0:f269e3021894 532 return $Super$$main();
elessair 0:f269e3021894 533 }
elessair 0:f269e3021894 534
elessair 0:f269e3021894 535 extern "C" void _platform_post_stackheap_init (void) {
elessair 0:f269e3021894 536 mbed_sdk_init();
elessair 0:f269e3021894 537 }
elessair 0:f269e3021894 538
elessair 0:f269e3021894 539 #elif defined(TOOLCHAIN_GCC)
elessair 0:f269e3021894 540 extern "C" int __real_main(void);
elessair 0:f269e3021894 541
elessair 0:f269e3021894 542 extern "C" int __wrap_main(void) {
elessair 0:f269e3021894 543 mbed_main();
elessair 0:f269e3021894 544 return __real_main();
elessair 0:f269e3021894 545 }
elessair 0:f269e3021894 546 #elif defined(TOOLCHAIN_IAR)
elessair 0:f269e3021894 547 // IAR doesn't have the $Super/$Sub mechanism of armcc, nor something equivalent
elessair 0:f269e3021894 548 // to ld's --wrap. It does have a --redirect, but that doesn't help, since redirecting
elessair 0:f269e3021894 549 // 'main' to another symbol looses the original 'main' symbol. However, its startup
elessair 0:f269e3021894 550 // code will call a function to setup argc and argv (__iar_argc_argv) if it is defined.
elessair 0:f269e3021894 551 // Since mbed doesn't use argc/argv, we use this function to call our mbed_main.
elessair 0:f269e3021894 552 extern "C" void __iar_argc_argv() {
elessair 0:f269e3021894 553 mbed_main();
elessair 0:f269e3021894 554 }
elessair 0:f269e3021894 555 #endif
elessair 0:f269e3021894 556
elessair 0:f269e3021894 557 // Provide implementation of _sbrk (low-level dynamic memory allocation
elessair 0:f269e3021894 558 // routine) for GCC_ARM which compares new heap pointer with MSP instead of
elessair 0:f269e3021894 559 // SP. This make it compatible with RTX RTOS thread stacks.
elessair 0:f269e3021894 560 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
elessair 0:f269e3021894 561 // Linker defined symbol used by _sbrk to indicate where heap should start.
elessair 0:f269e3021894 562 extern "C" int __end__;
elessair 0:f269e3021894 563
elessair 0:f269e3021894 564 #if defined(TARGET_CORTEX_A)
elessair 0:f269e3021894 565 extern "C" uint32_t __HeapLimit;
elessair 0:f269e3021894 566 #endif
elessair 0:f269e3021894 567
elessair 0:f269e3021894 568 // Turn off the errno macro and use actual global variable instead.
elessair 0:f269e3021894 569 #undef errno
elessair 0:f269e3021894 570 extern "C" int errno;
elessair 0:f269e3021894 571
elessair 0:f269e3021894 572 // For ARM7 only
elessair 0:f269e3021894 573 register unsigned char * stack_ptr __asm ("sp");
elessair 0:f269e3021894 574
elessair 0:f269e3021894 575 // Dynamic memory allocation related syscall.
elessair 0:f269e3021894 576 #if defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NUMAKER_PFM_M453)
elessair 0:f269e3021894 577 // Overwrite _sbrk() to support two region model (heap and stack are two distinct regions).
elessair 0:f269e3021894 578 // __wrap__sbrk() is implemented in:
elessair 0:f269e3021894 579 // TARGET_NUMAKER_PFM_NUC472 hal/targets/cmsis/TARGET_NUVOTON/TARGET_NUC472/TARGET_NUMAKER_PFM_NUC472/TOOLCHAIN_GCC_ARM/retarget.c
elessair 0:f269e3021894 580 // TARGET_NUMAKER_PFM_M453 hal/targets/cmsis/TARGET_NUVOTON/TARGET_M451/TARGET_NUMAKER_PFM_M453/TOOLCHAIN_GCC_ARM/retarget.c
elessair 0:f269e3021894 581 extern "C" void *__wrap__sbrk(int incr);
elessair 0:f269e3021894 582 extern "C" caddr_t _sbrk(int incr) {
elessair 0:f269e3021894 583 return (caddr_t) __wrap__sbrk(incr);
elessair 0:f269e3021894 584 }
elessair 0:f269e3021894 585 #else
elessair 0:f269e3021894 586 extern "C" caddr_t _sbrk(int incr) {
elessair 0:f269e3021894 587 static unsigned char* heap = (unsigned char*)&__end__;
elessair 0:f269e3021894 588 unsigned char* prev_heap = heap;
elessair 0:f269e3021894 589 unsigned char* new_heap = heap + incr;
elessair 0:f269e3021894 590
elessair 0:f269e3021894 591 #if defined(TARGET_ARM7)
elessair 0:f269e3021894 592 if (new_heap >= stack_ptr) {
elessair 0:f269e3021894 593 #elif defined(TARGET_CORTEX_A)
elessair 0:f269e3021894 594 if (new_heap >= (unsigned char*)&__HeapLimit) { /* __HeapLimit is end of heap section */
elessair 0:f269e3021894 595 #else
elessair 0:f269e3021894 596 if (new_heap >= (unsigned char*)__get_MSP()) {
elessair 0:f269e3021894 597 #endif
elessair 0:f269e3021894 598 errno = ENOMEM;
elessair 0:f269e3021894 599 return (caddr_t)-1;
elessair 0:f269e3021894 600 }
elessair 0:f269e3021894 601
elessair 0:f269e3021894 602 // Additional heap checking if set
elessair 0:f269e3021894 603 if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) {
elessair 0:f269e3021894 604 errno = ENOMEM;
elessair 0:f269e3021894 605 return (caddr_t)-1;
elessair 0:f269e3021894 606 }
elessair 0:f269e3021894 607
elessair 0:f269e3021894 608 heap = new_heap;
elessair 0:f269e3021894 609 return (caddr_t) prev_heap;
elessair 0:f269e3021894 610 }
elessair 0:f269e3021894 611 #endif
elessair 0:f269e3021894 612 #endif
elessair 0:f269e3021894 613
elessair 0:f269e3021894 614 #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
elessair 0:f269e3021894 615 extern "C" void _exit(int return_code) {
elessair 0:f269e3021894 616 #else
elessair 0:f269e3021894 617 namespace std {
elessair 0:f269e3021894 618 extern "C" void exit(int return_code) {
elessair 0:f269e3021894 619 #endif
elessair 0:f269e3021894 620
elessair 0:f269e3021894 621 #if DEVICE_STDIO_MESSAGES
elessair 0:f269e3021894 622 #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT
elessair 0:f269e3021894 623 fflush(stdout);
elessair 0:f269e3021894 624 fflush(stderr);
elessair 0:f269e3021894 625 #endif
elessair 0:f269e3021894 626 #endif
elessair 0:f269e3021894 627
elessair 0:f269e3021894 628 #if DEVICE_SEMIHOST
elessair 0:f269e3021894 629 if (mbed_interface_connected()) {
elessair 0:f269e3021894 630 semihost_exit();
elessair 0:f269e3021894 631 }
elessair 0:f269e3021894 632 #endif
elessair 0:f269e3021894 633 if (return_code) {
elessair 0:f269e3021894 634 mbed_die();
elessair 0:f269e3021894 635 }
elessair 0:f269e3021894 636
elessair 0:f269e3021894 637 while (1);
elessair 0:f269e3021894 638 }
elessair 0:f269e3021894 639
elessair 0:f269e3021894 640 #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR)
elessair 0:f269e3021894 641 } //namespace std
elessair 0:f269e3021894 642 #endif
elessair 0:f269e3021894 643
elessair 0:f269e3021894 644 #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC)
elessair 0:f269e3021894 645
elessair 0:f269e3021894 646 // This series of function disable the registration of global destructors
elessair 0:f269e3021894 647 // in a dynamic table which will be called when the application exit.
elessair 0:f269e3021894 648 // In mbed, program never exit properly, it dies.
elessair 0:f269e3021894 649 // More informations about this topic for ARMCC here:
elessair 0:f269e3021894 650 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html
elessair 0:f269e3021894 651 extern "C" {
elessair 0:f269e3021894 652 int __aeabi_atexit(void *object, void (*dtor)(void* /*this*/), void *handle) {
elessair 0:f269e3021894 653 return 1;
elessair 0:f269e3021894 654 }
elessair 0:f269e3021894 655
elessair 0:f269e3021894 656 int __cxa_atexit(void (*dtor)(void* /*this*/), void *object, void *handle) {
elessair 0:f269e3021894 657 return 1;
elessair 0:f269e3021894 658 }
elessair 0:f269e3021894 659
elessair 0:f269e3021894 660 void __cxa_finalize(void *handle) {
elessair 0:f269e3021894 661 }
elessair 0:f269e3021894 662
elessair 0:f269e3021894 663 } // end of extern "C"
elessair 0:f269e3021894 664
elessair 0:f269e3021894 665 #endif
elessair 0:f269e3021894 666
elessair 0:f269e3021894 667
elessair 0:f269e3021894 668 #if defined(TOOLCHAIN_GCC)
elessair 0:f269e3021894 669
elessair 0:f269e3021894 670 /*
elessair 0:f269e3021894 671 * Depending on how newlib is configured, it is often not enough to define
elessair 0:f269e3021894 672 * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the
elessair 0:f269e3021894 673 * behavior regarding the registration of handlers with atexit.
elessair 0:f269e3021894 674 *
elessair 0:f269e3021894 675 * To overcome this limitation, exit and atexit are overriden here.
elessair 0:f269e3021894 676 */
elessair 0:f269e3021894 677 extern "C"{
elessair 0:f269e3021894 678
elessair 0:f269e3021894 679 /**
elessair 0:f269e3021894 680 * @brief Retarget of exit for GCC.
elessair 0:f269e3021894 681 * @details Unlike the standard version, this function doesn't call any function
elessair 0:f269e3021894 682 * registered with atexit before calling _exit.
elessair 0:f269e3021894 683 */
elessair 0:f269e3021894 684 void __wrap_exit(int return_code) {
elessair 0:f269e3021894 685 _exit(return_code);
elessair 0:f269e3021894 686 }
elessair 0:f269e3021894 687
elessair 0:f269e3021894 688 /**
elessair 0:f269e3021894 689 * @brief Retarget atexit from GCC.
elessair 0:f269e3021894 690 * @details This function will always fail and never register any handler to be
elessair 0:f269e3021894 691 * called at exit.
elessair 0:f269e3021894 692 */
elessair 0:f269e3021894 693 int __wrap_atexit(void (*func)()) {
elessair 0:f269e3021894 694 return 1;
elessair 0:f269e3021894 695 }
elessair 0:f269e3021894 696
elessair 0:f269e3021894 697 }
elessair 0:f269e3021894 698
elessair 0:f269e3021894 699 #endif
elessair 0:f269e3021894 700
elessair 0:f269e3021894 701
elessair 0:f269e3021894 702
elessair 0:f269e3021894 703 namespace mbed {
elessair 0:f269e3021894 704
elessair 0:f269e3021894 705 void mbed_set_unbuffered_stream(FILE *_file) {
elessair 0:f269e3021894 706 #if defined (__ICCARM__)
elessair 0:f269e3021894 707 char buf[2];
elessair 0:f269e3021894 708 std::setvbuf(_file,buf,_IONBF,NULL);
elessair 0:f269e3021894 709 #else
elessair 0:f269e3021894 710 setbuf(_file, NULL);
elessair 0:f269e3021894 711 #endif
elessair 0:f269e3021894 712 }
elessair 0:f269e3021894 713
elessair 0:f269e3021894 714 int mbed_getc(FILE *_file){
elessair 0:f269e3021894 715 #if defined (__ICCARM__)
elessair 0:f269e3021894 716 /*This is only valid for unbuffered streams*/
elessair 0:f269e3021894 717 int res = std::fgetc(_file);
elessair 0:f269e3021894 718 if (res>=0){
elessair 0:f269e3021894 719 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
elessair 0:f269e3021894 720 _file->_Rend = _file->_Wend;
elessair 0:f269e3021894 721 _file->_Next = _file->_Wend;
elessair 0:f269e3021894 722 }
elessair 0:f269e3021894 723 return res;
elessair 0:f269e3021894 724 #else
elessair 0:f269e3021894 725 return std::fgetc(_file);
elessair 0:f269e3021894 726 #endif
elessair 0:f269e3021894 727 }
elessair 0:f269e3021894 728
elessair 0:f269e3021894 729 char* mbed_gets(char*s, int size, FILE *_file){
elessair 0:f269e3021894 730 #if defined (__ICCARM__)
elessair 0:f269e3021894 731 /*This is only valid for unbuffered streams*/
elessair 0:f269e3021894 732 char *str = fgets(s,size,_file);
elessair 0:f269e3021894 733 if (str!=NULL){
elessair 0:f269e3021894 734 _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
elessair 0:f269e3021894 735 _file->_Rend = _file->_Wend;
elessair 0:f269e3021894 736 _file->_Next = _file->_Wend;
elessair 0:f269e3021894 737 }
elessair 0:f269e3021894 738 return str;
elessair 0:f269e3021894 739 #else
elessair 0:f269e3021894 740 return std::fgets(s,size,_file);
elessair 0:f269e3021894 741 #endif
elessair 0:f269e3021894 742 }
elessair 0:f269e3021894 743
elessair 0:f269e3021894 744 } // namespace mbed
elessair 0:f269e3021894 745
elessair 0:f269e3021894 746 #if defined (__ICCARM__)
elessair 0:f269e3021894 747 // Stub out locks when an rtos is not present
elessair 0:f269e3021894 748 extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {}
elessair 0:f269e3021894 749 extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {}
elessair 0:f269e3021894 750 extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {}
elessair 0:f269e3021894 751 extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {}
elessair 0:f269e3021894 752 extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {}
elessair 0:f269e3021894 753 extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {}
elessair 0:f269e3021894 754 extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {}
elessair 0:f269e3021894 755 extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {}
elessair 0:f269e3021894 756 #elif defined(__CC_ARM)
elessair 0:f269e3021894 757 // Do nothing
elessair 0:f269e3021894 758 #elif defined (__GNUC__)
elessair 0:f269e3021894 759 struct _reent;
elessair 0:f269e3021894 760 // Stub out locks when an rtos is not present
elessair 0:f269e3021894 761 extern "C" WEAK void __rtos_malloc_lock( struct _reent *_r ) {}
elessair 0:f269e3021894 762 extern "C" WEAK void __rtos_malloc_unlock( struct _reent *_r ) {}
elessair 0:f269e3021894 763 extern "C" WEAK void __rtos_env_lock( struct _reent *_r ) {}
elessair 0:f269e3021894 764 extern "C" WEAK void __rtos_env_unlock( struct _reent *_r ) {}
elessair 0:f269e3021894 765
elessair 0:f269e3021894 766 extern "C" void __malloc_lock( struct _reent *_r )
elessair 0:f269e3021894 767 {
elessair 0:f269e3021894 768 __rtos_malloc_lock(_r);
elessair 0:f269e3021894 769 }
elessair 0:f269e3021894 770
elessair 0:f269e3021894 771 extern "C" void __malloc_unlock( struct _reent *_r )
elessair 0:f269e3021894 772 {
elessair 0:f269e3021894 773 __rtos_malloc_unlock(_r);
elessair 0:f269e3021894 774 }
elessair 0:f269e3021894 775
elessair 0:f269e3021894 776 extern "C" void __env_lock( struct _reent *_r )
elessair 0:f269e3021894 777 {
elessair 0:f269e3021894 778 __rtos_env_lock(_r);
elessair 0:f269e3021894 779 }
elessair 0:f269e3021894 780
elessair 0:f269e3021894 781 extern "C" void __env_unlock( struct _reent *_r )
elessair 0:f269e3021894 782 {
elessair 0:f269e3021894 783 __rtos_env_unlock(_r);
elessair 0:f269e3021894 784 }
elessair 0:f269e3021894 785
elessair 0:f269e3021894 786 #define CXA_GUARD_INIT_DONE (1 << 0)
elessair 0:f269e3021894 787 #define CXA_GUARD_INIT_IN_PROGRESS (1 << 1)
elessair 0:f269e3021894 788 #define CXA_GUARD_MASK (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS)
elessair 0:f269e3021894 789
elessair 0:f269e3021894 790 extern "C" int __cxa_guard_acquire(int *guard_object_p)
elessair 0:f269e3021894 791 {
elessair 0:f269e3021894 792 uint8_t *guard_object = (uint8_t *)guard_object_p;
elessair 0:f269e3021894 793 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
elessair 0:f269e3021894 794 return 0;
elessair 0:f269e3021894 795 }
elessair 0:f269e3021894 796 singleton_lock();
elessair 0:f269e3021894 797 if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
elessair 0:f269e3021894 798 singleton_unlock();
elessair 0:f269e3021894 799 return 0;
elessair 0:f269e3021894 800 }
elessair 0:f269e3021894 801 MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK));
elessair 0:f269e3021894 802 *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS;
elessair 0:f269e3021894 803 return 1;
elessair 0:f269e3021894 804 }
elessair 0:f269e3021894 805
elessair 0:f269e3021894 806 extern "C" void __cxa_guard_release(int *guard_object_p)
elessair 0:f269e3021894 807 {
elessair 0:f269e3021894 808 uint8_t *guard_object = (uint8_t *)guard_object_p;
elessair 0:f269e3021894 809 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
elessair 0:f269e3021894 810 *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE;
elessair 0:f269e3021894 811 singleton_unlock();
elessair 0:f269e3021894 812 }
elessair 0:f269e3021894 813
elessair 0:f269e3021894 814 extern "C" void __cxa_guard_abort(int *guard_object_p)
elessair 0:f269e3021894 815 {
elessair 0:f269e3021894 816 uint8_t *guard_object = (uint8_t *)guard_object_p;
elessair 0:f269e3021894 817 MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
elessair 0:f269e3021894 818 *guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS;
elessair 0:f269e3021894 819 singleton_unlock();
elessair 0:f269e3021894 820 }
elessair 0:f269e3021894 821
elessair 0:f269e3021894 822 #endif
elessair 0:f269e3021894 823
elessair 0:f269e3021894 824 void *operator new(std::size_t count)
elessair 0:f269e3021894 825 {
elessair 0:f269e3021894 826 void *buffer = malloc(count);
elessair 0:f269e3021894 827 if (NULL == buffer) {
elessair 0:f269e3021894 828 error("Operator new out of memory\r\n");
elessair 0:f269e3021894 829 }
elessair 0:f269e3021894 830 return buffer;
elessair 0:f269e3021894 831 }
elessair 0:f269e3021894 832
elessair 0:f269e3021894 833 void *operator new[](std::size_t count)
elessair 0:f269e3021894 834 {
elessair 0:f269e3021894 835 void *buffer = malloc(count);
elessair 0:f269e3021894 836 if (NULL == buffer) {
elessair 0:f269e3021894 837 error("Operator new[] out of memory\r\n");
elessair 0:f269e3021894 838 }
elessair 0:f269e3021894 839 return buffer;
elessair 0:f269e3021894 840 }
elessair 0:f269e3021894 841
elessair 0:f269e3021894 842 void operator delete(void *ptr)
elessair 0:f269e3021894 843 {
elessair 0:f269e3021894 844 if (ptr != NULL) {
elessair 0:f269e3021894 845 free(ptr);
elessair 0:f269e3021894 846 }
elessair 0:f269e3021894 847 }
elessair 0:f269e3021894 848 void operator delete[](void *ptr)
elessair 0:f269e3021894 849 {
elessair 0:f269e3021894 850 if (ptr != NULL) {
elessair 0:f269e3021894 851 free(ptr);
elessair 0:f269e3021894 852 }
elessair 0:f269e3021894 853 }