Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
SemihostedFileSystem.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 #include "SemihostedFileSystem.h" 00017 #include "mbed_semihost_api_shim.h" 00018 #include <string.h> 00019 #include <stdio.h> 00020 #include <errno.h> 00021 #include <cstdarg> 00022 00023 #define STRING_STACK_LIMIT 120 00024 00025 #define OPEN_R 0 00026 #define OPEN_B 1 00027 #define OPEN_PLUS 2 00028 #define OPEN_W 4 00029 #define OPEN_A 8 00030 #define OPEN_INVALID -1 00031 00032 static int posix_to_semihost_open_flags(int flags) { 00033 /* POSIX flags -> semihosting open mode */ 00034 int openmode; 00035 if (flags & O_RDWR) { 00036 /* a plus mode */ 00037 openmode = OPEN_PLUS; 00038 if (flags & O_APPEND) { 00039 openmode |= OPEN_A; 00040 } else if (flags & O_TRUNC) { 00041 openmode |= OPEN_W; 00042 } else { 00043 openmode |= OPEN_R; 00044 } 00045 } else if (flags & O_WRONLY) { 00046 /* write or append */ 00047 if (flags & O_APPEND) { 00048 openmode = OPEN_A; 00049 } else { 00050 openmode = OPEN_W; 00051 } 00052 } else if (flags == O_RDONLY) { 00053 /* read mode */ 00054 openmode = OPEN_R; 00055 } else { 00056 /* invalid flags */ 00057 openmode = OPEN_INVALID; 00058 } 00059 00060 return openmode; 00061 } 00062 00063 FILEHANDLE semihosted_file_open(const char* name, int flags) { 00064 int openmode = posix_to_semihost_open_flags(flags); 00065 if (openmode == OPEN_INVALID) { 00066 return (FILEHANDLE)NULL; 00067 } 00068 00069 FILEHANDLE fh = semihost_open(name, openmode); 00070 if (fh == -1) { 00071 return (FILEHANDLE)NULL; 00072 } 00073 00074 return fh; 00075 } 00076 00077 SemihostedFileHandle::SemihostedFileHandle(FILEHANDLE fh) : _fh(fh), pos(0) { 00078 // No lock needed in constructor 00079 } 00080 00081 SemihostedFileHandle::SemihostedFileHandle(const char* name, int flags) 00082 : _fh(semihosted_file_open(name, flags)), pos(0) { 00083 // No lock needed in constructor 00084 } 00085 00086 int SemihostedFileHandle::close() { 00087 int retval = semihost_close(_fh); 00088 delete this; 00089 return retval; 00090 } 00091 00092 ssize_t SemihostedFileHandle::write(const void *buffer, size_t length) { 00093 lock(); 00094 ssize_t n = semihost_write(_fh, (const unsigned char*)buffer, length, 0); // number of characters not written 00095 n = length - n; // number of characters written 00096 pos += n; 00097 unlock(); 00098 return n; 00099 } 00100 00101 ssize_t SemihostedFileHandle::read(void *buffer, size_t length) { 00102 lock(); 00103 ssize_t n = semihost_read(_fh, (unsigned char*)buffer, length, 0); // number of characters not read 00104 n = length - n; // number of characters read 00105 pos += n; 00106 unlock(); 00107 return n; 00108 } 00109 00110 int SemihostedFileHandle::isatty() { 00111 lock(); 00112 int ret = semihost_istty(_fh); 00113 unlock(); 00114 return ret; 00115 } 00116 00117 off_t SemihostedFileHandle::seek(off_t position, int whence) { 00118 lock(); 00119 if (whence == SEEK_CUR) { 00120 position += pos; 00121 } else if (whence == SEEK_END) { 00122 position += semihost_flen(_fh); 00123 } /* otherwise SEEK_SET, so position is fine */ 00124 00125 /* Always seems to return -1, so just ignore for now. */ 00126 semihost_seek(_fh, position); 00127 pos = position; 00128 unlock(); 00129 return position; 00130 } 00131 00132 int SemihostedFileHandle::sync() { 00133 lock(); 00134 int ret = semihost_ensure(_fh); 00135 unlock(); 00136 return ret; 00137 } 00138 00139 off_t SemihostedFileHandle::size() { 00140 lock(); 00141 off_t off = semihost_flen(_fh); 00142 unlock(); 00143 return off; 00144 } 00145 00146 void SemihostedFileHandle::lock() { 00147 _mutex.lock(); 00148 } 00149 00150 void SemihostedFileHandle::unlock() { 00151 _mutex.unlock(); 00152 } 00153 00154 // Experimental support for printf in RawSerial. No Stream inheritance 00155 // means we can't call printf() directly, so we use sprintf() instead. 00156 // We only call malloc() for the sprintf() buffer if the buffer 00157 // length is above a certain threshold, otherwise we use just the stack. 00158 int SemihostedFileHandle::printf(const char *format, ...) { 00159 lock(); 00160 std::va_list arg; 00161 va_start(arg, format); 00162 // ARMCC microlib does not properly handle a size of 0. 00163 // As a workaround supply a dummy buffer with a size of 1. 00164 char dummy_buf[1]; 00165 int len = vsnprintf(dummy_buf, sizeof(dummy_buf), format, arg); 00166 if (len < STRING_STACK_LIMIT) { 00167 char temp[STRING_STACK_LIMIT]; 00168 vsprintf(temp, format, arg); 00169 write(temp, len); 00170 } else { 00171 char *temp = new char[len + 1]; 00172 vsprintf(temp, format, arg); 00173 write(temp, len); 00174 delete[] temp; 00175 } 00176 va_end(arg); 00177 unlock(); 00178 return len; 00179 }
Generated on Thu Jul 14 2022 18:48:16 by
