00001
00053 #include "ser.h"
00054 #include "wdt.h"
00055 #include "timer.h"
00056 #include "ser_p.h"
00057
00058 #include "cfg/cfg_ser.h"
00059 #include "cfg/cfg_proc.h"
00060 #include <cfg/debug.h>
00061
00062 #include <mware/formatwr.h>
00063
00064 #include <cpu/power.h>
00065
00066 #include <string.h>
00067
00068
00069
00070
00071 #if !defined(CONFIG_KERN) || ((CONFIG_KERN != 0) && CONFIG_KERN != 1)
00072 #error CONFIG_KERN must be set to either 0 or 1 in cfg_kern.h
00073 #endif
00074 #if !defined(CONFIG_SER_RXTIMEOUT)
00075 #error CONFIG_SER_TXTIMEOUT missing in cfg_ser.h
00076 #endif
00077 #if !defined(CONFIG_SER_RXTIMEOUT)
00078 #error CONFIG_SER_RXTIMEOUT missing in cfg_ser.h
00079 #endif
00080 #if !defined(CONFIG_SER_DEFBAUDRATE)
00081 #error CONFIG_SER_DEFBAUDRATE missing in cfg_ser.h
00082 #endif
00083
00084
00085 struct Serial *ser_handles[SER_CNT];
00086
00095 static int ser_putchar(int c, struct Serial *port)
00096 {
00097 if (fifo_isfull_locked(&port->txfifo))
00098 {
00099 #if CONFIG_SER_TXTIMEOUT != -1
00100
00101 if (port->txtimeout == 0)
00102 return EOF;
00103
00104 ticks_t start_time = timer_clock();
00105 #endif
00106
00107
00108 do
00109 {
00110 cpu_relax();
00111
00112 #if CONFIG_SER_TXTIMEOUT != -1
00113 if (timer_clock() - start_time >= port->txtimeout)
00114 {
00115 ATOMIC(port->status |= SERRF_TXTIMEOUT);
00116 return EOF;
00117 }
00118 #endif
00119 }
00120 while (fifo_isfull_locked(&port->txfifo));
00121 }
00122
00123 fifo_push_locked(&port->txfifo, (unsigned char)c);
00124
00125
00126 port->hw->table->txStart(port->hw);
00127
00128
00129 return (int)((unsigned char)c);
00130 }
00131
00132
00141 static int ser_getchar(struct Serial *port)
00142 {
00143 if (fifo_isempty_locked(&port->rxfifo))
00144 {
00145 #if CONFIG_SER_RXTIMEOUT != -1
00146
00147 if (port->rxtimeout == 0)
00148 return EOF;
00149
00150 ticks_t start_time = timer_clock();
00151 #endif
00152
00153
00154 do
00155 {
00156 cpu_relax();
00157
00158 #if CONFIG_SER_RXTIMEOUT != -1
00159 if (timer_clock() - start_time >= port->rxtimeout)
00160 {
00161 ATOMIC(port->status |= SERRF_RXTIMEOUT);
00162 return EOF;
00163 }
00164 #endif
00165 }
00166 while (fifo_isempty_locked(&port->rxfifo) && (ser_getstatus(port) & SERRF_RX) == 0);
00167 }
00168
00169
00170
00171
00172
00173 if (ser_getstatus(port) & SERRF_RX)
00174 return EOF;
00175 return (int)(unsigned char)fifo_pop_locked(&port->rxfifo);
00176 }
00177
00184 int ser_getchar_nowait(struct Serial *fd)
00185 {
00186 if (fifo_isempty_locked(&fd->rxfifo))
00187 return EOF;
00188
00189
00190 return (int)(unsigned char)fifo_pop_locked(&fd->rxfifo);
00191 }
00192
00193
00194
00200 static size_t ser_read(struct KFile *fd, void *_buf, size_t size)
00201 {
00202 Serial *fds = SERIAL_CAST(fd);
00203
00204 size_t i = 0;
00205 char *buf = (char *)_buf;
00206 int c;
00207
00208 while (i < size)
00209 {
00210 if ((c = ser_getchar(fds)) == EOF)
00211 break;
00212 buf[i++] = c;
00213 }
00214
00215 return i;
00216 }
00217
00225 static size_t ser_write(struct KFile *fd, const void *_buf, size_t size)
00226 {
00227 Serial *fds = SERIAL_CAST(fd);
00228 const char *buf = (const char *)_buf;
00229 size_t i = 0;
00230
00231 while (size--)
00232 {
00233 if (ser_putchar(*buf++, fds) == EOF)
00234 break;
00235 i++;
00236 }
00237 return i;
00238 }
00239
00240
00241 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
00242 void ser_settimeouts(struct Serial *fd, mtime_t rxtimeout, mtime_t txtimeout)
00243 {
00244 fd->rxtimeout = ms_to_ticks(rxtimeout);
00245 fd->txtimeout = ms_to_ticks(txtimeout);
00246 }
00247 #endif
00248
00249 #if CONFIG_SER_RXTIMEOUT != -1
00250
00258 void ser_resync(struct Serial *fd, mtime_t delay)
00259 {
00260 mtime_t old_rxtimeout = ticks_to_ms(fd->rxtimeout);
00261
00262 ser_settimeouts(fd, delay, ticks_to_ms(fd->txtimeout));
00263 do
00264 {
00265 ser_setstatus(fd, 0);
00266 ser_getchar(fd);
00267 }
00268 while (!(ser_getstatus(fd) & SERRF_RXTIMEOUT));
00269
00270
00271 ser_setstatus(fd, 0);
00272 ser_settimeouts(fd, old_rxtimeout, ticks_to_ms(fd->txtimeout));
00273 }
00274 #endif
00275
00276
00277 void ser_setbaudrate(struct Serial *fd, unsigned long rate)
00278 {
00279 fd->hw->table->setBaudrate(fd->hw, rate);
00280 }
00281
00282
00283 void ser_setparity(struct Serial *fd, int parity)
00284 {
00285 fd->hw->table->setParity(fd->hw, parity);
00286 }
00287
00288 static int ser_error(struct KFile *fd)
00289 {
00290 Serial *fds = SERIAL_CAST(fd);
00291 return ser_getstatus(fds);
00292 }
00293
00294 static void ser_clearerr(struct KFile *fd)
00295 {
00296 Serial *fds = SERIAL_CAST(fd);
00297 ser_setstatus(fds, 0);
00298 }
00299
00300
00301
00305 void ser_purge(struct Serial *fd)
00306 {
00307 ser_purgeRx(fd);
00308 ser_purgeTx(fd);
00309 }
00310
00314 void ser_purgeRx(struct Serial *fd)
00315 {
00316 fifo_flush_locked(&fd->rxfifo);
00317 }
00318
00322 void ser_purgeTx(struct Serial *fd)
00323 {
00324 fifo_flush_locked(&fd->txfifo);
00325 }
00326
00327
00336 static int ser_flush(struct KFile *fd)
00337 {
00338 Serial *fds = SERIAL_CAST(fd);
00339
00340
00341
00342
00343
00344 while (!fifo_isempty(&fds->txfifo)
00345 || fds->hw->table->txSending(fds->hw))
00346 cpu_relax();
00347 return 0;
00348 }
00349
00350
00357 static struct Serial *ser_open(struct Serial *fd, unsigned int unit)
00358 {
00359 ASSERT(unit < countof(ser_handles));
00360
00361 ser_handles[unit] = fd;
00362 ASSERT(!fd->is_open);
00363 DB(fd->is_open = true);
00364
00365 fd->unit = unit;
00366
00367 fd->hw = ser_hw_getdesc(unit);
00368
00369
00370 ASSERT(fd->hw->txbuffer);
00371 ASSERT(fd->hw->rxbuffer);
00372 fifo_init(&fd->txfifo, fd->hw->txbuffer, fd->hw->txbuffer_size);
00373 fifo_init(&fd->rxfifo, fd->hw->rxbuffer, fd->hw->rxbuffer_size);
00374
00375 fd->hw->table->init(fd->hw, fd);
00376
00377
00378 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
00379 ser_settimeouts(fd, CONFIG_SER_RXTIMEOUT, CONFIG_SER_TXTIMEOUT);
00380 #endif
00381 #if CONFIG_SER_DEFBAUDRATE
00382 ser_setbaudrate(fd, CONFIG_SER_DEFBAUDRATE);
00383 #endif
00384
00385
00386 ser_setstatus(fd, 0);
00387
00388 return fd;
00389 }
00390
00391
00395 static int ser_close(struct KFile *fd)
00396 {
00397 Serial *fds = SERIAL_CAST(fd);
00398 Serial *port = fds;
00399
00400 ASSERT(port->is_open);
00401 DB(port->is_open = false);
00402
00403
00404 ser_flush(fd);
00405
00406 port->hw->table->cleanup(port->hw);
00407 DB(port->hw = NULL);
00408
00409
00410
00411
00412
00413 ser_purge(fds);
00414 return 0;
00415 }
00416
00420 static struct KFile *ser_reopen(struct KFile *fd)
00421 {
00422 Serial *fds = SERIAL_CAST(fd);
00423
00424 ser_close(fd);
00425 ser_open(fds, fds->unit);
00426 return (KFile *)fds;
00427 }
00428
00432 void ser_init(struct Serial *fds, unsigned int unit)
00433 {
00434 memset(fds, 0, sizeof(*fds));
00435
00436 DB(fds->fd._type = KFT_SERIAL);
00437 fds->fd.reopen = ser_reopen;
00438 fds->fd.close = ser_close;
00439 fds->fd.read = ser_read;
00440 fds->fd.write = ser_write;
00441 fds->fd.flush = ser_flush;
00442 fds->fd.error = ser_error;
00443 fds->fd.clearerr = ser_clearerr;
00444 ser_open(fds, unit);
00445 }
00446
00447
00453 static size_t spimaster_read(struct KFile *fd, void *_buf, size_t size)
00454 {
00455 Serial *fd_spi = SERIAL_CAST(fd);
00456
00457 ser_flush(&fd_spi->fd);
00458 ser_purgeRx(fd_spi);
00459
00460 size_t total_rd = 0;
00461 uint8_t *buf = (uint8_t *)_buf;
00462 int c;
00463
00464 while (size--)
00465 {
00466
00467
00468
00469
00470 ser_putchar(0, fd_spi);
00471
00472 if ((c = ser_getchar(fd_spi)) == EOF)
00473 break;
00474
00475 *buf++ = c;
00476 total_rd++;
00477 }
00478 return total_rd;
00479 }
00480
00484 static size_t spimaster_write(struct KFile *fd, const void *buf, size_t size)
00485 {
00486 Serial *fd_spi = SERIAL_CAST(fd);
00487
00488 ser_purgeRx(fd_spi);
00489
00490 return ser_write(&fd_spi->fd, buf, size);
00491 }
00492
00493
00505 void spimaster_init(Serial *fds, unsigned int unit)
00506 {
00507 ser_init(fds, unit);
00508 fds->fd.read = spimaster_read;
00509 fds->fd.write = spimaster_write;
00510 }
00511
00512