mbed_retarget.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641
  1. /* mbed Microcontroller Library
  2. * Copyright (c) 2006-2015 ARM Limited
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <time.h>
  17. #include "platform/platform.h"
  18. #include "platform/FilePath.h"
  19. #include "hal/serial_api.h"
  20. #include "hal/us_ticker_api.h"
  21. #include "platform/mbed_toolchain.h"
  22. #include "platform/mbed_semihost_api.h"
  23. #include "platform/mbed_interface.h"
  24. #include "platform/SingletonPtr.h"
  25. #include "platform/PlatformMutex.h"
  26. #include "platform/mbed_error.h"
  27. #include "platform/mbed_stats.h"
  28. #include "platform/mbed_critical.h"
  29. #include "platform/mbed_poll.h"
  30. #include "platform/PlatformMutex.h"
  31. #include "drivers/UARTSerial.h"
  32. #include "us_ticker_api.h"
  33. #include "lp_ticker_api.h"
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <limits.h>
  37. #ifndef SSIZE_MAX
  38. #define SSIZE_MAX INT_MAX
  39. #endif
  40. #include <stdio.h>
  41. #include <errno.h>
  42. #include "platform/mbed_retarget.h"
  43. static SingletonPtr<PlatformMutex> _mutex;
  44. #if defined(__ARMCC_VERSION)
  45. # if __ARMCC_VERSION >= 6010050
  46. # include <arm_compat.h>
  47. # endif
  48. # include <rt_sys.h>
  49. # include <rt_misc.h>
  50. # include <stdint.h>
  51. # define PREFIX(x) _sys##x
  52. # define OPEN_MAX _SYS_OPEN
  53. # ifdef __MICROLIB
  54. # pragma import(__use_full_stdio)
  55. # endif
  56. #elif defined(__ICCARM__)
  57. # include <yfuns.h>
  58. # define PREFIX(x) _##x
  59. # define OPEN_MAX 16
  60. # define STDIN_FILENO 0
  61. # define STDOUT_FILENO 1
  62. # define STDERR_FILENO 2
  63. #else
  64. # include <sys/syslimits.h>
  65. # define PREFIX(x) x
  66. #endif
  67. #define FILE_HANDLE_RESERVED ((FileHandle*)0xFFFFFFFF)
  68. /**
  69. * Macros for setting console flow control.
  70. */
  71. #define CONSOLE_FLOWCONTROL_RTS 1
  72. #define CONSOLE_FLOWCONTROL_CTS 2
  73. #define CONSOLE_FLOWCONTROL_RTSCTS 3
  74. #define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x
  75. #define mbed_console_concat(x) mbed_console_concat_(x)
  76. #define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL)
  77. using namespace mbed;
  78. #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
  79. // Before version 5.03, we were using a patched version of microlib with proper names
  80. extern const char __stdin_name[] = ":tt";
  81. extern const char __stdout_name[] = ":tt";
  82. extern const char __stderr_name[] = ":tt";
  83. #else
  84. extern const char __stdin_name[] = "/stdin";
  85. extern const char __stdout_name[] = "/stdout";
  86. extern const char __stderr_name[] = "/stderr";
  87. #endif
  88. unsigned char *mbed_heap_start = 0;
  89. uint32_t mbed_heap_size = 0;
  90. /* newlib has the filehandle field in the FILE struct as a short, so
  91. * we can't just return a Filehandle* from _open and instead have to
  92. * put it in a filehandles array and return the index into that array
  93. */
  94. static FileHandle *filehandles[OPEN_MAX] = { FILE_HANDLE_RESERVED, FILE_HANDLE_RESERVED, FILE_HANDLE_RESERVED };
  95. static char stdio_in_prev[OPEN_MAX];
  96. static char stdio_out_prev[OPEN_MAX];
  97. static SingletonPtr<PlatformMutex> filehandle_mutex;
  98. namespace mbed {
  99. void mbed_set_unbuffered_stream(std::FILE *_file);
  100. void remove_filehandle(FileHandle *file)
  101. {
  102. filehandle_mutex->lock();
  103. /* Remove all open filehandles for this */
  104. for (unsigned int fh_i = 0; fh_i < sizeof(filehandles) / sizeof(*filehandles); fh_i++) {
  105. if (filehandles[fh_i] == file) {
  106. filehandles[fh_i] = NULL;
  107. }
  108. }
  109. filehandle_mutex->unlock();
  110. }
  111. }
  112. #if DEVICE_SERIAL
  113. extern int stdio_uart_inited;
  114. extern serial_t stdio_uart;
  115. /* Private FileHandle to implement backwards-compatible functionality of
  116. * direct HAL serial access for default stdin/stdout/stderr.
  117. * This is not a particularly well-behaved FileHandle for a stream, which
  118. * is why it's not public. People should be using UARTSerial.
  119. */
  120. class DirectSerial : public FileHandle {
  121. public:
  122. DirectSerial(PinName tx, PinName rx, int baud);
  123. virtual ssize_t write(const void *buffer, size_t size);
  124. virtual ssize_t read(void *buffer, size_t size);
  125. virtual off_t seek(off_t offset, int whence = SEEK_SET)
  126. {
  127. return -ESPIPE;
  128. }
  129. virtual off_t size()
  130. {
  131. return -EINVAL;
  132. }
  133. virtual int isatty()
  134. {
  135. return true;
  136. }
  137. virtual int close()
  138. {
  139. return 0;
  140. }
  141. virtual short poll(short events) const;
  142. };
  143. DirectSerial::DirectSerial(PinName tx, PinName rx, int baud)
  144. {
  145. if (stdio_uart_inited) {
  146. return;
  147. }
  148. serial_init(&stdio_uart, tx, rx);
  149. serial_baud(&stdio_uart, baud);
  150. #if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
  151. serial_set_flow_control(&stdio_uart, FlowControlRTS, STDIO_UART_RTS, NC);
  152. #elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
  153. serial_set_flow_control(&stdio_uart, FlowControlCTS, NC, STDIO_UART_CTS);
  154. #elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
  155. serial_set_flow_control(&stdio_uart, FlowControlRTSCTS, STDIO_UART_RTS, STDIO_UART_CTS);
  156. #endif
  157. }
  158. ssize_t DirectSerial::write(const void *buffer, size_t size)
  159. {
  160. const unsigned char *buf = static_cast<const unsigned char *>(buffer);
  161. for (size_t i = 0; i < size; i++) {
  162. serial_putc(&stdio_uart, buf[i]);
  163. }
  164. return size;
  165. }
  166. ssize_t DirectSerial::read(void *buffer, size_t size)
  167. {
  168. unsigned char *buf = static_cast<unsigned char *>(buffer);
  169. if (size == 0) {
  170. return 0;
  171. }
  172. buf[0] = serial_getc(&stdio_uart);
  173. return 1;
  174. }
  175. short DirectSerial::poll(short events) const
  176. {
  177. short revents = 0;
  178. if ((events & POLLIN) && serial_readable(&stdio_uart)) {
  179. revents |= POLLIN;
  180. }
  181. if ((events & POLLOUT) && serial_writable(&stdio_uart)) {
  182. revents |= POLLOUT;
  183. }
  184. return revents;
  185. }
  186. #endif
  187. class Sink : public FileHandle {
  188. public:
  189. virtual ssize_t write(const void *buffer, size_t size);
  190. virtual ssize_t read(void *buffer, size_t size);
  191. virtual off_t seek(off_t offset, int whence = SEEK_SET)
  192. {
  193. return ESPIPE;
  194. }
  195. virtual off_t size()
  196. {
  197. return -EINVAL;
  198. }
  199. virtual int isatty()
  200. {
  201. return true;
  202. }
  203. virtual int close()
  204. {
  205. return 0;
  206. }
  207. };
  208. ssize_t Sink::write(const void *buffer, size_t size)
  209. {
  210. // Just swallow the data - this is historical non-DEVICE_SERIAL behaviour
  211. return size;
  212. }
  213. ssize_t Sink::read(void *buffer, size_t size)
  214. {
  215. // Produce 1 zero byte - historical behaviour returned 1 without touching
  216. // the buffer
  217. unsigned char *buf = static_cast<unsigned char *>(buffer);
  218. buf[0] = 0;
  219. return 1;
  220. }
  221. MBED_WEAK FileHandle *mbed::mbed_target_override_console(int fd)
  222. {
  223. return NULL;
  224. }
  225. MBED_WEAK FileHandle *mbed::mbed_override_console(int fd)
  226. {
  227. return NULL;
  228. }
  229. static FileHandle *default_console()
  230. {
  231. #if DEVICE_SERIAL
  232. # if MBED_CONF_PLATFORM_STDIO_BUFFERED_SERIAL
  233. static UARTSerial console(STDIO_UART_TX, STDIO_UART_RX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
  234. # if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
  235. console.set_flow_control(SerialBase::RTS, STDIO_UART_RTS, NC);
  236. # elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
  237. console.set_flow_control(SerialBase::CTS, NC, STDIO_UART_CTS);
  238. # elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
  239. console.set_flow_control(SerialBase::RTSCTS, STDIO_UART_RTS, STDIO_UART_CTS);
  240. # endif
  241. # else
  242. static DirectSerial console(STDIO_UART_TX, STDIO_UART_RX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE);
  243. # endif
  244. #else // DEVICE_SERIAL
  245. static Sink console;
  246. #endif
  247. return &console;
  248. }
  249. /* Locate the default console for stdout, stdin, stderr */
  250. static FileHandle *get_console(int fd)
  251. {
  252. FileHandle *fh = mbed_override_console(fd);
  253. if (fh) {
  254. return fh;
  255. }
  256. fh = mbed_target_override_console(fd);
  257. if (fh) {
  258. return fh;
  259. }
  260. return default_console();
  261. }
  262. /* Deal with the fact C library may not _open descriptors 0, 1, 2 - auto bind */
  263. static FileHandle *get_fhc(int fd)
  264. {
  265. if (fd >= OPEN_MAX) {
  266. return NULL;
  267. }
  268. FileHandle *fh = filehandles[fd];
  269. if (fh == FILE_HANDLE_RESERVED && fd < 3) {
  270. filehandles[fd] = fh = get_console(fd);
  271. }
  272. return fh;
  273. }
  274. /**
  275. * Sets errno when file opening fails.
  276. * Wipes out the filehandle too.
  277. *
  278. * @param error is a negative error code returned from an mbed function and
  279. * will be negated to store a positive error code in errno
  280. */
  281. static int handle_open_errors(int error, unsigned filehandle_idx)
  282. {
  283. errno = -error;
  284. // Free file handle
  285. filehandles[filehandle_idx] = NULL;
  286. return -1;
  287. }
  288. static inline int openflags_to_posix(int openflags)
  289. {
  290. int posix = openflags;
  291. #ifdef __ARMCC_VERSION
  292. if (openflags & OPEN_PLUS) {
  293. posix = O_RDWR;
  294. } else if (openflags & OPEN_W) {
  295. posix = O_WRONLY;
  296. } else if (openflags & OPEN_A) {
  297. posix = O_WRONLY | O_APPEND;
  298. } else {
  299. posix = O_RDONLY;
  300. }
  301. /* a, w, a+, w+ all create if file does not already exist */
  302. if (openflags & (OPEN_A | OPEN_W)) {
  303. posix |= O_CREAT;
  304. }
  305. /* w and w+ truncate */
  306. if (openflags & OPEN_W) {
  307. posix |= O_TRUNC;
  308. }
  309. #elif defined(__ICCARM__)
  310. switch (openflags & _LLIO_RDWRMASK) {
  311. case _LLIO_RDONLY:
  312. posix = O_RDONLY;
  313. break;
  314. case _LLIO_WRONLY:
  315. posix = O_WRONLY;
  316. break;
  317. case _LLIO_RDWR :
  318. posix = O_RDWR ;
  319. break;
  320. }
  321. if (openflags & _LLIO_CREAT) {
  322. posix |= O_CREAT;
  323. }
  324. if (openflags & _LLIO_APPEND) {
  325. posix |= O_APPEND;
  326. }
  327. if (openflags & _LLIO_TRUNC) {
  328. posix |= O_TRUNC;
  329. }
  330. #elif defined(TOOLCHAIN_GCC)
  331. posix &= ~O_BINARY;
  332. #endif
  333. return posix;
  334. }
  335. static int reserve_filehandle()
  336. {
  337. // find the first empty slot in filehandles, after the slots reserved for stdin/stdout/stderr
  338. filehandle_mutex->lock();
  339. int fh_i;
  340. for (fh_i = 3; fh_i < OPEN_MAX; fh_i++) {
  341. /* Take a next free filehandle slot available. */
  342. if (filehandles[fh_i] == NULL) {
  343. break;
  344. }
  345. }
  346. if (fh_i >= OPEN_MAX) {
  347. /* Too many file handles have been opened */
  348. errno = EMFILE;
  349. filehandle_mutex->unlock();
  350. return -1;
  351. }
  352. filehandles[fh_i] = FILE_HANDLE_RESERVED;
  353. filehandle_mutex->unlock();
  354. return fh_i;
  355. }
  356. int mbed::bind_to_fd(FileHandle *fh)
  357. {
  358. int fildes = reserve_filehandle();
  359. if (fildes < 0) {
  360. return fildes;
  361. }
  362. filehandles[fildes] = fh;
  363. stdio_in_prev[fildes] = 0;
  364. stdio_out_prev[fildes] = 0;
  365. return fildes;
  366. }
  367. static int unbind_from_fd(int fd, FileHandle *fh)
  368. {
  369. if (filehandles[fd] == fh) {
  370. filehandles[fd] = NULL;
  371. return 0;
  372. } else {
  373. errno = EBADF;
  374. return -1;
  375. }
  376. }
  377. #ifndef __IAR_SYSTEMS_ICC__
  378. /* IAR provides fdopen itself */
  379. extern "C" std::FILE *fdopen(int fildes, const char *mode)
  380. {
  381. // This is to avoid scanf and the bloat it brings.
  382. char buf[1 + sizeof fildes]; /* @(integer) */
  383. MBED_STATIC_ASSERT(sizeof buf == 5, "Integers should be 4 bytes.");
  384. buf[0] = '@';
  385. memcpy(buf + 1, &fildes, sizeof fildes);
  386. std::FILE *stream = std::fopen(buf, mode);
  387. /* newlib-nano doesn't appear to ever call _isatty itself, so
  388. * happily fully buffers an interactive stream. Deal with that here.
  389. */
  390. if (stream && isatty(fildes)) {
  391. mbed_set_unbuffered_stream(stream);
  392. }
  393. return stream;
  394. }
  395. #endif
  396. namespace mbed {
  397. std::FILE *fdopen(FileHandle *fh, const char *mode)
  398. {
  399. // First reserve the integer file descriptor
  400. int fd = bind_to_fd(fh);
  401. if (!fd) {
  402. return NULL;
  403. }
  404. // Then bind that to the C stream. If successful, C library
  405. // takes ownership and responsibility to close.
  406. std::FILE *stream = ::fdopen(fd, mode);
  407. if (!stream) {
  408. unbind_from_fd(fd, fh);
  409. }
  410. return stream;
  411. }
  412. }
  413. /* @brief standard c library fopen() retargeting function.
  414. *
  415. * This function is invoked by the standard c library retargeting to handle fopen()
  416. *
  417. * @return
  418. * On success, a valid FILEHANDLE is returned.
  419. * On failure, -1 is returned and errno is set to an appropriate value e.g.
  420. * ENOENT file not found (default errno setting)
  421. * EMFILE the maximum number of open files was exceeded.
  422. *
  423. * */
  424. extern "C" FILEHANDLE PREFIX(_open)(const char *name, int openflags)
  425. {
  426. #if defined(__MICROLIB) && (__ARMCC_VERSION>5030000)
  427. #if !defined(MBED_CONF_RTOS_PRESENT)
  428. // valid only for mbed 2
  429. // for ulib, this is invoked after RAM init, prior c++
  430. // used as hook, as post stack/heap is not active there
  431. extern void mbed_copy_nvic(void);
  432. extern void mbed_sdk_init(void);
  433. static int mbed_sdk_inited = 0;
  434. if (!mbed_sdk_inited) {
  435. mbed_copy_nvic();
  436. mbed_sdk_init();
  437. mbed_sdk_inited = 1;
  438. }
  439. #endif
  440. // Before version 5.03, we were using a patched version of microlib with proper names
  441. // This is the workaround that the microlib author suggested us
  442. static int n = 0;
  443. if (std::strcmp(name, ":tt") == 0 && n < 3) {
  444. return n++;
  445. }
  446. #else
  447. /* Use the posix convention that stdin,out,err are filehandles 0,1,2.
  448. */
  449. if (std::strcmp(name, __stdin_name) == 0) {
  450. get_fhc(STDIN_FILENO);
  451. return STDIN_FILENO;
  452. } else if (std::strcmp(name, __stdout_name) == 0) {
  453. get_fhc(STDOUT_FILENO);
  454. return STDOUT_FILENO;
  455. } else if (std::strcmp(name, __stderr_name) == 0) {
  456. get_fhc(STDERR_FILENO);
  457. return STDERR_FILENO;
  458. }
  459. #endif
  460. #ifndef __IAR_SYSTEMS_ICC__
  461. /* FILENAME: "@(integer)" gives an already-allocated descriptor */
  462. if (name[0] == '@') {
  463. int fd;
  464. memcpy(&fd, name + 1, sizeof fd);
  465. return fd;
  466. }
  467. #endif
  468. return open(name, openflags_to_posix(openflags));
  469. }
  470. extern "C" int open(const char *name, int oflag, ...)
  471. {
  472. int fildes = reserve_filehandle();
  473. if (fildes < 0) {
  474. return fildes;
  475. }
  476. FileHandle *res = NULL;
  477. FilePath path(name);
  478. if (!path.exists()) {
  479. /* The first part of the filename (between first 2 '/') is not a
  480. * registered mount point in the namespace.
  481. */
  482. return handle_open_errors(-ENODEV, fildes);
  483. }
  484. if (path.isFile()) {
  485. res = path.file();
  486. } else {
  487. FileSystemHandle *fs = path.fileSystem();
  488. if (fs == NULL) {
  489. return handle_open_errors(-ENODEV, fildes);
  490. }
  491. int err = fs->open(&res, path.fileName(), oflag);
  492. if (err) {
  493. return handle_open_errors(err, fildes);
  494. }
  495. }
  496. filehandles[fildes] = res;
  497. stdio_in_prev[fildes] = 0;
  498. stdio_out_prev[fildes] = 0;
  499. return fildes;
  500. }
  501. extern "C" int PREFIX(_close)(FILEHANDLE fh)
  502. {
  503. return close(fh);
  504. }
  505. extern "C" int close(int fildes)
  506. {
  507. FileHandle *fhc = get_fhc(fildes);
  508. filehandles[fildes] = NULL;
  509. if (fhc == NULL) {
  510. errno = EBADF;
  511. return -1;
  512. }
  513. int err = fhc->close();
  514. if (err < 0) {
  515. errno = -err;
  516. return -1;
  517. } else {
  518. return 0;
  519. }
  520. }
  521. static bool convert_crlf(int fd)
  522. {
  523. #if MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES
  524. return isatty(fd);
  525. #elif MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES
  526. return fd < 3 && isatty(fd);
  527. #else
  528. return false;
  529. #endif
  530. }
  531. #if defined(__ICCARM__)
  532. extern "C" size_t __write(int fh, const unsigned char *buffer, size_t length)
  533. {
  534. #else
  535. extern "C" int PREFIX(_write)(FILEHANDLE fh, const unsigned char *buffer, unsigned int length, int mode)
  536. {
  537. #endif
  538. #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT)
  539. if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) {
  540. MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_PROHIBITED_IN_ISR_CONTEXT), "Error - writing to a file in an ISR or critical section\r\n", fh);
  541. }
  542. #endif
  543. if (length > SSIZE_MAX) {
  544. errno = EINVAL;
  545. return -1;
  546. }
  547. ssize_t slength = length;
  548. ssize_t written = 0;
  549. if (convert_crlf(fh)) {
  550. // local prev is previous in buffer during seek
  551. // stdio_out_prev[fh] is last thing actually written
  552. char prev = stdio_out_prev[fh];
  553. // Seek for '\n' without preceding '\r'; if found flush
  554. // preceding and insert '\r'. Continue until end of input.
  555. for (ssize_t cur = 0; cur < slength; cur++) {
  556. if (buffer[cur] == '\n' && prev != '\r') {
  557. ssize_t r;
  558. // flush stuff preceding the \n
  559. if (cur > written) {
  560. r = write(fh, buffer + written, cur - written);
  561. if (r < 0) {
  562. return -1;
  563. }
  564. written += r;
  565. if (written < cur) {
  566. // For some reason, didn't write all - give up now
  567. goto finish;
  568. }
  569. stdio_out_prev[fh] = prev;
  570. }
  571. // insert a \r now, leaving the \n still to be written
  572. r = write(fh, "\r", 1);
  573. if (r < 0) {
  574. return -1;
  575. }
  576. if (r < 1) {
  577. goto finish;
  578. }
  579. stdio_out_prev[fh] = '\r';
  580. }
  581. prev = buffer[cur];
  582. }
  583. }
  584. // Flush remaining from conversion, or the whole thing if no conversion
  585. if (written < slength) {
  586. ssize_t r = write(fh, buffer + written, slength - written);
  587. if (r < 0) {
  588. return -1;
  589. }
  590. written += r;
  591. if (written > 0) {
  592. stdio_out_prev[fh] = buffer[written - 1];
  593. }
  594. }
  595. finish:
  596. #ifdef __ARMCC_VERSION
  597. if (written >= 0) {
  598. return slength - written;
  599. } else {
  600. return written;
  601. }
  602. #else
  603. return written;
  604. #endif
  605. }
  606. extern "C" ssize_t write(int fildes, const void *buf, size_t length)
  607. {
  608. FileHandle *fhc = get_fhc(fildes);
  609. if (fhc == NULL) {
  610. errno = EBADF;
  611. return -1;
  612. }
  613. ssize_t ret = fhc->write(buf, length);
  614. if (ret < 0) {
  615. errno = -ret;
  616. return -1;
  617. } else {
  618. return ret;
  619. }
  620. }
  621. #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
  622. extern "C" void PREFIX(_exit)(int return_code)
  623. {
  624. while (1) {}
  625. }
  626. extern "C" void _ttywrch(int ch)
  627. {
  628. char c = ch;
  629. write(STDOUT_FILENO, &c, 1);
  630. }
  631. #endif
  632. #if defined(__ICCARM__)
  633. extern "C" size_t __read(int fh, unsigned char *buffer, size_t length)
  634. {
  635. #else
  636. extern "C" int PREFIX(_read)(FILEHANDLE fh, unsigned char *buffer, unsigned int length, int mode)
  637. {
  638. #endif
  639. #if defined(MBED_TRAP_ERRORS_ENABLED) && MBED_TRAP_ERRORS_ENABLED && defined(MBED_CONF_RTOS_PRESENT)
  640. if (core_util_is_isr_active() || !core_util_are_interrupts_enabled()) {
  641. MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_PROHIBITED_IN_ISR_CONTEXT), "Error - reading from a file in an ISR or critical section\r\n", fh);
  642. }
  643. #endif
  644. if (length > SSIZE_MAX) {
  645. errno = EINVAL;
  646. return -1;
  647. }
  648. ssize_t bytes_read = 0;
  649. if (convert_crlf(fh)) {
  650. while (true) {
  651. char c;
  652. ssize_t r = read(fh, &c, 1);
  653. if (r < 0) {
  654. return -1;
  655. }
  656. if (r == 0) {
  657. return bytes_read;
  658. }
  659. if ((c == '\r' && stdio_in_prev[fh] != '\n') ||
  660. (c == '\n' && stdio_in_prev[fh] != '\r')) {
  661. stdio_in_prev[fh] = c;
  662. *buffer = '\n';
  663. break;
  664. } else if ((c == '\r' && stdio_in_prev[fh] == '\n') ||
  665. (c == '\n' && stdio_in_prev[fh] == '\r')) {
  666. stdio_in_prev[fh] = c;
  667. continue;
  668. } else {
  669. stdio_in_prev[fh] = c;
  670. *buffer = c;
  671. break;
  672. }
  673. }
  674. bytes_read = 1;
  675. } else {
  676. bytes_read = read(fh, buffer, length);
  677. }
  678. #ifdef __ARMCC_VERSION
  679. if (bytes_read < 0) {
  680. return -1;
  681. } else if (bytes_read == 0) {
  682. return 0x80000000 | length; // weird EOF indication
  683. } else {
  684. return (ssize_t)length - bytes_read;
  685. }
  686. #else
  687. return bytes_read;
  688. #endif
  689. }
  690. extern "C" ssize_t read(int fildes, void *buf, size_t length)
  691. {
  692. FileHandle *fhc = get_fhc(fildes);
  693. if (fhc == NULL) {
  694. errno = EBADF;
  695. return -1;
  696. }
  697. ssize_t ret = fhc->read(buf, length);
  698. if (ret < 0) {
  699. errno = -ret;
  700. return -1;
  701. } else {
  702. return ret;
  703. }
  704. }
  705. #ifdef __ARMCC_VERSION
  706. extern "C" int PREFIX(_istty)(FILEHANDLE fh)
  707. #else
  708. extern "C" int _isatty(FILEHANDLE fh)
  709. #endif
  710. {
  711. return isatty(fh);
  712. }
  713. extern "C" int isatty(int fildes)
  714. {
  715. FileHandle *fhc = get_fhc(fildes);
  716. if (fhc == NULL) {
  717. errno = EBADF;
  718. return 0;
  719. }
  720. int tty = fhc->isatty();
  721. if (tty < 0) {
  722. errno = -tty;
  723. return 0;
  724. } else {
  725. return tty;
  726. }
  727. }
  728. extern "C"
  729. #if defined(__ARMCC_VERSION)
  730. int _sys_seek(FILEHANDLE fh, long offset)
  731. #elif defined(__ICCARM__)
  732. long __lseek(int fh, long offset, int whence)
  733. #else
  734. int _lseek(FILEHANDLE fh, int offset, int whence)
  735. #endif
  736. {
  737. #if defined(__ARMCC_VERSION)
  738. int whence = SEEK_SET;
  739. #endif
  740. off_t off = lseek(fh, offset, whence);
  741. // Assuming INT_MAX = LONG_MAX, so we don't care about prototype difference
  742. if (off > INT_MAX) {
  743. errno = EOVERFLOW;
  744. return -1;
  745. }
  746. return off;
  747. }
  748. extern "C" off_t lseek(int fildes, off_t offset, int whence)
  749. {
  750. FileHandle *fhc = get_fhc(fildes);
  751. if (fhc == NULL) {
  752. errno = EBADF;
  753. return -1;
  754. }
  755. off_t off = fhc->seek(offset, whence);
  756. if (off < 0) {
  757. errno = -off;
  758. return -1;
  759. }
  760. return off;
  761. }
  762. #ifdef __ARMCC_VERSION
  763. extern "C" int PREFIX(_ensure)(FILEHANDLE fh)
  764. {
  765. return fsync(fh);
  766. }
  767. #endif
  768. extern "C" int fsync(int fildes)
  769. {
  770. FileHandle *fhc = get_fhc(fildes);
  771. if (fhc == NULL) {
  772. errno = EBADF;
  773. return -1;
  774. }
  775. int err = fhc->sync();
  776. if (err < 0) {
  777. errno = -err;
  778. return -1;
  779. } else {
  780. return 0;
  781. }
  782. }
  783. #ifdef __ARMCC_VERSION
  784. extern "C" long PREFIX(_flen)(FILEHANDLE fh)
  785. {
  786. FileHandle *fhc = get_fhc(fh);
  787. if (fhc == NULL) {
  788. errno = EBADF;
  789. return -1;
  790. }
  791. off_t size = fhc->size();
  792. if (size < 0) {
  793. errno = -size;
  794. return -1;
  795. }
  796. if (size > LONG_MAX) {
  797. errno = EOVERFLOW;
  798. return -1;
  799. }
  800. return size;
  801. }
  802. extern "C" char Image$$RW_IRAM1$$ZI$$Limit[];
  803. extern "C" MBED_WEAK __value_in_regs struct __initial_stackheap _mbed_user_setup_stackheap(uint32_t R0, uint32_t R1, uint32_t R2, uint32_t R3)
  804. {
  805. uint32_t zi_limit = (uint32_t)Image$$RW_IRAM1$$ZI$$Limit;
  806. uint32_t sp_limit = __current_sp();
  807. zi_limit = (zi_limit + 7) & ~0x7; // ensure zi_limit is 8-byte aligned
  808. struct __initial_stackheap r;
  809. r.heap_base = zi_limit;
  810. r.heap_limit = sp_limit;
  811. return r;
  812. }
  813. extern "C" __value_in_regs struct __initial_stackheap __user_setup_stackheap(uint32_t R0, uint32_t R1, uint32_t R2, uint32_t R3)
  814. {
  815. return _mbed_user_setup_stackheap(R0, R1, R2, R3);
  816. }
  817. #endif
  818. #if !defined(__ARMCC_VERSION) && !defined(__ICCARM__)
  819. extern "C" int _fstat(int fh, struct stat *st)
  820. {
  821. return fstat(fh, st);
  822. }
  823. #endif
  824. extern "C" int fstat(int fildes, struct stat *st)
  825. {
  826. FileHandle *fhc = get_fhc(fildes);
  827. if (fhc == NULL) {
  828. errno = EBADF;
  829. return -1;
  830. }
  831. st->st_mode = fhc->isatty() ? S_IFCHR : S_IFREG;
  832. st->st_size = fhc->size();
  833. return 0;
  834. }
  835. extern "C" int fcntl(int fildes, int cmd, ...)
  836. {
  837. FileHandle *fhc = get_fhc(fildes);
  838. if (fhc == NULL) {
  839. errno = EBADF;
  840. return -1;
  841. }
  842. switch (cmd) {
  843. case F_GETFL: {
  844. int flags = 0;
  845. if (fhc->is_blocking()) {
  846. flags |= O_NONBLOCK;
  847. }
  848. return flags;
  849. }
  850. case F_SETFL: {
  851. va_list ap;
  852. va_start(ap, cmd);
  853. int flags = va_arg(ap, int);
  854. va_end(ap);
  855. int ret = fhc->set_blocking(flags & O_NONBLOCK);
  856. if (ret < 0) {
  857. errno = -ret;
  858. return -1;
  859. }
  860. return 0;
  861. }
  862. default: {
  863. errno = EINVAL;
  864. return -1;
  865. }
  866. }
  867. }
  868. extern "C" int poll(struct pollfd fds[], nfds_t nfds, int timeout)
  869. {
  870. if (nfds > OPEN_MAX) {
  871. errno = EINVAL;
  872. return -1;
  873. }
  874. struct mbed::pollfh fhs[OPEN_MAX];
  875. for (nfds_t n = 0; n < nfds; n++) {
  876. // Underlying FileHandle poll returns POLLNVAL if given NULL, so
  877. // we don't need to take special action.
  878. fhs[n].fh = get_fhc(fds[n].fd);
  879. fhs[n].events = fds[n].events;
  880. }
  881. int ret = poll(fhs, nfds, timeout);
  882. for (nfds_t n = 0; n < nfds; n++) {
  883. fds[n].revents = fhs[n].revents;
  884. }
  885. return ret;
  886. }
  887. namespace std {
  888. extern "C" int remove(const char *path)
  889. {
  890. FilePath fp(path);
  891. FileSystemHandle *fs = fp.fileSystem();
  892. if (fs == NULL) {
  893. errno = ENODEV;
  894. return -1;
  895. }
  896. int err = fs->remove(fp.fileName());
  897. if (err < 0) {
  898. errno = -err;
  899. return -1;
  900. } else {
  901. return 0;
  902. }
  903. }
  904. extern "C" int rename(const char *oldname, const char *newname)
  905. {
  906. FilePath fpOld(oldname);
  907. FilePath fpNew(newname);
  908. FileSystemHandle *fsOld = fpOld.fileSystem();
  909. FileSystemHandle *fsNew = fpNew.fileSystem();
  910. if (fsOld == NULL) {
  911. errno = ENODEV;
  912. return -1;
  913. }
  914. /* rename only if both files are on the same FS */
  915. if (fsOld != fsNew) {
  916. errno = EXDEV;
  917. return -1;
  918. }
  919. int err = fsOld->rename(fpOld.fileName(), fpNew.fileName());
  920. if (err < 0) {
  921. errno = -err;
  922. return -1;
  923. } else {
  924. return 0;
  925. }
  926. }
  927. extern "C" char *tmpnam(char *s)
  928. {
  929. errno = EBADF;
  930. return NULL;
  931. }
  932. extern "C" FILE *tmpfile()
  933. {
  934. errno = EBADF;
  935. return NULL;
  936. }
  937. } // namespace std
  938. #ifdef __ARMCC_VERSION
  939. extern "C" char *_sys_command_string(char *cmd, int len)
  940. {
  941. return NULL;
  942. }
  943. #endif
  944. extern "C" DIR *opendir(const char *path)
  945. {
  946. FilePath fp(path);
  947. FileSystemHandle *fs = fp.fileSystem();
  948. if (fs == NULL) {
  949. errno = ENODEV;
  950. return NULL;
  951. }
  952. DirHandle *dir;
  953. int err = fs->open(&dir, fp.fileName());
  954. if (err < 0) {
  955. errno = -err;
  956. return NULL;
  957. }
  958. return dir;
  959. }
  960. extern "C" struct dirent *readdir(DIR *dir)
  961. {
  962. static struct dirent ent;
  963. int err = dir->read(&ent);
  964. if (err < 1) {
  965. if (err < 0) {
  966. errno = -err;
  967. }
  968. return NULL;
  969. }
  970. return &ent;
  971. }
  972. extern "C" int closedir(DIR *dir)
  973. {
  974. int err = dir->close();
  975. if (err < 0) {
  976. errno = -err;
  977. return -1;
  978. } else {
  979. return 0;
  980. }
  981. }
  982. extern "C" void rewinddir(DIR *dir)
  983. {
  984. dir->rewind();
  985. }
  986. extern "C" off_t telldir(DIR *dir)
  987. {
  988. return dir->tell();
  989. }
  990. extern "C" void seekdir(DIR *dir, off_t off)
  991. {
  992. dir->seek(off);
  993. }
  994. extern "C" int mkdir(const char *path, mode_t mode)
  995. {
  996. FilePath fp(path);
  997. FileSystemHandle *fs = fp.fileSystem();
  998. if (fs == NULL) {
  999. errno = ENODEV;
  1000. return -1;
  1001. }
  1002. int err = fs->mkdir(fp.fileName(), mode);
  1003. if (err < 0) {
  1004. errno = -err;
  1005. return -1;
  1006. } else {
  1007. return 0;
  1008. }
  1009. }
  1010. extern "C" int stat(const char *path, struct stat *st)
  1011. {
  1012. FilePath fp(path);
  1013. FileSystemHandle *fs = fp.fileSystem();
  1014. if (fs == NULL) {
  1015. errno = ENODEV;
  1016. return -1;
  1017. }
  1018. int err = fs->stat(fp.fileName(), st);
  1019. if (err < 0) {
  1020. errno = -err;
  1021. return -1;
  1022. } else {
  1023. return 0;
  1024. }
  1025. }
  1026. extern "C" int statvfs(const char *path, struct statvfs *buf)
  1027. {
  1028. FilePath fp(path);
  1029. FileSystemHandle *fs = fp.fileSystem();
  1030. if (fs == NULL) {
  1031. errno = ENODEV;
  1032. return -1;
  1033. }
  1034. int err = fs->statvfs(fp.fileName(), buf);
  1035. if (err < 0) {
  1036. errno = -err;
  1037. return -1;
  1038. } else {
  1039. return 0;
  1040. }
  1041. }
  1042. #if defined(TOOLCHAIN_GCC)
  1043. /* prevents the exception handling name demangling code getting pulled in */
  1044. #include "mbed_error.h"
  1045. namespace __gnu_cxx {
  1046. void __verbose_terminate_handler()
  1047. {
  1048. MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_CLIB_EXCEPTION), "Exception", 0);
  1049. }
  1050. }
  1051. extern "C" WEAK void __cxa_pure_virtual(void);
  1052. extern "C" WEAK void __cxa_pure_virtual(void)
  1053. {
  1054. exit(1);
  1055. }
  1056. #endif
  1057. // Provide implementation of _sbrk (low-level dynamic memory allocation
  1058. // routine) for GCC_ARM which compares new heap pointer with MSP instead of
  1059. // SP. This make it compatible with RTX RTOS thread stacks.
  1060. #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
  1061. #if defined(TARGET_CORTEX_A)
  1062. extern "C" uint32_t __HeapLimit;
  1063. #endif
  1064. // Turn off the errno macro and use actual global variable instead.
  1065. #undef errno
  1066. extern "C" int errno;
  1067. // Dynamic memory allocation related syscall.
  1068. #if defined(TWO_RAM_REGIONS)
  1069. // Overwrite _sbrk() to support two region model (heap and stack are two distinct regions).
  1070. // __wrap__sbrk() is implemented in:
  1071. // TARGET_STM32L4 targets/TARGET_STM/TARGET_STM32L4/TARGET_STM32L4/l4_retarget.c
  1072. extern "C" void *__wrap__sbrk(int incr);
  1073. extern "C" caddr_t _sbrk(int incr)
  1074. {
  1075. return (caddr_t) __wrap__sbrk(incr);
  1076. }
  1077. #else
  1078. // Linker defined symbol used by _sbrk to indicate where heap should start.
  1079. extern "C" uint32_t __end__;
  1080. // Weak attribute allows user to override, e.g. to use external RAM for dynamic memory.
  1081. extern "C" WEAK caddr_t _sbrk(int incr)
  1082. {
  1083. static unsigned char *heap = (unsigned char *)&__end__;
  1084. unsigned char *prev_heap = heap;
  1085. unsigned char *new_heap = heap + incr;
  1086. #if defined(TARGET_CORTEX_A)
  1087. if (new_heap >= (unsigned char *)&__HeapLimit) { /* __HeapLimit is end of heap section */
  1088. #else
  1089. if (new_heap >= (unsigned char *)__get_MSP()) {
  1090. #endif
  1091. errno = ENOMEM;
  1092. return (caddr_t) -1;
  1093. }
  1094. // Additional heap checking if set
  1095. if (mbed_heap_size && (new_heap >= mbed_heap_start + mbed_heap_size)) {
  1096. errno = ENOMEM;
  1097. return (caddr_t) -1;
  1098. }
  1099. heap = new_heap;
  1100. return (caddr_t) prev_heap;
  1101. }
  1102. #endif
  1103. #endif
  1104. #if defined(TOOLCHAIN_GCC_ARM) || defined(TOOLCHAIN_GCC_CR)
  1105. extern "C" void _exit(int return_code)
  1106. {
  1107. #else
  1108. namespace std {
  1109. extern "C" void exit(int return_code)
  1110. {
  1111. #endif
  1112. #if DEVICE_STDIO_MESSAGES
  1113. #if MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT
  1114. fflush(stdout);
  1115. fflush(stderr);
  1116. #endif
  1117. #endif
  1118. #if DEVICE_SEMIHOST
  1119. if (mbed_interface_connected()) {
  1120. semihost_exit();
  1121. }
  1122. #endif
  1123. if (return_code) {
  1124. mbed_die();
  1125. }
  1126. while (1);
  1127. }
  1128. #if !defined(TOOLCHAIN_GCC_ARM) && !defined(TOOLCHAIN_GCC_CR)
  1129. } //namespace std
  1130. #endif
  1131. #if defined(TOOLCHAIN_ARM) || defined(TOOLCHAIN_GCC)
  1132. // This series of function disable the registration of global destructors
  1133. // in a dynamic table which will be called when the application exit.
  1134. // In mbed, program never exit properly, it dies.
  1135. // More informations about this topic for ARMCC here:
  1136. // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/6449.html
  1137. extern "C" {
  1138. int __aeabi_atexit(void *object, void (*dtor)(void * /*this*/), void *handle)
  1139. {
  1140. return 1;
  1141. }
  1142. int __cxa_atexit(void (*dtor)(void * /*this*/), void *object, void *handle)
  1143. {
  1144. return 1;
  1145. }
  1146. void __cxa_finalize(void *handle)
  1147. {
  1148. }
  1149. } // end of extern "C"
  1150. #endif
  1151. #if defined(TOOLCHAIN_GCC)
  1152. /*
  1153. * Depending on how newlib is configured, it is often not enough to define
  1154. * __aeabi_atexit, __cxa_atexit and __cxa_finalize in order to override the
  1155. * behavior regarding the registration of handlers with atexit.
  1156. *
  1157. * To overcome this limitation, exit and atexit are overriden here.
  1158. */
  1159. extern "C" {
  1160. /**
  1161. * @brief Retarget of exit for GCC.
  1162. * @details Unlike the standard version, this function doesn't call any function
  1163. * registered with atexit before calling _exit.
  1164. */
  1165. void __wrap_exit(int return_code)
  1166. {
  1167. _exit(return_code);
  1168. }
  1169. /**
  1170. * @brief Retarget atexit from GCC.
  1171. * @details This function will always fail and never register any handler to be
  1172. * called at exit.
  1173. */
  1174. int __wrap_atexit(void (*func)())
  1175. {
  1176. return 1;
  1177. }
  1178. }
  1179. #endif
  1180. namespace mbed {
  1181. void mbed_set_unbuffered_stream(std::FILE *_file)
  1182. {
  1183. #if defined (__ICCARM__)
  1184. char buf[2];
  1185. std::setvbuf(_file, buf, _IONBF, NULL);
  1186. #else
  1187. setbuf(_file, NULL);
  1188. #endif
  1189. }
  1190. int mbed_getc(std::FILE *_file)
  1191. {
  1192. #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000)
  1193. /*This is only valid for unbuffered streams*/
  1194. int res = std::fgetc(_file);
  1195. if (res >= 0) {
  1196. _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
  1197. _file->_Rend = _file->_Wend;
  1198. _file->_Next = _file->_Wend;
  1199. }
  1200. return res;
  1201. #else
  1202. return std::fgetc(_file);
  1203. #endif
  1204. }
  1205. char *mbed_gets(char *s, int size, std::FILE *_file)
  1206. {
  1207. #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ < 8000000)
  1208. /*This is only valid for unbuffered streams*/
  1209. char *str = fgets(s, size, _file);
  1210. if (str != NULL) {
  1211. _file->_Mode = (unsigned short)(_file->_Mode & ~ 0x1000);/* Unset read mode */
  1212. _file->_Rend = _file->_Wend;
  1213. _file->_Next = _file->_Wend;
  1214. }
  1215. return str;
  1216. #else
  1217. return std::fgets(s, size, _file);
  1218. #endif
  1219. }
  1220. } // namespace mbed
  1221. #if defined (__ICCARM__)
  1222. // Stub out locks when an rtos is not present
  1223. extern "C" WEAK void __iar_system_Mtxinit(__iar_Rmtx *mutex) {}
  1224. extern "C" WEAK void __iar_system_Mtxdst(__iar_Rmtx *mutex) {}
  1225. extern "C" WEAK void __iar_system_Mtxlock(__iar_Rmtx *mutex) {}
  1226. extern "C" WEAK void __iar_system_Mtxunlock(__iar_Rmtx *mutex) {}
  1227. extern "C" WEAK void __iar_file_Mtxinit(__iar_Rmtx *mutex) {}
  1228. extern "C" WEAK void __iar_file_Mtxdst(__iar_Rmtx *mutex) {}
  1229. extern "C" WEAK void __iar_file_Mtxlock(__iar_Rmtx *mutex) {}
  1230. extern "C" WEAK void __iar_file_Mtxunlock(__iar_Rmtx *mutex) {}
  1231. #if defined(__IAR_SYSTEMS_ICC__ ) && (__VER__ >= 8000000)
  1232. #pragma section="__iar_tls$$DATA"
  1233. extern "C" WEAK void *__aeabi_read_tp(void)
  1234. {
  1235. // Thread Local storage is not supported, using main thread memory for errno
  1236. return __section_begin("__iar_tls$$DATA");
  1237. }
  1238. #endif
  1239. #elif defined(__CC_ARM)
  1240. // Do nothing
  1241. #elif defined (__GNUC__)
  1242. struct _reent;
  1243. // Stub out locks when an rtos is not present
  1244. extern "C" WEAK void __rtos_malloc_lock(struct _reent *_r) {}
  1245. extern "C" WEAK void __rtos_malloc_unlock(struct _reent *_r) {}
  1246. extern "C" WEAK void __rtos_env_lock(struct _reent *_r) {}
  1247. extern "C" WEAK void __rtos_env_unlock(struct _reent *_r) {}
  1248. extern "C" void __malloc_lock(struct _reent *_r)
  1249. {
  1250. __rtos_malloc_lock(_r);
  1251. }
  1252. extern "C" void __malloc_unlock(struct _reent *_r)
  1253. {
  1254. __rtos_malloc_unlock(_r);
  1255. }
  1256. extern "C" void __env_lock(struct _reent *_r)
  1257. {
  1258. __rtos_env_lock(_r);
  1259. }
  1260. extern "C" void __env_unlock(struct _reent *_r)
  1261. {
  1262. __rtos_env_unlock(_r);
  1263. }
  1264. #endif
  1265. #if defined (__GNUC__) || defined(__CC_ARM) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
  1266. #define CXA_GUARD_INIT_DONE (1 << 0)
  1267. #define CXA_GUARD_INIT_IN_PROGRESS (1 << 1)
  1268. #define CXA_GUARD_MASK (CXA_GUARD_INIT_DONE | CXA_GUARD_INIT_IN_PROGRESS)
  1269. extern "C" int __cxa_guard_acquire(int *guard_object_p)
  1270. {
  1271. uint8_t *guard_object = (uint8_t *)guard_object_p;
  1272. if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
  1273. return 0;
  1274. }
  1275. singleton_lock();
  1276. if (CXA_GUARD_INIT_DONE == (*guard_object & CXA_GUARD_MASK)) {
  1277. singleton_unlock();
  1278. return 0;
  1279. }
  1280. MBED_ASSERT(0 == (*guard_object & CXA_GUARD_MASK));
  1281. *guard_object = *guard_object | CXA_GUARD_INIT_IN_PROGRESS;
  1282. return 1;
  1283. }
  1284. extern "C" void __cxa_guard_release(int *guard_object_p)
  1285. {
  1286. uint8_t *guard_object = (uint8_t *)guard_object_p;
  1287. MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
  1288. *guard_object = (*guard_object & ~CXA_GUARD_MASK) | CXA_GUARD_INIT_DONE;
  1289. singleton_unlock();
  1290. }
  1291. extern "C" void __cxa_guard_abort(int *guard_object_p)
  1292. {
  1293. uint8_t *guard_object = (uint8_t *)guard_object_p;
  1294. MBED_ASSERT(CXA_GUARD_INIT_IN_PROGRESS == (*guard_object & CXA_GUARD_MASK));
  1295. *guard_object = *guard_object & ~CXA_GUARD_INIT_IN_PROGRESS;
  1296. singleton_unlock();
  1297. }
  1298. #endif
  1299. #if defined(MBED_MEM_TRACING_ENABLED) && (defined(__CC_ARM) || defined(__ICCARM__) || (defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)))
  1300. // If the memory tracing is enabled, the wrappers in mbed_alloc_wrappers.cpp
  1301. // provide the implementation for these. Note: this needs to use the wrappers
  1302. // instead of malloc()/free() as the caller address would point to wrappers,
  1303. // not the caller of "new" or "delete".
  1304. extern "C" void *malloc_wrapper(size_t size, const void *caller);
  1305. extern "C" void free_wrapper(void *ptr, const void *caller);
  1306. void *operator new (std::size_t count)
  1307. {
  1308. void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR());
  1309. if (NULL == buffer) {
  1310. MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count);
  1311. }
  1312. return buffer;
  1313. }
  1314. void *operator new[](std::size_t count)
  1315. {
  1316. void *buffer = malloc_wrapper(count, MBED_CALLER_ADDR());
  1317. if (NULL == buffer) {
  1318. error("Operator new[] out of memory\r\n");
  1319. }
  1320. return buffer;
  1321. }
  1322. void *operator new (std::size_t count, const std::nothrow_t &tag)
  1323. {
  1324. return malloc_wrapper(count, MBED_CALLER_ADDR());
  1325. }
  1326. void *operator new[](std::size_t count, const std::nothrow_t &tag)
  1327. {
  1328. return malloc_wrapper(count, MBED_CALLER_ADDR());
  1329. }
  1330. void operator delete (void *ptr)
  1331. {
  1332. free_wrapper(ptr, MBED_CALLER_ADDR());
  1333. }
  1334. void operator delete[](void *ptr)
  1335. {
  1336. free_wrapper(ptr, MBED_CALLER_ADDR());
  1337. }
  1338. #elif defined(MBED_MEM_TRACING_ENABLED) && defined(__GNUC__)
  1339. #include <reent.h>
  1340. extern "C" void *malloc_wrapper(struct _reent *r, size_t size, void *caller);
  1341. extern "C" void free_wrapper(struct _reent *r, void *ptr, void *caller);
  1342. void *operator new (std::size_t count)
  1343. {
  1344. void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
  1345. if (NULL == buffer) {
  1346. MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count);
  1347. }
  1348. return buffer;
  1349. }
  1350. void *operator new[](std::size_t count)
  1351. {
  1352. void *buffer = malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
  1353. if (NULL == buffer) {
  1354. MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count);
  1355. }
  1356. return buffer;
  1357. }
  1358. void *operator new (std::size_t count, const std::nothrow_t &tag)
  1359. {
  1360. return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
  1361. }
  1362. void *operator new[](std::size_t count, const std::nothrow_t &tag)
  1363. {
  1364. return malloc_wrapper(_REENT, count, MBED_CALLER_ADDR());
  1365. }
  1366. void operator delete (void *ptr)
  1367. {
  1368. free_wrapper(_REENT, ptr, MBED_CALLER_ADDR());
  1369. }
  1370. void operator delete[](void *ptr)
  1371. {
  1372. free_wrapper(_REENT, ptr, MBED_CALLER_ADDR());
  1373. }
  1374. #else
  1375. void *operator new (std::size_t count)
  1376. {
  1377. void *buffer = malloc(count);
  1378. if (NULL == buffer) {
  1379. MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new out of memory\r\n", count);
  1380. }
  1381. return buffer;
  1382. }
  1383. void *operator new[](std::size_t count)
  1384. {
  1385. void *buffer = malloc(count);
  1386. if (NULL == buffer) {
  1387. MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OUT_OF_MEMORY), "Operator new[] out of memory\r\n", count);
  1388. }
  1389. return buffer;
  1390. }
  1391. void *operator new (std::size_t count, const std::nothrow_t &tag)
  1392. {
  1393. return malloc(count);
  1394. }
  1395. void *operator new[](std::size_t count, const std::nothrow_t &tag)
  1396. {
  1397. return malloc(count);
  1398. }
  1399. void operator delete (void *ptr)
  1400. {
  1401. free(ptr);
  1402. }
  1403. void operator delete[](void *ptr)
  1404. {
  1405. free(ptr);
  1406. }
  1407. #endif
  1408. /* @brief standard c library clock() function.
  1409. *
  1410. * This function returns the number of clock ticks elapsed since the start of the program.
  1411. *
  1412. * @note Synchronization level: Thread safe
  1413. *
  1414. * @return
  1415. * the number of clock ticks elapsed since the start of the program.
  1416. *
  1417. * */
  1418. extern "C" clock_t clock()
  1419. {
  1420. _mutex->lock();
  1421. clock_t t = ticker_read(get_us_ticker_data());
  1422. t /= 1000000 / CLOCKS_PER_SEC; // convert to processor time
  1423. _mutex->unlock();
  1424. return t;
  1425. }
  1426. // temporary - Default to 1MHz at 32 bits if target does not have us_ticker_get_info
  1427. MBED_WEAK const ticker_info_t *us_ticker_get_info()
  1428. {
  1429. static const ticker_info_t info = {
  1430. 1000000,
  1431. 32
  1432. };
  1433. return &info;
  1434. }
  1435. // temporary - Default to 1MHz at 32 bits if target does not have lp_ticker_get_info
  1436. MBED_WEAK const ticker_info_t *lp_ticker_get_info()
  1437. {
  1438. static const ticker_info_t info = {
  1439. 1000000,
  1440. 32
  1441. };
  1442. return &info;
  1443. }