Skip to content

Commit c0c6644

Browse files
committed
Backup-Point #2: This async access works but god knows its hacky as fuck.
1 parent 6b4cd90 commit c0c6644

File tree

7 files changed

+327
-156
lines changed

7 files changed

+327
-156
lines changed

Diff for: ThreadsafeIO/examples/ts_spi/ts_spi.ino

+14-8
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ void bmp388_deselect();
2323
* GLOBAL VARIABLES
2424
**************************************************************************************/
2525

26+
SpiDispatcher spi_dispatcher;
2627

2728
SpiBusDevice bmp388{"SPI",
28-
SpiBusDeviceConfig{
29-
SPISettings{1000000, MSBFIRST, SPI_MODE0},
30-
bmp388_select,
31-
bmp388_deselect,
32-
0x00}};
29+
SpiBusDeviceConfig {
30+
SPISettings{1000000, MSBFIRST, SPI_MODE0},
31+
/* bmp388_select or ... */ [](){ digitalWrite(BMP388_CS_PIN, LOW ); },
32+
/* bmp388_deselect or ... */ [](){ digitalWrite(BMP388_CS_PIN, HIGH); }
33+
}
34+
};
3335

3436
/**************************************************************************************
3537
* SETUP/LOOP
@@ -39,8 +41,10 @@ void setup()
3941
{
4042
Serial.begin(9600);
4143
while (!Serial) { }
42-
43-
SPI.begin();
44+
45+
//SPI.begin();
46+
spi_dispatcher.begin();
47+
delay(2000); /* Ensure that the SPI dispatcher has been started. */
4448

4549
pinMode(BMP388_CS_PIN, OUTPUT);
4650
digitalWrite(BMP388_CS_PIN, HIGH);
@@ -53,7 +57,9 @@ void setup()
5357

5458
SpiIoRequest req(tx_buf, sizeof(tx_buf), rx_buf, &rx_buf_len);
5559

56-
bmp388.transfer(req);
60+
bmp388.transfer(req);
61+
62+
rtos::ThisThread::sleep_for(5000); /* TODO: Wait for results, otherwise the rx/tx buffers go out of range. */
5763

5864
return rx_buf[2];
5965
};

Diff for: ThreadsafeIO/src/BusDevice.h

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* A deeply magical library providing threadsafe IO via pipes.
3+
*/
4+
5+
#ifndef BUS_DEVICE_H_
6+
#define BUS_DEVICE_H_
7+
8+
/**************************************************************************************
9+
* INCLUDE
10+
**************************************************************************************/
11+
12+
#include "IoRequest.h"
13+
14+
/**************************************************************************************
15+
* CLASS DECLARATION
16+
**************************************************************************************/
17+
18+
class BusDevice
19+
{
20+
public:
21+
virtual ~BusDevice() { }
22+
23+
enum class Status : int
24+
{
25+
Ok = 0,
26+
ConfigError = -1,
27+
};
28+
29+
virtual Status transfer(IoRequest & req) = 0;
30+
};
31+
32+
#endif /* BUS_DEVICE_H_ */

Diff for: ThreadsafeIO/src/IoRequest.h

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* A deeply magical library providing threadsafe IO via pipes.
3+
*/
4+
5+
#ifndef IO_REQUEST_H_
6+
#define IO_REQUEST_H_
7+
8+
/**************************************************************************************
9+
* INCLUDE
10+
**************************************************************************************/
11+
12+
#include <stdint.h>
13+
14+
/**************************************************************************************
15+
* CLASS DECLARATION
16+
**************************************************************************************/
17+
18+
class IoRequest
19+
{
20+
public:
21+
22+
enum class Type
23+
{
24+
None,
25+
SPI
26+
};
27+
28+
IoRequest(Type const type, uint8_t const * const tx_buf, size_t const tx_buf_len, uint8_t * rx_buf, size_t * rx_buf_len)
29+
: _type{type}
30+
, _tx_buf{tx_buf}
31+
, _tx_buf_len{tx_buf_len}
32+
, _rx_buf{rx_buf}
33+
, _rx_buf_len{rx_buf_len}
34+
{ }
35+
36+
/*
37+
inline Type type () const { return _type; }
38+
inline uint8_t const * tx_buf () const { return _tx_buf; }
39+
inline size_t tx_buf_len() const { return _tx_buf_len; }
40+
inline uint8_t * rx_buf () { return _rx_buf; }
41+
inline size_t * rx_buf_len() { return _rx_buf_len; }
42+
43+
private:
44+
*/
45+
Type _type{Type::None};
46+
uint8_t const * const _tx_buf{nullptr};
47+
size_t const _tx_buf_len{0};
48+
uint8_t * _rx_buf{nullptr};
49+
size_t * _rx_buf_len{0};
50+
};
51+
52+
#endif /* IO_REQUEST_H_ */

Diff for: ThreadsafeIO/src/SpiBusDevice.h

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* A deeply magical library providing threadsafe IO via pipes.
3+
*/
4+
5+
#ifndef SPI_BUS_DEVICE_H_
6+
#define SPI_BUS_DEVICE_H_
7+
8+
/**************************************************************************************
9+
* INCLUDE
10+
**************************************************************************************/
11+
12+
#include <functional>
13+
14+
#include <Arduino.h>
15+
#include <mbed.h>
16+
#include <SPI.h>
17+
18+
#include "IoRequest.h"
19+
#include "BusDevice.h"
20+
21+
/**************************************************************************************
22+
* CLASS DECLARATION
23+
**************************************************************************************/
24+
25+
class SpiBusDeviceConfig
26+
{
27+
public:
28+
typedef std::function<void(void)> SpiSelectFunc;
29+
typedef std::function<void(void)> SpiDeselectFunc;
30+
SpiBusDeviceConfig(SPISettings const & spi_settings, SpiSelectFunc spi_select, SpiDeselectFunc spi_deselect, uint8_t const fill_symbol = 0xFF)
31+
: _spi_settings{spi_settings}
32+
, _spi_select{spi_select}
33+
, _spi_deselect{spi_deselect}
34+
, _fill_symbol{fill_symbol}
35+
{ }
36+
bool good () const { return (_spi_select && _spi_deselect); }
37+
SPISettings settings () const { return _spi_settings; }
38+
void select () const { if (_spi_select) _spi_select(); }
39+
void deselect () const { if (_spi_deselect) _spi_deselect(); }
40+
uint8_t fill_symbol() const { return _fill_symbol; }
41+
private:
42+
SPISettings _spi_settings;
43+
SpiSelectFunc _spi_select{nullptr};
44+
SpiDeselectFunc _spi_deselect{nullptr};
45+
uint8_t _fill_symbol{0xFF};
46+
};
47+
48+
class SpiIoRequest : public IoRequest
49+
{
50+
public:
51+
SpiIoRequest(uint8_t const * const tx_buf, size_t const tx_buf_len, uint8_t * rx_buf, size_t * rx_buf_len)
52+
: IoRequest(IoRequest::Type::SPI, tx_buf, tx_buf_len, rx_buf, rx_buf_len)
53+
{ }
54+
55+
void set_config(SpiBusDeviceConfig * config) { _config = config; }
56+
SpiBusDeviceConfig & config() { return *_config; }
57+
58+
private:
59+
SpiBusDeviceConfig * _config{nullptr};
60+
};
61+
62+
extern rtos::Queue<IoRequest, 32> _request_queue;
63+
64+
class SpiBusDevice : public BusDevice
65+
{
66+
public:
67+
SpiBusDevice(std::string const & spi_bus, SpiBusDeviceConfig const & config) : _config{config}
68+
{
69+
/* TODO: Select SPI bus based in string. */
70+
}
71+
virtual Status transfer(IoRequest & req) override
72+
{
73+
if (!_config.good())
74+
return Status::ConfigError;
75+
76+
reinterpret_cast<SpiIoRequest*>(&req)->set_config(&_config);
77+
78+
/* Insert into queue. */
79+
_request_queue.try_put(&req);
80+
81+
/* TODO: Instead of directly processing in here push
82+
* the whole request into a queue and hand over processing
83+
* to the IO thread.
84+
*/
85+
/*
86+
_config.select();
87+
88+
SPI.beginTransaction(_config.settings());
89+
90+
size_t bytes_received = 0,
91+
bytes_sent = 0;
92+
for(; bytes_received < (*req.rx_buf_len()); bytes_received++, bytes_sent++)
93+
{
94+
uint8_t tx_byte = 0;
95+
96+
if (bytes_sent < req.tx_buf_len())
97+
tx_byte = req.tx_buf()[bytes_sent];
98+
else
99+
tx_byte = _config.fill_symbol();
100+
101+
req.rx_buf()[bytes_received] = SPI.transfer(tx_byte);
102+
}
103+
*req.rx_buf_len() = bytes_received;
104+
105+
SPI.endTransaction();
106+
107+
_config.deselect();
108+
*/
109+
110+
return Status::Ok;
111+
}
112+
113+
private:
114+
115+
SpiBusDeviceConfig _config;
116+
117+
};
118+
119+
#endif /* SPI_BUS_DEVICE_H_ */

Diff for: ThreadsafeIO/src/SpiDispatcher.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include "SpiDispatcher.h"
2+
3+
rtos::Queue<IoRequest, 32> _request_queue;

Diff for: ThreadsafeIO/src/SpiDispatcher.h

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* A deeply magical library providing threadsafe IO via pipes.
3+
*/
4+
5+
#ifndef SPI_DISPATCHER_H_
6+
#define SPI_DISPATCHER_H_
7+
8+
/**************************************************************************************
9+
* INCLUDE
10+
**************************************************************************************/
11+
12+
#include <Arduino.h>
13+
#include <mbed.h>
14+
#include <SPI.h>
15+
16+
#include "IoRequest.h"
17+
#include "SpiBusDevice.h"
18+
19+
/**************************************************************************************
20+
* CLASS DECLARATION
21+
**************************************************************************************/
22+
23+
extern rtos::Queue<IoRequest, 32> _request_queue;
24+
25+
class SpiDispatcher
26+
{
27+
public:
28+
29+
SpiDispatcher() : _thread(osPriorityNormal, 4096, nullptr, "SpiDispatcher") { }
30+
~SpiDispatcher() { end(); }
31+
32+
enum class Status : int
33+
{
34+
Ok = 0
35+
};
36+
37+
Status begin()
38+
{
39+
SPI.begin();
40+
_thread.start(mbed::callback(this, &SpiDispatcher::threadFunc)); /* TODO: Check return code */
41+
return Status::Ok;
42+
}
43+
44+
Status end()
45+
{
46+
_terminate_thread = true;
47+
_thread.join(); /* TODO: Check return code */
48+
SPI.end();
49+
return Status::Ok;
50+
}
51+
52+
private:
53+
54+
rtos::Thread _thread;
55+
bool _terminate_thread{false};
56+
57+
void threadFunc()
58+
{
59+
while(!_terminate_thread)
60+
{
61+
//rtos::ThisThread::yield();
62+
IoRequest * io_reqest = nullptr;
63+
if (_request_queue.try_get(&io_reqest))
64+
{
65+
if (io_reqest->_type == IoRequest::Type::SPI)
66+
{
67+
SpiIoRequest * spi_io_request = reinterpret_cast<SpiIoRequest *>(io_reqest);
68+
69+
spi_io_request->config().select();
70+
71+
SPI.beginTransaction(spi_io_request->config().settings());
72+
73+
size_t bytes_received = 0,
74+
bytes_sent = 0;
75+
for(; bytes_received < *(spi_io_request->_rx_buf_len); bytes_received++, bytes_sent++)
76+
{
77+
uint8_t tx_byte = 0;
78+
79+
if (bytes_sent < spi_io_request->_tx_buf_len)
80+
tx_byte = spi_io_request->_tx_buf[bytes_sent];
81+
else
82+
tx_byte = spi_io_request->config().fill_symbol();
83+
84+
uint8_t const rx_byte = SPI.transfer(tx_byte);
85+
86+
Serial.print("TX ");
87+
Serial.print(tx_byte, HEX);
88+
Serial.print("| RX ");
89+
Serial.print(rx_byte, HEX);
90+
Serial.println();
91+
92+
spi_io_request->_rx_buf[bytes_received] = rx_byte;
93+
}
94+
*spi_io_request->_rx_buf_len = bytes_received;
95+
96+
SPI.endTransaction();
97+
98+
spi_io_request->config().deselect();
99+
}
100+
}
101+
}
102+
}
103+
};
104+
105+
#endif /* SPI_DISPATCHER_H_ */

0 commit comments

Comments
 (0)