Teensy 3 SPI wrapper class

Status
Not open for further replies.

christoph

Well-known member
I needed access to the SPI's CTAR's in an array-like manner, because I wanted to use the CTAR number as template argument for a class that needs to define a CTAR. So I created a wrapper that provides that:

Code:
#ifndef _SPI_H_
#define _SPI_H_

#include <mk20dx128.h>

#include <stdint.h>

class DSPI_REGS
{
  public:
    volatile uint32_t MCR;   // +0x00
  private:
    uint32_t _dummy0;         // +0x04
  public:
    volatile uint32_t TCR;   // +0x08
    volatile uint32_t CTAR0; // +0x0C
    volatile uint32_t CTAR1; // +0x10
  private:
    uint32_t _dummy1[6];
  public:
    volatile uint32_t SR;    // +0x2C
    volatile uint32_t RSER;  // +0x30
    volatile uint32_t PUSHR; // +0x34
    volatile uint32_t POPR;  // +0x38
    volatile uint32_t TXFR0; // +0x3C
    volatile uint32_t TXFR1; // +0x40
    volatile uint32_t TXFR2; // +0x44
    volatile uint32_t TXFR3; // +0x48
  private:
    uint32_t _dummy2[12];
  public:
    volatile uint32_t RXFR0; // +0x7C
    volatile uint32_t RXFR1; // +0x80
    volatile uint32_t RXFR2; // +0x84
    volatile uint32_t RXFR3; // +0x88
} __attribute__((packed));

template<uint32_t base> // couldn't use a pointer argument here, sorry!
class DSPI : public DSPI_REGS
{
  class CTARn
  {
    public:
      volatile uint32_t& operator[](const uint8_t& i) const
      {
        volatile uint32_t* p = &(((DSPI_REGS*)base)->CTAR0);
        return p[i & 1];
      }
  };
  class TXFRn
  {
    public:
      volatile uint32_t& operator[](const uint8_t& i) const
      {
        volatile uint32_t* p = &(((DSPI_REGS*)base)->TXFR0);
        return p[i & 3];
      }
  };
  class RXFRn
  {
    public:
      volatile uint32_t& operator[](const uint8_t& i) const
      {
        volatile uint32_t* p = &(((DSPI_REGS*)base)->RXFR0);
        return p[i & 3];
      }
  };
  public:
    CTARn CTAR;
    TXFRn TXFR;
    RXFRn RXFR;
};

DSPI<0x4002C000>& SPI0 = *( ( DSPI<0x4002C000>* ) 0x4002C000 );

#endif // _SPI_H_
It's not fully tested, but compiles fine and each member's address is correct, it seems. If anyone tries it, please tell me if you found any errors or caveats.

The SPI can now be used like a structure, as in
Code:
SPI0.MCR = SPI_MCR_MSTR | SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF;
SPI0.CTAR[0] = SPI_CTAR_BR(3);

Regards

Christoph
 
Status
Not open for further replies.
Back
Top