haitomatic commented on code in PR #17161: URL: https://github.com/apache/nuttx/pull/17161#discussion_r2435267881
########## arch/risc-v/src/mpfs/mpfs_can.c: ########## @@ -0,0 +1,2923 @@ +/**************************************************************************** + * arch/risc-v/src/mpfs/mpfs_can.c + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <sys/time.h> +#include <inttypes.h> +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <time.h> +#include <string.h> +#include <debug.h> +#include <errno.h> + +#include <nuttx/can.h> +#include <nuttx/wdog.h> +#include <nuttx/irq.h> +#include <nuttx/arch.h> +#include <nuttx/wqueue.h> +#include <nuttx/signal.h> +#include <nuttx/net/netdev.h> +#include <nuttx/net/can.h> +#include <nuttx/can/can.h> + +#include <arch/board/board.h> + +#include "mpfs_can.h" +#include "riscv_internal.h" +#include "mpfs_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_MPFS_MSS_CAN +# error This should not be compiled if MSS CAN block is not enabled +#endif + +/* CAN 0 and 1 register base definition */ + +#define CAN0_BASE MPFS_CAN0_LO_BASE +#define CAN1_BASE MPFS_CAN1_LO_BASE + +/* High level driver operational configuration */ + +#define CANWORK HPWORK + +/* For allocating the tx and rx CAN frame buffer */ + +#define POOL_SIZE 1 +#define TIMESTAMP_SIZE sizeof(struct timeval) /* support timestamping frame */ + +/* MSS CAN TX/RX buffer configuration */ + +#define CAN_RX_BUFFER 32 +#define CAN_TX_BUFFER 32 +#define CAN_RX_BUFFER_CTRL_DEFAULT MPFS_CAN_RX_MSG_CTRL_CMD_WPNH \ + | MPFS_CAN_RX_MSG_CTRL_CMD_WPNL \ + | MPFS_CAN_RX_MSG_CTRL_CMD_RX_BUFFER_EBL \ + | MPFS_CAN_RX_MSG_CTRL_CMD_RX_INT_ENABLE + +/* MSS CAN Configuration and Speed definitions */ + +#define CAN_SAMPLE_BOTH_EDGES MPFS_CAN_CAN_CONFIG_EDGE_MODE +#define CAN_THREE_SAMPLES MPFS_CAN_CAN_CONFIG_SAMPLING_MODE +#define CAN_SET_SJW(_sjw) (_sjw << MPFS_CAN_CAN_CONFIG_CFG_SJW_SHIFT) +#define CAN_AUTO_RESTART MPFS_CAN_CAN_CONFIG_AUTO_RESTART +#define CAN_SET_TSEG2(_tseg2) (_tseg2 << MPFS_CAN_CAN_CONFIG_CFG_TSEG2_SHIFT) +#define CAN_SET_TSEG1(_tseg1) (_tseg1 << MPFS_CAN_CAN_CONFIG_CFG_TSEG1_SHIFT) +#define CAN_SET_BITRATE(_br) (_br << MPFS_CAN_CAN_CONFIG_CFG_BITRATE_SHIFT) +#define CAN_ARB_FIXED_PRIO MPFS_CAN_CAN_CONFIG_CFG_ARBITER +#define CAN_LITTLE_ENDIAN MPFS_CAN_CAN_CONFIG_SWAP_ENDIAN + +/* The following constants are used in the PolarFire SoC MSS CAN driver for + * bitrate definitions: + * + * | Constants | Description | + * |--------------------|---------------------------------------------------| + * | CAN_SPEED_8M_5K | Indicates CAN controller shall be configured with | + * | | 5Kbps baud rate if the input clock is 8MHz. | + * | CAN_SPEED_16M_5K | Indicates CAN controller shall be configured with | + * | | 5Kbps baud rate if the input clock is 16MHz. | + * | CAN_SPEED_32M_5K | Indicates CAN controller shall be configured with | + * | | 5Kbps baud rate if the input clock is 32MHz. | + * | CAN_SPEED_8M_10K | Indicates CAN controller shall be configured with | + * | | 10Kbps baud rate if the input clock is 8MHz. | + * | CAN_SPEED_16M_10K | Indicates CAN controller shall be configured with | + * | | 10Kbps baud rate if the input clock is 16MHz. | + * | CAN_SPEED_32M_10K | Indicates CAN controller shall be configured with | + * | | 10Kbps baud rate if the input clock is 32MHz. | + * | CAN_SPEED_8M_20K | Indicates CAN controller shall be configured with | + * | | 20Kbps baud rate if the input clock is 8MHz. | + * | CAN_SPEED_16M_20K | Indicates CAN controller shall be configured with | + * | | 20Kbps baud rate if the input clock is 16MHz. | + * | CAN_SPEED_32M_20K | Indicates CAN controller shall be configured with | + * | | 20Kbps baud rate if the input clock is 32MHz. | + * | CAN_SPEED_8M_50K | Indicates CAN controller shall be configured with | + * | | 50Kbps baud rate if the input clock is 8MHz. | + * | CAN_SPEED_16M_50K | Indicates CAN controller shall be configured with | + * | | 50Kbps baud rate if the input clock is 16MHz. | + * | CAN_SPEED_32M_50K | Indicates CAN controller shall be configured with | + * | | 50Kbps baud rate if the input clock is 32MHz. | + * | CAN_SPEED_8M_100K | Indicates CAN controller shall be configured with | + * | | 100Kbps baud rate if the input clock is 8MHz. | + * | CAN_SPEED_16M_100K | Indicates CAN controller shall be configured with | + * | | 100Kbps baud rate if the input clock is 16MHz. | + * | CAN_SPEED_32M_100K | Indicates CAN controller shall be configured with | + * | | 100Kbps baud rate if the input clock is 32MHz. | + * | CAN_SPEED_8M_125K | Indicates CAN controller shall be configured with | + * | | 125Kbps baud rate if the input clock is 8MHz. | + * | CAN_SPEED_16M_125K | Indicates CAN controller shall be configured with | + * | | 125Kbps baud rate if the input clock is 16MHz. | + * | CAN_SPEED_32M_125K | Indicates CAN controller shall be configured with | + * | | 125Kbps baud rate if the input clock is 32MHz. | + * | CAN_SPEED_8M_250K | Indicates CAN controller shall be configured with | + * | | 250Kbps baud rate if the input clock is 8MHz. | + * | CAN_SPEED_16M_250K | Indicates CAN controller shall be configured with | + * | | 250Kbps baud rate if the input clock is 16MHz. | + * | CAN_SPEED_32M_250K | Indicates CAN controller shall be configured with | + * | | 250Kbps baud rate if the input clock is 32MHz. | + * | CAN_SPEED_8M_500K | Indicates CAN controller shall be configured with | + * | | 500Kbps baud rate if the input clock is 8MHz. | + * | CAN_SPEED_16M_500K | Indicates CAN controller shall be configured with | + * | | 500Kbps baud rate if the input clock is 16MHz. | + * | CAN_SPEED_32M_500K | Indicates CAN controller shall be configured with | + * | | 500Kbps baud rate if the input clock is 32MHz. | + * | CAN_SPEED_8M_1M | Indicates CAN controller shall be configured with | + * | | 1MBPS baud rate if the input clock is 8MHz. | + * | CAN_SPEED_16M_1M | Indicates CAN controller shall be configured with | + * | | 1MBPS baud rate if the input clock is 16MHz. | + * | CAN_SPEED_32M_1M | Indicates CAN controller shall be configured with | + * | | 1MBPS baud rate if the input clock is 32MHz. | + */ + +/* 5000m 81% Sample bit three times */ + +#define CAN_SPEED_8M_5K CAN_SET_BITRATE(99)|CAN_SET_TSEG1(11) \ + |CAN_SET_TSEG2(2)|CAN_THREE_SAMPLES +#define CAN_SPEED_16M_5K CAN_SET_BITRATE(199)|CAN_SET_TSEG1(11) \ + |CAN_SET_TSEG2(2)|CAN_THREE_SAMPLES +#define CAN_SPEED_32M_5K CAN_SET_BITRATE(399)|CAN_SET_TSEG1(11) \ + |CAN_SET_TSEG2(2)|CAN_THREE_SAMPLES + +/* 5000m 81% Sample bit three times */ + +#define CAN_SPEED_8M_10K CAN_SET_BITRATE(49)|CAN_SET_TSEG1(11) \ + |CAN_SET_TSEG2(2)|CAN_THREE_SAMPLES +#define CAN_SPEED_16M_10K CAN_SET_BITRATE(99)|CAN_SET_TSEG1(11) \ + |CAN_SET_TSEG2(2)|CAN_THREE_SAMPLES +#define CAN_SPEED_32M_10K CAN_SET_BITRATE(199)|CAN_SET_TSEG1(11) \ + |CAN_SET_TSEG2(2)|CAN_THREE_SAMPLES + +/* 2500m 81% Sample bit three times */ + +#define CAN_SPEED_8M_20K CAN_SET_BITRATE(24)|CAN_SET_TSEG1(11) \ + |CAN_SET_TSEG2(2)|CAN_THREE_SAMPLES +#define CAN_SPEED_16M_20K CAN_SET_BITRATE(49)|CAN_SET_TSEG1(11) \ + |CAN_SET_TSEG2(2)|CAN_THREE_SAMPLES +#define CAN_SPEED_32M_20K CAN_SET_BITRATE(99)|CAN_SET_TSEG1(11) \ + |CAN_SET_TSEG2(2)|CAN_THREE_SAMPLES + +/* 1000m 87% */ + +#define CAN_SPEED_8M_50K CAN_SET_BITRATE(9)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) +#define CAN_SPEED_16M_50K CAN_SET_BITRATE(19)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) +#define CAN_SPEED_32M_50K CAN_SET_BITRATE(39)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) + +/* 600m 87% */ + +#define CAN_SPEED_8M_100K CAN_SET_BITRATE(4)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) +#define CAN_SPEED_16M_100K CAN_SET_BITRATE(9)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) +#define CAN_SPEED_32M_100K CAN_SET_BITRATE(19)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) + +/* 500m 87% */ + +#define CAN_SPEED_8M_125K CAN_SET_BITRATE(3)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) +#define CAN_SPEED_16M_125K CAN_SET_BITRATE(7)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) +#define CAN_SPEED_32M_125K CAN_SET_BITRATE(15)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) + +/* 250m 87% */ + +#define CAN_SPEED_8M_250K CAN_SET_BITRATE(1)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) +#define CAN_SPEED_16M_250K CAN_SET_BITRATE(3)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) +#define CAN_SPEED_32M_250K CAN_SET_BITRATE(7)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) + +/* 100m 75% @ 8M, 87% @ 16M */ + +#define CAN_SPEED_8M_500K CAN_SET_BITRATE(1)|CAN_SET_TSEG1(4) \ + |CAN_SET_TSEG2(1) +#define CAN_SPEED_16M_500K CAN_SET_BITRATE(1)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) +#define CAN_SPEED_32M_500K CAN_SET_BITRATE(3)|CAN_SET_TSEG1(12) \ + |CAN_SET_TSEG2(1) + +/* 25m 75% */ +#define CAN_SPEED_8M_1M CAN_SET_BITRATE(0)|CAN_SET_TSEG1(4) \ + |CAN_SET_TSEG2(1) +#define CAN_SPEED_16M_1M CAN_SET_BITRATE(1)|CAN_SET_TSEG1(4) \ + |CAN_SET_TSEG2(1) +#define CAN_SPEED_32M_1M CAN_SET_BITRATE(3)|CAN_SET_TSEG1(4) \ + |CAN_SET_TSEG2(1) + +/* The following constants are used for error codes: + * + * | Constants | Description | + * |-----------------------|---------------------------------------------| + * | CAN_OK | Indicates there is no error | + * | CAN_ERR | Indicates error condition | + * | CAN_TSEG1_TOO_SMALL | Value provided to configure TSEG1 is too | + * | | small | + * | CAN_TSEG2_TOO_SMALL | Value provided to configure TSEG2 is too | + * | | small | + * | CAN_SJW_TOO_BIG | Value provided to configure synchronous jump| + * | | width (SJW) is too big. | + * | CAN_BASIC_CAN_BUFFER | Indicates that buffer is configured for | + * | | Basic CAN operation | + * | CAN_NO_RTR_BUFFER | Indicates that there is no buffer for | + * | | remote transmit request (RTR) frame | + * | CAN_INVALID_BUFFER | Indicates invalid buffer number | + * | CAN_NO_MSG | Indicates no message available | + * | CAN_VALID_MSG | Indicates message is valid | + */ + +#define CAN_OK 0 +#define CAN_ERR 1 +#define CAN_TSEG1_TOO_SMALL 2 +#define CAN_TSEG2_TOO_SMALL 3 +#define CAN_SJW_TOO_BIG 4 +#define CAN_BASIC_CAN_BUFFER 5 +#define CAN_NO_RTR_BUFFER 6 +#define CAN_INVALID_BUFFER 7 +#define CAN_NO_MSG 8 +#define CAN_VALID_MSG 0 + +/**************************************************************************** + * Utility definitions + ****************************************************************************/ + +#define print_uint32_t(prefix, val) do { \ + const char p_str[] = prefix; \ + /* prefix + " 0b" + 32 bits + null terminator */ \ + char binary_str[sizeof(p_str) + 2 + 32 + 1]; \ + sprintf(binary_str, "%s 0b", p_str); \ + for (int i = 31; i >= 0; i--) { \ + sprintf(binary_str + strlen(binary_str), "%d", ((val) >> i) & 1); \ + } \ + caninfo("%s", binary_str); \ +} while (0) + +#if __GNUC__ >= 3 +# define expect(expr,value) __builtin_expect((expr),(value)) +#else +# define expect(expr,value) (expr) +#endif + +#define expect_false(expr) expect((expr) != 0, 0) +#define expect_true(expr) expect((expr) != 0, 1) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* The mpfs_can_mode_t enumeration specifies the possible operating modes of + * CAN controller. The meaning of the constants is as described below + * + * | Modes | Description | + * |----------------------------|------------------------------------------| + * | CANOP_MODE_NORMAL | Indicates CAN controller is in normal | + * | | operational mode. | + * | CANOP_MODE_LISTEN_ONLY | Indicates CAN controller is in listen | + * | | only mode. | + * | CANOP_MODE_EXT_LOOPBACK | Indicates CAN controller is in external | + * | | loop back mode. | + * | CANOP_MODE_INT_LOOPBACK | Indicates CAN controller is in internal | + * | | loop back mode. | + * | CANOP_SRAM_TEST_MODE | Indicates CAN controller is in test mode.| + */ + +typedef enum _mpfs_can_mode +{ + CANOP_MODE_NORMAL = MPFS_CAN_CAN_COMMAND_RUN_STOP_MODE, + CANOP_MODE_LISTEN_ONLY = MPFS_CAN_CAN_COMMAND_RUN_STOP_MODE | + MPFS_CAN_CAN_COMMAND_LISTEN_ONLY_MODE, + CANOP_MODE_EXT_LOOPBACK = MPFS_CAN_CAN_COMMAND_RUN_STOP_MODE | + MPFS_CAN_CAN_COMMAND_LOOPBACK_TEST_MODE, + CANOP_MODE_INT_LOOPBACK = MPFS_CAN_CAN_COMMAND_RUN_STOP_MODE | + MPFS_CAN_CAN_COMMAND_LISTEN_ONLY_MODE | + MPFS_CAN_CAN_COMMAND_LOOPBACK_TEST_MODE, + CANOP_SRAM_TEST_MODE = MPFS_CAN_CAN_COMMAND_SRAM_TEST_MODE +} mpfs_can_mode_t; + +/* CAN message object */ + +typedef struct _mpfs_can_msgobject +{ + /* CAN Message flags */ + + uint32_t msg_ctrl; + + /* CAN Message ID. */ + + uint32_t id; + + /* CAN Message Data organized as two 32 bit words */ + + uint32_t data_high; + uint32_t data_low; +} mpfs_can_msgobject_t; + +typedef mpfs_can_msgobject_t * pmpfs_can_msgobject_t; + +/* CAN RX message object */ + +typedef struct _mpfs_can_rxmsgobject +{ + /* CAN Message flags */ + + uint32_t rx_msg_ctrl; + + /* CAN Message ID */ + + uint32_t id; + + /* CAN Message Data organized as two 32 bit words */ + + uint32_t data_high; + uint32_t data_low; + + /* CAN Message Filter: acceptance mask and code */ + + uint32_t amr; + uint32_t acr; + + /* CAN Message Filter: Acceptance mask and code data bits */ + + uint32_t amr_data; + uint32_t acr_data; +} mpfs_can_rxmsgobject_t; + +typedef mpfs_can_rxmsgobject_t * pmpfs_can_rxmsgobject_t; + +/* CAN filter object */ + +typedef struct _can_filterobject +{ + /* Use sw mask filter */ + + bool use_mask_filter; + + /* CAN Message Filter: acceptance mask and code */ + + uint32_t amr; + uint32_t acr; + + /* CAN Message Filter: Acceptance mask and code data bits */ + + uint32_t amr_data; + uint32_t acr_data; +} mpfs_can_filterobject_t; + +/* CAN device statistics */ + +typedef struct _device_stats +{ + volatile uint32_t error_passive; /* Changes to error passive count */ + volatile uint32_t bus_off; /* Changes to bus off count */ + volatile uint32_t arbitration_loss; /* Arbitration loss errors count */ + volatile uint32_t rx_overload; /* Rx overload errors count */ + volatile uint32_t bit_errors; /* Bit errors count */ + volatile uint32_t stuff_errors; /* Stuffing errors count */ + volatile uint32_t ack_errors; /* Ack errors count */ + volatile uint32_t form_errors; /* Form errors count */ + volatile uint32_t crc_errors; /* CRC errors count */ + volatile uint32_t stuck_at_0; /* Stuck at 0 errors count */ + volatile uint32_t restarts; /* CAN controller re-starts count */ + volatile uint32_t txb_sent; /* Tx messages sent count */ +} mpfs_can_device_stats_t; + +/* The structure mpfs_can_instance_t is used by the driver to manage the + * configuration and operation of each MSS CAN peripheral. The instance + * content should only be accessed by using the respective API functions. + * + * Each API function has a pointer to this instance as first argument. + */ + +typedef struct can_instance +{ + uintptr_t reg_base; /* Pointer to CAN base register address */ + + uint32_t bitrate_value; /* The numerical bitrate value in bit/s */ + + bool bifup; /* Indicates if the CAN is up or down. */ + + /* Interrupt handling */ + + uint8_t irqn; /* IRQ number */ + uint32_t isr; /* Interrupt status register */ + + /* Error status and Stats */ + + uint8_t error_status; /* Error status */ + uint32_t tx_err_count; /* Tx error count */ + uint32_t rx_err_count; /* Rx error count */ + mpfs_can_device_stats_t stats; /* Device statistics */ + + /* buffer count */ + + uint8_t basic_can_rxb_count; /* number of rx buffers */ + uint8_t basic_can_txb_count; /* number of tx buffers */ + + /* Frame descriptors */ + + struct can_frame *txdesc; /* Pointer to the transmit frame descriptor. */ + struct can_frame *rxdesc; /* Pointer to the receive frame descriptor. */ + + /* MSS CAN composite message objects */ + + pmpfs_can_msgobject_t tx_msg; /* Pointer to the transmit message object */ + pmpfs_can_msgobject_t rx_msg; /* Pointer to the receive message object */ + + /* Work queue entries */ + + struct work_s rxwork; /* for deferring rx interrupt work to the wq */ + struct work_s txdwork; /* For deferring tx done interrupt work to the wq */ + struct work_s pollwork; /* For deferring poll work to the wq */ + + mpfs_can_filterobject_t filter; /* hardware and software filters */ + + struct net_driver_s dev; /* Interface understood by the Nuttx network */ +} mpfs_can_instance_t; + +/* Driver memory pool */ + +#ifdef CONFIG_MPFS_MSS_CAN0 +static mpfs_can_instance_t g_can0; + +static uint8_t g_tx_pool0[(sizeof(struct can_frame) + TIMESTAMP_SIZE) * + POOL_SIZE] aligned_data(sizeof(uint32_t)); +static uint8_t g_rx_pool0[(sizeof(struct can_frame) + TIMESTAMP_SIZE) * + POOL_SIZE] aligned_data(sizeof(uint32_t)); + +static mpfs_can_msgobject_t g_tx_msg0; +static mpfs_can_msgobject_t g_rx_msg0; +#endif + +#ifdef CONFIG_MPFS_MSS_CAN1 +static mpfs_can_instance_t g_can1; + +static uint8_t g_tx_pool1[(sizeof(struct can_frame) + TIMESTAMP_SIZE) * + POOL_SIZE] aligned_data(sizeof(uint32_t)); +static uint8_t g_rx_pool1[(sizeof(struct can_frame) + TIMESTAMP_SIZE) * + POOL_SIZE] aligned_data(sizeof(uint32_t)); + +static mpfs_can_msgobject_t g_tx_msg1; +static mpfs_can_msgobject_t g_rx_msg1; +#endif + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* (from interrupt) High-level RX related functions */ + +static bool mpfs_can_retrieve_rx_frame(mpfs_can_instance_t *priv, + struct can_frame *cf); +static void mpfs_receive_work(void *arg); + +/* (from interrupt) High-level TX related functions */ + +static void mpfs_txdone_work(void *arg); + +/* High-level periodical TX related functions */ + +static int mpfs_transmit(mpfs_can_instance_t *priv); +static int mpfs_txpoll(struct net_driver_s *dev); +static void mpfs_txavail_work(void *arg); +static int mpfs_txavail(struct net_driver_s *dev); + +/* (from interrupt) High-level error handling related functions */ + +static void mpfs_err_interrupt(mpfs_can_instance_t *priv, uint32_t isr); + +/* Interrupt service routine */ + +static int mpfs_interrupt(int irq, void *context, void *arg); + +/* RX SW/HW filter related functions */ + +#ifdef CONFIG_NETDEV_CAN_FILTER_IOCTL +static uint8_t mpfs_can_add_filter(mpfs_can_instance_t *priv, + uint8_t filter_type, + uint32_t filter_id1, + uint32_t filter_id2); +#endif /* CONFIG_NETDEV_CAN_FILTER_IOCTL */ + +static uint8_t mpfs_can_reset_filter(mpfs_can_instance_t *priv); + +/* CAN controller configuration setter and status getter helper functions */ + +static void mpfs_can_reset(mpfs_can_instance_t *priv); + +static void mpfs_can_set_mode(mpfs_can_instance_t *priv, + mpfs_can_mode_t mode); + +#ifdef CONFIG_DEBUG_CAN_INFO +static uint32_t mpfs_can_get_can_command_reg(mpfs_can_instance_t *priv); + +static uint32_t mpfs_can_get_can_config_reg(mpfs_can_instance_t *priv); +#endif + +static void mpfs_can_set_int_ebl(mpfs_can_instance_t *priv, uint32_t flag); +static void mpfs_can_clear_int_ebl(mpfs_can_instance_t *priv, uint32_t flag); +static uint32_t mpfs_can_get_int_ebl(mpfs_can_instance_t *priv); + +static void mpfs_can_clear_int_status(mpfs_can_instance_t *priv, + uint32_t flag); +static uint32_t mpfs_can_get_int_status(mpfs_can_instance_t *priv); + +static uint8_t mpfs_can_get_error_status(mpfs_can_instance_t *priv); + +#ifdef CONFIG_DEBUG_CAN_INFO +static void mpfs_can_print_status (mpfs_can_instance_t *priv); +#endif + +/* CAN controller life cycle functions */ + +static void mpfs_can_start(mpfs_can_instance_t *priv); +static void mpfs_can_stop(mpfs_can_instance_t *priv); + +/* CAN message helper functions */ + +static uint32_t mpfs_can_canid_to_msgid(uint32_t canid); +static uint32_t mpfs_can_msgid_to_canid(uint32_t id, bool ide, bool rtr); +static uint8_t mpfs_can_set_bitrate(mpfs_can_instance_t *priv, + uint32_t bitrate); +#if defined(CONFIG_DEBUG_CAN_INFO) || defined(CONFIG_NETDEV_CAN_BITRATE_IOCTL) +static uint32_t mpfs_can_get_sample_point(mpfs_can_instance_t *priv); +#endif + +/* CAN message RX buffer setter/getter functions */ + +static uint8_t mpfs_can_config_buffer(mpfs_can_instance_t *priv); + +static uint8_t mpfs_can_config_buffer_n(mpfs_can_instance_t *priv, + uint8_t buffer_number, + pmpfs_can_rxmsgobject_t pmsg); + +static uint8_t mpfs_can_get_message(mpfs_can_instance_t *priv); + +#ifdef CONFIG_DEBUG_CAN_INFO +static uint32_t mpfs_can_get_rx_buffer_status(mpfs_can_instance_t *priv); +#endif + +static uint32_t mpfs_can_get_rx_error_count(mpfs_can_instance_t *priv); + +#ifdef CONFIG_DEBUG_CAN_INFO +static bool mpfs_can_get_rx_gte96(mpfs_can_instance_t *priv); +#endif + +/* CAN message TX buffer setter/getter functions */ + +static uint8_t mpfs_can_send_message_ready(mpfs_can_instance_t *priv); +static uint8_t mpfs_can_send_message(mpfs_can_instance_t *priv); +static uint8_t mpfs_can_send_message_abort(mpfs_can_instance_t *priv); +static uint32_t mpfs_can_get_tx_buffer_status(mpfs_can_instance_t *priv); + +static uint32_t mpfs_can_get_tx_error_count(mpfs_can_instance_t *priv); + +#ifdef CONFIG_DEBUG_CAN_INFO +static bool mpfs_can_get_tx_gte96(mpfs_can_instance_t *priv); +#endif + +/* Driver interface to Nuttx network callbacks */ + +static int mpfs_ifup(struct net_driver_s *dev); +static int mpfs_ifdown(struct net_driver_s *dev); +#ifdef CONFIG_NETDEV_CAN_BITRATE_IOCTL +static int mpfs_ioctl(struct net_driver_s *dev, int cmd, unsigned long arg); +#endif + +/**************************************************************************** + * Private Function + ****************************************************************************/ + +/**************************************************************************** + * Name: mpfs_can_retrieve_rx_frame + * + * Description: + * Retrieve CAN 2.0B frame from RX Buffer + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * cf - Pointer to CAN frame structure + * + * Returned Value: + * This function returns CAN_OK on successful retrieval of CAN frame else + * it returns CAN_ERR + * + * Assumptions: + * Frame format word is already parsed in advance and provided as 'ffw' arg + * + ****************************************************************************/ + +static bool mpfs_can_retrieve_rx_frame(mpfs_can_instance_t *priv, + struct can_frame *cf) +{ + uint8_t dlc; + bool ide; + bool rtr; + pmpfs_can_msgobject_t pmsg = priv->rx_msg; + + /* CAN ID & EFF & RTR Flags */ + + ide = (bool)(pmsg->msg_ctrl & MPFS_CAN_RX_MSG_CTRL_CMD_IDE); + rtr = (bool)(pmsg->msg_ctrl & MPFS_CAN_RX_MSG_CTRL_CMD_RTR); + cf->can_id = mpfs_can_msgid_to_canid(pmsg->id, ide, rtr); + + /* DLC */ + + dlc = (pmsg->msg_ctrl & MPFS_CAN_RX_MSG_CTRL_CMD_DLC) + >> MPFS_CAN_RX_MSG_CTRL_CMD_DLC_SHIFT; + if (dlc <= 8) + { + cf->can_dlc = dlc; + } + else + { + canerr("DLC = %d is out of range\n", dlc); + return CAN_ERR; + } + + /* Data (big endian) */ + + *(uint32_t *)&cf->data[0] = __builtin_bswap32(pmsg->data_high); + *(uint32_t *)&cf->data[4] = __builtin_bswap32(pmsg->data_low); + + return CAN_OK; +} + +/**************************************************************************** + * Name: mpfs_receive_work + * + * Description: + * An interrupt was received indicating the availability of a new RX packet + * + * Input Parameters: + * priv - Pointer to the private CAN driver state structure + * + * Returned Value: + * None + * + * Assumptions: + * Global interrupts are disabled by interrupt handling logic. + * + ****************************************************************************/ + +static void mpfs_receive_work(void *arg) +{ + mpfs_can_instance_t *priv = (mpfs_can_instance_t *)arg; + +#ifdef CONFIG_DEBUG_CAN_INFO Review Comment: right. thanks :+1: -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
