Skip to content

Possible direction for __ARDUINO_CI_SFR_MOCK #201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions SampleProjects/TestSomething/test/defines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,26 @@ unittest(binary)
assertEqual(100, B1100100);
}

#ifdef __AVR__
#define DDRE _SFR_IO8(0x02)

unittest(SFR_IO8)
{
// in normal arduino code, you can do this. in arduino_ci, you might get an
// error like: cannot take the address of an rvalue of type 'int'
//
// this tests that directly
auto foo = &DDRE; // avoid compiler warning by using the result of an expression
}

unittest(read_write)
{
_SFR_IO8(1) = 0x11;
_SFR_IO8(2) = 0x22;
assertEqual((int) 0x11, (int) _SFR_IO8(1));
assertEqual((int) 0x22, (int) _SFR_IO8(2));
assertEqual((int) 0x2211, (int) _SFR_IO16(1));
}
#endif

unittest_main()
21 changes: 20 additions & 1 deletion SampleProjects/TestSomething/test/godmode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,18 +175,35 @@ unittest(spi) {
// 8-bit
state->reset();
state->spi.dataIn = "LMNO";
SPI.beginTransaction(SPISettings(14000000, LSBFIRST, SPI_MODE0));
uint8_t out8 = SPI.transfer('a');
SPI.endTransaction();
assertEqual("a", state->spi.dataOut);
assertEqual('L', out8);
assertEqual("MNO", state->spi.dataIn);

// 16-bit
// 16-bit MSBFIRST
union { uint16_t val; struct { char lsb; char msb; }; } in16, out16;
state->reset();
state->spi.dataIn = "LMNO";
in16.lsb = 'a';
in16.msb = 'b';
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0));
out16.val = SPI.transfer16(in16.val);
SPI.endTransaction();
assertEqual("NO", state->spi.dataIn);
assertEqual('M', out16.lsb);
assertEqual('L', out16.msb);
assertEqual("ba", state->spi.dataOut);

// 16-bit LSBFIRST
state->reset();
state->spi.dataIn = "LMNO";
in16.lsb = 'a';
in16.msb = 'b';
SPI.beginTransaction(SPISettings(14000000, LSBFIRST, SPI_MODE0));
out16.val = SPI.transfer16(in16.val);
SPI.endTransaction();
assertEqual("NO", state->spi.dataIn);
assertEqual('L', out16.lsb);
assertEqual('M', out16.msb);
Expand All @@ -196,7 +213,9 @@ unittest(spi) {
state->reset();
state->spi.dataIn = "LMNOP";
char inBuf[6] = "abcde";
SPI.beginTransaction(SPISettings(14000000, LSBFIRST, SPI_MODE0));
SPI.transfer(inBuf, 4);
SPI.endTransaction();

assertEqual("abcd", state->spi.dataOut);
assertEqual("LMNOe", String(inBuf));
Expand Down
2 changes: 2 additions & 0 deletions cpp/arduino/Godmode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,5 @@ SPIClass SPI = SPIClass(&GODMODE()->spi.dataIn, &GODMODE()->spi.dataOut);

// defined in Wire.h
TwoWire Wire = TwoWire();

volatile uint8_t __ARDUINO_CI_SFR_MOCK[1024];
26 changes: 25 additions & 1 deletion cpp/arduino/SPI.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <cassert>
#include "Stream.h"

// defines from original file
Expand Down Expand Up @@ -40,7 +41,10 @@

class SPISettings {
public:
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode){};
uint8_t bitOrder;
SPISettings(uint32_t clock, uint8_t bitOrder = MSBFIRST, uint8_t dataMode = SPI_MODE0){
this->bitOrder = bitOrder;
};
SPISettings(){};
};

Expand Down Expand Up @@ -68,6 +72,13 @@ class SPIClass: public ObservableDataStream {
// and configure the correct settings.
void beginTransaction(SPISettings settings)
{
// Set DORD to zero to send the most significant bit (MSB) first.
// Set DORD to one to send the least significant bit (LSB) first.
int dord = settings.bitOrder == MSBFIRST ? 0b0 : 0b1;
SPCR = (0b1 << SPE) // SPE (SPI Enable) bit
| (0b0 << CPOL) // CPOL (Clock Polarity)
| (0b0 << CPHA) // CPHA (Clock Phase)
| (dord << DORD); // DORD (Data Order) bit
#ifdef SPI_TRANSACTION_MISMATCH_LED
if (inTransactionFlag) {
pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
Expand All @@ -79,6 +90,9 @@ class SPIClass: public ObservableDataStream {

// Write to the SPI bus (MOSI pin) and also receive (MISO pin)
uint8_t transfer(uint8_t data) {
#ifdef SPI_TRANSACTION_MISMATCH_LED
assert(inTransactionFlag);
#endif
//FIXME!
// push memory->bus
dataOut->append(String((char)data));
Expand All @@ -93,6 +107,9 @@ class SPIClass: public ObservableDataStream {

uint16_t transfer16(uint16_t data) {
union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out;
#ifdef SPI_TRANSACTION_MISMATCH_LED
assert(inTransactionFlag);
#endif
in.val = data;
if (!(SPCR & (1 << DORD))) {
out.msb = transfer(in.msb);
Expand All @@ -105,6 +122,9 @@ class SPIClass: public ObservableDataStream {
}

void transfer(void *buf, size_t count) {
#ifdef SPI_TRANSACTION_MISMATCH_LED
assert(inTransactionFlag);
#endif
// TODO: this logic is rewritten from the original,
// I'm not sure what role the SPDR register (which I removed) plays

Expand All @@ -117,6 +137,10 @@ class SPIClass: public ObservableDataStream {
// After performing a group of transfers and releasing the chip select
// signal, this function allows others to access the SPI bus
void endTransaction(void) {
#ifdef SPI_TRANSACTION_MISMATCH_LED
assert(inTransactionFlag);
#endif
SPCR = 0; // set all flags to zero pending another transaction
#ifdef SPI_TRANSACTION_MISMATCH_LED
if (!inTransactionFlag) {
pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
Expand Down
10 changes: 9 additions & 1 deletion cpp/arduino/avr/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,15 @@
#ifndef _AVR_IO_H_
#define _AVR_IO_H_

#define _SFR_IO8(io_addr) (io_addr) // this macro is all we need from the sfr file
#include <stdint.h>

// hardware mocks
extern volatile uint8_t __ARDUINO_CI_SFR_MOCK[1024];
#define _SFR_IO8(io_addr) (*(volatile uint8_t *)(__ARDUINO_CI_SFR_MOCK + io_addr)) // this macro is all we need from the sfr file
#define _SFR_IO16(io_addr) (*(volatile uint16_t *)(__ARDUINO_CI_SFR_MOCK + io_addr)) // this macro is all we need from the sfr file
#define _SFR_MEM8(io_addr) (*(volatile uint8_t *)(__ARDUINO_CI_SFR_MOCK + io_addr)) // this macro is all we need from the sfr file
#define _SFR_MEM16(io_addr) (*(volatile uint16_t *)(__ARDUINO_CI_SFR_MOCK + io_addr)) // this macro is all we need from the sfr file
#define _SFR_MEM32(io_addr) (*(volatile uint32_t *)(__ARDUINO_CI_SFR_MOCK + io_addr)) // this macro is all we need from the sfr file

#if defined (__AVR_AT94K__)
# include "ioat94k.h"
Expand Down