RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
Parent:
0:38ceb79fef03
2019-03-13

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 0:38ceb79fef03 1 /* mbed Microcontroller Library
kevman 0:38ceb79fef03 2 * Copyright (c) 2006-2013 ARM Limited
kevman 0:38ceb79fef03 3 *
kevman 0:38ceb79fef03 4 * Licensed under the Apache License, Version 2.0 (the "License");
kevman 0:38ceb79fef03 5 * you may not use this file except in compliance with the License.
kevman 0:38ceb79fef03 6 * You may obtain a copy of the License at
kevman 0:38ceb79fef03 7 *
kevman 0:38ceb79fef03 8 * http://www.apache.org/licenses/LICENSE-2.0
kevman 0:38ceb79fef03 9 *
kevman 0:38ceb79fef03 10 * Unless required by applicable law or agreed to in writing, software
kevman 0:38ceb79fef03 11 * distributed under the License is distributed on an "AS IS" BASIS,
kevman 0:38ceb79fef03 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kevman 0:38ceb79fef03 13 * See the License for the specific language governing permissions and
kevman 0:38ceb79fef03 14 * limitations under the License.
kevman 0:38ceb79fef03 15 */
kevman 0:38ceb79fef03 16 #include "platform/LocalFileSystem.h"
kevman 0:38ceb79fef03 17
kevman 0:38ceb79fef03 18 #if DEVICE_LOCALFILESYSTEM
kevman 0:38ceb79fef03 19
kevman 0:38ceb79fef03 20 #include "platform/mbed_semihost_api.h"
kevman 0:38ceb79fef03 21 #include <string.h>
kevman 0:38ceb79fef03 22 #include <stdio.h>
kevman 0:38ceb79fef03 23 #include <errno.h>
kevman 0:38ceb79fef03 24
kevman 0:38ceb79fef03 25 namespace mbed {
kevman 0:38ceb79fef03 26
kevman 0:38ceb79fef03 27 /* Extension to FINFO type defined in RTL.h (in Keil RL) - adds 'create time'. */
kevman 0:38ceb79fef03 28 typedef struct {
kevman 0:38ceb79fef03 29 unsigned char hr; /* Hours [0..23] */
kevman 0:38ceb79fef03 30 unsigned char min; /* Minutes [0..59] */
kevman 0:38ceb79fef03 31 unsigned char sec; /* Seconds [0..59] */
kevman 0:38ceb79fef03 32 unsigned char day; /* Day [1..31] */
kevman 0:38ceb79fef03 33 unsigned char mon; /* Month [1..12] */
kevman 0:38ceb79fef03 34 unsigned short year; /* Year [1980..2107] */
kevman 0:38ceb79fef03 35 } FTIME;
kevman 0:38ceb79fef03 36
kevman 0:38ceb79fef03 37 typedef struct { /* File Search info record */
kevman 0:38ceb79fef03 38 char name[32]; /* File name */
kevman 0:38ceb79fef03 39 long size; /* File size in bytes */
kevman 0:38ceb79fef03 40 int fileID; /* System File Identification */
kevman 0:38ceb79fef03 41 FTIME create_time; /* Date & time file was created */
kevman 0:38ceb79fef03 42 FTIME write_time; /* Date & time of last write */
kevman 0:38ceb79fef03 43 } XFINFO;
kevman 0:38ceb79fef03 44
kevman 0:38ceb79fef03 45 #define RESERVED_FOR_USER_APPLICATIONS (0x100) /* 0x100 - 0x1ff */
kevman 0:38ceb79fef03 46 #define USR_XFFIND (RESERVED_FOR_USER_APPLICATIONS + 0)
kevman 0:38ceb79fef03 47
kevman 0:38ceb79fef03 48 static int xffind(const char *pattern, XFINFO *info)
kevman 0:38ceb79fef03 49 {
kevman 0:38ceb79fef03 50 unsigned param[4];
kevman 0:38ceb79fef03 51
kevman 0:38ceb79fef03 52 param[0] = (unsigned long)pattern;
kevman 0:38ceb79fef03 53 param[1] = (unsigned long)strlen(pattern);
kevman 0:38ceb79fef03 54 param[2] = (unsigned long)info;
kevman 0:38ceb79fef03 55 param[3] = (unsigned long)sizeof(XFINFO);
kevman 0:38ceb79fef03 56
kevman 0:38ceb79fef03 57 return __semihost(USR_XFFIND, param);
kevman 0:38ceb79fef03 58 }
kevman 0:38ceb79fef03 59
kevman 0:38ceb79fef03 60 #define OPEN_R 0
kevman 0:38ceb79fef03 61 #define OPEN_B 1
kevman 0:38ceb79fef03 62 #define OPEN_PLUS 2
kevman 0:38ceb79fef03 63 #define OPEN_W 4
kevman 0:38ceb79fef03 64 #define OPEN_A 8
kevman 0:38ceb79fef03 65 #define OPEN_INVALID -1
kevman 0:38ceb79fef03 66
kevman 0:38ceb79fef03 67 int posix_to_semihost_open_flags(int flags)
kevman 0:38ceb79fef03 68 {
kevman 0:38ceb79fef03 69 /* POSIX flags -> semihosting open mode */
kevman 0:38ceb79fef03 70 int openmode;
kevman 0:38ceb79fef03 71 if (flags & O_RDWR) {
kevman 0:38ceb79fef03 72 /* a plus mode */
kevman 0:38ceb79fef03 73 openmode = OPEN_PLUS;
kevman 0:38ceb79fef03 74 if (flags & O_APPEND) {
kevman 0:38ceb79fef03 75 openmode |= OPEN_A;
kevman 0:38ceb79fef03 76 } else if (flags & O_TRUNC) {
kevman 0:38ceb79fef03 77 openmode |= OPEN_W;
kevman 0:38ceb79fef03 78 } else {
kevman 0:38ceb79fef03 79 openmode |= OPEN_R;
kevman 0:38ceb79fef03 80 }
kevman 0:38ceb79fef03 81 } else if (flags & O_WRONLY) {
kevman 0:38ceb79fef03 82 /* write or append */
kevman 0:38ceb79fef03 83 if (flags & O_APPEND) {
kevman 0:38ceb79fef03 84 openmode = OPEN_A;
kevman 0:38ceb79fef03 85 } else {
kevman 0:38ceb79fef03 86 openmode = OPEN_W;
kevman 0:38ceb79fef03 87 }
kevman 0:38ceb79fef03 88 } else if (flags == O_RDONLY) {
kevman 0:38ceb79fef03 89 /* read mode */
kevman 0:38ceb79fef03 90 openmode = OPEN_R;
kevman 0:38ceb79fef03 91 } else {
kevman 0:38ceb79fef03 92 /* invalid flags */
kevman 0:38ceb79fef03 93 openmode = OPEN_INVALID;
kevman 0:38ceb79fef03 94 }
kevman 0:38ceb79fef03 95
kevman 0:38ceb79fef03 96 return openmode;
kevman 0:38ceb79fef03 97 }
kevman 0:38ceb79fef03 98
kevman 0:38ceb79fef03 99 FILEHANDLE local_file_open(const char *name, int flags)
kevman 0:38ceb79fef03 100 {
kevman 0:38ceb79fef03 101 int openmode = posix_to_semihost_open_flags(flags);
kevman 0:38ceb79fef03 102 if (openmode == OPEN_INVALID) {
kevman 0:38ceb79fef03 103 return (FILEHANDLE)NULL;
kevman 0:38ceb79fef03 104 }
kevman 0:38ceb79fef03 105
kevman 0:38ceb79fef03 106 FILEHANDLE fh = semihost_open(name, openmode);
kevman 0:38ceb79fef03 107 if (fh == -1) {
kevman 0:38ceb79fef03 108 return (FILEHANDLE)NULL;
kevman 0:38ceb79fef03 109 }
kevman 0:38ceb79fef03 110
kevman 0:38ceb79fef03 111 return fh;
kevman 0:38ceb79fef03 112 }
kevman 0:38ceb79fef03 113
kevman 0:38ceb79fef03 114 LocalFileHandle::LocalFileHandle(FILEHANDLE fh) : _fh(fh), pos(0)
kevman 0:38ceb79fef03 115 {
kevman 0:38ceb79fef03 116 // No lock needed in constructor
kevman 0:38ceb79fef03 117 }
kevman 0:38ceb79fef03 118
kevman 0:38ceb79fef03 119 int LocalFileHandle::close()
kevman 0:38ceb79fef03 120 {
kevman 0:38ceb79fef03 121 int retval = semihost_close(_fh);
kevman 0:38ceb79fef03 122 delete this;
kevman 0:38ceb79fef03 123 return retval;
kevman 0:38ceb79fef03 124 }
kevman 0:38ceb79fef03 125
kevman 0:38ceb79fef03 126 ssize_t LocalFileHandle::write(const void *buffer, size_t length)
kevman 0:38ceb79fef03 127 {
kevman 0:38ceb79fef03 128 lock();
kevman 0:38ceb79fef03 129 ssize_t n = semihost_write(_fh, (const unsigned char *)buffer, length, 0); // number of characters not written
kevman 0:38ceb79fef03 130 n = length - n; // number of characters written
kevman 0:38ceb79fef03 131 pos += n;
kevman 0:38ceb79fef03 132 unlock();
kevman 0:38ceb79fef03 133 return n;
kevman 0:38ceb79fef03 134 }
kevman 0:38ceb79fef03 135
kevman 0:38ceb79fef03 136 ssize_t LocalFileHandle::read(void *buffer, size_t length)
kevman 0:38ceb79fef03 137 {
kevman 0:38ceb79fef03 138 lock();
kevman 0:38ceb79fef03 139 ssize_t n = semihost_read(_fh, (unsigned char *)buffer, length, 0); // number of characters not read
kevman 0:38ceb79fef03 140 n = length - n; // number of characters read
kevman 0:38ceb79fef03 141 pos += n;
kevman 0:38ceb79fef03 142 unlock();
kevman 0:38ceb79fef03 143 return n;
kevman 0:38ceb79fef03 144 }
kevman 0:38ceb79fef03 145
kevman 0:38ceb79fef03 146 int LocalFileHandle::isatty()
kevman 0:38ceb79fef03 147 {
kevman 0:38ceb79fef03 148 lock();
kevman 0:38ceb79fef03 149 int ret = semihost_istty(_fh);
kevman 0:38ceb79fef03 150 unlock();
kevman 0:38ceb79fef03 151 return ret;
kevman 0:38ceb79fef03 152 }
kevman 0:38ceb79fef03 153
kevman 0:38ceb79fef03 154 off_t LocalFileHandle::seek(off_t position, int whence)
kevman 0:38ceb79fef03 155 {
kevman 0:38ceb79fef03 156 lock();
kevman 0:38ceb79fef03 157 if (whence == SEEK_CUR) {
kevman 0:38ceb79fef03 158 position += pos;
kevman 0:38ceb79fef03 159 } else if (whence == SEEK_END) {
kevman 0:38ceb79fef03 160 position += semihost_flen(_fh);
kevman 0:38ceb79fef03 161 } /* otherwise SEEK_SET, so position is fine */
kevman 0:38ceb79fef03 162
kevman 0:38ceb79fef03 163 /* Always seems to return -1, so just ignore for now. */
kevman 0:38ceb79fef03 164 semihost_seek(_fh, position);
kevman 0:38ceb79fef03 165 pos = position;
kevman 0:38ceb79fef03 166 unlock();
kevman 0:38ceb79fef03 167 return position;
kevman 0:38ceb79fef03 168 }
kevman 0:38ceb79fef03 169
kevman 0:38ceb79fef03 170 int LocalFileHandle::sync()
kevman 0:38ceb79fef03 171 {
kevman 0:38ceb79fef03 172 lock();
kevman 0:38ceb79fef03 173 int ret = semihost_ensure(_fh);
kevman 0:38ceb79fef03 174 unlock();
kevman 0:38ceb79fef03 175 return ret;
kevman 0:38ceb79fef03 176 }
kevman 0:38ceb79fef03 177
kevman 0:38ceb79fef03 178 off_t LocalFileHandle::size()
kevman 0:38ceb79fef03 179 {
kevman 0:38ceb79fef03 180 lock();
kevman 0:38ceb79fef03 181 off_t off = semihost_flen(_fh);
kevman 0:38ceb79fef03 182 unlock();
kevman 0:38ceb79fef03 183 return off;
kevman 0:38ceb79fef03 184 }
kevman 0:38ceb79fef03 185
kevman 0:38ceb79fef03 186 void LocalFileHandle::lock()
kevman 0:38ceb79fef03 187 {
kevman 0:38ceb79fef03 188 _mutex.lock();
kevman 0:38ceb79fef03 189 }
kevman 0:38ceb79fef03 190
kevman 0:38ceb79fef03 191 void LocalFileHandle::unlock()
kevman 0:38ceb79fef03 192 {
kevman 0:38ceb79fef03 193 _mutex.unlock();
kevman 0:38ceb79fef03 194 }
kevman 0:38ceb79fef03 195
kevman 0:38ceb79fef03 196 class LocalDirHandle : public DirHandle {
kevman 0:38ceb79fef03 197
kevman 0:38ceb79fef03 198 public:
kevman 0:38ceb79fef03 199 XFINFO info;
kevman 0:38ceb79fef03 200
kevman 0:38ceb79fef03 201 LocalDirHandle() : info()
kevman 0:38ceb79fef03 202 {
kevman 0:38ceb79fef03 203 }
kevman 0:38ceb79fef03 204
kevman 0:38ceb79fef03 205 virtual int close()
kevman 0:38ceb79fef03 206 {
kevman 0:38ceb79fef03 207 // No lock can be used in destructor
kevman 0:38ceb79fef03 208 delete this;
kevman 0:38ceb79fef03 209 return 0;
kevman 0:38ceb79fef03 210 }
kevman 0:38ceb79fef03 211
kevman 0:38ceb79fef03 212 virtual int read(struct dirent *ent)
kevman 0:38ceb79fef03 213 {
kevman 0:38ceb79fef03 214 lock();
kevman 0:38ceb79fef03 215 if (xffind("*", &info) != 0) {
kevman 0:38ceb79fef03 216 unlock();
kevman 0:38ceb79fef03 217 return 0;
kevman 0:38ceb79fef03 218 }
kevman 0:38ceb79fef03 219 memcpy(ent->d_name, info.name, sizeof(info.name));
kevman 0:38ceb79fef03 220 unlock();
kevman 0:38ceb79fef03 221 return 1;
kevman 0:38ceb79fef03 222 }
kevman 0:38ceb79fef03 223
kevman 0:38ceb79fef03 224 virtual void rewind()
kevman 0:38ceb79fef03 225 {
kevman 0:38ceb79fef03 226 lock();
kevman 0:38ceb79fef03 227 info.fileID = 0;
kevman 0:38ceb79fef03 228 unlock();
kevman 0:38ceb79fef03 229 }
kevman 0:38ceb79fef03 230
kevman 0:38ceb79fef03 231 virtual off_t tell()
kevman 0:38ceb79fef03 232 {
kevman 0:38ceb79fef03 233 lock();
kevman 0:38ceb79fef03 234 int fileId = info.fileID;
kevman 0:38ceb79fef03 235 unlock();
kevman 0:38ceb79fef03 236 return fileId;
kevman 0:38ceb79fef03 237 }
kevman 0:38ceb79fef03 238
kevman 0:38ceb79fef03 239 virtual void seek(off_t offset)
kevman 0:38ceb79fef03 240 {
kevman 0:38ceb79fef03 241 lock();
kevman 0:38ceb79fef03 242 info.fileID = offset;
kevman 0:38ceb79fef03 243 unlock();
kevman 0:38ceb79fef03 244 }
kevman 0:38ceb79fef03 245
kevman 0:38ceb79fef03 246 protected:
kevman 0:38ceb79fef03 247 PlatformMutex _mutex;
kevman 0:38ceb79fef03 248
kevman 0:38ceb79fef03 249 virtual void lock()
kevman 0:38ceb79fef03 250 {
kevman 0:38ceb79fef03 251 _mutex.lock();
kevman 0:38ceb79fef03 252 }
kevman 0:38ceb79fef03 253
kevman 0:38ceb79fef03 254 virtual void unlock()
kevman 0:38ceb79fef03 255 {
kevman 0:38ceb79fef03 256 _mutex.unlock();
kevman 0:38ceb79fef03 257 }
kevman 0:38ceb79fef03 258 };
kevman 0:38ceb79fef03 259
kevman 0:38ceb79fef03 260 int LocalFileSystem::open(FileHandle **file, const char *name, int flags)
kevman 0:38ceb79fef03 261 {
kevman 0:38ceb79fef03 262 // No global state modified so function is thread safe
kevman 0:38ceb79fef03 263
kevman 0:38ceb79fef03 264 /* reject filenames with / in them */
kevman 0:38ceb79fef03 265 for (const char *tmp = name; *tmp; tmp++) {
kevman 0:38ceb79fef03 266 if (*tmp == '/') {
kevman 0:38ceb79fef03 267 return -EINVAL;
kevman 0:38ceb79fef03 268 }
kevman 0:38ceb79fef03 269 }
kevman 0:38ceb79fef03 270
kevman 0:38ceb79fef03 271 int openmode = posix_to_semihost_open_flags(flags);
kevman 0:38ceb79fef03 272 if (openmode == OPEN_INVALID) {
kevman 0:38ceb79fef03 273 return -EINVAL;
kevman 0:38ceb79fef03 274 }
kevman 0:38ceb79fef03 275
kevman 0:38ceb79fef03 276 FILEHANDLE fh = semihost_open(name, openmode);
kevman 0:38ceb79fef03 277 if (fh == -1) {
kevman 0:38ceb79fef03 278 return -EIO;
kevman 0:38ceb79fef03 279 }
kevman 0:38ceb79fef03 280
kevman 0:38ceb79fef03 281 *file = new LocalFileHandle(fh);
kevman 0:38ceb79fef03 282 return 0;
kevman 0:38ceb79fef03 283 }
kevman 0:38ceb79fef03 284
kevman 0:38ceb79fef03 285 int LocalFileSystem::remove(const char *filename)
kevman 0:38ceb79fef03 286 {
kevman 0:38ceb79fef03 287 // No global state modified so function is thread safe
kevman 0:38ceb79fef03 288
kevman 0:38ceb79fef03 289 return semihost_remove(filename);
kevman 0:38ceb79fef03 290 }
kevman 0:38ceb79fef03 291
kevman 0:38ceb79fef03 292 int LocalFileSystem::open(DirHandle **dir, const char *name)
kevman 0:38ceb79fef03 293 {
kevman 0:38ceb79fef03 294 // No global state modified so function is thread safe
kevman 0:38ceb79fef03 295
kevman 0:38ceb79fef03 296 *dir = new LocalDirHandle();
kevman 0:38ceb79fef03 297 return 0;
kevman 0:38ceb79fef03 298 }
kevman 0:38ceb79fef03 299
kevman 0:38ceb79fef03 300 } // namespace mbed
kevman 0:38ceb79fef03 301
kevman 0:38ceb79fef03 302 #endif