implement CAN driver for simulator (#4312)
* stub simulator CAN driver * comments * CAN sensor * maybe implement? * s * fix * tx and rx actually work!?!?! * check_can_isr * modify chibios * Sim has no CAN on Windows (for now?) * safer init/deinit, enable assertions * smarter handling of missing CAN device * better guards * guards for windows
This commit is contained in:
parent
47b5a03211
commit
a95bc3ad03
|
@ -1 +1 @@
|
|||
Subproject commit eed346d57f80efd78bd4130c7088066a1169d495
|
||||
Subproject commit 4a81e00519e4b592176d974c37abc6249ab5294b
|
|
@ -187,10 +187,6 @@ void setFrankensoConfiguration() {
|
|||
|
||||
// todo: 8.2 or 10k?
|
||||
engineConfiguration->vbattDividerCoeff = ((float) (10 + 33)) / 10 * 2;
|
||||
|
||||
#if EFI_CAN_SUPPORT
|
||||
enableFrankensoCan();
|
||||
#endif /* EFI_CAN_SUPPORT */
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -125,9 +125,5 @@ void setHonda600() {
|
|||
|
||||
// todo: 8.2 or 10k?
|
||||
engineConfiguration->vbattDividerCoeff = ((float) (10 + 33)) / 10 * 2;
|
||||
|
||||
#if EFI_CAN_SUPPORT
|
||||
enableFrankensoCan();
|
||||
#endif /* EFI_CAN_SUPPORT */
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "can_listener.h"
|
||||
#include "can_msg_tx.h"
|
||||
|
||||
#if EFI_PROD_CODE
|
||||
#if EFI_PROD_CODE | EFI_SIMULATOR
|
||||
#define can_msg_t msg_t
|
||||
#define can_sysinterval_t sysinterval_t
|
||||
#define CAN_MSG_OK MSG_OK
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#if !EFI_PROD_CODE || !EFI_CAN_SUPPORT
|
||||
#if EFI_UNIT_TEST || !EFI_CAN_SUPPORT
|
||||
#include "can_mocks.h"
|
||||
#endif // EFI_PROD_CODE
|
||||
|
||||
|
|
|
@ -56,9 +56,11 @@ void CanWrite::PeriodicTask(efitime_t nowNt) {
|
|||
updateDash(cycle);
|
||||
#endif /* DISABLE_CAN_UPDATE_DASH */
|
||||
|
||||
#if EFI_WIDEBAND_FIRMWARE_UPDATE
|
||||
if (engineConfiguration->enableAemXSeries && cycle.isInterval(CI::_50ms)) {
|
||||
sendWidebandInfo();
|
||||
}
|
||||
#endif
|
||||
|
||||
cycleCount++;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,10 @@ static void populateFrame(Sensors1& msg) {
|
|||
msg.aux1 = Sensor::getOrZero(SensorType::AuxTemp1) + PACK_ADD_TEMPERATURE;
|
||||
msg.aux2 = Sensor::getOrZero(SensorType::AuxTemp2) + PACK_ADD_TEMPERATURE;
|
||||
|
||||
#if HAL_USE_ADC
|
||||
msg.mcuTemp = getMCUInternalTemperature();
|
||||
#endif
|
||||
|
||||
msg.fuelLevel = Sensor::getOrZero(SensorType::FuelLevel);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
static bool isCanEnabled = false;
|
||||
|
||||
#if EFI_PROD_CODE
|
||||
|
||||
// Values below calculated with http://www.bittiming.can-wiki.info/
|
||||
// Pick ST micro bxCAN
|
||||
// Clock rate of 42mhz for f4, 54mhz for f7, 80mhz for h7
|
||||
|
@ -120,6 +122,15 @@ static const CANConfig canConfig1000 = {
|
|||
};
|
||||
#endif
|
||||
|
||||
#else // not EFI_PROD_CODE
|
||||
// Nothing to actually set for the simulator's CAN config.
|
||||
// It's impossible to set CAN bitrate from userspace, so we can't set it.
|
||||
static const CANConfig canConfig100;
|
||||
static const CANConfig canConfig250;
|
||||
static const CANConfig canConfig500;
|
||||
static const CANConfig canConfig1000;
|
||||
#endif
|
||||
|
||||
class CanRead final : protected ThreadController<UTILITY_THREAD_STACK_SIZE> {
|
||||
public:
|
||||
CanRead(size_t index)
|
||||
|
@ -238,11 +249,13 @@ void startCanPins() {
|
|||
return;
|
||||
}
|
||||
|
||||
#if EFI_PROD_CODE
|
||||
efiSetPadModeIfConfigurationChanged("CAN TX", canTxPin, PAL_MODE_ALTERNATE(EFI_CAN_TX_AF));
|
||||
efiSetPadModeIfConfigurationChanged("CAN RX", canRxPin, PAL_MODE_ALTERNATE(EFI_CAN_RX_AF));
|
||||
|
||||
efiSetPadModeIfConfigurationChanged("CAN2 TX", can2TxPin, PAL_MODE_ALTERNATE(EFI_CAN_TX_AF));
|
||||
efiSetPadModeIfConfigurationChanged("CAN2 RX", can2RxPin, PAL_MODE_ALTERNATE(EFI_CAN_RX_AF));
|
||||
#endif // EFI_PROD_CODE
|
||||
}
|
||||
|
||||
static const CANConfig * findConfig(can_baudrate_e rate) {
|
||||
|
@ -262,7 +275,7 @@ static const CANConfig * findConfig(can_baudrate_e rate) {
|
|||
}
|
||||
}
|
||||
|
||||
void initCan(void) {
|
||||
void initCan() {
|
||||
addConsoleAction("caninfo", canInfo);
|
||||
|
||||
isCanEnabled = false;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include "efifeatures.h"
|
||||
|
||||
void initCan(void);
|
||||
void initCan();
|
||||
void setCanType(int type);
|
||||
void setCanVss(int type);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include "pch.h"
|
||||
|
||||
#if EFI_CAN_SUPPORT
|
||||
#if EFI_PROD_CODE && EFI_CAN_SUPPORT
|
||||
#include "can_sensor.h"
|
||||
#include "can.h"
|
||||
|
||||
|
@ -50,4 +50,4 @@ void initCanSensors() {
|
|||
registerCanSensor(obdTpsSensor);
|
||||
}
|
||||
}
|
||||
#endif // EFI_CAN_SUPPORT
|
||||
#endif // EFI_PROD_CODE && EFI_CAN_SUPPORT
|
||||
|
|
|
@ -46,7 +46,7 @@ static void deInitOldAnalogInputs() {
|
|||
}
|
||||
|
||||
void initNewSensors() {
|
||||
#if EFI_CAN_SUPPORT
|
||||
#if EFI_PROD_CODE && EFI_CAN_SUPPORT
|
||||
initCanSensors();
|
||||
#endif
|
||||
|
||||
|
|
|
@ -46,8 +46,9 @@ ifeq ($(USE_OPT),)
|
|||
# USE_OPT += -O0 -g
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
USE_OPT += -DEFI_SIM_IS_WINDOWS=1
|
||||
else
|
||||
USE_OPT += -m32
|
||||
USE_OPT += -m32 -DEFI_SIM_IS_WINDOWS=0
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -157,6 +158,7 @@ include $(PROJECT_DIR)/common.mk
|
|||
# setting.
|
||||
CSRC = $(ALLCSRC) \
|
||||
|
||||
|
||||
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
|
||||
# setting.
|
||||
CPPSRC = $(ALLCPPSRC) \
|
||||
|
@ -167,6 +169,7 @@ CPPSRC = $(ALLCPPSRC) \
|
|||
$(CONSOLE_SRC_CPP) \
|
||||
$(DEV_SIMULATOR_SRC_CPP) \
|
||||
simulator/rusEfiFunctionalTest.cpp \
|
||||
simulator/can/hal_can_lld.cpp \
|
||||
simulator/framework.cpp \
|
||||
simulator/boards.cpp \
|
||||
$(TEST_SRC_CPP) \
|
||||
|
@ -183,6 +186,7 @@ INCDIR = . \
|
|||
$(PROJECT_DIR)/hw_layer/drivers/can \
|
||||
${CHIBIOS}/os/various \
|
||||
$(CHIBIOS)/os/hal/lib/streams \
|
||||
simulator/can \
|
||||
simulator
|
||||
|
||||
# List ASM source files here
|
||||
|
|
|
@ -533,7 +533,7 @@
|
|||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_DBG_ENABLE_CHECKS)
|
||||
#define CH_DBG_ENABLE_CHECKS FALSE
|
||||
#define CH_DBG_ENABLE_CHECKS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -545,7 +545,7 @@
|
|||
* @note The default is @p FALSE.
|
||||
*/
|
||||
#if !defined(CH_DBG_ENABLE_ASSERTS)
|
||||
#define CH_DBG_ENABLE_ASSERTS FALSE
|
||||
#define CH_DBG_ENABLE_ASSERTS TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
* @brief Enables the CAN subsystem.
|
||||
*/
|
||||
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
|
||||
#define HAL_USE_CAN FALSE
|
||||
#define HAL_USE_CAN !EFI_SIM_IS_WINDOWS
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hal_can_lld.c
|
||||
* @brief PLATFORM CAN subsystem low level driver source.
|
||||
*
|
||||
* @addtogroup CAN
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
#if (HAL_USE_CAN == TRUE) || defined(__DOXYGEN__)
|
||||
|
||||
#include <linux/can.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <queue>
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief CAN1 driver identifier.
|
||||
*/
|
||||
CANDriver CAND1;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level CAN driver initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void can_lld_init(void) {
|
||||
/* Driver initialization.*/
|
||||
canObjectInit(&CAND1);
|
||||
|
||||
CAND1.sock = -1;
|
||||
}
|
||||
|
||||
static std::vector<CANDriver*> instances;
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the CAN peripheral.
|
||||
*
|
||||
* @param[in] canp pointer to the @p CANDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void can_lld_start(CANDriver *canp) {
|
||||
(void)canp;
|
||||
|
||||
// Check that this device is not already started
|
||||
osalDbgCheck(canp->sock <= 0);
|
||||
|
||||
// Check that a name is set
|
||||
osalDbgCheck(canp->deviceName != nullptr);
|
||||
|
||||
// create socket
|
||||
int sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
|
||||
if (sock < 0) {
|
||||
// TODO: handle
|
||||
return;
|
||||
}
|
||||
|
||||
sockaddr_can addr;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.can_family = AF_CAN;
|
||||
|
||||
{
|
||||
// Determine index of the CAN device with the requested name
|
||||
ifreq ifr;
|
||||
strcpy(ifr.ifr_name, canp->deviceName);
|
||||
ioctl(sock, SIOCGIFINDEX, &ifr);
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
}
|
||||
|
||||
if (bind(sock, (sockaddr*)&addr, sizeof(addr)) < 0) {
|
||||
// TODO: handle
|
||||
return;
|
||||
}
|
||||
|
||||
canp->sock = sock;
|
||||
|
||||
// Initialize the rx queue
|
||||
canp->rx = new std::queue<can_frame>;
|
||||
|
||||
// Add this instance so it will have receive listened to by the "interrupt handler"
|
||||
instances.push_back(canp);
|
||||
|
||||
// TODO: can we even set bitrate from userspace?
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the CAN peripheral.
|
||||
*
|
||||
* @param[in] canp pointer to the @p CANDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void can_lld_stop(CANDriver *canp) {
|
||||
(void)canp;
|
||||
|
||||
// Remove from the "interrupt handler" list
|
||||
std::remove(instances.begin(), instances.end(), canp);
|
||||
|
||||
// Close the socket.
|
||||
close(canp->sock);
|
||||
canp->sock = -1;
|
||||
|
||||
// Free the rx queue
|
||||
delete reinterpret_cast<std::queue<can_frame>*>(canp->rx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines whether a frame can be transmitted.
|
||||
*
|
||||
* @param[in] canp pointer to the @p CANDriver object
|
||||
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
|
||||
*
|
||||
* @return The queue space availability.
|
||||
* @retval false no space in the transmit queue.
|
||||
* @retval true transmit slot available.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox) {
|
||||
(void)canp;
|
||||
(void)mailbox;
|
||||
|
||||
// The queue is practically infinitely deep, so it is always safe to call can_lld_transmit.
|
||||
// Therefore, just return whether or not the CAN interface actually got initialized
|
||||
return canp->sock >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inserts a frame into the transmit queue.
|
||||
*
|
||||
* @param[in] canp pointer to the @p CANDriver object
|
||||
* @param[in] ctfp pointer to the CAN frame to be transmitted
|
||||
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void can_lld_transmit(CANDriver *canp,
|
||||
canmbx_t mailbox,
|
||||
const CANTxFrame *ctfp) {
|
||||
(void)mailbox;
|
||||
|
||||
can_frame frame;
|
||||
|
||||
memcpy(frame.data, ctfp->data8, 8);
|
||||
frame.can_dlc = ctfp->DLC;
|
||||
|
||||
frame.can_id = ctfp->IDE ? ctfp->EID : ctfp->SID;
|
||||
// bit 31 is 1 for extended, 0 for standard
|
||||
frame.can_id |= ctfp->IDE ? (1 << 31) : 0;
|
||||
|
||||
int res = write(canp->sock, &frame, sizeof(frame));
|
||||
|
||||
if (res != sizeof(frame)) {
|
||||
// TODO: handle err
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines whether a frame has been received.
|
||||
*
|
||||
* @param[in] canp pointer to the @p CANDriver object
|
||||
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
|
||||
*
|
||||
* @return The queue space availability.
|
||||
* @retval false no space in the transmit queue.
|
||||
* @retval true transmit slot available.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox) {
|
||||
(void)mailbox;
|
||||
|
||||
// CAN init failed, claim that the queue is full.
|
||||
if (canp->sock < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !reinterpret_cast<std::queue<can_frame>*>(canp->rx)->empty();
|
||||
}
|
||||
|
||||
bool check_can_isr() {
|
||||
bool intOccured = false;
|
||||
|
||||
for (auto canp : instances) {
|
||||
can_frame frame;
|
||||
|
||||
// nonblocking read so it fails instantly in case no frame is queued
|
||||
int result = recv(canp->sock, &frame, sizeof(frame), MSG_DONTWAIT);
|
||||
|
||||
// no frame received, nothing to do
|
||||
if (result != sizeof(frame)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
intOccured = true;
|
||||
|
||||
CH_IRQ_PROLOGUE();
|
||||
reinterpret_cast<std::queue<can_frame>*>(canp->rx)->push(frame);
|
||||
_can_rx_full_isr(canp, 0);
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
return intOccured;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives a frame from the input queue.
|
||||
*
|
||||
* @param[in] canp pointer to the @p CANDriver object
|
||||
* @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox
|
||||
* @param[out] crfp pointer to the buffer where the CAN frame is copied
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void can_lld_receive(CANDriver *canp,
|
||||
canmbx_t mailbox,
|
||||
CANRxFrame *crfp) {
|
||||
(void)mailbox;
|
||||
|
||||
auto queue = reinterpret_cast<std::queue<can_frame>*>(canp->rx);
|
||||
|
||||
can_frame frame = queue->front();
|
||||
queue->pop();
|
||||
|
||||
crfp->DLC = frame.can_dlc;
|
||||
|
||||
memcpy(crfp->data8, frame.data, crfp->DLC);
|
||||
|
||||
// If <8 byte packet, pad with zeroes to avoid spilling stack state or garbage data from the returned frame
|
||||
if (crfp->DLC < 8) {
|
||||
memset(crfp->data8 + crfp->DLC, 0, 8 - crfp->DLC);
|
||||
}
|
||||
|
||||
// SID bits overlap with EID, no reason to copy both, but mask off err/rtr/etc bits
|
||||
crfp->EID = CAN_ERR_MASK & frame.can_id;
|
||||
|
||||
crfp->IDE = (frame.can_id & CAN_EFF_FLAG) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tries to abort an ongoing transmission.
|
||||
*
|
||||
* @param[in] canp pointer to the @p CANDriver object
|
||||
* @param[in] mailbox mailbox number
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void can_lld_abort(CANDriver *canp,
|
||||
canmbx_t mailbox) {
|
||||
(void)canp;
|
||||
(void)mailbox;
|
||||
}
|
||||
|
||||
#endif /* HAL_USE_CAN == TRUE */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,194 @@
|
|||
#ifndef HAL_CAN_LLD_H
|
||||
#define HAL_CAN_LLD_H
|
||||
|
||||
#if HAL_USE_CAN || defined(__DOXYGEN__)
|
||||
|
||||
/**
|
||||
* @brief This switch defines whether the driver implementation supports
|
||||
* a low power switch mode with automatic an wakeup feature.
|
||||
*/
|
||||
#define CAN_SUPPORTS_SLEEP FALSE
|
||||
|
||||
/**
|
||||
* @brief This implementation supports three transmit mailboxes.
|
||||
*/
|
||||
#define CAN_TX_MAILBOXES 1
|
||||
|
||||
/**
|
||||
* @brief This implementation supports two receive mailboxes.
|
||||
*/
|
||||
#define CAN_RX_MAILBOXES 1
|
||||
|
||||
#define CAN_BTR_BRP(n) (n) /**< @brief BRP field macro.*/
|
||||
#define CAN_BTR_TS1(n) ((n) << 16) /**< @brief TS1 field macro.*/
|
||||
#define CAN_BTR_TS2(n) ((n) << 20) /**< @brief TS2 field macro.*/
|
||||
#define CAN_BTR_SJW(n) ((n) << 24) /**< @brief SJW field macro.*/
|
||||
|
||||
#define CAN_IDE_STD 0 /**< @brief Standard id. */
|
||||
#define CAN_IDE_EXT 1 /**< @brief Extended id. */
|
||||
|
||||
#define CAN_RTR_DATA 0 /**< @brief Data frame. */
|
||||
#define CAN_RTR_REMOTE 1 /**< @brief Remote frame. */
|
||||
|
||||
|
||||
typedef uint32_t canmbx_t;
|
||||
|
||||
typedef struct CANDriver CANDriver;
|
||||
|
||||
typedef struct { } CANConfig;
|
||||
|
||||
struct CANDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
canstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const CANConfig *config;
|
||||
/**
|
||||
* @brief Transmission threads queue.
|
||||
*/
|
||||
threads_queue_t txqueue;
|
||||
/**
|
||||
* @brief Receive threads queue.
|
||||
*/
|
||||
threads_queue_t rxqueue;
|
||||
#if (CAN_ENFORCE_USE_CALLBACKS == FALSE) || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief One or more frames become available.
|
||||
* @note After broadcasting this event it will not be broadcasted again
|
||||
* until the received frames queue has been completely emptied. It
|
||||
* is <b>not</b> broadcasted for each received frame. It is
|
||||
* responsibility of the application to empty the queue by
|
||||
* repeatedly invoking @p canReceive() when listening to this event.
|
||||
* This behavior minimizes the interrupt served by the system
|
||||
* because CAN traffic.
|
||||
* @note The flags associated to the listeners will indicate which
|
||||
* receive mailboxes become non-empty.
|
||||
*/
|
||||
event_source_t rxfull_event;
|
||||
/**
|
||||
* @brief One or more transmission mailbox become available.
|
||||
* @note The flags associated to the listeners will indicate which
|
||||
* transmit mailboxes become empty.
|
||||
* @note The upper 16 bits are transmission error flags associated
|
||||
* to the transmit mailboxes.
|
||||
*/
|
||||
event_source_t txempty_event;
|
||||
/**
|
||||
* @brief A CAN bus error happened.
|
||||
* @note The flags associated to the listeners will indicate that
|
||||
* receive error(s) have occurred.
|
||||
* @note In this implementation the upper 16 bits are filled with the
|
||||
* unprocessed content of the ESR register.
|
||||
*/
|
||||
event_source_t error_event;
|
||||
#else /* CAN_ENFORCE_USE_CALLBACKS == TRUE */
|
||||
/**
|
||||
* @brief One or more frames become available.
|
||||
* @note After calling this function it will not be called again
|
||||
* until the received frames queue has been completely emptied. It
|
||||
* is <b>not</b> called for each received frame. It is
|
||||
* responsibility of the application to empty the queue by
|
||||
* repeatedly invoking @p chTryReceiveI().
|
||||
* This behavior minimizes the interrupt served by the system
|
||||
* because CAN traffic.
|
||||
*/
|
||||
can_callback_t rxfull_cb;
|
||||
/**
|
||||
* @brief One or more transmission mailbox become available.
|
||||
* @note The flags associated to the callback will indicate which
|
||||
* transmit mailboxes become empty.
|
||||
*/
|
||||
can_callback_t txempty_cb;
|
||||
/**
|
||||
* @brief A CAN bus error happened.
|
||||
*/
|
||||
can_callback_t error_cb;
|
||||
#endif
|
||||
|
||||
const char* deviceName;
|
||||
|
||||
int sock;
|
||||
|
||||
// This contains a std::queue of received frames
|
||||
void* rx;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
uint8_t DLC:4; /**< @brief Data length. */
|
||||
uint8_t RTR:1; /**< @brief Frame type. */
|
||||
uint8_t IDE:1; /**< @brief Identifier type. */
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint32_t SID:11; /**< @brief Standard identifier.*/
|
||||
};
|
||||
struct {
|
||||
uint32_t EID:29; /**< @brief Extended identifier.*/
|
||||
};
|
||||
};
|
||||
union {
|
||||
uint8_t data8[8]; /**< @brief Frame data. */
|
||||
uint16_t data16[4]; /**< @brief Frame data. */
|
||||
uint32_t data32[2]; /**< @brief Frame data. */
|
||||
uint64_t data64[1]; /**< @brief Frame data. */
|
||||
};
|
||||
} CANTxFrame;
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
uint8_t FMI; /**< @brief Filter id. */
|
||||
uint16_t TIME; /**< @brief Time stamp. */
|
||||
};
|
||||
struct {
|
||||
uint8_t DLC:4; /**< @brief Data length. */
|
||||
uint8_t RTR:1; /**< @brief Frame type. */
|
||||
uint8_t IDE:1; /**< @brief Identifier type. */
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint32_t SID:11; /**< @brief Standard identifier.*/
|
||||
};
|
||||
struct {
|
||||
uint32_t EID:29; /**< @brief Extended identifier.*/
|
||||
};
|
||||
};
|
||||
union {
|
||||
uint8_t data8[8]; /**< @brief Frame data. */
|
||||
uint16_t data16[4]; /**< @brief Frame data. */
|
||||
uint32_t data32[2]; /**< @brief Frame data. */
|
||||
uint64_t data64[1]; /**< @brief Frame data. */
|
||||
};
|
||||
} CANRxFrame;
|
||||
|
||||
extern CANDriver CAND1;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void can_lld_init(void);
|
||||
void can_lld_start(CANDriver *canp);
|
||||
void can_lld_stop(CANDriver *canp);
|
||||
bool can_lld_is_tx_empty(CANDriver *canp, canmbx_t mailbox);
|
||||
void can_lld_transmit(CANDriver *canp,
|
||||
canmbx_t mailbox,
|
||||
const CANTxFrame *crfp);
|
||||
bool can_lld_is_rx_nonempty(CANDriver *canp, canmbx_t mailbox);
|
||||
void can_lld_receive(CANDriver *canp,
|
||||
canmbx_t mailbox,
|
||||
CANRxFrame *ctfp);
|
||||
void can_lld_abort(CANDriver *canp,
|
||||
canmbx_t mailbox);
|
||||
|
||||
// Called from _sim_check_for_interrupts
|
||||
bool check_can_isr(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // HAL_USE_CAN
|
||||
|
||||
#endif // HAL_CAN_LLD_H
|
|
@ -96,7 +96,11 @@
|
|||
#define EFI_MAIN_RELAY_CONTROL FALSE
|
||||
#define EFI_HIP_9011 TRUE
|
||||
#define EFI_CJ125 TRUE
|
||||
#define EFI_CAN_SUPPORT FALSE
|
||||
|
||||
// Simulator supports real CAN, but not on Windows (yet?)
|
||||
#define EFI_CAN_SUPPORT !EFI_SIM_IS_WINDOWS
|
||||
|
||||
#define EFI_WIDEBAND_FIRMWARE_UPDATE TRUE
|
||||
#define EFI_MAX_31855 FALSE
|
||||
|
||||
#define EFI_ELECTRONIC_THROTTLE_BODY TRUE
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "chprintf.h"
|
||||
#include "cli_registry.h"
|
||||
#include "eficonsole.h"
|
||||
#include <ch.hpp>
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define hasOsPanicError() (FALSE)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#if HAL_USE_CAN
|
||||
CANDriver* detectCanDevice(brain_pin_e pinRx, brain_pin_e pinTx);
|
||||
bool isValidCanTxPin(brain_pin_e) { return true; }
|
||||
bool isValidCanRxPin(brain_pin_e) { return true; }
|
||||
#endif // HAL_USE_CAN
|
|
@ -24,6 +24,7 @@
|
|||
#include "memstreams.h"
|
||||
#include <chprintf.h>
|
||||
#include "rusefi_lua.h"
|
||||
#include "can_hw.h"
|
||||
|
||||
#define DEFAULT_SIM_RPM 1200
|
||||
#define DEFAULT_SNIFFER_THR 2500
|
||||
|
@ -115,6 +116,15 @@ void rusEfiFunctionalTest(void) {
|
|||
|
||||
startSerialChannels();
|
||||
|
||||
engineConfiguration->enableVerboseCanTx = true;
|
||||
|
||||
#if HAL_USE_CAN
|
||||
// Set CAN device name
|
||||
CAND1.deviceName = "can0";
|
||||
|
||||
initCan();
|
||||
#endif // HAL_USE_CAN
|
||||
|
||||
startLua();
|
||||
|
||||
extern bool main_loop_started;
|
||||
|
@ -150,3 +160,15 @@ void logMsg(const char *format, ...) {
|
|||
//
|
||||
// fclose(fp);
|
||||
}
|
||||
|
||||
#if HAL_USE_CAN
|
||||
static bool didInitCan = false;
|
||||
CANDriver* detectCanDevice(brain_pin_e pinRx, brain_pin_e pinTx) {
|
||||
if (didInitCan) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
didInitCan = true;
|
||||
return &CAND1;
|
||||
}
|
||||
#endif // HAL_USE_CAN
|
||||
|
|
Loading…
Reference in New Issue