##############################################################################
#                                                                            #
# IAR ARM ANSI C/C++ Compiler V4.11A/W32               20/Jul/2004  18:58:49 #
# Copyright 1999-2004 IAR Systems. All rights reserved.                      #
#                                                                            #
#    Cpu mode        =  arm                                                  #
#    Endian          =  little                                               #
#    Stack alignment =  4                                                    #
#    Source file     =  C:\medusa\spi.c                                      #
#    Command line    =  -I "C:\Program Files\IAR Systems\Embedded Workbench  #
#                       4.0\ARM\INC\" -lc C:\medusa\Debug\List\ -la          #
#                       C:\medusa\Debug\List\ -o C:\medusa\Debug\Obj\ -s2    #
#                       --no_cse --no_unroll --no_inline --no_code_motion    #
#                       --no_tbaa --no_clustering --no_scheduling --debug    #
#                       --cpu_mode arm --endian little --cpu ARM7TDMI-S      #
#                       --stack_align 4 -e --fpu None                        #
#                       "-D_DLIB_CONFIG_FILE=C:\Program Files\IAR            #
#                       Systems\Embedded Workbench                           #
#                       4.0\ARM\LIB\dl4tpannl8n.h" C:\medusa\spi.c           #
#    List file       =  C:\medusa\Debug\List\spi.lst                         #
#    Object file     =  C:\medusa\Debug\Obj\spi.r79                          #
#                                                                            #
#                                                                            #
##############################################################################

C:\medusa\spi.c
      1          #include "archinc.h"
      2          #include "spi.h"
      3          #include "spiregs.h"
      4          
      5          /*
      6           * LPC210x SPI driver (Master/slave mode)
      7           *
      8           * From Philips errata sheet for LPC2106...
      9           *
     10           * Functional Deviations of LPC2106
     11           * SPI.1 Unintentional clearing of SPI interrupt flag
     12           *
     13           * Introduction: The SPI interrupt flag is set by the SPI interface to 
     14           * generate an interrupt. It is cleared by writing a 1 to this bit.
     15           *
     16           * Problem: A write to any register associated with the SPI peripheral 
     17           * will clear the SPI interrupt register.
     18           *
     19           * Work around: Avoid writing to SPI registers while transmissions are 
     20           * in progress or while SPI interrupts are pending.
     21           */
     22           
     23          /*
     24          SSCS is actually always an input to the LPC21XX... it is used by some
     25          external SPI master to select the LPC21XX spi hardware as the target
     26          slave. So if it's not de-asserted for the duration of SPI transfers
     27          originating from the LPC21XX, you get what they call a mode fault.
     28          That's why it's safe to simply pull it high via a resistor if the
     29          LPC21XX will never be a SPI slave.
     30          
     31          As for the clocking... do you have the PLL set up to run CCLK at 60 MHz?
     32          Do you have the PCLK divider set to 1 (I think it defaults to 4)? You
     33          might also check the SPICLK period... 12,500 sixteen-bit samples per
     34          second would imply that you're only running the SPI at 200 KHz, or a
     35          PCLK of 1.6 MHz with SPCCR=8. You can definitely get much faster than that.
     36          
     37          Of course the delay could be coming from something besides the SPI
     38          hardware (i.e. the software...). This would show up if you see a fast
     39          SPICLK, but long durations between samples.
     40          
     41          Ryan
     42           */
     43          #ifdef CONFIG_INCLUDE_LPC210X_SPI_SLAVE
     44          
     45          typedef enum {idle, master, slave} spiMode;
     46          
     47          static spiMode interfaceMode = idle;
     48          static boolean useMasterMode = false;
     49          
     50          static boolean doLoopback = false;
     51          
     52          /*
     53           * Anomaly counters
     54           */
     55          
     56          static unsigned int slaveAborts = 0;
     57          static unsigned int modeFaults = 0;
     58          static unsigned int readOverruns = 0;
     59          static unsigned int writeCollisions = 0;
     60          
     61          /*
     62           * Queues
     63           */
     64          
     65          static char rxQueue[CONFIG_SPI_RX_QUEUE_SIZE];
     66          static int rxHead = 0;
     67          static int rxTail = 0;
     68          static int rxLen = 0;
     69          static int rxErrors = 0;
     70          static int rxCharsDropped = 0;
     71          
     72          static char txQueue[CONFIG_SPI_TX_QUEUE_SIZE];
     73          static int txHead = 0;
     74          static int txTail = 0;
     75          static int txLen = 0;
     76          static int txErrors = 0;
     77          static int txCharsDropped = 0;
     78          
     79          static int spiMasterSendBegin(void);
     80          
     81          /* 
     82           * ISR declaration
     83           */
     84          
     85          DECLARE_ISR(spiSPIFIsr);
     86          DECLARE_ISR(spiMODFIsr);
     87          
     88          int spiPut(unsigned char sendData)
     89          {
     90            if (txLen == CONFIG_SPI_TX_QUEUE_SIZE)
     91              return -1;
     92          
     93            if (interfaceMode == idle) {
     94              SPDR = sendData;
     95              interfaceMode = ((useMasterMode == true) ? master : slave);
     96              }
     97            else {
     98              txQueue[txHead] = sendData;
     99              circInc(txHead, 0, (CONFIG_SPI_TX_QUEUE_SIZE-1));
    100              IRQ_DISABLE();
    101              txLen++;
    102              IRQ_ENABLE();
    103              }
    104          
    105            // this is OK: spiMasterSendBegin() will return for slave-only operation
    106          
    107            return 0;
    108          }
    109          
    110          int spiGet(unsigned char *pRcvData)
    111          {
    112            if (rxLen == 0)
    113              return -1;
    114          
    115            *pRcvData = rxQueue[rxTail];
    116            IRQ_DISABLE();
    117            circInc(rxTail, 0, (CONFIG_SPI_RX_QUEUE_SIZE-1));
    118            rxLen--;
    119            IRQ_ENABLE();
    120          
    121            return 0;
    122          }
    123          
    124          
    125          /*
    126           * Interrupt handling
    127           */
    128           
    129          static lpc210x_reg dummy;
    130          static lpc210x_reg statusReg;
    131          
    132          #ifdef CONFIG_TOOLCHAIN_IAR
    133          #pragma inline
    134          #endif
    135          static INLINE_KEYWORD void doErrorHandling(void)
    136          {
    137            /*
    138             * error handling: start by counting each error and implement more 
    139             * sophisticated error handling later.
    140             * 
    141             * STATUS_SLAVE_ABRT: slave abort
    142             * STATUS_MODE_FAULT: mode fault
    143             * STATUS_RD_OVERRUN: read overrun
    144             * STATUS_WRITE_COL: write collision (re-send data)
    145             * STATUS_XFER_DONE: transaction completed without error
    146             */
    147          
    148            if (statusReg & STATUS_SLAVE_ABRT) {
    149              slaveAborts++;
    150              }
    151          
    152            if (statusReg & STATUS_MODE_FAULT) {
    153              modeFaults++;
    154              }
    155          
    156            if (statusReg & STATUS_RD_OVERRUN) {
    157              readOverruns++;
    158              }
    159          
    160            if (statusReg & STATUS_WRITE_COL) {
    161              writeCollisions++;
    162              }
    163              
    164            return;
    165          }
    166          
    167          ISR_FUNCTION(spiSPIFIsr)
    168          {
    169            ISR_ENTER()
    170          
    171            // read the status reg first
    172            statusReg = SPSR;
    173          
    174            if (statusReg & STATUS_XFER_DONE) {
    175              // first, queue the received data
    176              if (rxLen != CONFIG_SPI_RX_QUEUE_SIZE) {
    177                rxQueue[rxHead] = SPDR;
    178                circInc(rxHead, 0, CONFIG_SPI_RX_QUEUE_SIZE);
    179                rxLen++;
    180                }
    181          
    182              // next, get the next byte to go out ready
    183              if (txLen != 0) {
    184                SPDR = txQueue[txTail];
    185                circInc(txTail, 0, CONFIG_SPI_TX_QUEUE_SIZE);
    186                txLen--;
    187                }
    188          
    189              eventqPut(SPI_RX_DATA);
    190              } // STATUS_XFER_DONE
    191          
    192            doErrorHandling();
    193            
    194            // acknowledge the interrupt at the SPI controller  
    195            SPINT = IRQ_ACKNOWLEDGE;
    196          
    197            // acknowledge the interrupt at the VIC
    198            VICIrqDone;
    199          
    200            ISR_LEAVE()
    201          }
    202          
    203          
    204          static int spiPutHandler(int argc, char *argv[], int flags)
    205          {
    206            int retVal = -1;
    207            int bufLen;
    208            char * pOutBuf;
    209            unsigned char putData;
    210          
    211            pOutBuf = clicharGetOutputBuffer(&bufLen);
    212            putData = (unsigned char)strtol(argv[1], (char **)NULL, 16);
    213          
    214          }
    215          
    216          
    217          int spiInit(boolean enableMasterMode) 
    218          {
    219            int retStat;
    220              
    221            interfaceMode = idle;
    222            useMasterMode = enableMasterMode;
    223          
    224            SPCR = 0;
    225          
    226            if (useMasterMode == true) {
    227              SPCR |= CTRL_MASTER_MODE;
    228              }
    229          
    230            // connect the interrupt vector
    231            if ((retStat = armvicIntConnect(LPC210X_IRQVEC_SPI, spiSPIFIsr)) != 0)
    232              return retStat;
    233          
    234            // enable the interrupt at the VIC
    235            if ((retStat = armvicIntEnable(LPC210X_IRQVEC_SPI)) != 0)
    236              return retStat;
    237          
    238            // enable interrupt at transceiver
    239            SPCR |= CTRL_IRQ_ENABLE;
    240          
    241            cliRegisterCommand("spiput", spiPutHandler, "spiput [byte] - queue a byte for xmit on the SPI bus");
    242            cliRegisterCommand("spiloop", spiLoopbackHandler, "spiloop [{y,1} | {n,0}] - put the SPI interface into loopback");
    243          
    244            return 0;
    245          }
    246          
    247          
    248          
    249          
    250          
    251          #endif /* CONFIG_INCLUDE_LPC210X_SPI */


   Segment part sizes:

     Function/Label Bytes
     -------------- -----

 
 
 0 bytes of memory

Errors: none
Warnings: none
