Skip to content

Instantly share code, notes, and snippets.

@spirilis
Last active September 8, 2015 21:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spirilis/e40e7037300bc00e5f64 to your computer and use it in GitHub Desktop.
Save spirilis/e40e7037300bc00e5f64 to your computer and use it in GitHub Desktop.
take 1 on C++ templated RSPI driver
17:10:20 **** Incremental Build of configuration HardwareDebug for project test ****
make -j4 all
'Scanning and building file: ../src/test.cpp'
'Invoking: Scanner and Compiler'
rx-elf-gcc -MM -MP -MF "src/test.d" -MT"src/test.o" -MT"src/test.d" -x c++ -nostdinc -ffunction-sections -fno-function-cse -fdata-sections -fsection-anchors -free -flto-compression-level=0 -fno-cse-follow-jumps -fno-jump-tables -fno-guess-branch-probability -fno-move-loop-invariants -I"C:\PROGRA~2\KPIT\GNURXV~1.03-\rx-elf\rx-elf/lib/gcc/rx-elf/4.8-GNURX_v14.03/include" -I"C:\PROGRA~2\KPIT\GNURXV~1.03-\rx-elf\rx-elf/rx-elf/include" -I"C:\Renesas\workspace\test\src" -D__RX_LITTLE_ENDIAN__=1 -DCPPAPP -Os -g2 -g -flto -mlittle-endian-data -mcpu=rx200 -nofpu -fno-exceptions -fno-rtti "../src/test.cpp"
../src/test.cpp:22:29: error: cannot declare variable 'SPI' to be of abstract type 'RSPI_RX210<0u>'
RSPI_RX210<RSPI_INSTANCE_0> SPI;
^
In file included from ../src/test.cpp:20:0:
C:\Renesas\workspace\test\src/RSPI_RX210.h:26:7: note: because the following virtual functions are pure within 'RSPI_RX210<0u>':
class RSPI_RX210 : public SPIClass {
^
In file included from C:\Renesas\workspace\test\src/RSPI_RX210.h:14:0,
from ../src/test.cpp:20:
C:\Renesas\workspace\test\src/SPI.h:72:22: note: virtual void SPIClass::setClockDivider(int)
virtual void setClockDivider(int clockDiv) = 0;
^
In file included from ../src/test.cpp:20:0:
C:\Renesas\workspace\test\src/RSPI_RX210.h: In instantiation of 'uint8_t RSPI_RX210<rspi_instance>::transfer(uint8_t) [with unsigned int rspi_instance = 0u; uint8_t = unsigned char]':
../src/test.cpp:61:20: required from here
C:\Renesas\workspace\test\src/RSPI_RX210.h:119:23: error: no match for 'operator=' (operand types are 'volatile st_rspi::<anonymous union>::<anonymous struct>' and 'uint8_t {aka unsigned char}')
rspidrv->SPDR.WORD = inb;
^
C:\Renesas\workspace\test\src/RSPI_RX210.h:119:23: note: candidate is:
In file included from ../src/test.cpp:19:0:
../src/iodefine.h:5159:16: note: st_rspi::<anonymous union>::<anonymous struct>& st_rspi::<anonymous union>::<anonymous struct>::operator=(const st_rspi::<anonymous union>::<anonymous struct>&)
struct {
^
../src/iodefine.h:5159:16: note: no known conversion for argument 1 from 'uint8_t {aka unsigned char}' to 'const st_rspi::<anonymous union>::<anonymous struct>&'
In file included from ../src/test.cpp:20:0:
C:\Renesas\workspace\test\src/RSPI_RX210.h:122:34: error: invalid cast from type 'volatile st_rspi::<anonymous union>::<anonymous struct>' to type 'uint8_t {aka unsigned char}'
return (uint8_t)rspidrv->SPDR.WORD;
^
C:\Renesas\workspace\test\src/RSPI_RX210.h: In instantiation of 'uint16_t RSPI_RX210<rspi_instance>::transfer16(uint16_t) [with unsigned int rspi_instance = 0u; uint16_t = short unsigned int]':
../src/test.cpp:64:1: required from here
C:\Renesas\workspace\test\src/RSPI_RX210.h:148:23: error: no match for 'operator=' (operand types are 'volatile st_rspi::<anonymous union>::<anonymous struct>' and 'uint16_t {aka short unsigned int}')
rspidrv->SPDR.WORD = inw;
^
C:\Renesas\workspace\test\src/RSPI_RX210.h:148:23: note: candidate is:
In file included from ../src/test.cpp:19:0:
../src/iodefine.h:5159:16: note: st_rspi::<anonymous union>::<anonymous struct>& st_rspi::<anonymous union>::<anonymous struct>::operator=(const st_rspi::<anonymous union>::<anonymous struct>&)
struct {
^
../src/iodefine.h:5159:16: note: no known conversion for argument 1 from 'uint16_t {aka short unsigned int}' to 'const st_rspi::<anonymous union>::<anonymous struct>&'
In file included from ../src/test.cpp:20:0:
C:\Renesas\workspace\test\src/RSPI_RX210.h:151:35: error: invalid cast from type 'volatile st_rspi::<anonymous union>::<anonymous struct>' to type 'uint16_t {aka short unsigned int}'
return (uint16_t)rspidrv->SPDR.WORD;
^
C:\Renesas\workspace\test\src/RSPI_RX210.h: In instantiation of 'uint16_t RSPI_RX210<rspi_instance>::transfer9(uint16_t) [with unsigned int rspi_instance = 0u; uint16_t = short unsigned int]':
../src/test.cpp:64:1: required from here
C:\Renesas\workspace\test\src/RSPI_RX210.h:134:23: error: no match for 'operator=' (operand types are 'volatile st_rspi::<anonymous union>::<anonymous struct>' and 'uint16_t {aka short unsigned int}')
rspidrv->SPDR.WORD = inw;
^
C:\Renesas\workspace\test\src/RSPI_RX210.h:134:23: note: candidate is:
In file included from ../src/test.cpp:19:0:
../src/iodefine.h:5159:16: note: st_rspi::<anonymous union>::<anonymous struct>& st_rspi::<anonymous union>::<anonymous struct>::operator=(const st_rspi::<anonymous union>::<anonymous struct>&)
struct {
^
../src/iodefine.h:5159:16: note: no known conversion for argument 1 from 'uint16_t {aka short unsigned int}' to 'const st_rspi::<anonymous union>::<anonymous struct>&'
In file included from ../src/test.cpp:20:0:
C:\Renesas\workspace\test\src/RSPI_RX210.h:137:35: error: invalid cast from type 'volatile st_rspi::<anonymous union>::<anonymous struct>' to type 'uint16_t {aka short unsigned int}'
return (uint16_t)rspidrv->SPDR.WORD;
^
src/subdir.mk:38: recipe for target 'src/test.o' failed
make: *** [src/test.o] Error 1
17:10:21 Build Finished (took 530ms)
struct st_rspi {
union {
unsigned char BYTE;
struct {
unsigned char SPMS:1;
unsigned char TXMD:1;
unsigned char MODFEN:1;
unsigned char MSTR:1;
unsigned char SPEIE:1;
unsigned char SPTIE:1;
unsigned char SPE:1;
unsigned char SPRIE:1;
} BIT;
} SPCR;
union {
unsigned char BYTE;
struct {
unsigned char SSL0P:1;
unsigned char SSL1P:1;
unsigned char SSL2P:1;
unsigned char SSL3P:1;
unsigned char :4;
} BIT;
} SSLP;
union {
unsigned char BYTE;
struct {
unsigned char SPLP:1;
unsigned char SPLP2:1;
unsigned char :2;
unsigned char MOIFV:1;
unsigned char MOIFE:1;
unsigned char :2;
} BIT;
} SPPCR;
union {
unsigned char BYTE;
struct {
unsigned char OVRF:1;
unsigned char IDLNF:1;
unsigned char MODF:1;
unsigned char PERF:1;
unsigned char :4;
} BIT;
} SPSR;
union {
unsigned long LONG;
struct {
unsigned short H;
} WORD;
} SPDR;
union {
unsigned char BYTE;
struct {
unsigned char SPSLN:3;
unsigned char :5;
} BIT;
} SPSCR;
union {
unsigned char BYTE;
struct {
unsigned char SPCP:3;
unsigned char :1;
unsigned char SPECM:3;
unsigned char :1;
} BIT;
} SPSSR;
unsigned char SPBR;
union {
unsigned char BYTE;
struct {
unsigned char SPFC:2;
unsigned char :2;
unsigned char SPRDTD:1;
unsigned char SPLW:1;
unsigned char :2;
} BIT;
} SPDCR;
union {
unsigned char BYTE;
struct {
unsigned char SCKDL:3;
unsigned char :5;
} BIT;
} SPCKD;
union {
unsigned char BYTE;
struct {
unsigned char SLNDL:3;
unsigned char :5;
} BIT;
} SSLND;
union {
unsigned char BYTE;
struct {
unsigned char SPNDL:3;
unsigned char :5;
} BIT;
} SPND;
union {
unsigned char BYTE;
struct {
unsigned char SPPE:1;
unsigned char SPOE:1;
unsigned char SPIIE:1;
unsigned char PTE:1;
unsigned char :4;
} BIT;
} SPCR2;
union {
unsigned short WORD;
struct {
unsigned short CPHA:1;
unsigned short CPOL:1;
unsigned short BRDV:2;
unsigned short SSLA:3;
unsigned short SSLKP:1;
unsigned short SPB:4;
unsigned short LSBF:1;
unsigned short SPNDEN:1;
unsigned short SLNDEN:1;
unsigned short SCKDEN:1;
} BIT;
} SPCMD0;
union {
unsigned short WORD;
struct {
unsigned short CPHA:1;
unsigned short CPOL:1;
unsigned short BRDV:2;
unsigned short SSLA:3;
unsigned short SSLKP:1;
unsigned short SPB:4;
unsigned short LSBF:1;
unsigned short SPNDEN:1;
unsigned short SLNDEN:1;
unsigned short SCKDEN:1;
} BIT;
} SPCMD1;
union {
unsigned short WORD;
struct {
unsigned short CPHA:1;
unsigned short CPOL:1;
unsigned short BRDV:2;
unsigned short SSLA:3;
unsigned short SSLKP:1;
unsigned short SPB:4;
unsigned short LSBF:1;
unsigned short SPNDEN:1;
unsigned short SLNDEN:1;
unsigned short SCKDEN:1;
} BIT;
} SPCMD2;
union {
unsigned short WORD;
struct {
unsigned short CPHA:1;
unsigned short CPOL:1;
unsigned short BRDV:2;
unsigned short SSLA:3;
unsigned short SSLKP:1;
unsigned short SPB:4;
unsigned short LSBF:1;
unsigned short SPNDEN:1;
unsigned short SLNDEN:1;
unsigned short SCKDEN:1;
} BIT;
} SPCMD3;
union {
unsigned short WORD;
struct {
unsigned short CPHA:1;
unsigned short CPOL:1;
unsigned short BRDV:2;
unsigned short SSLA:3;
unsigned short SSLKP:1;
unsigned short SPB:4;
unsigned short LSBF:1;
unsigned short SPNDEN:1;
unsigned short SLNDEN:1;
unsigned short SCKDEN:1;
} BIT;
} SPCMD4;
union {
unsigned short WORD;
struct {
unsigned short CPHA:1;
unsigned short CPOL:1;
unsigned short BRDV:2;
unsigned short SSLA:3;
unsigned short SSLKP:1;
unsigned short SPB:4;
unsigned short LSBF:1;
unsigned short SPNDEN:1;
unsigned short SLNDEN:1;
unsigned short SCKDEN:1;
} BIT;
} SPCMD5;
union {
unsigned short WORD;
struct {
unsigned short CPHA:1;
unsigned short CPOL:1;
unsigned short BRDV:2;
unsigned short SSLA:3;
unsigned short SSLKP:1;
unsigned short SPB:4;
unsigned short LSBF:1;
unsigned short SPNDEN:1;
unsigned short SLNDEN:1;
unsigned short SCKDEN:1;
} BIT;
} SPCMD6;
union {
unsigned short WORD;
struct {
unsigned short CPHA:1;
unsigned short CPOL:1;
unsigned short BRDV:2;
unsigned short SSLA:3;
unsigned short SSLKP:1;
unsigned short SPB:4;
unsigned short LSBF:1;
unsigned short SPNDEN:1;
unsigned short SLNDEN:1;
unsigned short SCKDEN:1;
} BIT;
} SPCMD7;
};
/*
* RSPI_RX210.h
*
* Created on: Sep 8, 2015
* Author: ebrundick
*/
#ifndef RSPI_RX210_H
#define RSPI_RX210_H
#define NEVER_INLINE __attribute__((noinline))
#define ALWAYS_INLINE __attribute__((inline))
#include <SPI.h>
#include <iodefine.h>
#define PCLK_CPU 25000000UL
enum rspi_instance {
RSPI_INSTANCE_0 = 0,
};
template <
const unsigned int rspi_instance
>
class RSPI_RX210 : public SPIClass {
private:
static volatile struct st_rspi *rspidrv;
SPISettings _settings, _settings_old;
boolean _transaction_semaphore;
int _mask_irq;
public:
NEVER_INLINE
RSPI_RX210() {
rspidrv = &RSPI0;
};
NEVER_INLINE
void begin(void) {
_mask_irq = 0;
rspidrv->SPCR.BYTE = BIT0 | BIT3; // 3-wire SPI, Full-Duplex, no interrupts, Disabled
rspidrv->SPPCR.BYTE = BIT5; // MOSI at rest = 0
rspidrv->SPSCR.BYTE = 0x00; // Repeat SPCMD0 continuously
configClock(_settings._clock);
rspidrv->SPDCR.BYTE = 0x00; // Simple 1-frame buffer mode
rspidrv->SPCKD.BYTE = 0x00; // Minimal delay before SCK generation
rspidrv->SPCR2.BYTE = 0x00; // No parity
configMode(_settings._bitorder, _settings._datamode); // This sets SPCR.SPE = Enabled!
// Ready to roll!
};
NEVER_INLINE
void configClock(uint32_t bitrate) {
uint32_t i, div = PCLK_CPU / bitrate;
for (i = 0; i < 256; i++) {
uint32_t thisbr = PCLK_CPU / (2 * (i+1));
if (thisbr <= bitrate) {
rspidrv->SPBR = (uint8_t)thisbr;
return;
}
}
rspidrv->SPBR = 255; // SPBR happens not to be bitfielded.
};
NEVER_INLINE
void configMode(uint8_t bitorder, uint8_t mode) {
uint16_t cmd = 0x0000;
if (bitorder != MSBFIRST)
cmd |= BITC; // RSPI LSB First
switch (mode) {
case SPI_MODE1:
cmd |= BIT0; // CPOL=0, CPHA=1
break;
case SPI_MODE2:
cmd |= BIT1; // CPOL=1, CPHA=0
break;
case SPI_MODE3:
cmd |= BIT0 | BIT1; // CPOL=1, CPHA=1
break;
default: // SPI mode0 = CPOL=0, CPHA=0
break;
}
rspidrv->SPCMD0.WORD = cmd;
};
NEVER_INLINE
void end(void) {
rspidrv->SPCR.BYTE = 0x00; // Disable
};
NEVER_INLINE
void setBitOrder(unsigned int msblsb) {
_settings._bitorder = msblsb;
rspidrv->SPCR.BIT.SPE = 0;
configMode(_settings._bitorder, _settings._datamode);
rspidrv->SPCR.BIT.SPE = 1;
};
NEVER_INLINE
void setDataMode(unsigned int mode) {
_settings._datamode = mode;
rspidrv->SPCR.BIT.SPE = 0;
configMode(_settings._bitorder, _settings._datamode);
rspidrv->SPCR.BIT.SPE = 1;
}
// Data transfer
#define RSPI_SPCMD_FRAMESIZE_BITS (BIT8 | BIT9 | BITA | BITB)
NEVER_INLINE
uint8_t transfer(uint8_t inb) {
uint16_t cmd = rspidrv->SPCMD0.WORD;
if ( (cmd & RSPI_SPCMD_FRAMESIZE_BITS) != BITA ) {
// SPI currently not set to 8-bit mode; change this
cmd &= ~RSPI_SPCMD_FRAMESIZE_BITS;
cmd |= BITA; // 8 bits per transfer
rspidrv->SPCMD0.WORD = cmd;
}
rspidrv->SPDR.WORD = inb;
while (rspidrv->SPSR.BIT.IDLNF)
; // Waiting for RSPI to go Idle...
return (uint8_t)rspidrv->SPDR.WORD;
};
NEVER_INLINE
uint16_t transfer9(uint16_t inw) {
uint16_t cmd = rspidrv->SPCMD0.WORD;
if ( (cmd & RSPI_SPCMD_FRAMESIZE_BITS) != BITB ) {
// SPI currently not set to 9-bit mode; change this
cmd &= ~RSPI_SPCMD_FRAMESIZE_BITS;
cmd |= BITB; // 9 bits per transfer
rspidrv->SPCMD0.WORD = cmd;
}
rspidrv->SPDR.WORD = inw;
while (rspidrv->SPSR.BIT.IDLNF)
; // Waiting for RSPI to go Idle...
return (uint16_t)rspidrv->SPDR.WORD;
};
NEVER_INLINE
uint16_t transfer16(uint16_t inw) {
uint16_t cmd = rspidrv->SPCMD0.WORD;
if ( (cmd & RSPI_SPCMD_FRAMESIZE_BITS) != RSPI_SPCMD_FRAMESIZE_BITS ) {
// SPI currently not set to 9-bit mode; change this
cmd |= RSPI_SPCMD_FRAMESIZE_BITS; // 16 bits per transfer
rspidrv->SPCMD0.WORD = cmd;
}
rspidrv->SPDR.WORD = inw;
while (rspidrv->SPSR.BIT.IDLNF)
; // Waiting for RSPI to go Idle...
return (uint16_t)rspidrv->SPDR.WORD;
};
bool hasExtendedAPI(void) { return true; };
NEVER_INLINE
bool beginTransaction(SPISettings settings) {
// for atomicity in semaphore check
__builtin_rx_clrpsw(8); // Disable Global Interrupts
if (_transaction_semaphore) {
__builtin_rx_setpsw(8); // Enable interrupts
return false;
}
_transaction_semaphore = true;
// TODO: Disable masked IRQ if _mask_irq is set to something valid
if (_mask_irq != 255)
__builtin_rx_setpsw(8); // Enable interrupts
_settings_old.copy(_settings);
_settings.copy(settings);
configClock(_settings._clock);
configMode(_settings._bitorder, _settings._datamode);
return true;
};
NEVER_INLINE
void endTransaction(void) {
__builtin_rx_clrpsw(8); // Disable Global Interrupts
_transaction_semaphore = false;
// TODO: Unmask gpio IRQ
// Restore SPI settings under PSW(8)=CLR protection in case an IRQ fires which
// uses SPI and expects the default SPISettings to be intact.
_settings.copy(_settings_old);
configClock(_settings._clock);
configMode(_settings._bitorder, _settings._datamode);
__builtin_rx_setpsw(8); // Enable interrupts
};
NEVER_INLINE
void usingInterrupt(int pin) { ; }; // TODO
};
#endif /* RSPI_RX210_H */
/***************************************************************/
/* */
/* PROJECT NAME : test */
/* FILE : test.cpp */
/* DESCRIPTION : Main Program */
/* CPU SERIES : RX200 */
/* CPU TYPE : RX210 */
/* */
/* This file is generated by e2 studio. */
/* */
/***************************************************************/
/************************************************************************/
/* File Version: V1.00 */
/* Date Generated: 08/07/2013 */
/************************************************************************/
#include "iodefine.h"
#include <RSPI_RX210.h>
RSPI_RX210<RSPI_INSTANCE_0> SPI;
#ifdef CPPAPP
//Initialize global constructors
extern "C" void __main()
{
static int initialized;
if (! initialized)
{
typedef void (*pfunc) ();
extern pfunc __ctors[];
extern pfunc __ctors_end[];
pfunc *p;
initialized = 1;
for (p = __ctors_end; p > __ctors; )
(*--p) ();
}
}
#endif
int main(void)
{
// TODO: add application code here
/* P17 = LED0
* P16 = LED1
* P15 = LED2
*/
SPI.begin();
PORT1.PDR.BYTE |= BIT5 | BIT6 | BIT7;
PORT1.PMR.BYTE &= ~(BIT5 | BIT6 | BIT7);
PORT1.DSCR.BYTE |= BIT5 | BIT6 | BIT7;
while (1) {
static unsigned int i = 0;
PORT1.PODR.BYTE = BIT6;
SPI.transfer(0);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment