diff --git a/examples/nucleo_f439zi/can_m2515/main.cpp b/examples/nucleo_f439zi/can_m2515/main.cpp new file mode 100644 index 0000000000..8dcfd41538 --- /dev/null +++ b/examples/nucleo_f439zi/can_m2515/main.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2013, Kevin Läufer + * Copyright (c) 2013-2017, Niklas Hauser + * Copyright (c) 2016, Raphael Lehmann + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#include +#include +#include +#include + +// Set the log level +#undef MODM_LOG_LEVEL +#define MODM_LOG_LEVEL modm::log::DEBUG + +// If you use a different SPI instance, you may have to also choose different +// GPIOs to connect to. +using Cs = GpioOutputA4; +using Mosi = GpioOutputB5; +using Miso = GpioInputB4; +using Sck = GpioOutputB3; +using Int = GpioInputC7; +using SpiMaster = SpiMaster1; +// Note that you can also use a bit-banged SPI driver as a drop-in replacement +// using SpiMaster = BitBangSpiMaster; + +// Default filters to receive any extended CAN frame +FLASH_STORAGE(uint8_t canFilter[]) = { + MCP2515_FILTER_EXTENDED(0), // Filter 0 + MCP2515_FILTER_EXTENDED(0), // Filter 1 + + MCP2515_FILTER(0), // Filter 2 + MCP2515_FILTER(0), // Filter 3 + MCP2515_FILTER(0), // Filter 4 + MCP2515_FILTER(0), // Filter 5 + + MCP2515_MASK_EXTENDED(0), // Mask 0 + MCP2515_MASK(0), // Mask 1 +}; + +modm::Mcp2515 mcp2515; + +class CanThread : modm::pt::Protothread +{ +public: + CanThread() : + message_{}, + wait_{1s}, + i{0}, + j{0} + {} + + bool + run() + { + PT_BEGIN(); + + MODM_LOG_INFO << "Initializing mcp2515 ..." << modm::endl; + // Configure MCP2515 + while (!mcp2515.initialize<8_MHz, 500_kbps>()){ + PT_WAIT_UNTIL(wait_.isExpired()); + wait_.restart(); + } + /// Set filters of MCP2515 + MODM_LOG_INFO << "Setting filters of mcp2515 ..." << modm::endl; + mcp2515.setFilter(modm::accessor::asFlash(canFilter)); + MODM_LOG_INFO << "Running ... " << modm::endl; + while (true) + { + // receive messages + if (mcp2515.isMessageAvailable()) + { + MODM_LOG_INFO << "Message Available ... " << modm::endl; + mcp2515.getMessage(message_); + MODM_LOG_INFO << "Received message: " << modm::hex << message_.identifier << modm::endl; + for(i = 0; i < message_.length; ++i){ + MODM_LOG_INFO << modm::hex<< " 0x" << message_.data[i]; + } + MODM_LOG_INFO << modm::endl; + MODM_LOG_INFO << modm::endl; + } + + if(wait_.isExpired()) + { + wait_.restart(1000ms); + message_.identifier = 0xAA; + message_.length = 2; + message_.data[0] = 13; + message_.data[1] = 37; + MODM_LOG_INFO << "Sending Message ... "<< modm::endl; + for(j = 0; j < message_.length; ++j){ + MODM_LOG_INFO << modm::hex<< " 0x" << message_.data[j]; + } + MODM_LOG_INFO << modm::endl; + MODM_LOG_INFO << "Success: " << mcp2515.sendMessage(message_) << modm::endl; + } + + /// process internal mcp2515 queues + PT_CALL(mcp2515.update()); + PT_YIELD(); + } + + PT_END(); + } + +private: + modm::can::Message message_; + modm::ShortTimeout wait_; + uint8_t i, j; +}; + +CanThread canThread; + +int +main() +{ + Board::initialize(); + + MODM_LOG_INFO << "Mcp2515 Example" << modm::endl; + // Initialize SPI interface and the other pins + // needed by the MCP2515 + SpiMaster::connect(); + /// we initialize a higher baud rate then n the avr example, dunnow hats the mcp2515 is capable + /// of + SpiMaster::initialize(); + Cs::setOutput(); + Int::setInput(Gpio::InputType::PullUp); + + while (true) { + canThread.run(); + } +} \ No newline at end of file diff --git a/examples/nucleo_f439zi/can_m2515/project.xml b/examples/nucleo_f439zi/can_m2515/project.xml new file mode 100644 index 0000000000..9be0b96d5f --- /dev/null +++ b/examples/nucleo_f439zi/can_m2515/project.xml @@ -0,0 +1,13 @@ + + modm:nucleo-f439zi + + + + + modm:platform:spi:1 + modm:build:scons + modm:processing:protothread + modm:processing:timer + modm:driver:mcp2515 + + \ No newline at end of file diff --git a/src/modm/driver/can/mcp2515.hpp b/src/modm/driver/can/mcp2515.hpp index aef8149df0..6401c9bb5f 100644 --- a/src/modm/driver/can/mcp2515.hpp +++ b/src/modm/driver/can/mcp2515.hpp @@ -20,9 +20,14 @@ #include #include #include +#include +#include +#include +#include #include #include "mcp2515_definitions.hpp" +#include "mcp2515_options.hpp" #ifdef __DOXYGEN__ @@ -116,15 +121,24 @@ namespace modm template < typename SPI, typename CS, typename INT > - class Mcp2515 : public ::modm::Can + class Mcp2515 : public modm::Can, + public modm::SpiDevice, + protected modm::NestedResumable<4> { public: + Mcp2515() : messageBuffer{}, delayS{} { + this->attachConfigurationHandler([]() { + SPI::setDataMode(SPI::DataMode::Mode3); + SPI::setDataOrder(SPI::DataOrder::MsbFirst); + }); + } + template - static inline bool + static bool initialize(); private: - static inline bool + static bool initializeWithPrescaler( uint8_t prescaler, uint8_t sjw, @@ -133,10 +147,10 @@ namespace modm uint8_t ps2); public: - static void + void setFilter(accessor::Flash filter); - static void + void setMode(Can::Mode mode); @@ -144,14 +158,14 @@ namespace modm isMessageAvailable(); static bool - getMessage(can::Message& message); + getMessage(can::Message& message, uint8_t *filter_id=nullptr); /* * The CAN controller has a free slot to send a new message. * * \return true if a slot is available, false otherwise */ - static inline bool + static bool isReadyToSend(); /* @@ -162,18 +176,27 @@ namespace modm static bool sendMessage(const can::Message& message); + /* + * Poll the transmit buffer (should be called periodically) + * + * \return true if a message was send this cycle, false otherwise + */ + modm::ResumableResult + update(); + + public: // Extended Functionality /* * Fixme: Empty implementation, required by connector */ - static BusState + BusState getBusState() { return BusState::Connected; } - protected: + private: enum SpiCommand { RESET = 0xC0, @@ -187,28 +210,59 @@ namespace modm BIT_MODIFY = 0x05 }; + modm::ResumableResult + mcp2515ReadMessage(); + + bool + mcp2515IsReadyToSend(uint8_t status); + + modm::ResumableResult + mcp2515IsReadyToSend(); + + modm::ResumableResult + mcp2515SendMessage(const can::Message& message); + static void writeRegister(uint8_t address, uint8_t data); static uint8_t readRegister(uint8_t address); - static void + void bitModify(uint8_t address, uint8_t mask, uint8_t data); - static uint8_t + modm::ResumableResult readStatus(uint8_t type); - static inline void + modm::ResumableResult writeIdentifier(const uint32_t& identifier, bool isExtendedFrame); - static inline bool + modm::ResumableResult readIdentifier(uint32_t& identifier); - protected: + private: + inline static modm::mcp2515::options::TX_QUEUE txQueue; + inline static modm::mcp2515::options::RX_QUEUE rxQueue; + static SPI spi; static CS chipSelect; static INT interruptPin; + + modm::can::Message messageBuffer; + modm::ShortTimeout delayS; + uint8_t statusBuffer = 0; + uint8_t statusBufferR = 0; + uint8_t statusBufferS = 0; + uint8_t statusBufferReady = 0; + uint8_t addressBufferR = 0; + uint8_t addressBufferS = 0; + uint8_t i, j = 0; + uint8_t a = 0; + uint8_t b = 0; + uint8_t data = 0; + bool readSuccessfulFlag = false; + bool isReadyToSendFlag = false; + bool readIdentifierSuccessfulFlag = false; }; } diff --git a/src/modm/driver/can/mcp2515.lb b/src/modm/driver/can/mcp2515.lb index 845784d7b1..1eff76bb2a 100644 --- a/src/modm/driver/can/mcp2515.lb +++ b/src/modm/driver/can/mcp2515.lb @@ -25,12 +25,28 @@ def prepare(module, options): "is selected according to the clock speed.", default="16MHz")) + module.add_option( + NumericOption( + name="buffer.tx", + description="", + minimum=1, maximum=2 ** 16 - 2, + default=32)) + module.add_option( + NumericOption( + name="buffer.rx", + description="", + minimum=1, maximum=2 ** 16 - 2, + default=32)) + module.depends( ":architecture:accessor", ":architecture:assert", ":architecture:can", ":architecture:clock", ":architecture:delay", + ":architecture:spi.device", + ":processing:protothread", + ":processing:timer", ":debug") return True @@ -41,3 +57,5 @@ def build(env): env.copy("mcp2515_bit_timings.hpp") env.copy("mcp2515_definitions.hpp") env.template("mcp2515.cpp.in") + env.template("mcp2515_options.hpp.in") + diff --git a/src/modm/driver/can/mcp2515_impl.hpp b/src/modm/driver/can/mcp2515_impl.hpp index 9b705897b5..6efc79ce6a 100644 --- a/src/modm/driver/can/mcp2515_impl.hpp +++ b/src/modm/driver/can/mcp2515_impl.hpp @@ -16,25 +16,11 @@ #ifndef MODM_MCP2515_HPP #error "Don't include this file directly, use 'mcp2515.hpp' instead!" #endif - #include "mcp2515_bit_timings.hpp" #include "mcp2515_definitions.hpp" +#include "mcp2515_options.hpp" #include - -#undef MODM_LOG_LEVEL -#define MODM_LOG_LEVEL modm::log::DISABLED - -// ---------------------------------------------------------------------------- -template -SPI modm::Mcp2515::spi; - -template -CS modm::Mcp2515::chipSelect; - -template -INT modm::Mcp2515::interruptPin; - // ---------------------------------------------------------------------------- template @@ -53,18 +39,10 @@ modm::Mcp2515::initializeWithPrescaler( static constexpr uint8_t CNF1_idx = 2; static constexpr uint8_t CNF2_idx = 1; static constexpr uint8_t CNF3_idx = 0; - - MODM_LOG_DEBUG.printf("SJW: %d\nProp: %d\nPS1: %d\nPS2: %d\nprescaler: %d\n", - sjw, prop, ps1, ps2, prescaler); - cnf[CNF1_idx] = ((sjw - 1) << 6) | ((prescaler / 2 - 1) & 0x3f); - cnf[CNF2_idx] = (1 << 7) | ( (ps1 - 1) << 3) | ( (prop - 1) << 0); - cnf[CNF3_idx] = (ps2 - 1); - MODM_LOG_DEBUG.printf("CNF1 %02x, CNF2 %02x, CNF3 %02x\n", cnf[CNF1_idx], cnf[CNF2_idx], cnf[CNF3_idx]); - using namespace mcp2515; // software reset for the mcp2515, after this the chip is back in the @@ -134,11 +112,12 @@ modm::Mcp2515::setFilter(accessor::Flash filter) { using namespace mcp2515; + while(!this->acquireMaster()){}; + // change to configuration mode bitModify(CANCTRL, 0xe0, REQOP2); - while ((readRegister(CANSTAT) & 0xe0) != REQOP2) - ; + while ((readRegister(CANSTAT) & 0xe0) != REQOP2); writeRegister(RXB0CTRL, BUKT); writeRegister(RXB1CTRL, 0); @@ -158,8 +137,10 @@ modm::Mcp2515::setFilter(accessor::Flash filter) } chipSelect.set(); } - + chipSelect.set(); bitModify(CANCTRL, 0xe0, 0); + + while(!this->releaseMaster()); } // ---------------------------------------------------------------------------- @@ -186,124 +167,228 @@ modm::Mcp2515::setMode(Can::Mode mode) } // ---------------------------------------------------------------------------- + template bool modm::Mcp2515::isMessageAvailable() { - return !interruptPin.read(); + return rxQueue.isNotEmpty(); +} + +template +bool +modm::Mcp2515::getMessage(can::Message& message, uint8_t* /*filter_id*/) +{ + if (rxQueue.isEmpty()) + { + // no message in the receive buffer + return false; + } + else { + auto& rxMessage = rxQueue.get(); + memcpy(&message, &rxMessage, sizeof(message)); + rxQueue.pop(); + return true; + } +} + +// ---------------------------------------------------------------------------- +template +bool +modm::Mcp2515::isReadyToSend() +{ + return txQueue.isNotFull(); } // ---------------------------------------------------------------------------- template bool -modm::Mcp2515::getMessage(can::Message& message) +modm::Mcp2515::sendMessage(const can::Message& message) +{ + if (not modm_assert_continue_ignore(txQueue.push(message), "mcp2515.can.tx", + "CAN transmit software buffer overflowed!", 1)) { + /// buffer full, could not send + return false; + } + return true; +} + +// ---------------------------------------------------------------------------- +template +modm::ResumableResult +modm::Mcp2515::mcp2515ReadMessage() { using namespace mcp2515; - uint8_t status = readStatus(RX_STATUS); - uint8_t address; - if (status & FLAG_RXB0_FULL) { - address = READ_RX; // message in buffer 0 + RF_BEGIN(); + + // read status flag of the device + statusBufferR = RF_CALL(readStatus(RX_STATUS)); + + readSuccessfulFlag = true; + if (statusBufferR & FLAG_RXB0_FULL) { + addressBufferR = READ_RX; // message in buffer 0 } - else if (status & FLAG_RXB1_FULL) { - address = READ_RX | 0x04; // message in buffer 1 (RXB1SIDH) + else if (statusBufferR & FLAG_RXB1_FULL) { + addressBufferR = READ_RX | 0x04; // message in buffer 1 (RXB1SIDH) } else { - return false; // Error: no message available + readSuccessfulFlag = false; // Error: no message available } - chipSelect.reset(); - spi.transferBlocking(address); + if(readSuccessfulFlag) + { + RF_WAIT_UNTIL(this->acquireMaster()); + chipSelect.reset(); + RF_CALL(spi.transfer(addressBufferR)); - message.flags.extended = readIdentifier(message.identifier); - if (status & FLAG_RTR) { - message.flags.rtr = true; - } - else { - message.flags.rtr = false; - } - message.length = spi.transferBlocking(0xff) & 0x0f; + messageBuffer.flags.extended = RF_CALL(readIdentifier(messageBuffer.identifier)); + if (statusBufferR & FLAG_RTR) { + messageBuffer.flags.rtr = true; + } + else { + messageBuffer.flags.rtr = false; + } - for (uint8_t i = 0; i < message.length; ++i) { - message.data[i] = spi.transferBlocking(0xff); - } - chipSelect.set(); + messageBuffer.length = RF_CALL(spi.transfer(0xff)) & 0x0f; + for (j = 0; j < messageBuffer.length; ++j) { + data = RF_CALL(spi.transfer(0xff)); + messageBuffer.data[j] = data; + } + RF_WAIT_UNTIL(this->releaseMaster()); + chipSelect.set(); + } // RX0IF or RX1IF respectivly were already cleared automatically by rising CS. // See section 12.4 in datasheet. - return true; + RF_END_RETURN(readSuccessfulFlag); +} + +template +modm::ResumableResult +modm::Mcp2515::update(){ + using namespace mcp2515; + + RF_BEGIN(); + + // check if the device has received a message(pin = LOW) + // if yes: read it and put it into the rxQueue + if(!interruptPin.read()){ + if(RF_CALL(mcp2515ReadMessage())) + { + if(not modm_assert_continue_ignore(rxQueue.push(messageBuffer), "mcp2515.can.tx", + "CAN transmit software buffer overflowed!", 1)){} + } + } + + /// check if device accepts messages and start emptying the transmit queue if not empty + if (txQueue.isNotEmpty()) + { + if(RF_CALL(mcp2515SendMessage(txQueue.get()))){ + txQueue.pop(); + } + } + RF_END(); } // ---------------------------------------------------------------------------- template -bool -modm::Mcp2515::isReadyToSend() +modm::ResumableResult +modm::Mcp2515::mcp2515IsReadyToSend() { using namespace mcp2515; - if ((readStatus(READ_STATUS) & (TXB2CNTRL_TXREQ | TXB1CNTRL_TXREQ | TXB0CNTRL_TXREQ)) == + RF_BEGIN(); + + isReadyToSendFlag = true; + statusBufferReady = RF_CALL(readStatus(READ_STATUS)); + if (( statusBufferReady& (TXB2CNTRL_TXREQ | TXB1CNTRL_TXREQ | TXB0CNTRL_TXREQ)) == (TXB2CNTRL_TXREQ | TXB1CNTRL_TXREQ | TXB0CNTRL_TXREQ)) { // all buffers currently in use - return false; - } - else { - return true; + isReadyToSendFlag = false; } -} - -// ---------------------------------------------------------------------------- + RF_END_RETURN(isReadyToSendFlag); +} template bool -modm::Mcp2515::sendMessage(const can::Message& message) +modm::Mcp2515::mcp2515IsReadyToSend(uint8_t status) { using namespace mcp2515; - - uint8_t status = readStatus(READ_STATUS); - uint8_t address; - if ((status & TXB0CNTRL_TXREQ) == 0) { - address = 0x00; // TXB0SIDH - } - else if ((status & TXB1CNTRL_TXREQ) == 0) { - address = 0x02; // TXB1SIDH - } - else if ((status & TXB2CNTRL_TXREQ) == 0) { - address = 0x04; // TXB2SIDH - } - else { - // all buffer are in use => could not send the message + if ((status & (TXB2CNTRL_TXREQ | TXB1CNTRL_TXREQ | TXB0CNTRL_TXREQ)) == + (TXB2CNTRL_TXREQ | TXB1CNTRL_TXREQ | TXB0CNTRL_TXREQ)) + { + // all buffers currently in use return false; } + return true; +} - chipSelect.reset(); - spi.transferBlocking(WRITE_TX | address); - writeIdentifier(message.identifier, message.flags.extended); +// ---------------------------------------------------------------------------- +template +modm::ResumableResult +modm::Mcp2515::mcp2515SendMessage(const can::Message& message) +{ + using namespace modm::mcp2515; + RF_BEGIN(); - // if the message is a rtr-frame, is has a length but no attached data - if (message.flags.rtr) { - spi.transferBlocking(MCP2515_RTR | message.length); - } - else { - spi.transferBlocking(message.length); + statusBufferS = RF_CALL(readStatus(READ_STATUS)); - for (uint8_t i = 0; i < message.length; ++i) { - spi.transferBlocking(message.data[i]); - } - } - chipSelect.set(); + addressBufferS = static_cast(false); - modm::delay_us(1); + // /// send if ready, else return that nothing was sent + if(mcp2515IsReadyToSend(statusBufferS)) + { + if ((statusBufferS & TXB0CNTRL_TXREQ) == 0) + { + addressBufferS = 0x00; // TXB0SIDH + } else if ((statusBufferS & TXB1CNTRL_TXREQ) == 0) + { + addressBufferS = 0x02; // TXB1SIDH + } else if ((statusBufferS & TXB2CNTRL_TXREQ) == 0) + { + addressBufferS = 0x04; // TXB2SIDH + } else + { + // all buffer are in use => could not send the message + } - // send message via RTS command - chipSelect.reset(); - address = (address == 0) ? 1 : address; // 0 2 4 => 1 2 4 - spi.transferBlocking(RTS | address); - chipSelect.set(); + if (addressBufferS == 0x00 || addressBufferS == 0x02 || addressBufferS == 0x04) + { + RF_WAIT_UNTIL(this->acquireMaster()); + chipSelect.reset(); + RF_CALL(spi.transfer(WRITE_TX | addressBufferS)); + RF_CALL(writeIdentifier(message.identifier, message.flags.extended)); + + // if the message is a rtr-frame, is has a length but no attached data + if (message.flags.rtr) + { + RF_CALL(spi.transfer(MCP2515_RTR | message.length)); + } else + { + RF_CALL(spi.transfer(message.length)); + + for (i = 0; i < message.length; ++i) { + RF_CALL(spi.transfer(message.data[i])); + } + } + delayS.restart(1ms); + chipSelect.set(); + RF_WAIT_UNTIL(delayS.isExpired()); + + // send message via RTS command + chipSelect.reset(); + addressBufferS = (addressBufferS == 0) ? 1 : addressBufferS; // 0 2 4 => 1 2 4 + RF_CALL(spi.transfer(RTS | addressBufferS)); + RF_WAIT_UNTIL(this->releaseMaster()); + chipSelect.set(); + } + } - return address; + RF_END_RETURN(static_cast(addressBufferS)); } // ---------------------------------------------------------------------------- @@ -313,11 +398,9 @@ void modm::Mcp2515::writeRegister(uint8_t address, uint8_t data) { chipSelect.reset(); - spi.transferBlocking(WRITE); spi.transferBlocking(address); spi.transferBlocking(data); - chipSelect.set(); } @@ -326,13 +409,10 @@ uint8_t modm::Mcp2515::readRegister(uint8_t address) { chipSelect.reset(); - spi.transferBlocking(READ); spi.transferBlocking(address); uint8_t data = spi.transferBlocking(0xff); - chipSelect.set(); - return data; } @@ -341,99 +421,105 @@ void modm::Mcp2515::bitModify(uint8_t address, uint8_t mask, uint8_t data) { chipSelect.reset(); - spi.transferBlocking(BIT_MODIFY); spi.transferBlocking(address); spi.transferBlocking(mask); spi.transferBlocking(data); - chipSelect.set(); } template -uint8_t +modm::ResumableResult modm::Mcp2515::readStatus(uint8_t type) { - chipSelect.reset(); - - spi.transferBlocking(type); - uint8_t data = spi.transferBlocking(0xff); + RF_BEGIN(); + RF_WAIT_UNTIL(this->acquireMaster()); + chipSelect.reset(); + RF_CALL(spi.transfer(type)); + statusBuffer = RF_CALL(spi.transfer(0xff)); + RF_WAIT_UNTIL(this->releaseMaster()); chipSelect.set(); - return data; + RF_END_RETURN(statusBuffer); } // ---------------------------------------------------------------------------- template -void +modm::ResumableResult modm::Mcp2515::writeIdentifier(const uint32_t& identifier, bool isExtendedFrame) { using namespace mcp2515; - const uint32_t *ptr = &identifier; + RF_BEGIN(); + + RF_WAIT_UNTIL(this->acquireMaster()); if (isExtendedFrame) { - spi.transferBlocking(*((uint16_t *) ptr + 1) >> 5); + RF_CALL(spi.transfer(*((uint16_t *)ptr + 1) >> 5)); // calculate the next values - uint8_t temp; - temp = (*((uint8_t *) ptr + 2) << 3) & 0xe0; - temp |= MCP2515_IDE; - temp |= (*((uint8_t *) ptr + 2)) & 0x03; - - spi.transferBlocking(temp); - spi.transferBlocking(*((uint8_t *) ptr + 1)); - spi.transferBlocking(*((uint8_t *) ptr)); - } - else + a = (*((uint8_t *)ptr + 2) << 3) & 0xe0; + a |= MCP2515_IDE; + a |= (*((uint8_t *)ptr + 2)) & 0x03; + RF_CALL(spi.transfer(a)); + RF_CALL(spi.transfer(*((uint8_t *)ptr + 1))); + RF_CALL(spi.transfer(*((uint8_t *)ptr))); + } else { - spi.transferBlocking(*((uint16_t *) ptr) >> 3); - spi.transferBlocking(*((uint8_t *) ptr) << 5); - spi.transferBlocking(0); - spi.transferBlocking(0); + RF_CALL(spi.transfer(*((uint16_t *)ptr) >> 3)); + RF_CALL(spi.transfer(*((uint8_t *)ptr) << 5)); + RF_CALL(spi.transfer(0)); + RF_CALL(spi.transfer(0)); } + RF_WAIT_UNTIL(this->releaseMaster()); + + RF_END(); } -template -bool -modm::Mcp2515::readIdentifier(uint32_t& identifier) +template +modm::ResumableResult +modm::Mcp2515::readIdentifier(uint32_t &identifier) { using namespace mcp2515; + const uint32_t *ptr = &identifier; + + RF_BEGIN(); - uint32_t *ptr = &identifier; + RF_WAIT_UNTIL(this->acquireMaster()); + a = RF_CALL(spi.transfer(0xff)); + b = RF_CALL(spi.transfer(0xff)); - uint8_t first = spi.transferBlocking(0xff); - uint8_t second = spi.transferBlocking(0xff); + readIdentifierSuccessfulFlag = false; - if (second & MCP2515_IDE) + if (b & MCP2515_IDE) { - *((uint16_t *) ptr + 1) = (uint16_t) first << 5; - *((uint8_t *) ptr + 1) = spi.transferBlocking(0xff); + *((uint16_t *)ptr + 1) = (uint16_t)a << 5; + *((uint8_t *)ptr + 1) = RF_CALL(spi.transfer(0xff)); - *((uint8_t *) ptr + 2) |= (second >> 3) & 0x1C; - *((uint8_t *) ptr + 2) |= second & 0x03; + *((uint8_t *)ptr + 2) |= (b >> 3) & 0x1C; + *((uint8_t *)ptr + 2) |= b & 0x03; - *((uint8_t *) ptr) = spi.transferBlocking(0xff); + *((uint8_t *)ptr) = RF_CALL(spi.transfer(0xff)); - return true; - } - else + readIdentifierSuccessfulFlag = true; + } else { - spi.transferBlocking(0xff); + RF_CALL(spi.transfer(0xff)); - *((uint8_t *) ptr + 3) = 0; - *((uint8_t *) ptr + 2) = 0; + *((uint8_t *)ptr + 3) = 0; + *((uint8_t *)ptr + 2) = 0; - *((uint16_t *) ptr) = (uint16_t) first << 3; + *((uint16_t *)ptr) = (uint16_t)a << 3; - spi.transferBlocking(0xff); + RF_CALL(spi.transfer(0xff)); - *((uint8_t *) ptr) |= second >> 5; - - return false; + *((uint8_t *)ptr) |= b >> 5; } -} + RF_WAIT_UNTIL(this->releaseMaster()); + + RF_END_RETURN(readIdentifierSuccessfulFlag); +} \ No newline at end of file diff --git a/src/modm/driver/can/mcp2515_options.hpp.in b/src/modm/driver/can/mcp2515_options.hpp.in new file mode 100644 index 0000000000..8353a7b15b --- /dev/null +++ b/src/modm/driver/can/mcp2515_options.hpp.in @@ -0,0 +1,15 @@ + +#ifndef MODM_MCP2515_OPTIONS_HPP +#define MODM_MCP2515_OPTIONS_HPP + +#include + +namespace modm::mcp2515::options +{ + +using TX_QUEUE = modm::atomic::Queue; +using RX_QUEUE = modm::atomic::Queue; + +} // namespace modm::mcp2515::options + +#endif // MODM_MCP2515_OPTIONS_HPP