I'm writing structs and classes for the K20 peripherals, so I needed their base addresses in the linker script:
With this, I can declare
And use it as in
Which CTAR to use can now be specified in templates classes that build on top of the SPI (that's what I actually needed when this journey started).
I've done the same thing for the DMA and came up with an SPI driver that uses DMA for Tx (sort of) and Rx. AND it seems to work. I'll provide it if you're interested.
Regards
Christoph
Code:
/* hardware struct symbols, sorted by peripheral bridge slots (chapter 4.5.1) */
_DMA = 0x40008000; /* chapter 21 */
_DMA_TCDn = 0x40009000; /* chapter 21 */
_FMC = 0x4001F000; /* chapter 27 */
_FTFL = 0x40020000; /* chapter 28 */
_DMAMUX0 = 0x40021000; /* chapter 20 */
_SPI0 = 0x4002C000; /* chapter 42 */
_I2S0 = 0x4002F000; /* chapter 45 */
_CRC = 0x40032000; /* chapter 30 */
_USBDCD = 0x40035000; /* chapter 40 */
_PDB0 = 0x40036000; /* chapter 33 */
_PIT = 0x40037000; /* chapter 35 */
_FTM0 = 0x40038000; /* chapter 34 */
_FTM1 = 0x40039000; /* chapter 34 */
_ADC0 = 0x4003B000; /* chapter 31 */
_RTC = 0x4003D000; /* chapter 38 */
_VBAT = 0x4003E000; /* chapter ?? */
_LPTMR0 = 0x40040000; /* chapter 36 */
_SYSREG = 0x40041000; /* chapter ?? (system register file) */
_TSI0 = 0x40045000; /* chapter 47 */
_SIM = 0x40047000; /* chapter 12 */
_PORTA = 0x40049000; /* chapter 11 */
_PORTB = 0x4004A000; /* chapter 11 */
_PORTC = 0x4004B000; /* chapter 11 */
_PORTD = 0x4004C000; /* chapter 11 */
_PORTE = 0x4004D000; /* chapter 11 */
_WDOG = 0x40052000; /* chapter 23 */
_EWM = 0x40061000; /* chapter 22 */
_CMT = 0x40062000; /* chapter 37 */
_MCG = 0x40064000; /* chapter 24 */
_OSC = 0x40065000; /* chapter 25 */
_I2C0 = 0x40066000; /* chapter 43 */
_UART0 = 0x4006A000; /* chapter 44 */
_UART1 = 0x4006B000; /* chapter 44 */
_UART2 = 0x4006C000; /* chapter 44 */
_USB0 = 0x40072000; /* chapter 39 */
_CMP0 = 0x40073000; /* chapter 32 */
_LLWU = 0x4007C000; /* chapter 16 */
_PMC = 0x4007D000; /* chapter 15 */
_SMC = 0x4007E000; /* chapter 14 */
_RCM = 0x4007F000; /* chapter 13 */
_GPIOA = 0x400FF000; /* chapter 46 */
_GPIOB = 0x400FF040; /* chapter 46 */
_GPIOC = 0x400FF080; /* chapter 46 */
_GPIOD = 0x400FF0C0; /* chapter 46 */
_GPIOE = 0x400FF100; /* chapter 46 */
Code:
class DSPI_REGS
{
public:
volatile uint32_t MCR; // +0x00
private:
uint32_t _padding0; // +0x04
public:
volatile uint32_t TCR; // +0x08
volatile uint32_t CTAR0; // +0x0C
volatile uint32_t CTAR1; // +0x10
private:
uint32_t _padding1[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 _padding2[12];
public:
volatile uint32_t RXFR0; // +0x7C
volatile uint32_t RXFR1; // +0x80
volatile uint32_t RXFR2; // +0x84
volatile uint32_t RXFR3; // +0x88
} __attribute__((packed,aligned(4)));
template<DSPI_REGS& base>
class DSPI : public DSPI_REGS
{
class CTARn
{
public:
volatile uint32_t& operator[](const uint8_t& i) const
{
volatile uint32_t* p = &(base.CTAR0);
return p[i & 1];
}
};
class TXFRn
{
public:
volatile uint32_t& operator[](const uint8_t& i) const
{
volatile uint32_t* p = &(base.TXFR0);
return p[i & 3];
}
};
class RXFRn
{
public:
volatile uint32_t& operator[](const uint8_t& i) const
{
volatile uint32_t* p = &(base.RXFR0);
return p[i & 3];
}
};
public:
CTARn CTAR;
TXFRn TXFR;
RXFRn RXFR;
}
extern DSPI_REGS _SPI0;
DSPI<_SPI0>& SPI0 = (DSPI<_SPI0>&)_SPI0;
Code:
SPI0.CTAR[0] = SPI_CTAR_FMSZ(7) ...;
I've done the same thing for the DMA and came up with an SPI driver that uses DMA for Tx (sort of) and Rx. AND it seems to work. I'll provide it if you're interested.
Regards
Christoph