Skip to content

Instantly share code, notes, and snippets.

@spirilis
Created September 8, 2015 23:00
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/ba86744ada73baab2b69 to your computer and use it in GitHub Desktop.
Save spirilis/ba86744ada73baab2b69 to your computer and use it in GitHub Desktop.
C++ templated RSPI driver, take 2
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)
/*
* 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 */
/***************************************************************/
/* */
/* 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;
}
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