ser.c
Go to the documentation of this file.00001
00052 #include "ser.h"
00053 #include "wdt.h"
00054 #include "timer.h"
00055 #include "ser_p.h"
00056
00057 #include "cfg/cfg_ser.h"
00058 #include "cfg/cfg_proc.h"
00059 #include <cfg/debug.h>
00060
00061 #include <mware/formatwr.h>
00062
00063 #include <cpu/power.h>
00064
00065 #include <string.h>
00066
00067
00068
00069
00070 #if !defined(CONFIG_KERN) || ((CONFIG_KERN != 0) && CONFIG_KERN != 1)
00071 #error CONFIG_KERN must be set to either 0 or 1 in cfg_kern.h
00072 #endif
00073 #if !defined(CONFIG_SER_RXTIMEOUT)
00074 #error CONFIG_SER_TXTIMEOUT missing in cfg_ser.h
00075 #endif
00076 #if !defined(CONFIG_SER_RXTIMEOUT)
00077 #error CONFIG_SER_RXTIMEOUT missing in cfg_ser.h
00078 #endif
00079 #if !defined(CONFIG_SER_DEFBAUDRATE)
00080 #error CONFIG_SER_DEFBAUDRATE missing in cfg_ser.h
00081 #endif
00082
00083
00084 struct Serial *ser_handles[SER_CNT];
00085
00094 static int ser_putchar(int c, struct Serial *port)
00095 {
00096 if (fifo_isfull_locked(&port->txfifo))
00097 {
00098 #if CONFIG_SER_TXTIMEOUT != -1
00099
00100 if (port->txtimeout == 0)
00101 return EOF;
00102
00103 ticks_t start_time = timer_clock();
00104 #endif
00105
00106
00107 do
00108 {
00109 cpu_relax();
00110
00111 #if CONFIG_SER_TXTIMEOUT != -1
00112 if (timer_clock() - start_time >= port->txtimeout)
00113 {
00114 ATOMIC(port->status |= SERRF_TXTIMEOUT);
00115 return EOF;
00116 }
00117 #endif
00118 }
00119 while (fifo_isfull_locked(&port->txfifo));
00120 }
00121
00122 fifo_push_locked(&port->txfifo, (unsigned char)c);
00123
00124
00125 port->hw->table->txStart(port->hw);
00126
00127
00128 return (int)((unsigned char)c);
00129 }
00130
00131
00140 static int ser_getchar(struct Serial *port)
00141 {
00142 if (fifo_isempty_locked(&port->rxfifo))
00143 {
00144 #if CONFIG_SER_RXTIMEOUT != -1
00145
00146 if (port->rxtimeout == 0)
00147 return EOF;
00148
00149 ticks_t start_time = timer_clock();
00150 #endif
00151
00152
00153 do
00154 {
00155 cpu_relax();
00156
00157 #if CONFIG_SER_RXTIMEOUT != -1
00158 if (timer_clock() - start_time >= port->rxtimeout)
00159 {
00160 ATOMIC(port->status |= SERRF_RXTIMEOUT);
00161 return EOF;
00162 }
00163 #endif
00164 }
00165 while (fifo_isempty_locked(&port->rxfifo) && (ser_getstatus(port) & SERRF_RX) == 0);
00166 }
00167
00168
00169
00170
00171
00172 if (ser_getstatus(port) & SERRF_RX)
00173 return EOF;
00174 return (int)(unsigned char)fifo_pop_locked(&port->rxfifo);
00175 }
00176
00183 int ser_getchar_nowait(struct Serial *fd)
00184 {
00185 if (fifo_isempty_locked(&fd->rxfifo))
00186 return EOF;
00187
00188
00189 return (int)(unsigned char)fifo_pop_locked(&fd->rxfifo);
00190 }
00191
00192
00193
00199 static size_t ser_read(struct KFile *fd, void *_buf, size_t size)
00200 {
00201 Serial *fds = SERIAL_CAST(fd);
00202
00203 size_t i = 0;
00204 char *buf = (char *)_buf;
00205 int c;
00206
00207 while (i < size)
00208 {
00209 if ((c = ser_getchar(fds)) == EOF)
00210 break;
00211 buf[i++] = c;
00212 }
00213
00214 return i;
00215 }
00216
00224 static size_t ser_write(struct KFile *fd, const void *_buf, size_t size)
00225 {
00226 Serial *fds = SERIAL_CAST(fd);
00227 const char *buf = (const char *)_buf;
00228 size_t i = 0;
00229
00230 while (size--)
00231 {
00232 if (ser_putchar(*buf++, fds) == EOF)
00233 break;
00234 i++;
00235 }
00236 return i;
00237 }
00238
00239
00240 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
00241 void ser_settimeouts(struct Serial *fd, mtime_t rxtimeout, mtime_t txtimeout)
00242 {
00243 #if CONFIG_SER_RXTIMEOUT != -1
00244 fd->rxtimeout = ms_to_ticks(rxtimeout);
00245 #else
00246 (void)rxtimeout;
00247 #endif
00248
00249 #if CONFIG_SER_TXTIMEOUT != -1
00250 fd->txtimeout = ms_to_ticks(txtimeout);
00251 #else
00252 (void)txtimeout;
00253 #endif
00254 }
00255 #endif
00256
00257
00261 void ser_setbaudrate(struct Serial *fd, unsigned long rate)
00262 {
00263 fd->hw->table->setBaudrate(fd->hw, rate);
00264 }
00265
00266
00270 void ser_setparity(struct Serial *fd, int parity)
00271 {
00272 fd->hw->table->setParity(fd->hw, parity);
00273 }
00274
00275 static int ser_error(struct KFile *fd)
00276 {
00277 Serial *fds = SERIAL_CAST(fd);
00278 return ser_getstatus(fds);
00279 }
00280
00281 static void ser_clearerr(struct KFile *fd)
00282 {
00283 Serial *fds = SERIAL_CAST(fd);
00284 ser_setstatus(fds, 0);
00285 }
00286
00287
00288
00292 void ser_purge(struct Serial *fd)
00293 {
00294 ser_purgeRx(fd);
00295 ser_purgeTx(fd);
00296 }
00297
00301 void ser_purgeRx(struct Serial *fd)
00302 {
00303 fifo_flush_locked(&fd->rxfifo);
00304 }
00305
00309 void ser_purgeTx(struct Serial *fd)
00310 {
00311 fifo_flush_locked(&fd->txfifo);
00312 }
00313
00314
00323 static int ser_flush(struct KFile *fd)
00324 {
00325 Serial *fds = SERIAL_CAST(fd);
00326
00327
00328
00329
00330
00331 while (!fifo_isempty(&fds->txfifo)
00332 || fds->hw->table->txSending(fds->hw))
00333 cpu_relax();
00334 return 0;
00335 }
00336
00337
00344 static struct Serial *ser_open(struct Serial *fd, unsigned int unit)
00345 {
00346 ASSERT(unit < countof(ser_handles));
00347
00348 ser_handles[unit] = fd;
00349 ASSERT(!fd->is_open);
00350 DB(fd->is_open = true);
00351
00352 fd->unit = unit;
00353
00354 fd->hw = ser_hw_getdesc(unit);
00355
00356
00357 ASSERT(fd->hw->txbuffer);
00358 ASSERT(fd->hw->rxbuffer);
00359 fifo_init(&fd->txfifo, fd->hw->txbuffer, fd->hw->txbuffer_size);
00360 fifo_init(&fd->rxfifo, fd->hw->rxbuffer, fd->hw->rxbuffer_size);
00361
00362 fd->hw->table->init(fd->hw, fd);
00363
00364
00365 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
00366 ser_settimeouts(fd, CONFIG_SER_RXTIMEOUT, CONFIG_SER_TXTIMEOUT);
00367 #endif
00368 #if CONFIG_SER_DEFBAUDRATE
00369 ser_setbaudrate(fd, CONFIG_SER_DEFBAUDRATE);
00370 #endif
00371
00372
00373 ser_setstatus(fd, 0);
00374
00375 return fd;
00376 }
00377
00378
00382 static int ser_close(struct KFile *fd)
00383 {
00384 Serial *fds = SERIAL_CAST(fd);
00385 Serial *port = fds;
00386
00387 ASSERT(port->is_open);
00388 DB(port->is_open = false);
00389
00390
00391 ser_flush(fd);
00392
00393 port->hw->table->cleanup(port->hw);
00394 DB(port->hw = NULL);
00395
00396
00397
00398
00399
00400 ser_purge(fds);
00401 return 0;
00402 }
00403
00407 static struct KFile *ser_reopen(struct KFile *fd)
00408 {
00409 Serial *fds = SERIAL_CAST(fd);
00410
00411 ser_close(fd);
00412 ser_open(fds, fds->unit);
00413 return (KFile *)fds;
00414 }
00415
00421 void ser_init(struct Serial *fds, unsigned int unit)
00422 {
00423 memset(fds, 0, sizeof(*fds));
00424
00425 DB(fds->fd._type = KFT_SERIAL);
00426 fds->fd.reopen = ser_reopen;
00427 fds->fd.close = ser_close;
00428 fds->fd.read = ser_read;
00429 fds->fd.write = ser_write;
00430 fds->fd.flush = ser_flush;
00431 fds->fd.error = ser_error;
00432 fds->fd.clearerr = ser_clearerr;
00433 ser_open(fds, unit);
00434 }
00435
00436
00442 static size_t spimaster_read(struct KFile *fd, void *_buf, size_t size)
00443 {
00444 Serial *fd_spi = SERIAL_CAST(fd);
00445
00446 ser_flush(&fd_spi->fd);
00447 ser_purgeRx(fd_spi);
00448
00449 size_t total_rd = 0;
00450 uint8_t *buf = (uint8_t *)_buf;
00451 int c;
00452
00453 while (size--)
00454 {
00455
00456
00457
00458
00459 ser_putchar(0, fd_spi);
00460
00461 if ((c = ser_getchar(fd_spi)) == EOF)
00462 break;
00463
00464 *buf++ = c;
00465 total_rd++;
00466 }
00467 return total_rd;
00468 }
00469
00473 static size_t spimaster_write(struct KFile *fd, const void *buf, size_t size)
00474 {
00475 Serial *fd_spi = SERIAL_CAST(fd);
00476
00477 ser_purgeRx(fd_spi);
00478
00479 return ser_write(&fd_spi->fd, buf, size);
00480 }
00481
00482
00496 void spimaster_init(Serial *fds, unsigned int unit)
00497 {
00498 ser_init(fds, unit);
00499 fds->fd.read = spimaster_read;
00500 fds->fd.write = spimaster_write;
00501 }
00502
00503