00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
#include <config.h>
00033
00034
#include <stdio.h>
00035
#include <stdlib.h>
00036
00037
#include "avrerror.h"
00038
#include "avrmalloc.h"
00039
#include "avrclass.h"
00040
#include "utils.h"
00041
#include "callback.h"
00042
#include "op_names.h"
00043
00044
#include "storage.h"
00045
#include "flash.h"
00046
00047
#include "vdevs.h"
00048
#include "memory.h"
00049
#include "stack.h"
00050
#include "register.h"
00051
#include "sram.h"
00052
#include "eeprom.h"
00053
#include "timers.h"
00054
#include "ports.h"
00055
#include "spi.h"
00056
00057
#include "avrcore.h"
00058
00059
#include "intvects.h"
00060
00061
00062
00063
00064
00065
00066
00067
static uint8_t spi_intr_read (VDevice *dev,
int addr);
00068
static void spi_intr_write (VDevice *dev,
int addr, uint8_t val);
00069
static void spi_intr_reset (VDevice *dev);
00070
static char *spi_intr_reg_name (VDevice *dev,
int addr);
00071
static int spi_intr_cb (uint64_t time, AvrClass *data);
00072
00073
00074
00075 SPIIntr_T *
00076 spi_intr_new (
void)
00077 {
00078 SPIIntr_T *spi;
00079
00080 spi =
avr_new (SPIIntr_T, 1);
00081
spi_intr_construct (spi);
00082
class_overload_destroy ((AvrClass *)spi,
spi_intr_destroy);
00083
00084
return spi;
00085 }
00086
00087
00088
00089
void
00090 spi_intr_construct (SPIIntr_T *spi)
00091 {
00092
char *name =
"SPIIntr";
00093
00094
if (spi == NULL)
00095
avr_error (
"passed null ptr");
00096
00097
vdev_construct ((VDevice *)spi, name, SPI_INTR_BASE, SPI_INTR_SIZE,
00098 spi_intr_read, spi_intr_write, spi_intr_reset,
00099 spi_intr_reg_name);
00100
00101 spi_intr_reset ((VDevice *)spi);
00102 }
00103
00104
00105
00106
void
00107 spi_intr_destroy (
void *spi)
00108 {
00109
if (spi == NULL)
00110
return;
00111
00112
vdev_destroy (spi);
00113 }
00114
00115
static uint8_t
00116 spi_intr_read (VDevice *dev,
int addr)
00117 {
00118 SPIIntr_T *spi = (SPIIntr_T *)dev;
00119
00120
switch (addr -
vdev_get_base (dev))
00121 {
00122
case SPI_INTR_SPCR_ADDR:
00123
return (spi->spcr);
00124
case SPI_INTR_SPSR_ADDR:
00125
if (spi->spsr & mask_SPIF)
00126 spi->spsr_read |= mask_SPIF;
00127
if (spi->spsr & mask_WCOL)
00128 spi->spsr_read |= mask_WCOL;
00129
return (spi->spsr);
00130
default:
00131
avr_error (
"Bad address: 0x%04x", addr);
00132 }
00133
00134
return 0;
00135 }
00136
00137
static void
00138 spi_intr_write (VDevice *dev,
int addr, uint8_t val)
00139 {
00140 SPIIntr_T *spi = (SPIIntr_T *)dev;
00141 CallBack *cb;
00142
00143
switch (addr -
vdev_get_base (dev))
00144 {
00145
case SPI_INTR_SPCR_ADDR:
00146 spi->spcr = val;
00147
if (spi->spcr & mask_SPE)
00148 {
00149
00150 cb = callback_new (spi_intr_cb, (AvrClass *)spi);
00151 spi->intr_cb = cb;
00152
avr_core_async_cb_add ((AvrCore *)vdev_get_core (dev), cb);
00153 }
00154
else
00155 {
00156 spi->intr_cb = NULL;
00157
00158 }
00159
00160
break;
00161
default:
00162
avr_error (
"Bad address: 0x%04x", addr);
00163 }
00164 }
00165
00166
static void
00167 spi_intr_reset (VDevice *dev)
00168 {
00169 SPIIntr_T *spi = (SPIIntr_T *)dev;
00170
00171 spi->intr_cb = NULL;
00172
00173 spi->spcr = 0;
00174 spi->spsr = 0;
00175 spi->spsr_read = 0;
00176 }
00177
00178
static char *
00179 spi_intr_reg_name (VDevice *dev,
int addr)
00180 {
00181
switch (addr -
vdev_get_base (dev))
00182 {
00183
case SPI_INTR_SPCR_ADDR:
00184
return (
"SPCR");
00185
case SPI_INTR_SPSR_ADDR:
00186
return (
"SPSR");
00187
default:
00188
avr_error (
"Bad address: 0x%04x", addr);
00189 }
00190
00191
return NULL;
00192 }
00193
00194
static int
00195 spi_intr_cb (uint64_t time, AvrClass *data)
00196 {
00197 SPIIntr_T *spi = (SPIIntr_T *)data;
00198
00199
if (spi->intr_cb == NULL)
00200
return CB_RET_REMOVE;
00201
00202
if ((spi->spcr & mask_SPE) && (spi->spcr & mask_SPIE)
00203 && (spi->spsr & mask_SPIF))
00204 {
00205
00206 AvrCore *core = (AvrCore *)
vdev_get_core ((VDevice *)spi);
00207
avr_core_irq_raise (core, irq_vect_table_index (SPI_STC));
00208 spi->spsr &= ~mask_SPIF;
00209 spi->spsr = 0;
00210 }
00211
00212
return CB_RET_RETAIN;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
static uint8_t spi_read (VDevice *dev,
int addr);
00222
static void spi_write (VDevice *dev,
int addr, uint8_t val);
00223
static void spi_reset (VDevice *dev);
00224
static char *spi_reg_name (VDevice *dev,
int addr);
00225
static int spi_clk_incr_cb (uint64_t ck, AvrClass *data);
00226
00227
00228
00229 SPI_T *
00230 spi_new (
void)
00231 {
00232 SPI_T *spi;
00233
00234 spi =
avr_new (SPI_T, 1);
00235
spi_construct (spi);
00236
class_overload_destroy ((AvrClass *)spi,
spi_destroy);
00237
00238
return spi;
00239 }
00240
00241
00242
00243
void
00244 spi_construct (SPI_T *spi)
00245 {
00246
char *name =
"SPI";
00247
00248
if (spi == NULL)
00249
avr_error (
"passed null ptr");
00250
00251
vdev_construct ((VDevice *)spi, name, SPI_BASE, SPI_SIZE, spi_read,
00252 spi_write, spi_reset, spi_reg_name);
00253
00254 spi_reset ((VDevice *)spi);
00255 }
00256
00257
00258
00259
void
00260 spi_destroy (
void *spi)
00261 {
00262
if (spi == NULL)
00263
return;
00264
00265
vdev_destroy (spi);
00266 }
00267
00268
static uint8_t
00269 spi_read (VDevice *dev,
int addr)
00270 {
00271 SPI_T *spi = (SPI_T *)dev;
00272 SPIIntr_T *spi_ti;
00273
00274 spi_ti =
00275 (SPIIntr_T *)
avr_core_get_vdev_by_name ((AvrCore *)
00276 vdev_get_core ((VDevice *)
00277 spi),
00278
"SPIIntr");
00279
00280
switch (addr -
vdev_get_base (dev))
00281 {
00282
case SPI_SPDR_ADDR:
00283
if (spi_ti->spsr_read)
00284 {
00285 spi_ti->spsr &= ~spi_ti->spsr_read;
00286 spi_ti->spsr_read = 0;
00287 }
00288
return spi->spdr;
00289
default:
00290
avr_error (
"Bad address: 0x%04x", addr);
00291 }
00292
00293
return 0;
00294 }
00295
00296
static void
00297 spi_write (VDevice *dev,
int addr, uint8_t val)
00298 {
00299 SPI_T *spi = (SPI_T *)dev;
00300
int offset = addr -
vdev_get_base (dev);
00301 CallBack *cb;
00302 SPIIntr_T *spi_ti;
00303
00304 spi_ti =
00305 (SPIIntr_T *)
avr_core_get_vdev_by_name ((AvrCore *)
00306 vdev_get_core ((VDevice *)
00307 spi),
00308
"SPIIntr");
00309
00310
if (offset == SPI_SPDR_ADDR)
00311 {
00312
if (spi_ti->spsr_read)
00313 {
00314 spi_ti->spsr &= ~spi_ti->spsr_read;
00315 spi_ti->spsr_read = 0;
00316 }
00317
00318
if (spi->tcnt != 0)
00319 {
00320 spi_ti->spsr |= mask_WCOL;
00321 }
00322
00323 spi->spdr = val;
00324
00325
00326
00327
00328
00329
00330
switch ((spi_ti->spcr) & (mask_SPR0 | mask_SPR1))
00331 {
00332
case SPI_CK_4:
00333 spi->divisor = 4;
00334
break;
00335
case SPI_CK_16:
00336 spi->divisor = 16;
00337
break;
00338
case SPI_CK_64:
00339 spi->divisor = 64;
00340
break;
00341
case SPI_CK_128:
00342 spi->divisor = 128;
00343
break;
00344
default:
00345
avr_error (
"The impossible happened!");
00346 }
00347
00348
00349
if (spi->clk_cb == NULL)
00350 {
00351 cb = callback_new (spi_clk_incr_cb, (AvrClass *)spi);
00352 spi->clk_cb = cb;
00353
avr_core_clk_cb_add ((AvrCore *)vdev_get_core ((VDevice *)spi),
00354 cb);
00355 }
00356 spi->tcnt = 8;
00357 spi->spdr_in = spi_port_rd (addr);
00358 }
00359
else
00360 {
00361
avr_error (
"Bad address: 0x%04x", addr);
00362 }
00363 }
00364
00365
static void
00366 spi_reset (VDevice *dev)
00367 {
00368 SPI_T *spi = (SPI_T *)dev;
00369
00370 spi->clk_cb = NULL;
00371
00372 spi->spdr = 0;
00373 spi->tcnt = 0;
00374
00375 spi->divisor = 0;
00376 }
00377
00378
static char *
00379 spi_reg_name (VDevice *dev,
int addr)
00380 {
00381
switch (addr -
vdev_get_base (dev))
00382 {
00383
case SPI_SPDR_ADDR:
00384
return "SPDR";
00385
default:
00386
avr_error (
"Bad address: 0x%04x", addr);
00387 }
00388
00389
return NULL;
00390 }
00391
00392
static int
00393 spi_clk_incr_cb (uint64_t ck, AvrClass *data)
00394 {
00395 SPI_T *spi = (SPI_T *)data;
00396 uint8_t last = spi->tcnt;
00397 SPIIntr_T *spi_ti;
00398
00399 spi_ti =
00400 (SPIIntr_T *)
avr_core_get_vdev_by_name ((AvrCore *)
00401 vdev_get_core ((VDevice *)
00402 spi),
00403
"SPIIntr");
00404
00405
if (spi->clk_cb == NULL)
00406
return CB_RET_REMOVE;
00407
00408
if (spi->divisor <= 0)
00409
avr_error (
"Bad divisor value: %d", spi->divisor);
00410
00411
00412
00413
00414 spi->tcnt -= ((ck & (spi->divisor - 1)) == 0);
00415
00416
if (spi->tcnt != last)
00417 {
00418
if (spi->tcnt == 0)
00419 {
00420 spi_ti->spsr |= mask_SPIF;
00421
00422 spi_port_wr (spi->spdr);
00423 spi->spdr = spi->spdr_in;
00424
00425
return CB_RET_REMOVE;
00426 }
00427 }
00428
00429
return CB_RET_RETAIN;
00430 }
00431
00432
00433
00434
00435 uint8_t
00436 spi_port_rd (
int addr)
00437 {
00438
int data;
00439
char line[80];
00440
00441
while (1)
00442 {
00443 fprintf (stderr,
00444
"\nEnter a byte of hex data to read into the SPI at"
00445
" address 0x%04x: ", addr);
00446
00447
00448
if (fgets (line,
sizeof (line), stdin) == NULL)
00449
continue;
00450
00451
00452
if (sscanf (line,
"%x\n", &data) != 1)
00453
continue;
00454
00455
break;
00456 }
00457
00458
return (uint8_t) (data & 0xff);
00459 }
00460
00461
void
00462 spi_port_wr (uint8_t val)
00463 {
00464 fprintf (stderr,
"wrote 0x%02x to SPI\n", val);
00465 }