Skip to content

Commit 21e4036

Browse files
committed
added nonblocking stuff for can send api part; the read is still blocking, which should be fine because it is controlled via interrupt
1 parent 33db784 commit 21e4036

File tree

4 files changed

+145
-83
lines changed

4 files changed

+145
-83
lines changed

examples/stm32f4_discovery/can_m2515/main.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,21 @@ class MyTask : modm::pt::Protothread
5555
run()
5656
{
5757
PT_BEGIN();
58+
59+
// send a new message
60+
message_.length = 2;
61+
message_.data[0] = 0xab;
62+
message_.data[1] = 0xcd;
63+
mcp2515.sendMessage(message_);
64+
5865
while (true)
5966
{
60-
// send a new message
61-
message_.length = 2;
62-
message_.data[0] = 0xab;
63-
message_.data[1] = 0xcd;
64-
mcp2515.sendMessage(message_);
65-
6667
if (mcp2515.isMessageAvailable())
6768
{
6869
mcp2515.getMessage(message_);
6970
MODM_LOG_INFO << "Received message: " << message_.identifier << modm::endl;
7071
}
71-
mcp2515.update();
72+
PT_CALL(mcp2515.update());
7273
}
7374
PT_END();
7475
}

src/modm/driver/can/mcp2515.hpp

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
#include <modm/architecture/interface/accessor.hpp>
2121
#include <modm/architecture/interface/delay.hpp>
2222
#include <modm/architecture/interface/can.hpp>
23+
#include <modm/processing/protothread.hpp>
24+
#include <modm/processing/resumable.hpp>
25+
#include <modm/processing/timer.hpp>
2326
#include <modm/debug/logger.hpp>
2427

2528
#include "mcp2515_definitions.hpp"
@@ -115,7 +118,7 @@ namespace modm
115118
template < typename SPI,
116119
typename CS,
117120
typename INT >
118-
class Mcp2515 : public ::modm::Can
121+
class Mcp2515 : public ::modm::Can, modm::NestedResumable<4>
119122
{
120123
public:
121124
template<frequency_t ExternalClock, bitrate_t bitrate=kbps(125), percent_t tolerance=pct(1) >
@@ -158,15 +161,15 @@ namespace modm
158161
*
159162
* \return true if the message was send, false otherwise
160163
*/
161-
static bool
164+
bool
162165
sendMessage(const can::Message& message);
163166

164167
/*
165168
* Poll the transmit buffer (shoudl be called periodically)
166169
*
167170
* \return true if a message was send this cycle, false otherwise
168171
*/
169-
static bool
172+
modm::ResumableResult<bool>
170173
update();
171174

172175

@@ -201,11 +204,14 @@ namespace modm
201204
static bool
202205
mcp2515readMessage(can::Message& message);
203206

204-
static bool
207+
bool
208+
mcp2515isReadyToSend(uint8_t status);
209+
210+
modm::ResumableResult<bool>
205211
mcp2515isReadyToSend();
206212

207-
static bool
208-
mcp2515sendMessage(const can::Message& message);
213+
modm::ResumableResult<bool>
214+
mcp2515sendMessage(const can::Message& message, const uint8_t status = 0xff);
209215

210216
static void
211217
writeRegister(uint8_t address, uint8_t data);
@@ -216,10 +222,13 @@ namespace modm
216222
static void
217223
bitModify(uint8_t address, uint8_t mask, uint8_t data);
218224

219-
static uint8_t
225+
modm::ResumableResult<uint8_t>
220226
readStatus(uint8_t type);
221227

222-
static inline void
228+
static uint8_t
229+
readStatusBlocking(uint8_t type);
230+
231+
inline modm::ResumableResult<void>
223232
writeIdentifier(const uint32_t& identifier, bool isExtendedFrame);
224233

225234
static inline bool

src/modm/driver/can/mcp2515.lb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ def prepare(module, options):
3232
":architecture:clock",
3333
":architecture:delay",
3434
":architecture:interrupt",
35+
":processing:protothread",
36+
":processing:timer",
3537
":platform:exti",
3638
":debug")
3739
return True

src/modm/driver/can/mcp2515_impl.hpp

Lines changed: 118 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ CS modm::Mcp2515<SPI, CS, INT>::chipSelect;
3939
template <typename SPI, typename CS, typename INT>
4040
INT modm::Mcp2515<SPI, CS, INT>::interruptPin;
4141

42+
static uint8_t statusBuffer_;
43+
static uint8_t addressBuffer_;
44+
static uint8_t dataBuffer_;
45+
static uint8_t i_;
46+
static uint8_t a_;
47+
static bool temp_;
48+
static bool hasSend_;
49+
static modm::ShortTimeout delay_;
50+
4251
// ----------------------------------------------------------------------------
4352

4453
template <typename SPI, typename CS, typename INT>
@@ -258,7 +267,7 @@ bool
258267
modm::Mcp2515<SPI, CS, INT>::mcp2515readMessage(can::Message& message){
259268
using namespace mcp2515;
260269

261-
uint8_t status = readStatus(RX_STATUS);
270+
uint8_t status = readStatusBlocking(SpiCommand::RX_STATUS);
262271
uint8_t address;
263272

264273
if (status & FLAG_RXB0_FULL) {
@@ -294,93 +303,123 @@ modm::Mcp2515<SPI, CS, INT>::mcp2515readMessage(can::Message& message){
294303
}
295304

296305
template <typename SPI, typename CS, typename INT>
297-
bool
306+
modm::ResumableResult<bool>
298307
modm::Mcp2515<SPI, CS, INT>::update(){
299308
/// todo
300309
/// this should be a timer interrupt
301310
using namespace mcp2515;
302311

303-
bool hasSend = false;
312+
RF_BEGIN();
313+
hasSend_ = false;
304314
/// check if device accepts messages and start emptying the transmit queue if not empty
305315
if (txQueue.isNotEmpty())
306316
{
307-
if(mcp2515isReadyToSend()){
308-
hasSend = mcp2515sendMessage(txQueue.get());
317+
statusBuffer_ = RF_CALL(readStatus(READ_STATUS));
318+
if(mcp2515isReadyToSend(statusBuffer_)){
319+
hasSend_ = RF_CALL(mcp2515sendMessage(txQueue.get(), statusBuffer_));
309320
txQueue.pop();
310321
}
311322
}
312-
return hasSend;
323+
RF_END_RETURN(hasSend_);
313324
}
314325

315326
// ----------------------------------------------------------------------------
316327

317328
template <typename SPI, typename CS, typename INT>
318-
bool
329+
modm::ResumableResult<bool>
319330
modm::Mcp2515<SPI, CS, INT>::mcp2515isReadyToSend()
320331
{
321332
using namespace mcp2515;
322333

323-
if ((readStatus(READ_STATUS) & (TXB2CNTRL_TXREQ | TXB1CNTRL_TXREQ | TXB0CNTRL_TXREQ)) ==
334+
RF_BEGIN();
335+
336+
temp_ = true;
337+
statusBuffer_ = RF_CALL(readStatus(READ_STATUS));
338+
if (( statusBuffer_& (TXB2CNTRL_TXREQ | TXB1CNTRL_TXREQ | TXB0CNTRL_TXREQ)) ==
324339
(TXB2CNTRL_TXREQ | TXB1CNTRL_TXREQ | TXB0CNTRL_TXREQ))
325340
{
326341
// all buffers currently in use
327-
return false;
342+
temp_ = false;
328343
}
329-
else {
330-
return true;
344+
345+
RF_END_RETURN(temp_);
346+
}
347+
template <typename SPI, typename CS, typename INT>
348+
bool
349+
modm::Mcp2515<SPI, CS, INT>::mcp2515isReadyToSend(uint8_t status)
350+
{
351+
using namespace mcp2515;
352+
bool ready = true;
353+
if ((status & (TXB2CNTRL_TXREQ | TXB1CNTRL_TXREQ | TXB0CNTRL_TXREQ)) ==
354+
(TXB2CNTRL_TXREQ | TXB1CNTRL_TXREQ | TXB0CNTRL_TXREQ))
355+
{
356+
// all buffers currently in use
357+
ready = false;
331358
}
359+
360+
return ready;
332361
}
333362

334363
// ----------------------------------------------------------------------------
335364

336365
template <typename SPI, typename CS, typename INT>
337-
bool
338-
modm::Mcp2515<SPI, CS, INT>::mcp2515sendMessage(const can::Message& message)
366+
modm::ResumableResult<bool>
367+
modm::Mcp2515<SPI, CS, INT>::mcp2515sendMessage(const can::Message& message, const uint8_t status)
339368
{
340-
using namespace mcp2515;
369+
using namespace modm::mcp2515;
370+
RF_BEGIN();
341371

342-
uint8_t status = readStatus(READ_STATUS);
343-
uint8_t address;
344-
if ((status & TXB0CNTRL_TXREQ) == 0) {
345-
address = 0x00; // TXB0SIDH
372+
/// dont read status again if we have been provided one
373+
if(status == 0xff){
374+
statusBuffer_ = RF_CALL(readStatus(READ_STATUS));
346375
}
347-
else if ((status & TXB1CNTRL_TXREQ) == 0) {
348-
address = 0x02; // TXB1SIDH
376+
else{
377+
statusBuffer_ = status;
349378
}
350-
else if ((status & TXB2CNTRL_TXREQ) == 0) {
351-
address = 0x04; // TXB2SIDH
352-
}
353-
else {
379+
380+
if ((statusBuffer_ & TXB0CNTRL_TXREQ) == 0)
381+
{
382+
addressBuffer_ = 0x00; // TXB0SIDH
383+
} else if ((statusBuffer_ & TXB1CNTRL_TXREQ) == 0)
384+
{
385+
addressBuffer_ = 0x02; // TXB1SIDH
386+
} else if ((statusBuffer_ & TXB2CNTRL_TXREQ) == 0)
387+
{
388+
addressBuffer_ = 0x04; // TXB2SIDH
389+
} else
390+
{
354391
// all buffer are in use => could not send the message
355-
return false;
356392
}
357393

358-
chipSelect.reset();
359-
spi.transferBlocking(WRITE_TX | address);
360-
writeIdentifier(message.identifier, message.flags.extended);
394+
if (addressBuffer_ == 0x00 || addressBuffer_ == 0x02 || addressBuffer_ == 0x04)
395+
{
396+
chipSelect.reset();
397+
RF_CALL(spi.transfer(WRITE_TX | addressBuffer_));
398+
RF_CALL(writeIdentifier(message.identifier, message.flags.extended));
361399

362-
// if the message is a rtr-frame, is has a length but no attached data
363-
if (message.flags.rtr) {
364-
spi.transferBlocking(MCP2515_RTR | message.length);
365-
}
366-
else {
367-
spi.transferBlocking(message.length);
400+
// if the message is a rtr-frame, is has a length but no attached data
401+
if (message.flags.rtr)
402+
{
403+
RF_CALL(spi.transfer(MCP2515_RTR | message.length));
404+
} else
405+
{
406+
RF_CALL(spi.transfer(message.length));
368407

369-
for (uint8_t i = 0; i < message.length; ++i) {
370-
spi.transferBlocking(message.data[i]);
408+
for (i_ = 0; i_ < message.length; ++i_) {
409+
RF_CALL(spi.transfer(message.data[i_]));
410+
}
371411
}
372-
}
373-
chipSelect.set();
374-
375-
modm::delay_us(1);
376-
377-
// send message via RTS command
378-
chipSelect.reset();
379-
address = (address == 0) ? 1 : address; // 0 2 4 => 1 2 4
380-
spi.transferBlocking(RTS | address);
381-
chipSelect.set();
412+
delay_.restart(1ms);
413+
chipSelect.set();
414+
RF_WAIT_UNTIL(delay_.isExpired());
382415

383-
return static_cast<bool>(address);
416+
// send message via RTS command
417+
chipSelect.reset();
418+
addressBuffer_ = (addressBuffer_ == 0) ? 1 : addressBuffer_; // 0 2 4 => 1 2 4
419+
RF_CALL(spi.transfer(RTS | addressBuffer_));
420+
chipSelect.set();
421+
}
422+
RF_END_RETURN(static_cast<bool>(addressBuffer_));
384423
}
385424

386425
// ----------------------------------------------------------------------------
@@ -428,51 +467,62 @@ modm::Mcp2515<SPI, CS, INT>::bitModify(uint8_t address, uint8_t mask, uint8_t da
428467
}
429468

430469
template <typename SPI, typename CS, typename INT>
431-
uint8_t
470+
modm::ResumableResult<uint8_t>
432471
modm::Mcp2515<SPI, CS, INT>::readStatus(uint8_t type)
433472
{
473+
RF_BEGIN();
474+
434475
chipSelect.reset();
476+
dataBuffer_ = RF_CALL(spi.transfer(type));
477+
RF_CALL(spi.transfer(0xff));
478+
chipSelect.set();
435479

436-
spi.transferBlocking(type);
437-
uint8_t data = spi.transferBlocking(0xff);
480+
RF_END_RETURN(dataBuffer_);
481+
}
438482

483+
template <typename SPI, typename CS, typename INT>
484+
uint8_t
485+
modm::Mcp2515<SPI, CS, INT>::readStatusBlocking(uint8_t type)
486+
{
487+
chipSelect.reset();
488+
uint8_t data = spi.transferBlocking(type);
489+
spi.transferBlocking(0xff);
439490
chipSelect.set();
440-
441491
return data;
442492
}
443493

494+
444495
// ----------------------------------------------------------------------------
445496

446497
template <typename SPI, typename CS, typename INT>
447-
void
498+
modm::ResumableResult<void>
448499
modm::Mcp2515<SPI, CS, INT>::writeIdentifier(const uint32_t& identifier,
449500
bool isExtendedFrame)
450501
{
451502
using namespace mcp2515;
452-
453503
const uint32_t *ptr = &identifier;
454504

505+
RF_BEGIN();
506+
455507
if (isExtendedFrame)
456508
{
457-
spi.transferBlocking(*((uint16_t *) ptr + 1) >> 5);
509+
RF_CALL(spi.transfer(*((uint16_t *)ptr + 1) >> 5));
458510

459511
// calculate the next values
460-
uint8_t temp;
461-
temp = (*((uint8_t *) ptr + 2) << 3) & 0xe0;
462-
temp |= MCP2515_IDE;
463-
temp |= (*((uint8_t *) ptr + 2)) & 0x03;
464-
465-
spi.transferBlocking(temp);
466-
spi.transferBlocking(*((uint8_t *) ptr + 1));
467-
spi.transferBlocking(*((uint8_t *) ptr));
468-
}
469-
else
512+
a_ = (*((uint8_t *)ptr + 2) << 3) & 0xe0;
513+
a_ |= MCP2515_IDE;
514+
a_ |= (*((uint8_t *)ptr + 2)) & 0x03;
515+
RF_CALL(spi.transfer(a_));
516+
RF_CALL(spi.transfer(*((uint8_t *)ptr + 1)));
517+
RF_CALL(spi.transfer(*((uint8_t *)ptr)));
518+
} else
470519
{
471-
spi.transferBlocking(*((uint16_t *) ptr) >> 3);
472-
spi.transferBlocking(*((uint8_t *) ptr) << 5);
473-
spi.transferBlocking(0);
474-
spi.transferBlocking(0);
520+
RF_CALL(spi.transfer(*((uint16_t *)ptr) >> 3));
521+
RF_CALL(spi.transfer(*((uint8_t *)ptr) << 5));
522+
RF_CALL(spi.transfer(0));
523+
RF_CALL(spi.transfer(0));
475524
}
525+
RF_END();
476526
}
477527

478528
template <typename SPI, typename CS, typename INT>

0 commit comments

Comments
 (0)