Created
September 8, 2015 23:00
-
-
Save spirilis/ba86744ada73baab2b69 to your computer and use it in GitHub Desktop.
C++ templated RSPI driver, take 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18:58:42 **** 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" | |
In file included from ../src/test.cpp:20:0: | |
C:\Renesas\workspace\test\src/RSPI_RX210.h: In instantiation of 'uint8_t RSPI_RX210<rspidrv>::transfer(uint8_t) [with volatile st_rspi& rspidrv = (* & SFRBASE_RSPI0); uint8_t = unsigned char]': | |
../src/test.cpp:63:20: required from here | |
C:\Renesas\workspace\test\src/RSPI_RX210.h:116:22: 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:116:22: 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:119:33: 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<rspidrv>::transfer16(uint16_t) [with volatile st_rspi& rspidrv = (* & SFRBASE_RSPI0); uint16_t = short unsigned int]': | |
../src/test.cpp:66:1: required from here | |
C:\Renesas\workspace\test\src/RSPI_RX210.h:145:22: 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:145:22: 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:148:34: 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<rspidrv>::transfer9(uint16_t) [with volatile st_rspi& rspidrv = (* & SFRBASE_RSPI0); uint16_t = short unsigned int]': | |
../src/test.cpp:66:1: required from here | |
C:\Renesas\workspace\test\src/RSPI_RX210.h:131:22: 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:131:22: 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:134:34: 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; | |
^ | |
make: *** [src/test.o] Error 1 | |
src/subdir.mk:38: recipe for target 'src/test.o' failed | |
18:58:43 Build Finished (took 749ms) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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 | |
template < | |
volatile struct st_rspi & rspidrv | |
> | |
class RSPI_RX210 : public SPIClass { | |
private: | |
SPISettings _settings, _settings_old; | |
boolean _transaction_semaphore; | |
int _mask_irq; | |
public: | |
NEVER_INLINE | |
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; | |
} | |
NEVER_INLINE | |
void setClockDivider(int clockDiv) { | |
_settings._clock = PCLK_CPU / (1 << clockDiv); | |
configClock(_settings._clock); | |
}; | |
// 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 */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/***************************************************************/ | |
/* */ | |
/* 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> | |
extern volatile struct st_rspi SFRBASE_RSPI0; | |
RSPI_RX210<SFRBASE_RSPI0> 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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MEMORY | |
{ | |
RAM : ORIGIN = 0x0, LENGTH = 65536 | |
ROM : ORIGIN = 0xFFF80000, LENGTH = 524288 | |
} | |
SECTIONS | |
{ | |
.fvectors 0xFFFFFF80 : AT (0xFFFFFF80) | |
{ | |
KEEP(*(.fvectors)) | |
} > ROM | |
.text 0xFFF80000 : AT (0xFFF80000) | |
{ | |
*(.text) | |
*(.text.*) | |
*(P) | |
etext = .; | |
} > ROM | |
.rvectors : | |
{ | |
_rvectors_start = .; | |
KEEP(*(.rvectors)) | |
_rvectors_end = .; | |
} > ROM | |
.init : | |
{ | |
*(.init) | |
__preinit_array_start = .; | |
*(.preinit_array) | |
__preinit_array_end = .; | |
__init_array_start = (. + 3) & ~ 3; | |
*(.init_array) | |
*(SORT(.init_array.*)) | |
__init_array_end = .; | |
__fini_array_start = .; | |
*(.fini_array) | |
*(SORT(.fini_array.*)) | |
__fini_array_end = .; | |
} > ROM | |
.fini : | |
{ | |
*(.fini) | |
} > ROM | |
.got : | |
{ | |
*(.got) | |
*(.got.plt) | |
} > ROM | |
.rodata : | |
{ | |
*(.rodata) | |
*(.rodata.*) | |
*(C_1) | |
*(C_2) | |
*(C) | |
_erodata = .; | |
} > ROM | |
.eh_frame_hdr : | |
{ | |
*(.eh_frame_hdr) | |
} > ROM | |
.eh_frame : | |
{ | |
*(.eh_frame) | |
} > ROM | |
.jcr : | |
{ | |
*(.jcr) | |
} > ROM | |
.tors : | |
{ | |
__CTOR_LIST__ = .; | |
. = ALIGN(2); | |
___ctors = .; | |
*(.ctors) | |
___ctors_end = .; | |
__CTOR_END__ = .; | |
__DTOR_LIST__ = .; | |
___dtors = .; | |
*(.dtors) | |
___dtors_end = .; | |
__DTOR_END__ = .; | |
. = ALIGN(2); | |
_mdata = .; | |
} > ROM | |
.ustack 0x200 : AT (0x200) | |
{ | |
_ustack = .; | |
} > RAM | |
.istack 0x100 : AT (0x100) | |
{ | |
_istack = .; | |
} > RAM | |
.data 0x204 : AT (_mdata) | |
{ | |
_data = .; | |
*(.data) | |
*(.data.*) | |
*(D) | |
*(D_1) | |
*(D_2) | |
_edata = .; | |
} > RAM | |
.gcc_exc : | |
{ | |
*(.gcc_exc) | |
} > RAM | |
.bss : | |
{ | |
_bss = .; | |
*(.bss) | |
*(.bss.**) | |
*(COMMON) | |
*(B) | |
*(B_1) | |
*(B_2) | |
_ebss = .; | |
_end = .; | |
} > RAM | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment