mirror of
https://github.com/apache/nuttx.git
synced 2026-05-21 13:13:08 +08:00
drivers/can/sja1000: Add SJA1000 CAN driver support
This driver is based on ESP32 TWAI CAN drivers currently available in Nuttx, and captures the differences currently present across the TWAI drivers for easy future adaption to remaining ESP32 platforms with no loss of support/function. Also provides a generic SJA1000 CAN driver solution that is CPU-architecture independent. Changes: - Low-level driver re-written to allow usage independent of CPU architecture, and support both SJA1000 and TWAI CAN controllers. - Platform-specific settings abstracted away to be provided by board layer. - Support for multiple instances of SJA1000 driver.
This commit is contained in:
committed by
Alan Carvalho de Assis
parent
21572864e7
commit
8f9c337c66
+41
-1
@@ -193,4 +193,44 @@ config MCP2515_SPI_SCK_FREQUENCY
|
||||
|
||||
endif # CAN_MCP2515
|
||||
|
||||
endif
|
||||
menuconfig CAN_SJA1000
|
||||
tristate "Philips/NXP SJA1000 devices"
|
||||
|
||||
if CAN_SJA1000
|
||||
|
||||
config CAN_SJA1000_BITRATE
|
||||
int "SJA1000 bitrate"
|
||||
default 1000000
|
||||
---help---
|
||||
SJA1000 bit rate.
|
||||
|
||||
config CAN_SJA1000_SJW
|
||||
int "SJA1000 Synchronization Jump Width"
|
||||
default 1
|
||||
range 1 4
|
||||
---help---
|
||||
The duration of a synchronization jump is SJW.
|
||||
|
||||
config CAN_SJA1000_SAM
|
||||
bool "The CAN bus is sampled 3 times"
|
||||
default false
|
||||
---help---
|
||||
Recommended for low to medium speed buses
|
||||
to filter spikes on the bus-line.
|
||||
|
||||
config CAN_SJA1000_SAMPLEP
|
||||
int "SJA1000 CAN sample point (Percentage)"
|
||||
default 87
|
||||
range 0 100
|
||||
|
||||
config CANBUS_REGDEBUG
|
||||
bool "CAN BUS register debug enable."
|
||||
default false
|
||||
|
||||
config CAN_SJA1000_DEBUG
|
||||
bool "SJA1000 CAN BUS trace debug enable."
|
||||
default false
|
||||
|
||||
endif # CAN_SJA1000
|
||||
|
||||
endif # CAN
|
||||
|
||||
@@ -28,6 +28,10 @@ ifeq ($(CONFIG_CAN_MCP2515),y)
|
||||
CSRCS += mcp2515.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_CAN_SJA1000),y)
|
||||
CSRCS += sja1000.c
|
||||
endif
|
||||
|
||||
# Include CAN device driver build support
|
||||
|
||||
DEPPATH += --dep-path can
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,236 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/can/sja1000.h
|
||||
*
|
||||
* SJA1000 CAN driver based on esp32c3_twai.h
|
||||
*
|
||||
* License header retained from original source.
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_CAN_SJA1000_H
|
||||
#define __INCLUDE_NUTTX_CAN_SJA1000_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* CAN hardware-dependent bit-timing constant
|
||||
*
|
||||
* Used for calculating and checking bit-timing parameters
|
||||
*/
|
||||
|
||||
struct can_bittiming_const_s
|
||||
{
|
||||
char name[16]; /* Name of the CAN controller hardware */
|
||||
uint32_t tseg1_min; /* Time segment 1 = prop_seg + phase_seg1 */
|
||||
uint32_t tseg1_max;
|
||||
uint32_t tseg2_min; /* Time segment 2 = phase_seg2 */
|
||||
uint32_t tseg2_max;
|
||||
uint32_t sjw_max; /* Synchronisation jump width */
|
||||
uint32_t brp_min; /* Bit-rate prescaler */
|
||||
uint32_t brp_max;
|
||||
uint32_t brp_inc;
|
||||
};
|
||||
|
||||
/* Type of the SJA1000 interrupt handling callback */
|
||||
|
||||
struct sja1000_config_s; /* Forward reference */
|
||||
typedef CODE void (*sja1000_handler_t)(FAR struct sja1000_config_s *config,
|
||||
FAR void *arg);
|
||||
|
||||
/* A reference to a structure of this type must be passed to the SJA1000
|
||||
* driver when the driver is instantiated. This structure provides
|
||||
* information about the configuration of the SJA1000 and provides some
|
||||
* board-specific hooks.
|
||||
*
|
||||
* Memory for this structure is provided by the caller. It is not copied by
|
||||
* the driver and is presumed to persist while the driver is active. The
|
||||
* memory must be writeable because, under certain circumstances, the driver
|
||||
* may modify the frequency.
|
||||
*/
|
||||
|
||||
struct sja1000_config_s
|
||||
{
|
||||
/* Device configuration */
|
||||
|
||||
const struct can_bittiming_const_s *bittiming_const;
|
||||
uint8_t port; /* SJA1000 device port number */
|
||||
uint8_t periph; /* Peripheral ID (optional) */
|
||||
uint8_t irq; /* IRQ associated with this SJA1000 */
|
||||
uint8_t cpu; /* CPU ID */
|
||||
int8_t cpuint; /* CPU interrupt assigned to this SJA1000 */
|
||||
uint32_t bitrate; /* Configured bit rate */
|
||||
uint32_t samplep; /* Configured sample point */
|
||||
uint32_t sjw; /* Synchronization jump width */
|
||||
uint32_t clk_freq; /* Peripheral clock frequency */
|
||||
bool loopback; /* Enable loopback mode */
|
||||
bool triple_sample; /* Enable triple-sampling of CAN BUS */
|
||||
|
||||
/* Device characterization */
|
||||
|
||||
/* IRQ/GPIO access callbacks. These operations all hidden behind
|
||||
* callbacks to isolate the driver from differences in GPIO
|
||||
* interrupt handling by varying boards and MCUs.
|
||||
*
|
||||
* attach - Attach interrupt handler to the interrupt
|
||||
* detach - Detach interrupt handler from the interrupt
|
||||
*/
|
||||
|
||||
CODE int (*attach)(FAR struct sja1000_config_s *config,
|
||||
sja1000_handler_t handler, FAR void *arg);
|
||||
CODE int (*detach)(FAR struct sja1000_config_s *config);
|
||||
};
|
||||
|
||||
/* This structure provides the current state of a CAN peripheral */
|
||||
|
||||
struct sja1000_dev_s
|
||||
{
|
||||
FAR struct sja1000_config_s *config; /* The constant configuration */
|
||||
uint8_t filters; /* STD/EXT filter bit allocator. */
|
||||
uint8_t nalloc; /* Number of allocated filters */
|
||||
uint32_t base; /* SJA1000 register base address */
|
||||
|
||||
#ifdef CONFIG_ARCH_HAVE_MULTICPU
|
||||
spinlock_t lock; /* Device specific lock */
|
||||
#endif /* CONFIG_ARCH_HAVE_MULTICPU */
|
||||
|
||||
/* Register read/write callbacks. These operations all hidden behind
|
||||
* callbacks to isolate the driver from differences in register read/write
|
||||
* handling by varying boards and MCUs.
|
||||
*
|
||||
* getreg - Read from a register address
|
||||
* putreg - Write to a register address
|
||||
*/
|
||||
|
||||
CODE uint32_t (*getreg)(struct sja1000_dev_s *sja_priv, uint32_t reg);
|
||||
CODE void (*putreg)(struct sja1000_dev_s *sja_priv, uint32_t reg,
|
||||
uint32_t value);
|
||||
CODE void (*modifyreg32)(struct sja1000_dev_s *sja_priv, uint32_t reg,
|
||||
uint32_t clearbits, uint32_t setbits);
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Inline functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_CAN_SJA1000
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sja1000_getreg
|
||||
*
|
||||
* Description:
|
||||
* Read the value of an SJA1000 register.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - sja1000 lower-half driver context
|
||||
* reg - The SJA1000 register address to read
|
||||
*
|
||||
* Returned Value:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint32_t sja1000_getreg(struct sja1000_dev_s *sja_priv,
|
||||
uint32_t reg)
|
||||
{
|
||||
return sja_priv->getreg(sja_priv, reg);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sja1000_putreg
|
||||
*
|
||||
* Description:
|
||||
* Set the value of an SJA1000 register.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - sja1000 lower-half driver context
|
||||
* reg - The SJA1000 register address to write
|
||||
* value - The value to write to the register
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void sja1000_putreg(struct sja1000_dev_s *sja_priv,
|
||||
uint32_t reg, uint32_t value)
|
||||
{
|
||||
sja_priv->putreg(sja_priv, reg, value);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sja1000_modifyreg32
|
||||
*
|
||||
* Description:
|
||||
* Modify the value of an SJA1000 register.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - sja1000 lower-half driver context
|
||||
* reg - The SJA1000 register address to modify
|
||||
* clearbits - Bitmask of the bits to clear in a register
|
||||
* setbits - Bitmask of the bits to set in a register
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static inline void sja1000_modifyreg32(struct sja1000_dev_s *sja_priv,
|
||||
uint32_t reg, uint32_t clearbits, uint32_t setbits)
|
||||
{
|
||||
sja_priv->modifyreg32(sja_priv, reg, clearbits, setbits);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sja1000_instantiate
|
||||
*
|
||||
* Description:
|
||||
* Initialize the selected SJA1000 CAN Bus Controller
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - An instance of the "lower half" CAN driver state structure.
|
||||
*
|
||||
* Returned Value:
|
||||
* Valid CAN device structure reference on success; a NULL on failure
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct can_dev_s;
|
||||
|
||||
FAR struct can_dev_s *sja1000_instantiate(FAR struct sja1000_dev_s *priv);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* CONFIG_CAN_SJA1000 */
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_CAN_SJA1000_H */
|
||||
Reference in New Issue
Block a user