ser.c
Go to the documentation of this file.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 #if CONFIG_SER_RXTIMEOUT != -1
00245 fd->rxtimeout = ms_to_ticks(rxtimeout);
00246 #else
00247 (void)rxtimeout;
00248 #endif
00249
00250 #if CONFIG_SER_TXTIMEOUT != -1
00251 fd->txtimeout = ms_to_ticks(txtimeout);
00252 #else
00253 (void)txtimeout;
00254 #endif
00255 }
00256 #endif
00257
00258
00259 void ser_setbaudrate(struct Serial *fd, unsigned long rate)
00260 {
00261 fd->hw->table->setBaudrate(fd->hw, rate);
00262 }
00263
00264
00265 void ser_setparity(struct Serial *fd, int parity)
00266 {
00267 fd->hw->table->setParity(fd->hw, parity);
00268 }
00269
00270 static int ser_error(struct KFile *fd)
00271 {
00272 Serial *fds = SERIAL_CAST(fd);
00273 return ser_getstatus(fds);
00274 }
00275
00276 static void ser_clearerr(struct KFile *fd)
00277 {
00278 Serial *fds = SERIAL_CAST(fd);
00279 ser_setstatus(fds, 0);
00280 }
00281
00282
00283
00287 void ser_purge(struct Serial *fd)
00288 {
00289 ser_purgeRx(fd);
00290 ser_purgeTx(fd);
00291 }
00292
00296 void ser_purgeRx(struct Serial *fd)
00297 {
00298 fifo_flush_locked(&fd->rxfifo);
00299 }
00300
00304 void ser_purgeTx(struct Serial *fd)
00305 {
00306 fifo_flush_locked(&fd->txfifo);
00307 }
00308
00309
00318 static int ser_flush(struct KFile *fd)
00319 {
00320 Serial *fds = SERIAL_CAST(fd);
00321
00322
00323
00324
00325
00326 while (!fifo_isempty(&fds->txfifo)
00327 || fds->hw->table->txSending(fds->hw))
00328 cpu_relax();
00329 return 0;
00330 }
00331
00332
00339 static struct Serial *ser_open(struct Serial *fd, unsigned int unit)
00340 {
00341 ASSERT(unit < countof(ser_handles));
00342
00343 ser_handles[unit] = fd;
00344 ASSERT(!fd->is_open);
00345 DB(fd->is_open = true);
00346
00347 fd->unit = unit;
00348
00349 fd->hw = ser_hw_getdesc(unit);
00350
00351
00352 ASSERT(fd->hw->txbuffer);
00353 ASSERT(fd->hw->rxbuffer);
00354 fifo_init(&fd->txfifo, fd->hw->txbuffer, fd->hw->txbuffer_size);
00355 fifo_init(&fd->rxfifo, fd->hw->rxbuffer, fd->hw->rxbuffer_size);
00356
00357 fd->hw->table->init(fd->hw, fd);
00358
00359
00360 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
00361 ser_settimeouts(fd, CONFIG_SER_RXTIMEOUT, CONFIG_SER_TXTIMEOUT);
00362 #endif
00363 #if CONFIG_SER_DEFBAUDRATE
00364 ser_setbaudrate(fd, CONFIG_SER_DEFBAUDRATE);
00365 #endif
00366
00367
00368 ser_setstatus(fd, 0);
00369
00370 return fd;
00371 }
00372
00373
00377 static int ser_close(struct KFile *fd)
00378 {
00379 Serial *fds = SERIAL_CAST(fd);
00380 Serial *port = fds;
00381
00382 ASSERT(port->is_open);
00383 DB(port->is_open = false);
00384
00385
00386 ser_flush(fd);
00387
00388 port->hw->table->cleanup(port->hw);
00389 DB(port->hw = NULL);
00390
00391
00392
00393
00394
00395 ser_purge(fds);
00396 return 0;
00397 }
00398
00402 static struct KFile *ser_reopen(struct KFile *fd)
00403 {
00404 Serial *fds = SERIAL_CAST(fd);
00405
00406 ser_close(fd);
00407 ser_open(fds, fds->unit);
00408 return (KFile *)fds;
00409 }
00410
00416 void ser_init(struct Serial *fds, unsigned int unit)
00417 {
00418 memset(fds, 0, sizeof(*fds));
00419
00420 DB(fds->fd._type = KFT_SERIAL);
00421 fds->fd.reopen = ser_reopen;
00422 fds->fd.close = ser_close;
00423 fds->fd.read = ser_read;
00424 fds->fd.write = ser_write;
00425 fds->fd.flush = ser_flush;
00426 fds->fd.error = ser_error;
00427 fds->fd.clearerr = ser_clearerr;
00428 ser_open(fds, unit);
00429 }
00430
00431
00437 static size_t spimaster_read(struct KFile *fd, void *_buf, size_t size)
00438 {
00439 Serial *fd_spi = SERIAL_CAST(fd);
00440
00441 ser_flush(&fd_spi->fd);
00442 ser_purgeRx(fd_spi);
00443
00444 size_t total_rd = 0;
00445 uint8_t *buf = (uint8_t *)_buf;
00446 int c;
00447
00448 while (size--)
00449 {
00450
00451
00452
00453
00454 ser_putchar(0, fd_spi);
00455
00456 if ((c = ser_getchar(fd_spi)) == EOF)
00457 break;
00458
00459 *buf++ = c;
00460 total_rd++;
00461 }
00462 return total_rd;
00463 }
00464
00468 static size_t spimaster_write(struct KFile *fd, const void *buf, size_t size)
00469 {
00470 Serial *fd_spi = SERIAL_CAST(fd);
00471
00472 ser_purgeRx(fd_spi);
00473
00474 return ser_write(&fd_spi->fd, buf, size);
00475 }
00476
00477
00491 void spimaster_init(Serial *fds, unsigned int unit)
00492 {
00493 ser_init(fds, unit);
00494 fds->fd.read = spimaster_read;
00495 fds->fd.write = spimaster_write;
00496 }
00497
00498