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
00262 void ser_setbaudrate(struct Serial *fd, unsigned long rate)
00263 {
00264 fd->hw->table->setBaudrate(fd->hw, rate);
00265 }
00266
00267
00271 void ser_setparity(struct Serial *fd, int parity)
00272 {
00273 fd->hw->table->setParity(fd->hw, parity);
00274 }
00275
00276 static int ser_error(struct KFile *fd)
00277 {
00278 Serial *fds = SERIAL_CAST(fd);
00279 return ser_getstatus(fds);
00280 }
00281
00282 static void ser_clearerr(struct KFile *fd)
00283 {
00284 Serial *fds = SERIAL_CAST(fd);
00285 ser_setstatus(fds, 0);
00286 }
00287
00288
00289
00293 void ser_purge(struct Serial *fd)
00294 {
00295 ser_purgeRx(fd);
00296 ser_purgeTx(fd);
00297 }
00298
00302 void ser_purgeRx(struct Serial *fd)
00303 {
00304 fifo_flush_locked(&fd->rxfifo);
00305 }
00306
00310 void ser_purgeTx(struct Serial *fd)
00311 {
00312 fifo_flush_locked(&fd->txfifo);
00313 }
00314
00315
00324 static int ser_flush(struct KFile *fd)
00325 {
00326 Serial *fds = SERIAL_CAST(fd);
00327
00328
00329
00330
00331
00332 while (!fifo_isempty(&fds->txfifo)
00333 || fds->hw->table->txSending(fds->hw))
00334 cpu_relax();
00335 return 0;
00336 }
00337
00338
00345 static struct Serial *ser_open(struct Serial *fd, unsigned int unit)
00346 {
00347 ASSERT(unit < countof(ser_handles));
00348
00349 ser_handles[unit] = fd;
00350 ASSERT(!fd->is_open);
00351 DB(fd->is_open = true);
00352
00353 fd->unit = unit;
00354
00355 fd->hw = ser_hw_getdesc(unit);
00356
00357
00358 ASSERT(fd->hw->txbuffer);
00359 ASSERT(fd->hw->rxbuffer);
00360 fifo_init(&fd->txfifo, fd->hw->txbuffer, fd->hw->txbuffer_size);
00361 fifo_init(&fd->rxfifo, fd->hw->rxbuffer, fd->hw->rxbuffer_size);
00362
00363 fd->hw->table->init(fd->hw, fd);
00364
00365
00366 #if CONFIG_SER_RXTIMEOUT != -1 || CONFIG_SER_TXTIMEOUT != -1
00367 ser_settimeouts(fd, CONFIG_SER_RXTIMEOUT, CONFIG_SER_TXTIMEOUT);
00368 #endif
00369 #if CONFIG_SER_DEFBAUDRATE
00370 ser_setbaudrate(fd, CONFIG_SER_DEFBAUDRATE);
00371 #endif
00372
00373
00374 ser_setstatus(fd, 0);
00375
00376 return fd;
00377 }
00378
00379
00383 static int ser_close(struct KFile *fd)
00384 {
00385 Serial *fds = SERIAL_CAST(fd);
00386 Serial *port = fds;
00387
00388 ASSERT(port->is_open);
00389 DB(port->is_open = false);
00390
00391
00392 ser_flush(fd);
00393
00394 port->hw->table->cleanup(port->hw);
00395 DB(port->hw = NULL);
00396
00397
00398
00399
00400
00401 ser_purge(fds);
00402 return 0;
00403 }
00404
00408 static struct KFile *ser_reopen(struct KFile *fd)
00409 {
00410 Serial *fds = SERIAL_CAST(fd);
00411
00412 ser_close(fd);
00413 ser_open(fds, fds->unit);
00414 return (KFile *)fds;
00415 }
00416
00422 void ser_init(struct Serial *fds, unsigned int unit)
00423 {
00424 memset(fds, 0, sizeof(*fds));
00425
00426 DB(fds->fd._type = KFT_SERIAL);
00427 fds->fd.reopen = ser_reopen;
00428 fds->fd.close = ser_close;
00429 fds->fd.read = ser_read;
00430 fds->fd.write = ser_write;
00431 fds->fd.flush = ser_flush;
00432 fds->fd.error = ser_error;
00433 fds->fd.clearerr = ser_clearerr;
00434 ser_open(fds, unit);
00435 }
00436
00437
00443 static size_t spimaster_read(struct KFile *fd, void *_buf, size_t size)
00444 {
00445 Serial *fd_spi = SERIAL_CAST(fd);
00446
00447 ser_flush(&fd_spi->fd);
00448 ser_purgeRx(fd_spi);
00449
00450 size_t total_rd = 0;
00451 uint8_t *buf = (uint8_t *)_buf;
00452 int c;
00453
00454 while (size--)
00455 {
00456
00457
00458
00459
00460 ser_putchar(0, fd_spi);
00461
00462 if ((c = ser_getchar(fd_spi)) == EOF)
00463 break;
00464
00465 *buf++ = c;
00466 total_rd++;
00467 }
00468 return total_rd;
00469 }
00470
00474 static size_t spimaster_write(struct KFile *fd, const void *buf, size_t size)
00475 {
00476 Serial *fd_spi = SERIAL_CAST(fd);
00477
00478 ser_purgeRx(fd_spi);
00479
00480 return ser_write(&fd_spi->fd, buf, size);
00481 }
00482
00483
00497 void spimaster_init(Serial *fds, unsigned int unit)
00498 {
00499 ser_init(fds, unit);
00500 fds->fd.read = spimaster_read;
00501 fds->fd.write = spimaster_write;
00502 }
00503
00504