Skip to content

Commit 148e788

Browse files
committed
changed mcp2515 driver to use rx and tx buffers as well as uphold the standard modm::can api
1 parent 3f3ff3d commit 148e788

File tree

4 files changed

+112
-10
lines changed

4 files changed

+112
-10
lines changed

src/modm/driver/can/mcp2515.hpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ namespace modm
143143
isMessageAvailable();
144144

145145
static bool
146-
getMessage(can::Message& message);
146+
getMessage(can::Message& message, uint8_t *filter_id=nullptr);
147147

148148
/*
149149
* The CAN controller has a free slot to send a new message.
@@ -161,6 +161,15 @@ namespace modm
161161
static bool
162162
sendMessage(const can::Message& message);
163163

164+
/*
165+
* Poll the transmit buffer (shoudl be called periodically)
166+
*
167+
* \return true if a message was send this cycle, false otherwise
168+
*/
169+
static bool
170+
update();
171+
172+
164173
public:
165174
// Extended Functionality
166175

@@ -186,6 +195,18 @@ namespace modm
186195
BIT_MODIFY = 0x05
187196
};
188197

198+
static void
199+
mcp2515interrupt();
200+
201+
static bool
202+
mcp2515readMessage(can::Message& message);
203+
204+
static bool
205+
mcp2515isReadyToSend();
206+
207+
static bool
208+
mcp2515sendMessage(const can::Message& message);
209+
189210
static void
190211
writeRegister(uint8_t address, uint8_t data);
191212

src/modm/driver/can/mcp2515.lb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ def prepare(module, options):
3131
":architecture:can",
3232
":architecture:clock",
3333
":architecture:delay",
34+
":architecture:interrupt",
35+
":platform:exti",
3436
":debug")
3537
return True
3638

src/modm/driver/can/mcp2515_impl.hpp

Lines changed: 87 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,19 @@
1616
#ifndef MODM_MCP2515_HPP
1717
#error "Don't include this file directly, use 'mcp2515.hpp' instead!"
1818
#endif
19-
2019
#include "mcp2515_bit_timings.hpp"
2120
#include "mcp2515_definitions.hpp"
21+
#include <modm/architecture/driver/atomic/queue.hpp>
2222
#include <modm/architecture/interface/assert.hpp>
23-
23+
#include <modm/architecture/interface/interrupt.hpp>
24+
#include <modm/platform/exti/exti.hpp>
2425

2526
#undef MODM_LOG_LEVEL
2627
#define MODM_LOG_LEVEL modm::log::DISABLED
2728

29+
static modm::atomic::Queue<modm::can::Message, 32> txQueue;
30+
static modm::atomic::Queue<modm::can::Message, 32> rxQueue;
31+
2832
// ----------------------------------------------------------------------------
2933
template <typename SPI, typename CS, typename INT>
3034
SPI modm::Mcp2515<SPI, CS, INT>::spi;
@@ -119,6 +123,12 @@ modm::Mcp2515<SPI, CS, INT>::initialize()
119123
{
120124
using Timings = modm::CanBitTimingMcp2515<externalClockFrequency, bitrate>;
121125

126+
// initialize interrrupt on INT pin
127+
128+
modm::platform::Exti::connect<INT>(modm::platform::Exti::Trigger::FallingEdge, [](uint8_t){
129+
mcp2515interrupt();
130+
});
131+
122132
return initializeWithPrescaler(
123133
Timings::getPrescaler(),
124134
Timings::getSJW(),
@@ -186,22 +196,73 @@ modm::Mcp2515<SPI, CS, INT>::setMode(Can::Mode mode)
186196
}
187197

188198
// ----------------------------------------------------------------------------
199+
189200
template <typename SPI, typename CS, typename INT>
190201
bool
191202
modm::Mcp2515<SPI, CS, INT>::isMessageAvailable()
192203
{
193-
return !interruptPin.read();
204+
return rxQueue.isNotEmpty();
205+
}
206+
207+
template <typename SPI, typename CS, typename INT>
208+
bool
209+
modm::Mcp2515<SPI, CS, INT>::getMessage(can::Message& message, uint8_t* /*filter_id*/)
210+
{
211+
if (rxQueue.isEmpty())
212+
{
213+
// no message in the receive buffer
214+
return false;
215+
}
216+
else {
217+
auto& rxMessage = rxQueue.get();
218+
memcpy(&message, &rxMessage, sizeof(message));
219+
rxQueue.pop();
220+
return true;
221+
}
194222
}
195223

196224
// ----------------------------------------------------------------------------
197225
template <typename SPI, typename CS, typename INT>
198226
bool
199-
modm::Mcp2515<SPI, CS, INT>::getMessage(can::Message& message)
227+
modm::Mcp2515<SPI, CS, INT>::isReadyToSend()
200228
{
229+
return txQueue.isNotFull();
230+
}
231+
232+
// ----------------------------------------------------------------------------
233+
template <typename SPI, typename CS, typename INT>
234+
bool
235+
modm::Mcp2515<SPI, CS, INT>::sendMessage(const can::Message& message)
236+
{
237+
if (not modm_assert_continue_ignore(txQueue.push(message), "mcp2515.can.tx",
238+
"CAN transmit software buffer overflowed!", 1)) {
239+
return false;
240+
}
241+
return true;
242+
}
243+
244+
// ----------------------------------------------------------------------------
245+
template <typename SPI, typename CS, typename INT>
246+
void
247+
modm::Mcp2515<SPI, CS, INT>::mcp2515interrupt(){
248+
using namespace mcp2515;
249+
250+
can::Message message;
251+
bool success = mcp2515readMessage(message);
252+
if(success){
253+
modm_assert_continue_ignore(rxQueue.push(message), "mcp2515.can.rx.sw0",
254+
"CAN receive software buffer overflowed!", 1);
255+
}
256+
}
257+
258+
template <typename SPI, typename CS, typename INT>
259+
bool
260+
modm::Mcp2515<SPI, CS, INT>::mcp2515readMessage(can::Message& message){
201261
using namespace mcp2515;
202262

203263
uint8_t status = readStatus(RX_STATUS);
204264
uint8_t address;
265+
205266
if (status & FLAG_RXB0_FULL) {
206267
address = READ_RX; // message in buffer 0
207268
}
@@ -231,15 +292,33 @@ modm::Mcp2515<SPI, CS, INT>::getMessage(can::Message& message)
231292

232293
// RX0IF or RX1IF respectivly were already cleared automatically by rising CS.
233294
// See section 12.4 in datasheet.
234-
235295
return true;
236296
}
237297

298+
template <typename SPI, typename CS, typename INT>
299+
bool
300+
modm::Mcp2515<SPI, CS, INT>::update(){
301+
/// todo
302+
/// this should be a timer interrupt
303+
using namespace mcp2515;
304+
305+
bool hasSend = false;
306+
/// check if device accepts messages and start emptying the transmit queue if not empty
307+
if (txQueue.isNotEmpty())
308+
{
309+
if(mcp2515isReadyToSend()){
310+
hasSend = mcp2515sendMessage(txQueue.get());
311+
txQueue.pop();
312+
}
313+
}
314+
return hasSend;
315+
}
316+
238317
// ----------------------------------------------------------------------------
239318

240319
template <typename SPI, typename CS, typename INT>
241320
bool
242-
modm::Mcp2515<SPI, CS, INT>::isReadyToSend()
321+
modm::Mcp2515<SPI, CS, INT>::mcp2515isReadyToSend()
243322
{
244323
using namespace mcp2515;
245324

@@ -258,7 +337,7 @@ modm::Mcp2515<SPI, CS, INT>::isReadyToSend()
258337

259338
template <typename SPI, typename CS, typename INT>
260339
bool
261-
modm::Mcp2515<SPI, CS, INT>::sendMessage(const can::Message& message)
340+
modm::Mcp2515<SPI, CS, INT>::mcp2515sendMessage(const can::Message& message)
262341
{
263342
using namespace mcp2515;
264343

@@ -303,7 +382,7 @@ modm::Mcp2515<SPI, CS, INT>::sendMessage(const can::Message& message)
303382
spi.transferBlocking(RTS | address);
304383
chipSelect.set();
305384

306-
return address;
385+
return static_cast<bool>(address);
307386
}
308387

309388
// ----------------------------------------------------------------------------

0 commit comments

Comments
 (0)