apm32f103 fit can & uvcan with no shell

This commit is contained in:
hyl 2024-12-11 18:56:08 +08:00
parent d0e822c757
commit 3f08641909
39 changed files with 12748 additions and 431 deletions

View File

@ -18,6 +18,7 @@
* @date: 2023/2/17
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <transform.h>
#ifdef ADD_XIZI_FEATURES
@ -84,4 +85,51 @@ void TestCAN(void)
}
PRIV_SHELL_CMD_FUNCTION(TestCAN, a can test sample, PRIV_SHELL_CMD_MAIN_ATTR);
void func_can(void)
{
int test2=0;
KPrintf("%p\n", &test2);
}
void TestcanMain(void)
{
KTaskDescriptorType task = NONE;
task = GetKTaskDescriptor();
KPrintf("TestcanMain task %x \n", task);
KPrintf("TestcanMain task->Done %x \n", task->Done);
int can_fd;
KPrintf("Address of can_fd: %p\n", &can_fd);
struct PrivIoctlCfg ioctl_cfg;
KPrintf("Address of ioctl_cfg: %p\n", &ioctl_cfg);
struct CanDriverConfigure can_config;
KPrintf("Address of can_config: %p\n", &can_config);
uint8_t data_buff[64u] = {1,2,3,4,4,3,2,1};
KPrintf("Address of data_buff: %p %ps\n", &data_buff, &data_buff[1]);
struct CanSendConfigure frame_send;
KPrintf("Address of frame_send: %p\n", &frame_send);
struct CanSendConfigure frame_recv;
KPrintf("Address of frame_recv: %p\n", &frame_recv);
uint8_t recv_buff[65U] = {0};
KPrintf("Address of recv_buff: %p\n", &recv_buff);
func_can();
KPrintf("add of func %p\n", func_can);
int *test;
test = malloc(sizeof(int)*10);
task = GetKTaskDescriptor();
KPrintf("TestcanMain task %x \n", task);
KPrintf("TestcanMain task->Done %x \n", task->Done);
}
PRIV_SHELL_CMD_FUNCTION(TestcanMain, a shell CAN sample 1, PRIV_SHELL_CMD_MAIN_ATTR);
#endif

View File

@ -20,8 +20,11 @@ extern int FrameworkInit();
extern void ApplicationOtaTaskInit(void);
int main(void)
{
printf("Hello, world! \n");
int i=0;
KPrintf("main KPrintf1\n");
printf("Hello, world! %p\n",&i);
FrameworkInit();
TestcanMain();
#ifdef APPLICATION_OTA
ApplicationOtaTaskInit();
#endif

View File

@ -96,10 +96,10 @@ InterruptVectors:
.word IsrEntry
.word IsrEntry
.word IsrEntry
.word IsrEntry
.word IsrEntry
.word IsrEntry
.word IsrEntry
.word IsrEntry // CAN1 CAN1_TX_IRQHandler
.word USB_LP_CAN1_RX0_IRQHandler // CAN1 0
.word IsrEntry // CAN1 1 CAN1_RX1_IRQHandler
.word IsrEntry // CAN1 CAN1_SCE_IRQHandler
.word IsrEntry
.word IsrEntry
.word IsrEntry

View File

@ -92,5 +92,7 @@ void InitBoardHardware()
InitBoardMemory((void*)HEAP_START, (void*)HEAP_END);
InstallConsole(KERNEL_CONSOLE_BUS_NAME, KERNEL_CONSOLE_DRV_NAME, KERNEL_CONSOLE_DEVICE_NAME);
#ifdef BSP_USING_CAN
InitHwCan();
#endif // BSP_USING_CAN
}

View File

@ -23,6 +23,9 @@
#include <stm32f1xx.h>
#include <connect_uart.h>
#ifdef BSP_USING_CAN
#include <connect_can.h>
#endif // BSP_USING_CAN
extern void *__bss_end;
extern void *_heap_end;

View File

@ -0,0 +1,290 @@
#
# Automatically generated file; DO NOT EDIT.
# XiZi_IIoT Project Configuration
#
CONFIG_BOARD_STM32F103_NANO=y
CONFIG_ARCH_ARM=y
#
# stm32f103-nano feature
#
CONFIG_BSP_USING_UART=y
# CONFIG_BSP_USING_UART1 is not set
CONFIG_BSP_USING_UART2=y
CONFIG_SERIAL_BUS_NAME_2="uart2"
CONFIG_SERIAL_DRV_NAME_2="uart2_drv"
CONFIG_SERIAL_2_DEVICE_NAME_0="uart2_dev2"
CONFIG_BSP_USING_CAN=y
CONFIG_CAN_BUS_NAME_1="can1"
CONFIG_CAN_DRIVER_NAME="can1_drv"
CONFIG_CAN_1_DEVICE_NAME_1="can1_dev1"
#
# config default board resources
#
#
# config board app name
#
CONFIG_BOARD_APP_NAME="/XiUOS_stm32f103nano_app.bin"
#
# config board service table
#
CONFIG_SERVICE_TABLE_ADDRESS=0x20000000
#
# Hardware feature
#
CONFIG_RESOURCES_SERIAL=y
# CONFIG_SERIAL_USING_DMA is not set
CONFIG_SERIAL_RB_BUFSZ=128
CONFIG_RESOURCES_CAN=y
#
# Kernel feature
#
#
# separate compile(choose none for compile once)
#
# CONFIG_SEPARATE_COMPILE is not set
# CONFIG_COMPILER_APP is not set
# CONFIG_APP_STARTUP_FROM_SDCARD is not set
CONFIG_APP_STARTUP_FROM_FLASH=y
# CONFIG_COMPILER_KERNEL is not set
#
# Memory Management
#
# CONFIG_KERNEL_MEMBLOCK is not set
CONFIG_MEM_ALIGN_SIZE=8
# CONFIG_MEM_EXTERN_SRAM is not set
CONFIG_MM_PAGE_SIZE=4096
#
# Using small memory allocator
#
CONFIG_KERNEL_SMALL_MEM_ALLOC=y
CONFIG_SMALL_NUMBER_32B=64
CONFIG_SMALL_NUMBER_64B=32
#
# Task feature
#
CONFIG_USER_APPLICATION=y
# CONFIG_TASK_ISOLATION is not set
#
# Inter-Task communication
#
CONFIG_KERNEL_SEMAPHORE=y
CONFIG_KERNEL_MUTEX=y
CONFIG_KERNEL_EVENT=y
CONFIG_KERNEL_MESSAGEQUEUE=y
CONFIG_KERNEL_SOFTTIMER=y
CONFIG_SCHED_POLICY_RR_REMAINSLICE=y
# CONFIG_SCHED_POLICY_RR is not set
# CONFIG_SCHED_POLICY_FIFO is not set
# CONFIG_KTASK_PRIORITY_8 is not set
CONFIG_KTASK_PRIORITY_32=y
# CONFIG_KTASK_PRIORITY_256 is not set
CONFIG_KTASK_PRIORITY_MAX=32
CONFIG_TICK_PER_SECOND=1000
CONFIG_KERNEL_STACK_OVERFLOW_CHECK=y
CONFIG_IDLE_KTASK_STACKSIZE=256
CONFIG_ZOMBIE_KTASK_STACKSIZE=512
#
# Kernel Console
#
CONFIG_KERNEL_CONSOLE=y
CONFIG_KERNEL_BANNER=y
CONFIG_KERNEL_CONSOLEBUF_SIZE=128
#
# Kernel Hook
#
# CONFIG_KERNEL_HOOK is not set
#
# Command shell
#
CONFIG_TOOL_SHELL=y
CONFIG_SHELL_ENTER_CR=y
CONFIG_SHELL_ENTER_LF=y
CONFIG_SHELL_ENTER_CR_AND_LF=y
# CONFIG_SHELL_ENTER_CRLF is not set
#
# Set shell user control
#
CONFIG_SHELL_DEFAULT_USER="letter"
CONFIG_SHELL_DEFAULT_USER_PASSWORD=""
CONFIG_SHELL_LOCK_TIMEOUT=10000
#
# Set shell config param
#
CONFIG_SHELL_TASK_STACK_SIZE=512
CONFIG_SHELL_TASK_PRIORITY=20
CONFIG_SHELL_MAX_NUMBER=5
CONFIG_SHELL_PARAMETER_MAX_NUMBER=8
CONFIG_SHELL_HISTORY_MAX_NUMBER=5
CONFIG_SHELL_PRINT_BUFFER=128
CONFIG_SHELL_HELP_SHOW_PERMISSION=y
# CONFIG_SHELL_HELP_LIST_USER is not set
# CONFIG_SHELL_HELP_LIST_VAR is not set
# CONFIG_SHELL_HELP_LIST_KEY is not set
#
# Kernel data structure Manage
#
CONFIG_KERNEL_QUEUEMANAGE=y
CONFIG_KERNEL_WORKQUEUE=y
CONFIG_WORKQUEUE_KTASK_STACKSIZE=2048
CONFIG_WORKQUEUE_KTASK_PRIORITY=23
CONFIG_QUEUE_MAX=16
CONFIG_KERNEL_WAITQUEUE=y
CONFIG_KERNEL_DATAQUEUE=y
# CONFIG_KERNEL_CIRCULAR_AREA is not set
# CONFIG_KERNEL_AVL_TREE is not set
#
# Kernel components init
#
CONFIG_KERNEL_COMPONENTS_INIT=y
CONFIG_ENV_INIT_KTASK_STACK_SIZE=512
CONFIG_KERNEL_USER_MAIN=y
CONFIG_NAME_NUM_MAX=32
# CONFIG_KERNEL_DEBUG is not set
# CONFIG_ARCH_SMP is not set
#
# hash table config
#
CONFIG_ID_HTABLE_SIZE=16
CONFIG_ID_NUM_MAX=128
# CONFIG_KERNEL_TEST is not set
#
# Kernel Lib
#
CONFIG_LIB=y
CONFIG_LIB_POSIX=y
CONFIG_LIB_NEWLIB=y
# CONFIG_LIB_MUSLLIB is not set
# CONFIG_LIB_OTHER is not set
#
# C++ features
#
# CONFIG_LIB_CPLUSPLUS is not set
#
# File system
#
# CONFIG_FS_VFS is not set
#
# Tool feature
#
#
# OTA function
#
# CONFIG_TOOL_USING_OTA is not set
#
# APP_Framework
#
#
# Framework
#
CONFIG_TRANSFORM_LAYER_ATTRIUBUTE=y
CONFIG_ADD_XIZI_FEATURES=y
# CONFIG_ADD_NUTTX_FEATURES is not set
# CONFIG_ADD_RTTHREAD_FEATURES is not set
# CONFIG_SUPPORT_SENSOR_FRAMEWORK is not set
# CONFIG_SUPPORT_CONNECTION_FRAMEWORK is not set
# CONFIG_SUPPORT_KNOWING_FRAMEWORK is not set
# CONFIG_SUPPORT_CONTROL_FRAMEWORK is not set
#
# Security
#
# CONFIG_CRYPTO is not set
# CONFIG_MBEDTLS is not set
#
# Applications
#
#
# config stack size and priority of main task
#
CONFIG_MAIN_KTASK_STACK_SIZE=256
CONFIG_MAIN_KTASK_PRIORITY=16
#
# ota app
#
# CONFIG_APPLICATION_OTA is not set
#
# test app
#
# CONFIG_USER_TEST is not set
#
# connection app
#
# CONFIG_APPLICATION_CONNECTION is not set
#
# control app
#
#
# knowing app
#
# CONFIG_APPLICATION_KNOWING is not set
#
# sensor app
#
# CONFIG_APPLICATION_SENSOR is not set
# CONFIG_USING_EMBEDDED_DATABASE_APP is not set
# CONFIG_APP_USING_WEBNET is not set
#
# app lib
#
CONFIG_APP_SELECT_NEWLIB=y
# CONFIG_APP_SELECT_OTHER_LIB is not set
#
# lib using cJSON
#
# CONFIG_LIB_USING_CJSON is not set
#
# lib using queue
#
# CONFIG_LIB_USING_QUEUE is not set
#
# lib using LVGL
#
# CONFIG_LIB_LV is not set
#
# lib using embedded_database
#
# CONFIG_USING_EMBEDDED_DATABASE is not set
#
# lib using LoRaWan
#
# CONFIG_LIB_USING_LORAWAN is not set

View File

@ -5,7 +5,7 @@
/* Program Entry, set to mark it as "used" and avoid gc */
MEMORY
{
flash (rx) : ORIGIN = 0x08004000, LENGTH = 112k /* 128KB flash */
flash (rx) : ORIGIN = 0x08000000, LENGTH = 128k /* 128KB flash */
sram (rw) : ORIGIN = 0x20000000, LENGTH = 20k /* 20K sram */
}
OUTPUT_ARCH(arm)

View File

@ -5,3 +5,12 @@ select RESOURCES_SERIAL
if BSP_USING_UART
source "$BSP_DIR/third_party_driver/uart/Kconfig"
endif
menuconfig BSP_USING_CAN
bool "Using CAN device"
default y
select RESOURCES_CAN
if BSP_USING_CAN
source "$BSP_DIR/third_party_driver/can/Kconfig"
endif

View File

@ -3,6 +3,7 @@ SRC_DIR := libraries
ifeq ($(CONFIG_BSP_USING_UART),y)
SRC_DIR += uart
SRC_DIR += common
SRC_DIR += can
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,30 +1,11 @@
menuconfig BSP_USING_CAN
bool "Enable UART1"
default y
if BSP_USING_UART1
config SERIAL_BUS_NAME_1
string "serial bus 1 name"
default "uart1"
config SERIAL_DRV_NAME_1
string "serial bus 1 driver name"
default "uart1_drv"
config SERIAL_1_DEVICE_NAME_0
string "serial bus 1 device name"
default "uart1_dev1"
endif
config CAN_BUS_NAME_1
string "can bus name"
default "can1"
menuconfig BSP_USING_UART2
bool "Enable UART2"
default n
if BSP_USING_UART2
config SERIAL_BUS_NAME_2
string "serial bus 2 name"
default "uart2"
config SERIAL_DRV_NAME_2
string "serial bus 2 driver name"
default "uart2_drv"
config SERIAL_2_DEVICE_NAME_0
string "serial bus 2 device name"
default "uart2_dev2"
endif
config CAN_DRIVER_NAME
string "can driver name"
default "can1_drv"
config CAN_1_DEVICE_NAME_1
string "can bus 1 device 1 name"
default "can1_dev1"

View File

@ -0,0 +1,4 @@
SRC_FILES := connect_can.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -1,438 +1,285 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_uart.c
* @brief support stm32f103_nano board uart function and register to bus framework
* @version 1.1
* @author AIIT XUOS Lab
* @date 2021-11-25
*/
#include <board.h>
#include <connect_uart.h>
#include <connect_can.h>
#ifdef BSP_USING_UART1
static struct SerialBus serial_bus_1;
static struct SerialDriver serial_driver_1;
static struct SerialHardwareDevice serial_device_1;
#endif
#ifdef BSP_USING_UART2
static struct SerialBus serial_bus_2;
static struct SerialDriver serial_driver_2;
static struct SerialHardwareDevice serial_device_2;
#endif
// #ifdef BSP_USING_CAN1 - TODO change to struct Stm32Can
static void SerialCfgParamCheck(struct SerialCfgParam *serial_cfg_default, struct SerialCfgParam *serial_cfg_new)
{
struct SerialDataCfg *data_cfg_default = &serial_cfg_default->data_cfg;
struct SerialDataCfg *data_cfg_new = &serial_cfg_new->data_cfg;
static struct Stm32Can *stm32_can1;
if ((data_cfg_default->serial_baud_rate != data_cfg_new->serial_baud_rate) && (data_cfg_new->serial_baud_rate)) {
data_cfg_default->serial_baud_rate = data_cfg_new->serial_baud_rate;
}
// #endif // BSP_USING_CAN1
if ((data_cfg_default->serial_bit_order != data_cfg_new->serial_bit_order) && (data_cfg_new->serial_bit_order)) {
data_cfg_default->serial_bit_order = data_cfg_new->serial_bit_order;
}
if ((data_cfg_default->serial_buffer_size != data_cfg_new->serial_buffer_size) && (data_cfg_new->serial_buffer_size)) {
data_cfg_default->serial_buffer_size = data_cfg_new->serial_buffer_size;
}
if ((data_cfg_default->serial_data_bits != data_cfg_new->serial_data_bits) && (data_cfg_new->serial_data_bits)) {
data_cfg_default->serial_data_bits = data_cfg_new->serial_data_bits;
}
if ((data_cfg_default->serial_invert_mode != data_cfg_new->serial_invert_mode) && (data_cfg_new->serial_invert_mode)) {
data_cfg_default->serial_invert_mode = data_cfg_new->serial_invert_mode;
}
if ((data_cfg_default->serial_parity_mode != data_cfg_new->serial_parity_mode) && (data_cfg_new->serial_parity_mode)) {
data_cfg_default->serial_parity_mode = data_cfg_new->serial_parity_mode;
}
if ((data_cfg_default->serial_stop_bits != data_cfg_new->serial_stop_bits) && (data_cfg_new->serial_stop_bits)) {
data_cfg_default->serial_stop_bits = data_cfg_new->serial_stop_bits;
}
if ((data_cfg_default->serial_timeout != data_cfg_new->serial_timeout) && (data_cfg_new->serial_timeout)) {
data_cfg_default->serial_timeout = data_cfg_new->serial_timeout;
}
}
static void UartHandler(struct SerialBus *serial_bus, struct SerialDriver *serial_drv)
{
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_bus->bus.owner_haldev;
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
struct Stm32UartHwCfg *serial_hw_cfg = (struct Stm32UartHwCfg *)serial_cfg->hw_cfg.private_data;
/* UART in mode Receiver -------------------------------------------------*/
if ((__HAL_UART_GET_FLAG(&(serial_hw_cfg->uart_handle), UART_FLAG_RXNE) != RESET) &&
(__HAL_UART_GET_IT_SOURCE(&(serial_hw_cfg->uart_handle), UART_IT_RXNE) != RESET))
{
SerialSetIsr(serial_dev, SERIAL_EVENT_RX_IND);
}
else
{
if (__HAL_UART_GET_FLAG(&(serial_hw_cfg->uart_handle), UART_FLAG_ORE) != RESET)
{
__HAL_UART_CLEAR_OREFLAG(&serial_hw_cfg->uart_handle);
}
if (__HAL_UART_GET_FLAG(&(serial_hw_cfg->uart_handle), UART_FLAG_NE) != RESET)
{
__HAL_UART_CLEAR_NEFLAG(&serial_hw_cfg->uart_handle);
}
if (__HAL_UART_GET_FLAG(&(serial_hw_cfg->uart_handle), UART_FLAG_FE) != RESET)
{
__HAL_UART_CLEAR_FEFLAG(&serial_hw_cfg->uart_handle);
}
if (__HAL_UART_GET_FLAG(&(serial_hw_cfg->uart_handle), UART_FLAG_PE) != RESET)
{
__HAL_UART_CLEAR_PEFLAG(&serial_hw_cfg->uart_handle);
}
}
}
#ifdef BSP_USING_UART1
void UartIsr1(int vector, void *param)
{
/* get serial bus 1 */
UartHandler(&serial_bus_1, &serial_driver_1);
}
#endif
#ifdef BSP_USING_UART2
void UartIsr2(int vector, void *param)
{
/* get serial bus 2 */
UartHandler(&serial_bus_2, &serial_driver_2);
}
#endif
static uint32 SerialInit(struct SerialDriver *serial_drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(serial_drv);
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
struct Stm32UartHwCfg *serial_hw_cfg = (struct Stm32UartHwCfg *)serial_cfg->hw_cfg.private_data;
if (configure_info->private_data) {
struct SerialCfgParam *serial_cfg_new = (struct SerialCfgParam *)configure_info->private_data;
SerialCfgParamCheck(serial_cfg, serial_cfg_new);
}
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialDevParam *dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
// config serial receive sem timeout
dev_param->serial_timeout = serial_cfg->data_cfg.serial_timeout;
serial_hw_cfg->uart_handle.Instance = serial_hw_cfg->uart_device;
serial_hw_cfg->uart_handle.Init.BaudRate = serial_cfg->data_cfg.serial_baud_rate;
serial_hw_cfg->uart_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
serial_hw_cfg->uart_handle.Init.Mode = UART_MODE_TX_RX;
serial_hw_cfg->uart_handle.Init.OverSampling = UART_OVERSAMPLING_16;
switch (serial_cfg->data_cfg.serial_data_bits)
{
case DATA_BITS_8:
if (serial_cfg->data_cfg.serial_parity_mode == PARITY_ODD || serial_cfg->data_cfg.serial_parity_mode == PARITY_EVEN)
serial_hw_cfg->uart_handle.Init.WordLength = UART_WORDLENGTH_9B;
else
serial_hw_cfg->uart_handle.Init.WordLength = UART_WORDLENGTH_8B;
break;
case DATA_BITS_9:
serial_hw_cfg->uart_handle.Init.WordLength = UART_WORDLENGTH_9B;
break;
default:
serial_hw_cfg->uart_handle.Init.WordLength = UART_WORDLENGTH_8B;
break;
}
switch (serial_cfg->data_cfg.serial_stop_bits)
{
case STOP_BITS_1:
serial_hw_cfg->uart_handle.Init.StopBits = UART_STOPBITS_1;
break;
case STOP_BITS_2:
serial_hw_cfg->uart_handle.Init.StopBits = UART_STOPBITS_2;
break;
default:
serial_hw_cfg->uart_handle.Init.StopBits = UART_STOPBITS_1;
break;
}
switch (serial_cfg->data_cfg.serial_parity_mode)
{
case PARITY_NONE:
serial_hw_cfg->uart_handle.Init.Parity = UART_PARITY_NONE;
break;
case PARITY_ODD:
serial_hw_cfg->uart_handle.Init.Parity = UART_PARITY_ODD;
break;
case PARITY_EVEN:
serial_hw_cfg->uart_handle.Init.Parity = UART_PARITY_EVEN;
break;
default:
serial_hw_cfg->uart_handle.Init.Parity = UART_PARITY_NONE;
break;
}
if (HAL_UART_Init(&serial_hw_cfg->uart_handle) != HAL_OK)
{
return ERROR;
}
return EOK;
}
static uint32 SerialConfigure(struct SerialDriver *serial_drv, int serial_operation_cmd)
{
NULL_PARAM_CHECK(serial_drv);
struct SerialHardwareDevice *serial_dev = (struct SerialHardwareDevice *)serial_drv->driver.owner_bus->owner_haldev;
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_drv->private_data;
struct Stm32UartHwCfg *serial_hw_cfg = (struct Stm32UartHwCfg *)serial_cfg->hw_cfg.private_data;
struct SerialDevParam *serial_dev_param = (struct SerialDevParam *)serial_dev->haldev.private_data;
if (OPER_CLR_INT == serial_operation_cmd) {
if (SIGN_OPER_INT_RX & serial_dev_param->serial_work_mode) {
/* disable rx irq */
NVIC_DisableIRQ(serial_hw_cfg->irq_type);
/* disable interrupt */
__HAL_UART_DISABLE_IT(&(serial_hw_cfg->uart_handle), UART_IT_RXNE);
}
} else if (OPER_SET_INT == serial_operation_cmd) {
/* enable rx irq */
HAL_NVIC_SetPriority(serial_hw_cfg->irq_type, 1, 0);
HAL_NVIC_EnableIRQ(serial_hw_cfg->irq_type);
/* enable interrupt */
__HAL_UART_ENABLE_IT(&(serial_hw_cfg->uart_handle), UART_IT_RXNE);
}
return EOK;
}
static uint32 SerialDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
static unsigned int CanModeInit(void *drv, struct BusConfigureInfo *configure_info)
{
NULL_PARAM_CHECK(drv);
NULL_PARAM_CHECK(configure_info);
x_err_t ret = EOK;
int serial_operation_cmd;
struct SerialDriver *serial_drv = (struct SerialDriver *)drv;
switch (configure_info->configure_cmd)
struct CanDriverConfigure *config = (struct CanDriverConfigure *)configure_info->private_data;
struct CanDriver *can_drv = (struct CanDriver *)drv;
CAN_HandleTypeDef *hcan1 = &(stm32_can1->instance);
// hcan1->Instance = CAN1;
// hcan1->Init.Prescaler = config->brp;
// hcan1->Init.Mode = config->mode;
// hcan1->Init.SyncJumpWidth = config->tsjw;
// hcan1->Init.TimeSeg1 = config->tbs1;
// hcan1->Init.TimeSeg2 = config->tbs2;
// hcan1->Init.TimeTriggeredMode = DISABLE;
// hcan1->Init.AutoBusOff = ENABLE;
// hcan1->Init.AutoWakeUp = ENABLE;
// hcan1->Init.AutoRetransmission = DISABLE;
// hcan1->Init.ReceiveFifoLocked = DISABLE;
// hcan1->Init.TransmitFifoPriority = DISABLE;
hcan1->Instance = CAN1;
hcan1->Init.Prescaler = 6;
hcan1->Init.Mode = CAN_MODE_NORMAL;
hcan1->Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1->Init.TimeSeg1 = CAN_BS1_6TQ;
hcan1->Init.TimeSeg2 = CAN_BS2_5TQ;
hcan1->Init.TimeTriggeredMode = DISABLE;
hcan1->Init.AutoBusOff = DISABLE;
hcan1->Init.AutoWakeUp = DISABLE;
hcan1->Init.AutoRetransmission = DISABLE;
hcan1->Init.ReceiveFifoLocked = DISABLE;
hcan1->Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(hcan1) != HAL_OK)
{
case OPE_INT:
ret = SerialInit(serial_drv, configure_info);
break;
case OPE_CFG:
serial_operation_cmd = *(int *)configure_info->private_data;
ret = SerialConfigure(serial_drv, serial_operation_cmd);
break;
default:
break;
return ERROR;
}
return ret;
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterBank = 0; /* 过滤器组0 */
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; /* 屏蔽位模式 */
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; /* 32位。*/
// sFilterConfig.FilterIdHigh = (((uint32_t)CAN_RxExtId << 3) & 0xFFFF0000) >> 16; /* 要过滤的ID高位 */
// sFilterConfig.FilterIdLow = (((uint32_t)CAN_RxExtId << 3) | CAN_ID_EXT | CAN_RTR_DATA) & 0xFFFF; /* 要过滤的ID低位 */
// sFilterConfig.FilterMaskIdHigh = 0xFFFF; /* 过滤器高16位每位必须匹配 */
// sFilterConfig.FilterMaskIdLow = 0xFFFF; /* 过滤器低16位每位必须匹配 */
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; /* 过滤器被关联到FIFO 0 */
sFilterConfig.FilterActivation = ENABLE; /* 使能过滤器 */
sFilterConfig.SlaveStartFilterBank = 14;
if (HAL_CAN_ConfigFilter(hcan1, &sFilterConfig) != HAL_OK)
{
/* Filter configuration Error */
return ERROR;
}
static int SerialPutChar(struct SerialHardwareDevice *serial_dev, char c)
if (HAL_CAN_Start(hcan1) != HAL_OK)
{
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_dev->private_data;
struct Stm32UartHwCfg *serial_hw_cfg = (struct Stm32UartHwCfg *)serial_cfg->hw_cfg.private_data;
/* Start Error */
return ERROR;
}
UART_INSTANCE_CLEAR_FUNCTION(&(serial_hw_cfg->uart_handle), UART_FLAG_TC);
/*##-4- Activate CAN RX notification #######################################*/
if (HAL_CAN_ActivateNotification(hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
{
/* Start Error */
return ERROR;
}
}
serial_hw_cfg->uart_handle.Instance->DR = c;
while (__HAL_UART_GET_FLAG(&(serial_hw_cfg->uart_handle), UART_FLAG_TC) == RESET);
static uint32 CanOpen(void *dev)
{
KPrintf("Can open\n");
KTaskDescriptorType task = NONE;
task = GetKTaskDescriptor();
KPrintf("CanOpen MdelayKTask2 %x\n", task);
KPrintf("CanOpen task->Done %x \n", task->Done);
return 0;
}
static uint32 CanClose(void *dev)
{
KPrintf("Can close\n");
return 0;
}
static uint32 CanSendMsg(void *dev, struct BusBlockWriteParam *write_param)
{
NULL_PARAM_CHECK(dev);
CAN_HandleTypeDef *hcan1 = &(stm32_can1->instance);
uint8_t i = 0;
uint32_t TxMailbox;
uint8_t message[8];
uint8_t *data = (uint8 *)write_param->buffer;
uint16_t timer_count = 1000;
CAN_TxHeaderTypeDef TxHeader; // 发送
TxHeader.ExtId = CAN_TxExtId; // 扩展标识符(29位)
TxHeader.IDE = CAN_ID_EXT; // 使用扩展帧
TxHeader.RTR = CAN_RTR_DATA; // 数据帧
TxHeader.DLC = write_param->size;
TxHeader.TransmitGlobalTime = DISABLE;
for (i = 0; i < TxHeader.DLC; i++)
{
message[i] = data[i];
}
if (HAL_CAN_AddTxMessage(hcan1, &TxHeader, message, &TxMailbox) != HAL_OK) // 发送
{
return ERROR;
}
while (HAL_CAN_GetTxMailboxesFreeLevel(hcan1) != 3 && timer_count)
{
timer_count--;
}
if (timer_count <= 0)
{
return ERROR;
}
return EOK;
}
static int SerialGetChar(struct SerialHardwareDevice *serial_dev)
{
struct SerialCfgParam *serial_cfg = (struct SerialCfgParam *)serial_dev->private_data;
struct Stm32UartHwCfg *serial_hw_cfg = (struct Stm32UartHwCfg *)serial_cfg->hw_cfg.private_data;
int ch = -1;
if (__HAL_UART_GET_FLAG(&(serial_hw_cfg->uart_handle), UART_FLAG_RXNE) != RESET)
static uint32 CanRecvMsg(void *dev, struct BusBlockReadParam *databuf)
{
ch = serial_hw_cfg->uart_handle.Instance->DR & 0xff;
NULL_PARAM_CHECK(dev);
NULL_PARAM_CHECK(databuf);
int size = stm32_can1->can_recv_flag;
int i;
uint8_t *buf = (uint8 *)(databuf->buffer);
if (size != 0)
{
for(i=0;i<size;i++)
{
buf[i]=stm32_can1->can_Rx_Data[i];
//KPrintf("0x%02x ", buf[i]);
stm32_can1->can_Rx_Data[i]=0;
}
return ch;
//KPrintf("\n");
stm32_can1->can_recv_flag = 0;
}
return size;
}
static const struct SerialDataCfg data_cfg_init =
static struct CanDevDone can_dev_done =
{
.serial_baud_rate = BAUD_RATE_115200,
.serial_data_bits = DATA_BITS_8,
.serial_stop_bits = STOP_BITS_1,
.serial_parity_mode = PARITY_NONE,
.serial_bit_order = BIT_ORDER_LSB,
.serial_invert_mode = NRZ_NORMAL,
.serial_buffer_size = SERIAL_RB_BUFSZ,
.serial_timeout = WAITING_FOREVER,
.open = CanOpen,//None
.close = CanClose,
.write = CanSendMsg,
.read = CanRecvMsg
};
/*manage the serial device operations*/
static const struct SerialDrvDone drv_done =
{
.init = SerialInit,
.configure = SerialConfigure,
};
/*manage the serial device hal operations*/
static struct SerialHwDevDone hwdev_done =
{
.put_char = SerialPutChar,
.get_char = SerialGetChar,
};
// #ifdef BSP_USING_CAN1
static int BoardSerialBusInit(struct SerialBus *serial_bus, struct SerialDriver *serial_driver, const char *bus_name, const char *drv_name)
void USB_LP_CAN1_RX0_IRQHandler(void)
{
HAL_CAN_IRQHandler(&(stm32_can1->instance));
}
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *CanNum)
{
uint32_t i;
uint8_t RxData[8];
KPrintf("in CAN1_RX0_IRQHandler\n");
CAN_HandleTypeDef *hcan1 = &(stm32_can1->instance);
CAN_RxHeaderTypeDef RxHeader;
HAL_CAN_GetRxMessage(hcan1, CAN_RX_FIFO0, &RxHeader, stm32_can1->can_Rx_Data);
stm32_can1->can_recv_flag =RxHeader.DLC; //接收标志位
// for(i = 0; i<RxHeader.DLC;i++)
// {
// KPrintf("0x%02x ", stm32_can1->can_Rx_Data[i]);
// }
// KPrintf("\n%d",RxHeader.DLC);
}
// #endif // BSP_USING_CAN1
static int BoardCanBusInit(struct Stm32Can *stm32can_bus, struct CanDriver *can_driver)
{
x_err_t ret = EOK;
/*Init the serial bus */
ret = SerialBusInit(serial_bus, bus_name);
if (EOK != ret) {
KPrintf("InitHwUart SerialBusInit error %d\n", ret);
/*Init the can bus */
ret = CanBusInit(&stm32can_bus->can_bus, stm32can_bus->bus_name);
if (EOK != ret)
{
KPrintf("Board_can_init canBusInit error %d\n", ret);
return ERROR;
}
/*Init the serial driver*/
ret = SerialDriverInit(serial_driver, drv_name);
if (EOK != ret) {
KPrintf("InitHwUart SerialDriverInit error %d\n", ret);
/*Init the can driver*/
ret = CanDriverInit(can_driver, CAN_DRIVER_NAME);
if (EOK != ret)
{
KPrintf("Board_can_init canDriverInit error %d\n", ret);
return ERROR;
}
/*Attach the serial driver to the serial bus*/
ret = SerialDriverAttachToBus(drv_name, bus_name);
if (EOK != ret) {
KPrintf("InitHwUart SerialDriverAttachToBus error %d\n", ret);
/*Attach the can driver to the can bus*/
ret = CanDriverAttachToBus(CAN_DRIVER_NAME, stm32can_bus->bus_name);
if (EOK != ret)
{
KPrintf("Board_can_init CanDriverAttachToBus error %d\n", ret);
return ERROR;
}
return ret;
}
/*Attach the serial device to the serial bus*/
static int BoardSerialDevBend(struct SerialHardwareDevice *serial_device, void *serial_param, const char *bus_name, const char *dev_name)
static x_err_t HwCanDeviceAttach(const char *bus_name, const char *device_name, struct Stm32Can *can1)
{
NULL_PARAM_CHECK(bus_name);
NULL_PARAM_CHECK(device_name);
x_err_t result;
struct CanHardwareDevice *can_device;
/* attach the device to can bus*/
can_device = (struct CanHardwareDevice *)x_malloc(sizeof(struct CanHardwareDevice));
memset(can_device, 0, sizeof(struct CanHardwareDevice));
can_device->dev_done = &can_dev_done;
can_device->private_data = stm32_can1;
result = CanDeviceRegister(can_device, NONE, device_name);
if (EOK != result)
{
KPrintf("board_can_init canDeviceInit device %s error %d\n", "can1", result);
return ERROR;
}
result = CanDeviceAttachToBus(device_name, bus_name);
if (result != EOK)
{
SYS_ERR("%s attach to %s faild, %d\n", device_name, bus_name, result);
}
CHECK(result == EOK);
KPrintf("%s attach to %s done\n", device_name, bus_name);
return result;
}
int InitHwCan(void)
{
x_err_t ret = EOK;
struct CanDriver *can_driver;
ret = SerialDeviceRegister(serial_device, serial_param, dev_name);
if (EOK != ret) {
KPrintf("InitHwUart SerialDeviceInit device %s error %d\n", dev_name, ret);
return ERROR;
}
stm32_can1 = (struct Stm32Can *)x_malloc(sizeof(struct Stm32Can));
memset(stm32_can1, 0, sizeof(struct Stm32Can));
stm32_can1->bus_name = CAN_BUS_NAME_1;
stm32_can1->can_bus.private_data = stm32_can1;
ret = SerialDeviceAttachToBus(dev_name, bus_name);
if (EOK != ret) {
KPrintf("InitHwUart SerialDeviceAttachToBus device %s error %d\n", dev_name, ret);
return ERROR;
}
can_driver = (struct CanDriver *)x_malloc(sizeof(struct CanDriver));
memset(can_driver, 0, sizeof(struct CanDriver));
can_driver->configure = CanModeInit;
can_driver->private_data = stm32_can1;
return ret;
}
int InitHwUart(void)
ret = BoardCanBusInit(stm32_can1, can_driver);
if (EOK != ret)
{
x_err_t ret = EOK;
#ifdef BSP_USING_UART1
memset(&serial_bus_1, 0, sizeof(struct SerialBus));
memset(&serial_driver_1, 0, sizeof(struct SerialDriver));
memset(&serial_device_1, 0, sizeof(struct SerialHardwareDevice));
static struct SerialCfgParam serial_cfg_1;
memset(&serial_cfg_1, 0, sizeof(struct SerialCfgParam));
static struct Stm32UartHwCfg serial_hw_cfg_1;
memset(&serial_hw_cfg_1, 0, sizeof(struct Stm32UartHwCfg));
static struct SerialDevParam serial_dev_param_1;
memset(&serial_dev_param_1, 0, sizeof(struct SerialDevParam));
serial_driver_1.drv_done = &drv_done;
serial_driver_1.configure = &SerialDrvConfigure;
serial_device_1.hwdev_done = &hwdev_done;
serial_cfg_1.data_cfg = data_cfg_init;
serial_cfg_1.hw_cfg.private_data = (void *)&serial_hw_cfg_1;
serial_hw_cfg_1.uart_device = USART1;
serial_hw_cfg_1.irq_type = USART1_IRQn;
serial_driver_1.private_data = (void *)&serial_cfg_1;
serial_dev_param_1.serial_work_mode = SIGN_OPER_INT_RX;
serial_device_1.haldev.private_data = (void *)&serial_dev_param_1;
ret = BoardSerialBusInit(&serial_bus_1, &serial_driver_1, SERIAL_BUS_NAME_1, SERIAL_DRV_NAME_1);
if (EOK != ret) {
KPrintf("InitHwUart uarths error ret %u\n", ret);
KPrintf(" can_bus_init %s error ret %u\n", stm32_can1->bus_name, ret);
return ERROR;
}
ret = BoardSerialDevBend(&serial_device_1, (void *)&serial_cfg_1, SERIAL_BUS_NAME_1, SERIAL_1_DEVICE_NAME_0);
if (EOK != ret) {
KPrintf("InitHwUart uarths error ret %u\n", ret);
return ERROR;
}
#endif
#ifdef BSP_USING_UART2
memset(&serial_bus_2, 0, sizeof(struct SerialBus));
memset(&serial_driver_2, 0, sizeof(struct SerialDriver));
memset(&serial_device_2, 0, sizeof(struct SerialHardwareDevice));
static struct SerialCfgParam serial_cfg_2;
memset(&serial_cfg_2, 0, sizeof(struct SerialCfgParam));
static struct Stm32UartHwCfg serial_hw_cfg_2;
memset(&serial_hw_cfg_2, 0, sizeof(struct Stm32UartHwCfg));
static struct SerialDevParam serial_dev_param_2;
memset(&serial_dev_param_2, 0, sizeof(struct SerialDevParam));
serial_driver_2.drv_done = &drv_done;
serial_driver_2.configure = &SerialDrvConfigure;
serial_device_2.hwdev_done = &hwdev_done;
serial_cfg_2.data_cfg = data_cfg_init;
serial_cfg_2.hw_cfg.private_data = (void *)&serial_hw_cfg_2;
serial_hw_cfg_2.uart_device = USART2;
serial_hw_cfg_2.irq_type = USART2_IRQn;
serial_driver_2.private_data = (void *)&serial_cfg_2;
serial_dev_param_2.serial_work_mode = SIGN_OPER_INT_RX;
serial_device_2.haldev.private_data = (void *)&serial_dev_param_2;
ret = BoardSerialBusInit(&serial_bus_2, &serial_driver_2, SERIAL_BUS_NAME_2, SERIAL_DRV_NAME_2);
if (EOK != ret) {
KPrintf("InitHwUart uarths error ret %u\n", ret);
ret = HwCanDeviceAttach(CAN_BUS_NAME_1, CAN_1_DEVICE_NAME_1, stm32_can1);
if (EOK != ret)
{
KPrintf(" HwCanDeviceAttach %s error ret %u\n", stm32_can1->bus_name, ret);
return ERROR;
}
ret = BoardSerialDevBend(&serial_device_2, (void *)&serial_cfg_2, SERIAL_BUS_NAME_2, SERIAL_2_DEVICE_NAME_0);
if (EOK != ret) {
KPrintf("InitHwUart uarths error ret %u\n", ret);
return ERROR;
}
#endif
return ret;
return EOK;
}

View File

@ -1,3 +1,3 @@
SRC_FILES := ymodem.c
SRC_FILES :=
include $(KERNEL_ROOT)/compiler.mk

View File

@ -25,6 +25,8 @@ DMA_HandleTypeDef hdma_usart1_rx;
void ymodem_uart_init(void)
{
// need UART1 IRQ --> void UartIsr1(int vector, void *param)
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
@ -265,7 +267,8 @@ void ymodem_fun(void)
KPrintf("in ymodem func\n");
ymodem_uart_init();
while (1)
{
if(Get_state()==TO_START)
{
KPrintf("in ymodem wait\n");
@ -360,6 +363,7 @@ void ymodem_fun(void)
}
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file connect_can.h
* @brief define aiit-arm32-board can function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-22
*/
#ifndef CONNECT_CAN_H
#define CONNECT_CAN_H
#include <device.h>
#include "stm32f1xx_hal_can.h"
#include "stm32f103xb.h"
#include "stm32f1xx_hal_def.h"
#ifdef __cplusplus
extern "C" {
#endif
struct Stm32Can
{
CAN_HandleTypeDef instance;
char *bus_name;
struct CanBus can_bus;
uint8 can_recv_flag;
uint8_t can_Rx_Data[8];
};
#define CAN_RxExtId 0x1800D8D0
#define CAN_TxExtId 0x1800D0D8
int InitHwCan(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,859 @@
/**
******************************************************************************
* @file stm32f1xx_hal_can.h
* @author MCD Application Team
* @brief Header file of CAN HAL module.
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32F1xx_HAL_CAN_H
#define STM32F1xx_HAL_CAN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal_def.h"
/** @addtogroup STM32F1xx_HAL_Driver
* @{
*/
#if defined (CAN1)
/** @addtogroup CAN
* @{
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup CAN_Exported_Types CAN Exported Types
* @{
*/
/**
* @brief HAL State structures definition
*/
typedef enum
{
HAL_CAN_STATE_RESET = 0x00U, /*!< CAN not yet initialized or disabled */
HAL_CAN_STATE_READY = 0x01U, /*!< CAN initialized and ready for use */
HAL_CAN_STATE_LISTENING = 0x02U, /*!< CAN receive process is ongoing */
HAL_CAN_STATE_SLEEP_PENDING = 0x03U, /*!< CAN sleep request is pending */
HAL_CAN_STATE_SLEEP_ACTIVE = 0x04U, /*!< CAN sleep mode is active */
HAL_CAN_STATE_ERROR = 0x05U /*!< CAN error state */
} HAL_CAN_StateTypeDef;
/**
* @brief CAN init structure definition
*/
typedef struct
{
uint32_t Prescaler; /*!< Specifies the length of a time quantum.
This parameter must be a number between Min_Data = 1 and Max_Data = 1024. */
uint32_t Mode; /*!< Specifies the CAN operating mode.
This parameter can be a value of @ref CAN_operating_mode */
uint32_t SyncJumpWidth; /*!< Specifies the maximum number of time quanta the CAN hardware
is allowed to lengthen or shorten a bit to perform resynchronization.
This parameter can be a value of @ref CAN_synchronisation_jump_width */
uint32_t TimeSeg1; /*!< Specifies the number of time quanta in Bit Segment 1.
This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_1 */
uint32_t TimeSeg2; /*!< Specifies the number of time quanta in Bit Segment 2.
This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_2 */
FunctionalState TimeTriggeredMode; /*!< Enable or disable the time triggered communication mode.
This parameter can be set to ENABLE or DISABLE. */
FunctionalState AutoBusOff; /*!< Enable or disable the automatic bus-off management.
This parameter can be set to ENABLE or DISABLE. */
FunctionalState AutoWakeUp; /*!< Enable or disable the automatic wake-up mode.
This parameter can be set to ENABLE or DISABLE. */
FunctionalState AutoRetransmission; /*!< Enable or disable the non-automatic retransmission mode.
This parameter can be set to ENABLE or DISABLE. */
FunctionalState ReceiveFifoLocked; /*!< Enable or disable the Receive FIFO Locked mode.
This parameter can be set to ENABLE or DISABLE. */
FunctionalState TransmitFifoPriority;/*!< Enable or disable the transmit FIFO priority.
This parameter can be set to ENABLE or DISABLE. */
} CAN_InitTypeDef;
/**
* @brief CAN filter configuration structure definition
*/
typedef struct
{
uint32_t FilterIdHigh; /*!< Specifies the filter identification number (MSBs for a 32-bit
configuration, first one for a 16-bit configuration).
This parameter must be a number between
Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterIdLow; /*!< Specifies the filter identification number (LSBs for a 32-bit
configuration, second one for a 16-bit configuration).
This parameter must be a number between
Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterMaskIdHigh; /*!< Specifies the filter mask number or identification number,
according to the mode (MSBs for a 32-bit configuration,
first one for a 16-bit configuration).
This parameter must be a number between
Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterMaskIdLow; /*!< Specifies the filter mask number or identification number,
according to the mode (LSBs for a 32-bit configuration,
second one for a 16-bit configuration).
This parameter must be a number between
Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterFIFOAssignment; /*!< Specifies the FIFO (0 or 1U) which will be assigned to the filter.
This parameter can be a value of @ref CAN_filter_FIFO */
uint32_t FilterBank; /*!< Specifies the filter bank which will be initialized.
For single CAN instance(14 dedicated filter banks),
this parameter must be a number between Min_Data = 0 and Max_Data = 13.
For dual CAN instances(28 filter banks shared),
this parameter must be a number between Min_Data = 0 and Max_Data = 27. */
uint32_t FilterMode; /*!< Specifies the filter mode to be initialized.
This parameter can be a value of @ref CAN_filter_mode */
uint32_t FilterScale; /*!< Specifies the filter scale.
This parameter can be a value of @ref CAN_filter_scale */
uint32_t FilterActivation; /*!< Enable or disable the filter.
This parameter can be a value of @ref CAN_filter_activation */
uint32_t SlaveStartFilterBank; /*!< Select the start filter bank for the slave CAN instance.
For single CAN instances, this parameter is meaningless.
For dual CAN instances, all filter banks with lower index are assigned to master
CAN instance, whereas all filter banks with greater index are assigned to slave
CAN instance.
This parameter must be a number between Min_Data = 0 and Max_Data = 27. */
} CAN_FilterTypeDef;
/**
* @brief CAN Tx message header structure definition
*/
typedef struct
{
uint32_t StdId; /*!< Specifies the standard identifier.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */
uint32_t ExtId; /*!< Specifies the extended identifier.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */
uint32_t IDE; /*!< Specifies the type of identifier for the message that will be transmitted.
This parameter can be a value of @ref CAN_identifier_type */
uint32_t RTR; /*!< Specifies the type of frame for the message that will be transmitted.
This parameter can be a value of @ref CAN_remote_transmission_request */
uint32_t DLC; /*!< Specifies the length of the frame that will be transmitted.
This parameter must be a number between Min_Data = 0 and Max_Data = 8. */
FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start
of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].
@note: Time Triggered Communication Mode must be enabled.
@note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.
This parameter can be set to ENABLE or DISABLE. */
} CAN_TxHeaderTypeDef;
/**
* @brief CAN Rx message header structure definition
*/
typedef struct
{
uint32_t StdId; /*!< Specifies the standard identifier.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */
uint32_t ExtId; /*!< Specifies the extended identifier.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */
uint32_t IDE; /*!< Specifies the type of identifier for the message that will be transmitted.
This parameter can be a value of @ref CAN_identifier_type */
uint32_t RTR; /*!< Specifies the type of frame for the message that will be transmitted.
This parameter can be a value of @ref CAN_remote_transmission_request */
uint32_t DLC; /*!< Specifies the length of the frame that will be transmitted.
This parameter must be a number between Min_Data = 0 and Max_Data = 8. */
uint32_t Timestamp; /*!< Specifies the timestamp counter value captured on start of frame reception.
@note: Time Triggered Communication Mode must be enabled.
This parameter must be a number between Min_Data = 0 and Max_Data = 0xFFFF. */
uint32_t FilterMatchIndex; /*!< Specifies the index of matching acceptance filter element.
This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF. */
} CAN_RxHeaderTypeDef;
/**
* @brief CAN handle Structure definition
*/
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
typedef struct __CAN_HandleTypeDef
#else
typedef struct
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
{
CAN_TypeDef *Instance; /*!< Register base address */
CAN_InitTypeDef Init; /*!< CAN required parameters */
__IO HAL_CAN_StateTypeDef State; /*!< CAN communication state */
__IO uint32_t ErrorCode; /*!< CAN Error code.
This parameter can be a value of @ref CAN_Error_Code */
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
void (* TxMailbox0CompleteCallback)(struct __CAN_HandleTypeDef *hcan);/*!< CAN Tx Mailbox 0 complete callback */
void (* TxMailbox1CompleteCallback)(struct __CAN_HandleTypeDef *hcan);/*!< CAN Tx Mailbox 1 complete callback */
void (* TxMailbox2CompleteCallback)(struct __CAN_HandleTypeDef *hcan);/*!< CAN Tx Mailbox 2 complete callback */
void (* TxMailbox0AbortCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Tx Mailbox 0 abort callback */
void (* TxMailbox1AbortCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Tx Mailbox 1 abort callback */
void (* TxMailbox2AbortCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Tx Mailbox 2 abort callback */
void (* RxFifo0MsgPendingCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Rx FIFO 0 msg pending callback */
void (* RxFifo0FullCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Rx FIFO 0 full callback */
void (* RxFifo1MsgPendingCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Rx FIFO 1 msg pending callback */
void (* RxFifo1FullCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Rx FIFO 1 full callback */
void (* SleepCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Sleep callback */
void (* WakeUpFromRxMsgCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Wake Up from Rx msg callback */
void (* ErrorCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Error callback */
void (* MspInitCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Msp Init callback */
void (* MspDeInitCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Msp DeInit callback */
#endif /* (USE_HAL_CAN_REGISTER_CALLBACKS) */
} CAN_HandleTypeDef;
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
/**
* @brief HAL CAN common Callback ID enumeration definition
*/
typedef enum
{
HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID = 0x00U, /*!< CAN Tx Mailbox 0 complete callback ID */
HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID = 0x01U, /*!< CAN Tx Mailbox 1 complete callback ID */
HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID = 0x02U, /*!< CAN Tx Mailbox 2 complete callback ID */
HAL_CAN_TX_MAILBOX0_ABORT_CB_ID = 0x03U, /*!< CAN Tx Mailbox 0 abort callback ID */
HAL_CAN_TX_MAILBOX1_ABORT_CB_ID = 0x04U, /*!< CAN Tx Mailbox 1 abort callback ID */
HAL_CAN_TX_MAILBOX2_ABORT_CB_ID = 0x05U, /*!< CAN Tx Mailbox 2 abort callback ID */
HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID = 0x06U, /*!< CAN Rx FIFO 0 message pending callback ID */
HAL_CAN_RX_FIFO0_FULL_CB_ID = 0x07U, /*!< CAN Rx FIFO 0 full callback ID */
HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID = 0x08U, /*!< CAN Rx FIFO 1 message pending callback ID */
HAL_CAN_RX_FIFO1_FULL_CB_ID = 0x09U, /*!< CAN Rx FIFO 1 full callback ID */
HAL_CAN_SLEEP_CB_ID = 0x0AU, /*!< CAN Sleep callback ID */
HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID = 0x0BU, /*!< CAN Wake Up from Rx msg callback ID */
HAL_CAN_ERROR_CB_ID = 0x0CU, /*!< CAN Error callback ID */
HAL_CAN_MSPINIT_CB_ID = 0x0DU, /*!< CAN MspInit callback ID */
HAL_CAN_MSPDEINIT_CB_ID = 0x0EU, /*!< CAN MspDeInit callback ID */
} HAL_CAN_CallbackIDTypeDef;
/**
* @brief HAL CAN Callback pointer definition
*/
typedef void (*pCAN_CallbackTypeDef)(CAN_HandleTypeDef *hcan); /*!< pointer to a CAN callback function */
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
/**
* @}
*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup CAN_Exported_Constants CAN Exported Constants
* @{
*/
/** @defgroup CAN_Error_Code CAN Error Code
* @{
*/
#define HAL_CAN_ERROR_NONE (0x00000000U) /*!< No error */
#define HAL_CAN_ERROR_EWG (0x00000001U) /*!< Protocol Error Warning */
#define HAL_CAN_ERROR_EPV (0x00000002U) /*!< Error Passive */
#define HAL_CAN_ERROR_BOF (0x00000004U) /*!< Bus-off error */
#define HAL_CAN_ERROR_STF (0x00000008U) /*!< Stuff error */
#define HAL_CAN_ERROR_FOR (0x00000010U) /*!< Form error */
#define HAL_CAN_ERROR_ACK (0x00000020U) /*!< Acknowledgment error */
#define HAL_CAN_ERROR_BR (0x00000040U) /*!< Bit recessive error */
#define HAL_CAN_ERROR_BD (0x00000080U) /*!< Bit dominant error */
#define HAL_CAN_ERROR_CRC (0x00000100U) /*!< CRC error */
#define HAL_CAN_ERROR_RX_FOV0 (0x00000200U) /*!< Rx FIFO0 overrun error */
#define HAL_CAN_ERROR_RX_FOV1 (0x00000400U) /*!< Rx FIFO1 overrun error */
#define HAL_CAN_ERROR_TX_ALST0 (0x00000800U) /*!< TxMailbox 0 transmit failure due to arbitration lost */
#define HAL_CAN_ERROR_TX_TERR0 (0x00001000U) /*!< TxMailbox 0 transmit failure due to transmit error */
#define HAL_CAN_ERROR_TX_ALST1 (0x00002000U) /*!< TxMailbox 1 transmit failure due to arbitration lost */
#define HAL_CAN_ERROR_TX_TERR1 (0x00004000U) /*!< TxMailbox 1 transmit failure due to transmit error */
#define HAL_CAN_ERROR_TX_ALST2 (0x00008000U) /*!< TxMailbox 2 transmit failure due to arbitration lost */
#define HAL_CAN_ERROR_TX_TERR2 (0x00010000U) /*!< TxMailbox 2 transmit failure due to transmit error */
#define HAL_CAN_ERROR_TIMEOUT (0x00020000U) /*!< Timeout error */
#define HAL_CAN_ERROR_NOT_INITIALIZED (0x00040000U) /*!< Peripheral not initialized */
#define HAL_CAN_ERROR_NOT_READY (0x00080000U) /*!< Peripheral not ready */
#define HAL_CAN_ERROR_NOT_STARTED (0x00100000U) /*!< Peripheral not started */
#define HAL_CAN_ERROR_PARAM (0x00200000U) /*!< Parameter error */
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
#define HAL_CAN_ERROR_INVALID_CALLBACK (0x00400000U) /*!< Invalid Callback error */
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
#define HAL_CAN_ERROR_INTERNAL (0x00800000U) /*!< Internal error */
/**
* @}
*/
/** @defgroup CAN_InitStatus CAN InitStatus
* @{
*/
#define CAN_INITSTATUS_FAILED (0x00000000U) /*!< CAN initialization failed */
#define CAN_INITSTATUS_SUCCESS (0x00000001U) /*!< CAN initialization OK */
/**
* @}
*/
/** @defgroup CAN_operating_mode CAN Operating Mode
* @{
*/
#define CAN_MODE_NORMAL (0x00000000U) /*!< Normal mode */
#define CAN_MODE_LOOPBACK ((uint32_t)CAN_BTR_LBKM) /*!< Loopback mode */
#define CAN_MODE_SILENT ((uint32_t)CAN_BTR_SILM) /*!< Silent mode */
#define CAN_MODE_SILENT_LOOPBACK ((uint32_t)(CAN_BTR_LBKM | CAN_BTR_SILM)) /*!< Loopback combined with
silent mode */
/**
* @}
*/
/** @defgroup CAN_synchronisation_jump_width CAN Synchronization Jump Width
* @{
*/
#define CAN_SJW_1TQ (0x00000000U) /*!< 1 time quantum */
#define CAN_SJW_2TQ ((uint32_t)CAN_BTR_SJW_0) /*!< 2 time quantum */
#define CAN_SJW_3TQ ((uint32_t)CAN_BTR_SJW_1) /*!< 3 time quantum */
#define CAN_SJW_4TQ ((uint32_t)CAN_BTR_SJW) /*!< 4 time quantum */
/**
* @}
*/
/** @defgroup CAN_time_quantum_in_bit_segment_1 CAN Time Quantum in Bit Segment 1
* @{
*/
#define CAN_BS1_1TQ (0x00000000U) /*!< 1 time quantum */
#define CAN_BS1_2TQ ((uint32_t)CAN_BTR_TS1_0) /*!< 2 time quantum */
#define CAN_BS1_3TQ ((uint32_t)CAN_BTR_TS1_1) /*!< 3 time quantum */
#define CAN_BS1_4TQ ((uint32_t)(CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 4 time quantum */
#define CAN_BS1_5TQ ((uint32_t)CAN_BTR_TS1_2) /*!< 5 time quantum */
#define CAN_BS1_6TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_0)) /*!< 6 time quantum */
#define CAN_BS1_7TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_1)) /*!< 7 time quantum */
#define CAN_BS1_8TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 8 time quantum */
#define CAN_BS1_9TQ ((uint32_t)CAN_BTR_TS1_3) /*!< 9 time quantum */
#define CAN_BS1_10TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_0)) /*!< 10 time quantum */
#define CAN_BS1_11TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_1)) /*!< 11 time quantum */
#define CAN_BS1_12TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 12 time quantum */
#define CAN_BS1_13TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2)) /*!< 13 time quantum */
#define CAN_BS1_14TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2 | CAN_BTR_TS1_0)) /*!< 14 time quantum */
#define CAN_BS1_15TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2 | CAN_BTR_TS1_1)) /*!< 15 time quantum */
#define CAN_BS1_16TQ ((uint32_t)CAN_BTR_TS1) /*!< 16 time quantum */
/**
* @}
*/
/** @defgroup CAN_time_quantum_in_bit_segment_2 CAN Time Quantum in Bit Segment 2
* @{
*/
#define CAN_BS2_1TQ (0x00000000U) /*!< 1 time quantum */
#define CAN_BS2_2TQ ((uint32_t)CAN_BTR_TS2_0) /*!< 2 time quantum */
#define CAN_BS2_3TQ ((uint32_t)CAN_BTR_TS2_1) /*!< 3 time quantum */
#define CAN_BS2_4TQ ((uint32_t)(CAN_BTR_TS2_1 | CAN_BTR_TS2_0)) /*!< 4 time quantum */
#define CAN_BS2_5TQ ((uint32_t)CAN_BTR_TS2_2) /*!< 5 time quantum */
#define CAN_BS2_6TQ ((uint32_t)(CAN_BTR_TS2_2 | CAN_BTR_TS2_0)) /*!< 6 time quantum */
#define CAN_BS2_7TQ ((uint32_t)(CAN_BTR_TS2_2 | CAN_BTR_TS2_1)) /*!< 7 time quantum */
#define CAN_BS2_8TQ ((uint32_t)CAN_BTR_TS2) /*!< 8 time quantum */
/**
* @}
*/
/** @defgroup CAN_filter_mode CAN Filter Mode
* @{
*/
#define CAN_FILTERMODE_IDMASK (0x00000000U) /*!< Identifier mask mode */
#define CAN_FILTERMODE_IDLIST (0x00000001U) /*!< Identifier list mode */
/**
* @}
*/
/** @defgroup CAN_filter_scale CAN Filter Scale
* @{
*/
#define CAN_FILTERSCALE_16BIT (0x00000000U) /*!< Two 16-bit filters */
#define CAN_FILTERSCALE_32BIT (0x00000001U) /*!< One 32-bit filter */
/**
* @}
*/
/** @defgroup CAN_filter_activation CAN Filter Activation
* @{
*/
#define CAN_FILTER_DISABLE (0x00000000U) /*!< Disable filter */
#define CAN_FILTER_ENABLE (0x00000001U) /*!< Enable filter */
/**
* @}
*/
/** @defgroup CAN_filter_FIFO CAN Filter FIFO
* @{
*/
#define CAN_FILTER_FIFO0 (0x00000000U) /*!< Filter FIFO 0 assignment for filter x */
#define CAN_FILTER_FIFO1 (0x00000001U) /*!< Filter FIFO 1 assignment for filter x */
/**
* @}
*/
/** @defgroup CAN_identifier_type CAN Identifier Type
* @{
*/
#define CAN_ID_STD (0x00000000U) /*!< Standard Id */
#define CAN_ID_EXT (0x00000004U) /*!< Extended Id */
/**
* @}
*/
/** @defgroup CAN_remote_transmission_request CAN Remote Transmission Request
* @{
*/
#define CAN_RTR_DATA (0x00000000U) /*!< Data frame */
#define CAN_RTR_REMOTE (0x00000002U) /*!< Remote frame */
/**
* @}
*/
/** @defgroup CAN_receive_FIFO_number CAN Receive FIFO Number
* @{
*/
#define CAN_RX_FIFO0 (0x00000000U) /*!< CAN receive FIFO 0 */
#define CAN_RX_FIFO1 (0x00000001U) /*!< CAN receive FIFO 1 */
/**
* @}
*/
/** @defgroup CAN_Tx_Mailboxes CAN Tx Mailboxes
* @{
*/
#define CAN_TX_MAILBOX0 (0x00000001U) /*!< Tx Mailbox 0 */
#define CAN_TX_MAILBOX1 (0x00000002U) /*!< Tx Mailbox 1 */
#define CAN_TX_MAILBOX2 (0x00000004U) /*!< Tx Mailbox 2 */
/**
* @}
*/
/** @defgroup CAN_flags CAN Flags
* @{
*/
/* Transmit Flags */
#define CAN_FLAG_RQCP0 (0x00000500U) /*!< Request complete MailBox 0 flag */
#define CAN_FLAG_TXOK0 (0x00000501U) /*!< Transmission OK MailBox 0 flag */
#define CAN_FLAG_ALST0 (0x00000502U) /*!< Arbitration Lost MailBox 0 flag */
#define CAN_FLAG_TERR0 (0x00000503U) /*!< Transmission error MailBox 0 flag */
#define CAN_FLAG_RQCP1 (0x00000508U) /*!< Request complete MailBox1 flag */
#define CAN_FLAG_TXOK1 (0x00000509U) /*!< Transmission OK MailBox 1 flag */
#define CAN_FLAG_ALST1 (0x0000050AU) /*!< Arbitration Lost MailBox 1 flag */
#define CAN_FLAG_TERR1 (0x0000050BU) /*!< Transmission error MailBox 1 flag */
#define CAN_FLAG_RQCP2 (0x00000510U) /*!< Request complete MailBox2 flag */
#define CAN_FLAG_TXOK2 (0x00000511U) /*!< Transmission OK MailBox 2 flag */
#define CAN_FLAG_ALST2 (0x00000512U) /*!< Arbitration Lost MailBox 2 flag */
#define CAN_FLAG_TERR2 (0x00000513U) /*!< Transmission error MailBox 2 flag */
#define CAN_FLAG_TME0 (0x0000051AU) /*!< Transmit mailbox 0 empty flag */
#define CAN_FLAG_TME1 (0x0000051BU) /*!< Transmit mailbox 1 empty flag */
#define CAN_FLAG_TME2 (0x0000051CU) /*!< Transmit mailbox 2 empty flag */
#define CAN_FLAG_LOW0 (0x0000051DU) /*!< Lowest priority mailbox 0 flag */
#define CAN_FLAG_LOW1 (0x0000051EU) /*!< Lowest priority mailbox 1 flag */
#define CAN_FLAG_LOW2 (0x0000051FU) /*!< Lowest priority mailbox 2 flag */
/* Receive Flags */
#define CAN_FLAG_FF0 (0x00000203U) /*!< RX FIFO 0 Full flag */
#define CAN_FLAG_FOV0 (0x00000204U) /*!< RX FIFO 0 Overrun flag */
#define CAN_FLAG_FF1 (0x00000403U) /*!< RX FIFO 1 Full flag */
#define CAN_FLAG_FOV1 (0x00000404U) /*!< RX FIFO 1 Overrun flag */
/* Operating Mode Flags */
#define CAN_FLAG_INAK (0x00000100U) /*!< Initialization acknowledge flag */
#define CAN_FLAG_SLAK (0x00000101U) /*!< Sleep acknowledge flag */
#define CAN_FLAG_ERRI (0x00000102U) /*!< Error flag */
#define CAN_FLAG_WKU (0x00000103U) /*!< Wake up interrupt flag */
#define CAN_FLAG_SLAKI (0x00000104U) /*!< Sleep acknowledge interrupt flag */
/* Error Flags */
#define CAN_FLAG_EWG (0x00000300U) /*!< Error warning flag */
#define CAN_FLAG_EPV (0x00000301U) /*!< Error passive flag */
#define CAN_FLAG_BOF (0x00000302U) /*!< Bus-Off flag */
/**
* @}
*/
/** @defgroup CAN_Interrupts CAN Interrupts
* @{
*/
/* Transmit Interrupt */
#define CAN_IT_TX_MAILBOX_EMPTY ((uint32_t)CAN_IER_TMEIE) /*!< Transmit mailbox empty interrupt */
/* Receive Interrupts */
#define CAN_IT_RX_FIFO0_MSG_PENDING ((uint32_t)CAN_IER_FMPIE0) /*!< FIFO 0 message pending interrupt */
#define CAN_IT_RX_FIFO0_FULL ((uint32_t)CAN_IER_FFIE0) /*!< FIFO 0 full interrupt */
#define CAN_IT_RX_FIFO0_OVERRUN ((uint32_t)CAN_IER_FOVIE0) /*!< FIFO 0 overrun interrupt */
#define CAN_IT_RX_FIFO1_MSG_PENDING ((uint32_t)CAN_IER_FMPIE1) /*!< FIFO 1 message pending interrupt */
#define CAN_IT_RX_FIFO1_FULL ((uint32_t)CAN_IER_FFIE1) /*!< FIFO 1 full interrupt */
#define CAN_IT_RX_FIFO1_OVERRUN ((uint32_t)CAN_IER_FOVIE1) /*!< FIFO 1 overrun interrupt */
/* Operating Mode Interrupts */
#define CAN_IT_WAKEUP ((uint32_t)CAN_IER_WKUIE) /*!< Wake-up interrupt */
#define CAN_IT_SLEEP_ACK ((uint32_t)CAN_IER_SLKIE) /*!< Sleep acknowledge interrupt */
/* Error Interrupts */
#define CAN_IT_ERROR_WARNING ((uint32_t)CAN_IER_EWGIE) /*!< Error warning interrupt */
#define CAN_IT_ERROR_PASSIVE ((uint32_t)CAN_IER_EPVIE) /*!< Error passive interrupt */
#define CAN_IT_BUSOFF ((uint32_t)CAN_IER_BOFIE) /*!< Bus-off interrupt */
#define CAN_IT_LAST_ERROR_CODE ((uint32_t)CAN_IER_LECIE) /*!< Last error code interrupt */
#define CAN_IT_ERROR ((uint32_t)CAN_IER_ERRIE) /*!< Error Interrupt */
/**
* @}
*/
/**
* @}
*/
/* Exported macros -----------------------------------------------------------*/
/** @defgroup CAN_Exported_Macros CAN Exported Macros
* @{
*/
/** @brief Reset CAN handle state
* @param __HANDLE__ CAN handle.
* @retval None
*/
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
#define __HAL_CAN_RESET_HANDLE_STATE(__HANDLE__) do{ \
(__HANDLE__)->State = HAL_CAN_STATE_RESET; \
(__HANDLE__)->MspInitCallback = NULL; \
(__HANDLE__)->MspDeInitCallback = NULL; \
} while(0)
#else
#define __HAL_CAN_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_CAN_STATE_RESET)
#endif /*USE_HAL_CAN_REGISTER_CALLBACKS */
/**
* @brief Enable the specified CAN interrupts.
* @param __HANDLE__ CAN handle.
* @param __INTERRUPT__ CAN Interrupt sources to enable.
* This parameter can be any combination of @arg CAN_Interrupts
* @retval None
*/
#define __HAL_CAN_ENABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) |= (__INTERRUPT__))
/**
* @brief Disable the specified CAN interrupts.
* @param __HANDLE__ CAN handle.
* @param __INTERRUPT__ CAN Interrupt sources to disable.
* This parameter can be any combination of @arg CAN_Interrupts
* @retval None
*/
#define __HAL_CAN_DISABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) &= ~(__INTERRUPT__))
/** @brief Check if the specified CAN interrupt source is enabled or disabled.
* @param __HANDLE__ specifies the CAN Handle.
* @param __INTERRUPT__ specifies the CAN interrupt source to check.
* This parameter can be a value of @arg CAN_Interrupts
* @retval The state of __IT__ (TRUE or FALSE).
*/
#define __HAL_CAN_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) & (__INTERRUPT__))
/** @brief Check whether the specified CAN flag is set or not.
* @param __HANDLE__ specifies the CAN Handle.
* @param __FLAG__ specifies the flag to check.
* This parameter can be one of @arg CAN_flags
* @retval The state of __FLAG__ (TRUE or FALSE).
*/
#define __HAL_CAN_GET_FLAG(__HANDLE__, __FLAG__) \
((((__FLAG__) >> 8U) == 5U)? ((((__HANDLE__)->Instance->TSR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 2U)? ((((__HANDLE__)->Instance->RF0R) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 4U)? ((((__HANDLE__)->Instance->RF1R) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 1U)? ((((__HANDLE__)->Instance->MSR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 3U)? ((((__HANDLE__)->Instance->ESR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): 0U)
/** @brief Clear the specified CAN pending flag.
* @param __HANDLE__ specifies the CAN Handle.
* @param __FLAG__ specifies the flag to check.
* This parameter can be one of the following values:
* @arg CAN_FLAG_RQCP0: Request complete MailBox 0 Flag
* @arg CAN_FLAG_TXOK0: Transmission OK MailBox 0 Flag
* @arg CAN_FLAG_ALST0: Arbitration Lost MailBox 0 Flag
* @arg CAN_FLAG_TERR0: Transmission error MailBox 0 Flag
* @arg CAN_FLAG_RQCP1: Request complete MailBox 1 Flag
* @arg CAN_FLAG_TXOK1: Transmission OK MailBox 1 Flag
* @arg CAN_FLAG_ALST1: Arbitration Lost MailBox 1 Flag
* @arg CAN_FLAG_TERR1: Transmission error MailBox 1 Flag
* @arg CAN_FLAG_RQCP2: Request complete MailBox 2 Flag
* @arg CAN_FLAG_TXOK2: Transmission OK MailBox 2 Flag
* @arg CAN_FLAG_ALST2: Arbitration Lost MailBox 2 Flag
* @arg CAN_FLAG_TERR2: Transmission error MailBox 2 Flag
* @arg CAN_FLAG_FF0: RX FIFO 0 Full Flag
* @arg CAN_FLAG_FOV0: RX FIFO 0 Overrun Flag
* @arg CAN_FLAG_FF1: RX FIFO 1 Full Flag
* @arg CAN_FLAG_FOV1: RX FIFO 1 Overrun Flag
* @arg CAN_FLAG_WKUI: Wake up Interrupt Flag
* @arg CAN_FLAG_SLAKI: Sleep acknowledge Interrupt Flag
* @retval None
*/
#define __HAL_CAN_CLEAR_FLAG(__HANDLE__, __FLAG__) \
((((__FLAG__) >> 8U) == 5U)? (((__HANDLE__)->Instance->TSR) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 2U)? (((__HANDLE__)->Instance->RF0R) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 4U)? (((__HANDLE__)->Instance->RF1R) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 1U)? (((__HANDLE__)->Instance->MSR) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): 0U)
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup CAN_Exported_Functions CAN Exported Functions
* @{
*/
/** @addtogroup CAN_Exported_Functions_Group1 Initialization and de-initialization functions
* @brief Initialization and Configuration functions
* @{
*/
/* Initialization and de-initialization functions *****************************/
HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef *hcan);
void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan);
void HAL_CAN_MspDeInit(CAN_HandleTypeDef *hcan);
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
/* Callbacks Register/UnRegister functions ***********************************/
HAL_StatusTypeDef HAL_CAN_RegisterCallback(CAN_HandleTypeDef *hcan, HAL_CAN_CallbackIDTypeDef CallbackID,
void (* pCallback)(CAN_HandleTypeDef *_hcan));
HAL_StatusTypeDef HAL_CAN_UnRegisterCallback(CAN_HandleTypeDef *hcan, HAL_CAN_CallbackIDTypeDef CallbackID);
#endif /* (USE_HAL_CAN_REGISTER_CALLBACKS) */
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group2 Configuration functions
* @brief Configuration functions
* @{
*/
/* Configuration functions ****************************************************/
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, const CAN_FilterTypeDef *sFilterConfig);
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group3 Control functions
* @brief Control functions
* @{
*/
/* Control functions **********************************************************/
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_Stop(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_RequestSleep(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef *hcan);
uint32_t HAL_CAN_IsSleepActive(const CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, const CAN_TxHeaderTypeDef *pHeader,
const uint8_t aData[], uint32_t *pTxMailbox);
HAL_StatusTypeDef HAL_CAN_AbortTxRequest(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes);
uint32_t HAL_CAN_GetTxMailboxesFreeLevel(const CAN_HandleTypeDef *hcan);
uint32_t HAL_CAN_IsTxMessagePending(const CAN_HandleTypeDef *hcan, uint32_t TxMailboxes);
uint32_t HAL_CAN_GetTxTimestamp(const CAN_HandleTypeDef *hcan, uint32_t TxMailbox);
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo,
CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);
uint32_t HAL_CAN_GetRxFifoFillLevel(const CAN_HandleTypeDef *hcan, uint32_t RxFifo);
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group4 Interrupts management
* @brief Interrupts management
* @{
*/
/* Interrupts management ******************************************************/
HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs);
HAL_StatusTypeDef HAL_CAN_DeactivateNotification(CAN_HandleTypeDef *hcan, uint32_t InactiveITs);
void HAL_CAN_IRQHandler(CAN_HandleTypeDef *hcan);
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group5 Callback functions
* @brief Callback functions
* @{
*/
/* Callbacks functions ********************************************************/
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan);
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group6 Peripheral State and Error functions
* @brief CAN Peripheral State functions
* @{
*/
/* Peripheral State and Error functions ***************************************/
HAL_CAN_StateTypeDef HAL_CAN_GetState(const CAN_HandleTypeDef *hcan);
uint32_t HAL_CAN_GetError(const CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_ResetError(CAN_HandleTypeDef *hcan);
/**
* @}
*/
/**
* @}
*/
/* Private types -------------------------------------------------------------*/
/** @defgroup CAN_Private_Types CAN Private Types
* @{
*/
/**
* @}
*/
/* Private variables ---------------------------------------------------------*/
/** @defgroup CAN_Private_Variables CAN Private Variables
* @{
*/
/**
* @}
*/
/* Private constants ---------------------------------------------------------*/
/** @defgroup CAN_Private_Constants CAN Private Constants
* @{
*/
#define CAN_FLAG_MASK (0x000000FFU)
/**
* @}
*/
/* Private Macros -----------------------------------------------------------*/
/** @defgroup CAN_Private_Macros CAN Private Macros
* @{
*/
#define IS_CAN_MODE(MODE) (((MODE) == CAN_MODE_NORMAL) || \
((MODE) == CAN_MODE_LOOPBACK)|| \
((MODE) == CAN_MODE_SILENT) || \
((MODE) == CAN_MODE_SILENT_LOOPBACK))
#define IS_CAN_SJW(SJW) (((SJW) == CAN_SJW_1TQ) || ((SJW) == CAN_SJW_2TQ) || \
((SJW) == CAN_SJW_3TQ) || ((SJW) == CAN_SJW_4TQ))
#define IS_CAN_BS1(BS1) (((BS1) == CAN_BS1_1TQ) || ((BS1) == CAN_BS1_2TQ) || \
((BS1) == CAN_BS1_3TQ) || ((BS1) == CAN_BS1_4TQ) || \
((BS1) == CAN_BS1_5TQ) || ((BS1) == CAN_BS1_6TQ) || \
((BS1) == CAN_BS1_7TQ) || ((BS1) == CAN_BS1_8TQ) || \
((BS1) == CAN_BS1_9TQ) || ((BS1) == CAN_BS1_10TQ)|| \
((BS1) == CAN_BS1_11TQ)|| ((BS1) == CAN_BS1_12TQ)|| \
((BS1) == CAN_BS1_13TQ)|| ((BS1) == CAN_BS1_14TQ)|| \
((BS1) == CAN_BS1_15TQ)|| ((BS1) == CAN_BS1_16TQ))
#define IS_CAN_BS2(BS2) (((BS2) == CAN_BS2_1TQ) || ((BS2) == CAN_BS2_2TQ) || \
((BS2) == CAN_BS2_3TQ) || ((BS2) == CAN_BS2_4TQ) || \
((BS2) == CAN_BS2_5TQ) || ((BS2) == CAN_BS2_6TQ) || \
((BS2) == CAN_BS2_7TQ) || ((BS2) == CAN_BS2_8TQ))
#define IS_CAN_PRESCALER(PRESCALER) (((PRESCALER) >= 1U) && ((PRESCALER) <= 1024U))
#define IS_CAN_FILTER_ID_HALFWORD(HALFWORD) ((HALFWORD) <= 0xFFFFU)
#if defined(CAN2)
#define IS_CAN_FILTER_BANK_DUAL(BANK) ((BANK) <= 27U)
#endif
#define IS_CAN_FILTER_BANK_SINGLE(BANK) ((BANK) <= 13U)
#define IS_CAN_FILTER_MODE(MODE) (((MODE) == CAN_FILTERMODE_IDMASK) || \
((MODE) == CAN_FILTERMODE_IDLIST))
#define IS_CAN_FILTER_SCALE(SCALE) (((SCALE) == CAN_FILTERSCALE_16BIT) || \
((SCALE) == CAN_FILTERSCALE_32BIT))
#define IS_CAN_FILTER_ACTIVATION(ACTIVATION) (((ACTIVATION) == CAN_FILTER_DISABLE) || \
((ACTIVATION) == CAN_FILTER_ENABLE))
#define IS_CAN_FILTER_FIFO(FIFO) (((FIFO) == CAN_FILTER_FIFO0) || \
((FIFO) == CAN_FILTER_FIFO1))
#define IS_CAN_TX_MAILBOX(TRANSMITMAILBOX) (((TRANSMITMAILBOX) == CAN_TX_MAILBOX0 ) || \
((TRANSMITMAILBOX) == CAN_TX_MAILBOX1 ) || \
((TRANSMITMAILBOX) == CAN_TX_MAILBOX2 ))
#define IS_CAN_TX_MAILBOX_LIST(TRANSMITMAILBOX) ((TRANSMITMAILBOX) <= (CAN_TX_MAILBOX0 | CAN_TX_MAILBOX1 | \
CAN_TX_MAILBOX2))
#define IS_CAN_STDID(STDID) ((STDID) <= 0x7FFU)
#define IS_CAN_EXTID(EXTID) ((EXTID) <= 0x1FFFFFFFU)
#define IS_CAN_DLC(DLC) ((DLC) <= 8U)
#define IS_CAN_IDTYPE(IDTYPE) (((IDTYPE) == CAN_ID_STD) || \
((IDTYPE) == CAN_ID_EXT))
#define IS_CAN_RTR(RTR) (((RTR) == CAN_RTR_DATA) || ((RTR) == CAN_RTR_REMOTE))
#define IS_CAN_RX_FIFO(FIFO) (((FIFO) == CAN_RX_FIFO0) || ((FIFO) == CAN_RX_FIFO1))
#define IS_CAN_IT(IT) ((IT) <= (CAN_IT_TX_MAILBOX_EMPTY | CAN_IT_RX_FIFO0_MSG_PENDING | \
CAN_IT_RX_FIFO0_FULL | CAN_IT_RX_FIFO0_OVERRUN | \
CAN_IT_RX_FIFO1_MSG_PENDING | CAN_IT_RX_FIFO1_FULL | \
CAN_IT_RX_FIFO1_OVERRUN | CAN_IT_WAKEUP | \
CAN_IT_SLEEP_ACK | CAN_IT_ERROR_WARNING | \
CAN_IT_ERROR_PASSIVE | CAN_IT_BUSOFF | \
CAN_IT_LAST_ERROR_CODE | CAN_IT_ERROR))
/**
* @}
*/
/* End of private macros -----------------------------------------------------*/
/**
* @}
*/
#endif /* CAN1 */
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* STM32F1xx_HAL_CAN_H */

View File

@ -0,0 +1,125 @@
/**
******************************************************************************
* @file stm32f1xx_hal_can_ex_legacy.h
* @author MCD Application Team
* @brief Header file of CAN HAL Extension module.
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F1xx_HAL_CAN_EX_LEGACY_H
#define __STM32F1xx_HAL_CAN_EX_LEGACY_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || \
defined(STM32F103xG) || defined(STM32F105xC) || defined(STM32F107xC)
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal_def.h"
/** @addtogroup STM32F1xx_HAL_Driver
* @{
*/
/** @defgroup CANEx CANEx
* @{
*/
/* Exported types ------------------------------------------------------------*/
/**
* @brief CAN filter configuration structure definition
*/
/* CAN filter banks differences over STM32F1 devices: */
/* - STM32F1 Connectivity line: 28 filter banks shared between CAN1 and CAN2 */
/* - Other STM32F10x devices: 14 filter banks */
typedef struct
{
uint32_t FilterIdHigh; /*!< Specifies the filter identification number (MSBs for a 32-bit
configuration, first one for a 16-bit configuration).
This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterIdLow; /*!< Specifies the filter identification number (LSBs for a 32-bit
configuration, second one for a 16-bit configuration).
This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterMaskIdHigh; /*!< Specifies the filter mask number or identification number,
according to the mode (MSBs for a 32-bit configuration,
first one for a 16-bit configuration).
This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterMaskIdLow; /*!< Specifies the filter mask number or identification number,
according to the mode (LSBs for a 32-bit configuration,
second one for a 16-bit configuration).
This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterFIFOAssignment; /*!< Specifies the FIFO (0 or 1) which will be assigned to the filter.
This parameter can be a value of @ref CAN_filter_FIFO */
#if defined(STM32F105xC) || defined(STM32F107xC)
uint32_t FilterNumber; /*!< Specifies the filter which will be initialized.
This parameter must be a number between Min_Data = 0 and Max_Data = 27. */
#else
uint32_t FilterNumber; /*!< Specifies the filter which will be initialized.
This parameter must be a number between Min_Data = 0 and Max_Data = 13. */
#endif /* STM32F105xC || STM32F107xC */
uint32_t FilterMode; /*!< Specifies the filter mode to be initialized.
This parameter can be a value of @ref CAN_filter_mode */
uint32_t FilterScale; /*!< Specifies the filter scale.
This parameter can be a value of @ref CAN_filter_scale */
uint32_t FilterActivation; /*!< Enable or disable the filter.
This parameter can be set to ENABLE or DISABLE. */
uint32_t BankNumber; /*!< Select the start slave bank filter
This parameter must be a number between Min_Data = 0 and Max_Data = 28. */
}CAN_FilterConfTypeDef;
/* Exported constants --------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/** @defgroup CANEx_Private_Macros CAN Extended Private Macros
* @{
*/
#if defined(STM32F105xC) || defined(STM32F107xC)
#define IS_CAN_FILTER_NUMBER(NUMBER) ((NUMBER) <= 27U)
#else
#define IS_CAN_FILTER_NUMBER(NUMBER) ((NUMBER) <= 13U)
#endif /* STM32F105xC || STM32F107xC */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif /* STM32F103x6) || STM32F103xB || STM32F103xE || STM32F103xG) || STM32F105xC || STM32F107xC */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F1xx_HAL_CAN_EX_LEGACY_H */

View File

@ -0,0 +1,776 @@
/**
******************************************************************************
* @file stm32f1xx_hal_can_legacy.h
* @author MCD Application Team
* @brief Header file of CAN HAL module.
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F1xx_HAL_CAN_LEGACY_H
#define __STM32F1xx_HAL_CAN_LEGACY_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || \
defined(STM32F103xG) || defined(STM32F105xC) || defined(STM32F107xC)
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal_def.h"
/** @addtogroup STM32F1xx_HAL_Driver
* @{
*/
/** @addtogroup CAN
* @{
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup CAN_Exported_Types CAN Exported Types
* @{
*/
/**
* @brief HAL State structures definition
*/
typedef enum
{
HAL_CAN_STATE_RESET = 0x00U, /*!< CAN not yet initialized or disabled */
HAL_CAN_STATE_READY = 0x01U, /*!< CAN initialized and ready for use */
HAL_CAN_STATE_BUSY = 0x02U, /*!< CAN process is ongoing */
HAL_CAN_STATE_BUSY_TX = 0x12U, /*!< CAN process is ongoing */
HAL_CAN_STATE_BUSY_RX0 = 0x22U, /*!< CAN process is ongoing */
HAL_CAN_STATE_BUSY_RX1 = 0x32U, /*!< CAN process is ongoing */
HAL_CAN_STATE_BUSY_TX_RX0 = 0x42U, /*!< CAN process is ongoing */
HAL_CAN_STATE_BUSY_TX_RX1 = 0x52U, /*!< CAN process is ongoing */
HAL_CAN_STATE_BUSY_RX0_RX1 = 0x62U, /*!< CAN process is ongoing */
HAL_CAN_STATE_BUSY_TX_RX0_RX1 = 0x72U, /*!< CAN process is ongoing */
HAL_CAN_STATE_TIMEOUT = 0x03U, /*!< CAN in Timeout state */
HAL_CAN_STATE_ERROR = 0x04U /*!< CAN error state */
}HAL_CAN_StateTypeDef;
/**
* @brief CAN init structure definition
*/
typedef struct
{
uint32_t Prescaler; /*!< Specifies the length of a time quantum.
This parameter must be a number between Min_Data = 1 and Max_Data = 1024 */
uint32_t Mode; /*!< Specifies the CAN operating mode.
This parameter can be a value of @ref CAN_operating_mode */
uint32_t SJW; /*!< Specifies the maximum number of time quanta
the CAN hardware is allowed to lengthen or
shorten a bit to perform resynchronization.
This parameter can be a value of @ref CAN_synchronisation_jump_width */
uint32_t BS1; /*!< Specifies the number of time quanta in Bit Segment 1.
This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_1 */
uint32_t BS2; /*!< Specifies the number of time quanta in Bit Segment 2.
This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_2 */
uint32_t TTCM; /*!< Enable or disable the time triggered communication mode.
This parameter can be set to ENABLE or DISABLE. */
uint32_t ABOM; /*!< Enable or disable the automatic bus-off management.
This parameter can be set to ENABLE or DISABLE */
uint32_t AWUM; /*!< Enable or disable the automatic wake-up mode.
This parameter can be set to ENABLE or DISABLE */
uint32_t NART; /*!< Enable or disable the non-automatic retransmission mode.
This parameter can be set to ENABLE or DISABLE */
uint32_t RFLM; /*!< Enable or disable the receive FIFO Locked mode.
This parameter can be set to ENABLE or DISABLE */
uint32_t TXFP; /*!< Enable or disable the transmit FIFO priority.
This parameter can be set to ENABLE or DISABLE */
}CAN_InitTypeDef;
/**
* @brief CAN Tx message structure definition
*/
typedef struct
{
uint32_t StdId; /*!< Specifies the standard identifier.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF */
uint32_t ExtId; /*!< Specifies the extended identifier.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF */
uint32_t IDE; /*!< Specifies the type of identifier for the message that will be transmitted.
This parameter can be a value of @ref CAN_Identifier_Type */
uint32_t RTR; /*!< Specifies the type of frame for the message that will be transmitted.
This parameter can be a value of @ref CAN_remote_transmission_request */
uint32_t DLC; /*!< Specifies the length of the frame that will be transmitted.
This parameter must be a number between Min_Data = 0 and Max_Data = 8 */
uint8_t Data[8]; /*!< Contains the data to be transmitted.
This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF */
}CanTxMsgTypeDef;
/**
* @brief CAN Rx message structure definition
*/
typedef struct
{
uint32_t StdId; /*!< Specifies the standard identifier.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF */
uint32_t ExtId; /*!< Specifies the extended identifier.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF */
uint32_t IDE; /*!< Specifies the type of identifier for the message that will be received.
This parameter can be a value of @ref CAN_Identifier_Type */
uint32_t RTR; /*!< Specifies the type of frame for the received message.
This parameter can be a value of @ref CAN_remote_transmission_request */
uint32_t DLC; /*!< Specifies the length of the frame that will be received.
This parameter must be a number between Min_Data = 0 and Max_Data = 8 */
uint8_t Data[8]; /*!< Contains the data to be received.
This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF */
uint32_t FMI; /*!< Specifies the index of the filter the message stored in the mailbox passes through.
This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF */
uint32_t FIFONumber; /*!< Specifies the receive FIFO number.
This parameter can be CAN_FIFO0 or CAN_FIFO1 */
}CanRxMsgTypeDef;
/**
* @brief CAN handle Structure definition
*/
typedef struct
{
CAN_TypeDef *Instance; /*!< Register base address */
CAN_InitTypeDef Init; /*!< CAN required parameters */
CanTxMsgTypeDef* pTxMsg; /*!< Pointer to transmit structure */
CanRxMsgTypeDef* pRxMsg; /*!< Pointer to reception structure for RX FIFO0 msg */
CanRxMsgTypeDef* pRx1Msg; /*!< Pointer to reception structure for RX FIFO1 msg */
__IO HAL_CAN_StateTypeDef State; /*!< CAN communication state */
HAL_LockTypeDef Lock; /*!< CAN locking object */
__IO uint32_t ErrorCode; /*!< CAN Error code */
}CAN_HandleTypeDef;
/**
* @}
*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup CAN_Exported_Constants CAN Exported Constants
* @{
*/
/** @defgroup CAN_Error_Code CAN Error Code
* @{
*/
#define HAL_CAN_ERROR_NONE 0x00000000U /*!< No error */
#define HAL_CAN_ERROR_EWG 0x00000001U /*!< EWG error */
#define HAL_CAN_ERROR_EPV 0x00000002U /*!< EPV error */
#define HAL_CAN_ERROR_BOF 0x00000004U /*!< BOF error */
#define HAL_CAN_ERROR_STF 0x00000008U /*!< Stuff error */
#define HAL_CAN_ERROR_FOR 0x00000010U /*!< Form error */
#define HAL_CAN_ERROR_ACK 0x00000020U /*!< Acknowledgment error */
#define HAL_CAN_ERROR_BR 0x00000040U /*!< Bit recessive */
#define HAL_CAN_ERROR_BD 0x00000080U /*!< LEC dominant */
#define HAL_CAN_ERROR_CRC 0x00000100U /*!< LEC transfer error */
#define HAL_CAN_ERROR_FOV0 0x00000200U /*!< FIFO0 overrun error */
#define HAL_CAN_ERROR_FOV1 0x00000400U /*!< FIFO1 overrun error */
#define HAL_CAN_ERROR_TXFAIL 0x00000800U /*!< Transmit failure */
/**
* @}
*/
/** @defgroup CAN_InitStatus CAN initialization Status
* @{
*/
#define CAN_INITSTATUS_FAILED 0x00000000U /*!< CAN initialization failed */
#define CAN_INITSTATUS_SUCCESS 0x00000001U /*!< CAN initialization OK */
/**
* @}
*/
/** @defgroup CAN_operating_mode CAN Operating Mode
* @{
*/
#define CAN_MODE_NORMAL 0x00000000U /*!< Normal mode */
#define CAN_MODE_LOOPBACK ((uint32_t)CAN_BTR_LBKM) /*!< Loopback mode */
#define CAN_MODE_SILENT ((uint32_t)CAN_BTR_SILM) /*!< Silent mode */
#define CAN_MODE_SILENT_LOOPBACK ((uint32_t)(CAN_BTR_LBKM | CAN_BTR_SILM)) /*!< Loopback combined with silent mode */
/**
* @}
*/
/** @defgroup CAN_synchronisation_jump_width CAN Synchronization Jump Width
* @{
*/
#define CAN_SJW_1TQ 0x00000000U /*!< 1 time quantum */
#define CAN_SJW_2TQ ((uint32_t)CAN_BTR_SJW_0) /*!< 2 time quantum */
#define CAN_SJW_3TQ ((uint32_t)CAN_BTR_SJW_1) /*!< 3 time quantum */
#define CAN_SJW_4TQ ((uint32_t)CAN_BTR_SJW) /*!< 4 time quantum */
/**
* @}
*/
/** @defgroup CAN_time_quantum_in_bit_segment_1 CAN Time Quantum in Bit Segment 1
* @{
*/
#define CAN_BS1_1TQ 0x00000000U /*!< 1 time quantum */
#define CAN_BS1_2TQ ((uint32_t)CAN_BTR_TS1_0) /*!< 2 time quantum */
#define CAN_BS1_3TQ ((uint32_t)CAN_BTR_TS1_1) /*!< 3 time quantum */
#define CAN_BS1_4TQ ((uint32_t)(CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 4 time quantum */
#define CAN_BS1_5TQ ((uint32_t)CAN_BTR_TS1_2) /*!< 5 time quantum */
#define CAN_BS1_6TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_0)) /*!< 6 time quantum */
#define CAN_BS1_7TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_1)) /*!< 7 time quantum */
#define CAN_BS1_8TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 8 time quantum */
#define CAN_BS1_9TQ ((uint32_t)CAN_BTR_TS1_3) /*!< 9 time quantum */
#define CAN_BS1_10TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_0)) /*!< 10 time quantum */
#define CAN_BS1_11TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_1)) /*!< 11 time quantum */
#define CAN_BS1_12TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 12 time quantum */
#define CAN_BS1_13TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2)) /*!< 13 time quantum */
#define CAN_BS1_14TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2 | CAN_BTR_TS1_0)) /*!< 14 time quantum */
#define CAN_BS1_15TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2 | CAN_BTR_TS1_1)) /*!< 15 time quantum */
#define CAN_BS1_16TQ ((uint32_t)CAN_BTR_TS1) /*!< 16 time quantum */
/**
* @}
*/
/** @defgroup CAN_time_quantum_in_bit_segment_2 CAN Time Quantum in bit segment 2
* @{
*/
#define CAN_BS2_1TQ 0x00000000U /*!< 1 time quantum */
#define CAN_BS2_2TQ ((uint32_t)CAN_BTR_TS2_0) /*!< 2 time quantum */
#define CAN_BS2_3TQ ((uint32_t)CAN_BTR_TS2_1) /*!< 3 time quantum */
#define CAN_BS2_4TQ ((uint32_t)(CAN_BTR_TS2_1 | CAN_BTR_TS2_0)) /*!< 4 time quantum */
#define CAN_BS2_5TQ ((uint32_t)CAN_BTR_TS2_2) /*!< 5 time quantum */
#define CAN_BS2_6TQ ((uint32_t)(CAN_BTR_TS2_2 | CAN_BTR_TS2_0)) /*!< 6 time quantum */
#define CAN_BS2_7TQ ((uint32_t)(CAN_BTR_TS2_2 | CAN_BTR_TS2_1)) /*!< 7 time quantum */
#define CAN_BS2_8TQ ((uint32_t)CAN_BTR_TS2) /*!< 8 time quantum */
/**
* @}
*/
/** @defgroup CAN_filter_mode CAN Filter Mode
* @{
*/
#define CAN_FILTERMODE_IDMASK ((uint8_t)0x00) /*!< Identifier mask mode */
#define CAN_FILTERMODE_IDLIST ((uint8_t)0x01) /*!< Identifier list mode */
/**
* @}
*/
/** @defgroup CAN_filter_scale CAN Filter Scale
* @{
*/
#define CAN_FILTERSCALE_16BIT ((uint8_t)0x00) /*!< Two 16-bit filters */
#define CAN_FILTERSCALE_32BIT ((uint8_t)0x01) /*!< One 32-bit filter */
/**
* @}
*/
/** @defgroup CAN_filter_FIFO CAN Filter FIFO
* @{
*/
#define CAN_FILTER_FIFO0 ((uint8_t)0x00) /*!< Filter FIFO 0 assignment for filter x */
#define CAN_FILTER_FIFO1 ((uint8_t)0x01) /*!< Filter FIFO 1 assignment for filter x */
/**
* @}
*/
/** @defgroup CAN_Identifier_Type CAN Identifier Type
* @{
*/
#define CAN_ID_STD 0x00000000U /*!< Standard Id */
#define CAN_ID_EXT 0x00000004U /*!< Extended Id */
/**
* @}
*/
/** @defgroup CAN_remote_transmission_request CAN Remote Transmission Request
* @{
*/
#define CAN_RTR_DATA 0x00000000U /*!< Data frame */
#define CAN_RTR_REMOTE 0x00000002U /*!< Remote frame */
/**
* @}
*/
/** @defgroup CAN_transmit_constants CAN Transmit Constants
* @{
*/
#define CAN_TXSTATUS_NOMAILBOX ((uint8_t)0x04) /*!< CAN cell did not provide CAN_TxStatus_NoMailBox */
/**
* @}
*/
/** @defgroup CAN_receive_FIFO_number_constants CAN Receive FIFO Number
* @{
*/
#define CAN_FIFO0 ((uint8_t)0x00) /*!< CAN FIFO 0 used to receive */
#define CAN_FIFO1 ((uint8_t)0x01) /*!< CAN FIFO 1 used to receive */
/**
* @}
*/
/** @defgroup CAN_flags CAN Flags
* @{
*/
/* If the flag is 0x3XXXXXXX, it means that it can be used with CAN_GetFlagStatus()
and CAN_ClearFlag() functions. */
/* If the flag is 0x1XXXXXXX, it means that it can only be used with
CAN_GetFlagStatus() function. */
/* Transmit Flags */
#define CAN_FLAG_RQCP0 ((uint32_t)((TSR_REGISTER_INDEX << 8U) | CAN_TSR_RQCP0_BIT_POSITION)) /*!< Request MailBox0 flag */
#define CAN_FLAG_RQCP1 ((uint32_t)((TSR_REGISTER_INDEX << 8U) | CAN_TSR_RQCP1_BIT_POSITION)) /*!< Request MailBox1 flag */
#define CAN_FLAG_RQCP2 ((uint32_t)((TSR_REGISTER_INDEX << 8U) | CAN_TSR_RQCP2_BIT_POSITION)) /*!< Request MailBox2 flag */
#define CAN_FLAG_TXOK0 ((uint32_t)((TSR_REGISTER_INDEX << 8U) | CAN_TSR_TXOK0_BIT_POSITION)) /*!< Transmission OK MailBox0 flag */
#define CAN_FLAG_TXOK1 ((uint32_t)((TSR_REGISTER_INDEX << 8U) | CAN_TSR_TXOK1_BIT_POSITION)) /*!< Transmission OK MailBox1 flag */
#define CAN_FLAG_TXOK2 ((uint32_t)((TSR_REGISTER_INDEX << 8U) | CAN_TSR_TXOK2_BIT_POSITION)) /*!< Transmission OK MailBox2 flag */
#define CAN_FLAG_TME0 ((uint32_t)((TSR_REGISTER_INDEX << 8U) | CAN_TSR_TME0_BIT_POSITION)) /*!< Transmit mailbox 0 empty flag */
#define CAN_FLAG_TME1 ((uint32_t)((TSR_REGISTER_INDEX << 8U) | CAN_TSR_TME1_BIT_POSITION)) /*!< Transmit mailbox 0 empty flag */
#define CAN_FLAG_TME2 ((uint32_t)((TSR_REGISTER_INDEX << 8U) | CAN_TSR_TME2_BIT_POSITION)) /*!< Transmit mailbox 0 empty flag */
/* Receive Flags */
#define CAN_FLAG_FF0 ((uint32_t)((RF0R_REGISTER_INDEX << 8U) | CAN_RF0R_FF0_BIT_POSITION)) /*!< FIFO 0 Full flag */
#define CAN_FLAG_FOV0 ((uint32_t)((RF0R_REGISTER_INDEX << 8U) | CAN_RF0R_FOV0_BIT_POSITION)) /*!< FIFO 0 Overrun flag */
#define CAN_FLAG_FF1 ((uint32_t)((RF1R_REGISTER_INDEX << 8U) | CAN_RF1R_FF1_BIT_POSITION)) /*!< FIFO 1 Full flag */
#define CAN_FLAG_FOV1 ((uint32_t)((RF1R_REGISTER_INDEX << 8U) | CAN_RF1R_FOV1_BIT_POSITION)) /*!< FIFO 1 Overrun flag */
/* Operating Mode Flags */
#define CAN_FLAG_WKU ((uint32_t)((MSR_REGISTER_INDEX << 8U) | CAN_MSR_WKU_BIT_POSITION)) /*!< Wake up flag */
#define CAN_FLAG_SLAK ((uint32_t)((MSR_REGISTER_INDEX << 8U) | CAN_MSR_SLAK_BIT_POSITION)) /*!< Sleep acknowledge flag */
#define CAN_FLAG_SLAKI ((uint32_t)((MSR_REGISTER_INDEX << 8U) | CAN_MSR_SLAKI_BIT_POSITION)) /*!< Sleep acknowledge flag */
/* @note When SLAK interrupt is disabled (SLKIE=0), no polling on SLAKI is possible.
In this case the SLAK bit can be polled.*/
/* Error Flags */
#define CAN_FLAG_EWG ((uint32_t)((ESR_REGISTER_INDEX << 8U) | CAN_ESR_EWG_BIT_POSITION)) /*!< Error warning flag */
#define CAN_FLAG_EPV ((uint32_t)((ESR_REGISTER_INDEX << 8U) | CAN_ESR_EPV_BIT_POSITION)) /*!< Error passive flag */
#define CAN_FLAG_BOF ((uint32_t)((ESR_REGISTER_INDEX << 8U) | CAN_ESR_BOF_BIT_POSITION)) /*!< Bus-Off flag */
/**
* @}
*/
/** @defgroup CAN_Interrupts CAN Interrupts
* @{
*/
#define CAN_IT_TME ((uint32_t)CAN_IER_TMEIE) /*!< Transmit mailbox empty interrupt */
/* Receive Interrupts */
#define CAN_IT_FMP0 ((uint32_t)CAN_IER_FMPIE0) /*!< FIFO 0 message pending interrupt */
#define CAN_IT_FF0 ((uint32_t)CAN_IER_FFIE0) /*!< FIFO 0 full interrupt */
#define CAN_IT_FOV0 ((uint32_t)CAN_IER_FOVIE0) /*!< FIFO 0 overrun interrupt */
#define CAN_IT_FMP1 ((uint32_t)CAN_IER_FMPIE1) /*!< FIFO 1 message pending interrupt */
#define CAN_IT_FF1 ((uint32_t)CAN_IER_FFIE1) /*!< FIFO 1 full interrupt */
#define CAN_IT_FOV1 ((uint32_t)CAN_IER_FOVIE1) /*!< FIFO 1 overrun interrupt */
/* Operating Mode Interrupts */
#define CAN_IT_WKU ((uint32_t)CAN_IER_WKUIE) /*!< Wake-up interrupt */
#define CAN_IT_SLK ((uint32_t)CAN_IER_SLKIE) /*!< Sleep acknowledge interrupt */
/* Error Interrupts */
#define CAN_IT_EWG ((uint32_t)CAN_IER_EWGIE) /*!< Error warning interrupt */
#define CAN_IT_EPV ((uint32_t)CAN_IER_EPVIE) /*!< Error passive interrupt */
#define CAN_IT_BOF ((uint32_t)CAN_IER_BOFIE) /*!< Bus-off interrupt */
#define CAN_IT_LEC ((uint32_t)CAN_IER_LECIE) /*!< Last error code interrupt */
#define CAN_IT_ERR ((uint32_t)CAN_IER_ERRIE) /*!< Error Interrupt */
/**
* @}
*/
/**
* @}
*/
/** @defgroup CAN_Private_Constants CAN Private Constants
* @{
*/
/* CAN intermediate shift values used for CAN flags */
#define TSR_REGISTER_INDEX 0x5U
#define RF0R_REGISTER_INDEX 0x2U
#define RF1R_REGISTER_INDEX 0x4U
#define MSR_REGISTER_INDEX 0x1U
#define ESR_REGISTER_INDEX 0x3U
/* CAN flags bits position into their respective register (TSR, RF0R, RF1R or MSR registers) */
/* Transmit Flags */
#define CAN_TSR_RQCP0_BIT_POSITION 0x00000000U
#define CAN_TSR_RQCP1_BIT_POSITION 0x00000008U
#define CAN_TSR_RQCP2_BIT_POSITION 0x00000010U
#define CAN_TSR_TXOK0_BIT_POSITION 0x00000001U
#define CAN_TSR_TXOK1_BIT_POSITION 0x00000009U
#define CAN_TSR_TXOK2_BIT_POSITION 0x00000011U
#define CAN_TSR_TME0_BIT_POSITION 0x0000001AU
#define CAN_TSR_TME1_BIT_POSITION 0x0000001BU
#define CAN_TSR_TME2_BIT_POSITION 0x0000001CU
/* Receive Flags */
#define CAN_RF0R_FF0_BIT_POSITION 0x00000003U
#define CAN_RF0R_FOV0_BIT_POSITION 0x00000004U
#define CAN_RF1R_FF1_BIT_POSITION 0x00000003U
#define CAN_RF1R_FOV1_BIT_POSITION 0x00000004U
/* Operating Mode Flags */
#define CAN_MSR_WKU_BIT_POSITION 0x00000003U
#define CAN_MSR_SLAK_BIT_POSITION 0x00000001U
#define CAN_MSR_SLAKI_BIT_POSITION 0x00000004U
/* Error Flags */
#define CAN_ESR_EWG_BIT_POSITION 0x00000000U
#define CAN_ESR_EPV_BIT_POSITION 0x00000001U
#define CAN_ESR_BOF_BIT_POSITION 0x00000002U
/* Mask used by macro to get/clear CAN flags*/
#define CAN_FLAG_MASK 0x000000FFU
/* Mailboxes definition */
#define CAN_TXMAILBOX_0 ((uint8_t)0x00)
#define CAN_TXMAILBOX_1 ((uint8_t)0x01)
#define CAN_TXMAILBOX_2 ((uint8_t)0x02)
/**
* @}
*/
/* Exported macros -----------------------------------------------------------*/
/** @defgroup CAN_Exported_Macros CAN Exported Macros
* @{
*/
/** @brief Reset CAN handle state
* @param __HANDLE__: CAN handle.
* @retval None
*/
#define __HAL_CAN_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_CAN_STATE_RESET)
/**
* @brief Enable the specified CAN interrupts
* @param __HANDLE__: CAN handle.
* @param __INTERRUPT__: CAN Interrupt.
* This parameter can be one of the following values:
* @arg CAN_IT_TME: Transmit mailbox empty interrupt enable
* @arg CAN_IT_FMP0: FIFO 0 message pending interrupt
* @arg CAN_IT_FF0 : FIFO 0 full interrupt
* @arg CAN_IT_FOV0: FIFO 0 overrun interrupt
* @arg CAN_IT_FMP1: FIFO 1 message pending interrupt
* @arg CAN_IT_FF1 : FIFO 1 full interrupt
* @arg CAN_IT_FOV1: FIFO 1 overrun interrupt
* @arg CAN_IT_WKU : Wake-up interrupt
* @arg CAN_IT_SLK : Sleep acknowledge interrupt
* @arg CAN_IT_EWG : Error warning interrupt
* @arg CAN_IT_EPV : Error passive interrupt
* @arg CAN_IT_BOF : Bus-off interrupt
* @arg CAN_IT_LEC : Last error code interrupt
* @arg CAN_IT_ERR : Error Interrupt
* @retval None.
*/
#define __HAL_CAN_ENABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) |= (__INTERRUPT__))
/**
* @brief Disable the specified CAN interrupts
* @param __HANDLE__: CAN handle.
* @param __INTERRUPT__: CAN Interrupt.
* This parameter can be one of the following values:
* @arg CAN_IT_TME: Transmit mailbox empty interrupt enable
* @arg CAN_IT_FMP0: FIFO 0 message pending interrupt
* @arg CAN_IT_FF0 : FIFO 0 full interrupt
* @arg CAN_IT_FOV0: FIFO 0 overrun interrupt
* @arg CAN_IT_FMP1: FIFO 1 message pending interrupt
* @arg CAN_IT_FF1 : FIFO 1 full interrupt
* @arg CAN_IT_FOV1: FIFO 1 overrun interrupt
* @arg CAN_IT_WKU : Wake-up interrupt
* @arg CAN_IT_SLK : Sleep acknowledge interrupt
* @arg CAN_IT_EWG : Error warning interrupt
* @arg CAN_IT_EPV : Error passive interrupt
* @arg CAN_IT_BOF : Bus-off interrupt
* @arg CAN_IT_LEC : Last error code interrupt
* @arg CAN_IT_ERR : Error Interrupt
* @retval None.
*/
#define __HAL_CAN_DISABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) &= ~(__INTERRUPT__))
/**
* @brief Return the number of pending received messages.
* @param __HANDLE__: CAN handle.
* @param __FIFONUMBER__: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1.
* @retval The number of pending message.
*/
#define __HAL_CAN_MSG_PENDING(__HANDLE__, __FIFONUMBER__) (((__FIFONUMBER__) == CAN_FIFO0)? \
((uint8_t)((__HANDLE__)->Instance->RF0R & 0x03U)) : ((uint8_t)((__HANDLE__)->Instance->RF1R & 0x03U)))
/** @brief Check whether the specified CAN flag is set or not.
* @param __HANDLE__: specifies the CAN Handle.
* @param __FLAG__: specifies the flag to check.
* This parameter can be one of the following values:
* @arg CAN_TSR_RQCP0: Request MailBox0 Flag
* @arg CAN_TSR_RQCP1: Request MailBox1 Flag
* @arg CAN_TSR_RQCP2: Request MailBox2 Flag
* @arg CAN_FLAG_TXOK0: Transmission OK MailBox0 Flag
* @arg CAN_FLAG_TXOK1: Transmission OK MailBox1 Flag
* @arg CAN_FLAG_TXOK2: Transmission OK MailBox2 Flag
* @arg CAN_FLAG_TME0: Transmit mailbox 0 empty Flag
* @arg CAN_FLAG_TME1: Transmit mailbox 1 empty Flag
* @arg CAN_FLAG_TME2: Transmit mailbox 2 empty Flag
* @arg CAN_FLAG_FMP0: FIFO 0 Message Pending Flag
* @arg CAN_FLAG_FF0: FIFO 0 Full Flag
* @arg CAN_FLAG_FOV0: FIFO 0 Overrun Flag
* @arg CAN_FLAG_FMP1: FIFO 1 Message Pending Flag
* @arg CAN_FLAG_FF1: FIFO 1 Full Flag
* @arg CAN_FLAG_FOV1: FIFO 1 Overrun Flag
* @arg CAN_FLAG_WKU: Wake up Flag
* @arg CAN_FLAG_SLAK: Sleep acknowledge Flag
* @arg CAN_FLAG_SLAKI: Sleep acknowledge Flag
* @arg CAN_FLAG_EWG: Error Warning Flag
* @arg CAN_FLAG_EPV: Error Passive Flag
* @arg CAN_FLAG_BOF: Bus-Off Flag
* @retval The new state of __FLAG__ (TRUE or FALSE).
*/
#define __HAL_CAN_GET_FLAG(__HANDLE__, __FLAG__) \
((((__FLAG__) >> 8U) == 5U)? ((((__HANDLE__)->Instance->TSR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 2U)? ((((__HANDLE__)->Instance->RF0R) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 4U)? ((((__HANDLE__)->Instance->RF1R) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 1U)? ((((__HANDLE__)->Instance->MSR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
((((__HANDLE__)->Instance->ESR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))))
/** @brief Clear the specified CAN pending flag.
* @param __HANDLE__: specifies the CAN Handle.
* @param __FLAG__: specifies the flag to check.
* This parameter can be one of the following values:
* @arg CAN_TSR_RQCP0: Request MailBox0 Flag
* @arg CAN_TSR_RQCP1: Request MailBox1 Flag
* @arg CAN_TSR_RQCP2: Request MailBox2 Flag
* @arg CAN_FLAG_TXOK0: Transmission OK MailBox0 Flag
* @arg CAN_FLAG_TXOK1: Transmission OK MailBox1 Flag
* @arg CAN_FLAG_TXOK2: Transmission OK MailBox2 Flag
* @arg CAN_FLAG_TME0: Transmit mailbox 0 empty Flag
* @arg CAN_FLAG_TME1: Transmit mailbox 1 empty Flag
* @arg CAN_FLAG_TME2: Transmit mailbox 2 empty Flag
* @arg CAN_FLAG_FMP0: FIFO 0 Message Pending Flag
* @arg CAN_FLAG_FF0: FIFO 0 Full Flag
* @arg CAN_FLAG_FOV0: FIFO 0 Overrun Flag
* @arg CAN_FLAG_FMP1: FIFO 1 Message Pending Flag
* @arg CAN_FLAG_FF1: FIFO 1 Full Flag
* @arg CAN_FLAG_FOV1: FIFO 1 Overrun Flag
* @arg CAN_FLAG_WKU: Wake up Flag
* @arg CAN_FLAG_SLAKI: Sleep acknowledge Flag
* @retval The new state of __FLAG__ (TRUE or FALSE).
*/
#define __HAL_CAN_CLEAR_FLAG(__HANDLE__, __FLAG__) \
((((__FLAG__) >> 8U) == TSR_REGISTER_INDEX) ? (((__HANDLE__)->Instance->TSR) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == RF0R_REGISTER_INDEX)? (((__HANDLE__)->Instance->RF0R) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == RF1R_REGISTER_INDEX)? (((__HANDLE__)->Instance->RF1R) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == MSR_REGISTER_INDEX) ? (((__HANDLE__)->Instance->MSR) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): 0U)
/** @brief Check if the specified CAN interrupt source is enabled or disabled.
* @param __HANDLE__: specifies the CAN Handle.
* @param __INTERRUPT__: specifies the CAN interrupt source to check.
* This parameter can be one of the following values:
* @arg CAN_IT_TME: Transmit mailbox empty interrupt enable
* @arg CAN_IT_FMP0: FIFO 0 message pending interrupt
* @arg CAN_IT_FF0 : FIFO 0 full interrupt
* @arg CAN_IT_FOV0: FIFO 0 overrun interrupt
* @arg CAN_IT_FMP1: FIFO 1 message pending interrupt
* @arg CAN_IT_FF1 : FIFO 1 full interrupt
* @arg CAN_IT_FOV1: FIFO 1 overrun interrupt
* @arg CAN_IT_WKU : Wake-up interrupt
* @arg CAN_IT_SLK : Sleep acknowledge interrupt
* @arg CAN_IT_EWG : Error warning interrupt
* @arg CAN_IT_EPV : Error passive interrupt
* @arg CAN_IT_BOF : Bus-off interrupt
* @arg CAN_IT_LEC : Last error code interrupt
* @arg CAN_IT_ERR : Error Interrupt
* @retval The new state of __IT__ (TRUE or FALSE).
*/
#define __HAL_CAN_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) ((((__HANDLE__)->Instance->IER & (__INTERRUPT__)) == (__INTERRUPT__)) ? SET : RESET)
/**
* @brief Check the transmission status of a CAN Frame.
* @param __HANDLE__: specifies the CAN Handle.
* @param __TRANSMITMAILBOX__: the number of the mailbox that is used for transmission.
* @retval The new status of transmission (TRUE or FALSE).
*/
#define __HAL_CAN_TRANSMIT_STATUS(__HANDLE__, __TRANSMITMAILBOX__)\
(((__TRANSMITMAILBOX__) == CAN_TXMAILBOX_0)? ((((__HANDLE__)->Instance->TSR) & (CAN_TSR_RQCP0 | CAN_TSR_TME0)) == (CAN_TSR_RQCP0 | CAN_TSR_TME0)) :\
((__TRANSMITMAILBOX__) == CAN_TXMAILBOX_1)? ((((__HANDLE__)->Instance->TSR) & (CAN_TSR_RQCP1 | CAN_TSR_TME1)) == (CAN_TSR_RQCP1 | CAN_TSR_TME1)) :\
((((__HANDLE__)->Instance->TSR) & (CAN_TSR_RQCP2 | CAN_TSR_TME2)) == (CAN_TSR_RQCP2 | CAN_TSR_TME2)))
/**
* @brief Release the specified receive FIFO.
* @param __HANDLE__: CAN handle.
* @param __FIFONUMBER__: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1.
* @retval None.
*/
#define __HAL_CAN_FIFO_RELEASE(__HANDLE__, __FIFONUMBER__) (((__FIFONUMBER__) == CAN_FIFO0)? \
((__HANDLE__)->Instance->RF0R = CAN_RF0R_RFOM0) : ((__HANDLE__)->Instance->RF1R = CAN_RF1R_RFOM1))
/**
* @brief Cancel a transmit request.
* @param __HANDLE__: specifies the CAN Handle.
* @param __TRANSMITMAILBOX__: the number of the mailbox that is used for transmission.
* @retval None.
*/
#define __HAL_CAN_CANCEL_TRANSMIT(__HANDLE__, __TRANSMITMAILBOX__)\
(((__TRANSMITMAILBOX__) == CAN_TXMAILBOX_0)? ((__HANDLE__)->Instance->TSR = CAN_TSR_ABRQ0) :\
((__TRANSMITMAILBOX__) == CAN_TXMAILBOX_1)? ((__HANDLE__)->Instance->TSR = CAN_TSR_ABRQ1) :\
((__HANDLE__)->Instance->TSR = CAN_TSR_ABRQ2))
/**
* @brief Enable or disables the DBG Freeze for CAN.
* @param __HANDLE__: specifies the CAN Handle.
* @param __NEWSTATE__: new state of the CAN peripheral.
* This parameter can be: ENABLE (CAN reception/transmission is frozen
* during debug. Reception FIFOs can still be accessed/controlled normally)
* or DISABLE (CAN is working during debug).
* @retval None
*/
#define __HAL_CAN_DBG_FREEZE(__HANDLE__, __NEWSTATE__) (((__NEWSTATE__) == ENABLE)? \
((__HANDLE__)->Instance->MCR |= CAN_MCR_DBF) : ((__HANDLE__)->Instance->MCR &= ~CAN_MCR_DBF))
/**
* @}
*/
/* Include CAN HAL Extension module */
#include "stm32f1xx_hal_can_ex_legacy.h"
/* Exported functions --------------------------------------------------------*/
/** @addtogroup CAN_Exported_Functions
* @{
*/
/** @addtogroup CAN_Exported_Functions_Group1
* @brief Initialization and Configuration functions
* @{
*/
/* Initialization and de-initialization functions *****************************/
HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan);
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef* hcan, CAN_FilterConfTypeDef* sFilterConfig);
HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef* hcan);
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan);
void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan);
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group2
* @brief I/O operation functions
* @{
*/
/* I/O operation functions *****************************************************/
HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout);
HAL_StatusTypeDef HAL_CAN_Transmit_IT(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_Receive(CAN_HandleTypeDef *hcan, uint8_t FIFONumber, uint32_t Timeout);
HAL_StatusTypeDef HAL_CAN_Receive_IT(CAN_HandleTypeDef *hcan, uint8_t FIFONumber);
HAL_StatusTypeDef HAL_CAN_Sleep(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef *hcan);
void HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan);
void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan);
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan);
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan);
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group3
* @brief CAN Peripheral State functions
* @{
*/
/* Peripheral State and Error functions ***************************************/
uint32_t HAL_CAN_GetError(CAN_HandleTypeDef *hcan);
HAL_CAN_StateTypeDef HAL_CAN_GetState(CAN_HandleTypeDef* hcan);
/**
* @}
*/
/**
* @}
*/
/* Private macros --------------------------------------------------------*/
/** @defgroup CAN_Private_Macros CAN Private Macros
* @{
*/
#define IS_CAN_MODE(MODE) (((MODE) == CAN_MODE_NORMAL) || \
((MODE) == CAN_MODE_LOOPBACK)|| \
((MODE) == CAN_MODE_SILENT) || \
((MODE) == CAN_MODE_SILENT_LOOPBACK))
#define IS_CAN_SJW(SJW) (((SJW) == CAN_SJW_1TQ) || ((SJW) == CAN_SJW_2TQ)|| \
((SJW) == CAN_SJW_3TQ) || ((SJW) == CAN_SJW_4TQ))
#define IS_CAN_BS1(BS1) ((BS1) <= CAN_BS1_16TQ)
#define IS_CAN_BS2(BS2) ((BS2) <= CAN_BS2_8TQ)
#define IS_CAN_PRESCALER(PRESCALER) (((PRESCALER) >= 1U) && ((PRESCALER) <= 1024U))
#define IS_CAN_FILTER_MODE(MODE) (((MODE) == CAN_FILTERMODE_IDMASK) || \
((MODE) == CAN_FILTERMODE_IDLIST))
#define IS_CAN_FILTER_SCALE(SCALE) (((SCALE) == CAN_FILTERSCALE_16BIT) || \
((SCALE) == CAN_FILTERSCALE_32BIT))
#define IS_CAN_FILTER_FIFO(FIFO) (((FIFO) == CAN_FILTER_FIFO0) || \
((FIFO) == CAN_FILTER_FIFO1))
#define IS_CAN_BANKNUMBER(BANKNUMBER) ((BANKNUMBER) <= 28U)
#define IS_CAN_TRANSMITMAILBOX(TRANSMITMAILBOX) ((TRANSMITMAILBOX) <= ((uint8_t)0x02))
#define IS_CAN_STDID(STDID) ((STDID) <= 0x00007FFU)
#define IS_CAN_EXTID(EXTID) ((EXTID) <= 0x1FFFFFFFU)
#define IS_CAN_DLC(DLC) ((DLC) <= ((uint8_t)0x08))
#define IS_CAN_IDTYPE(IDTYPE) (((IDTYPE) == CAN_ID_STD) || \
((IDTYPE) == CAN_ID_EXT))
#define IS_CAN_RTR(RTR) (((RTR) == CAN_RTR_DATA) || ((RTR) == CAN_RTR_REMOTE))
#define IS_CAN_FIFO(FIFO) (((FIFO) == CAN_FIFO0) || ((FIFO) == CAN_FIFO1))
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#endif /* STM32F103x6) || STM32F103xB || STM32F103xE || STM32F103xG) || STM32F105xC || STM32F107xC */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F1xx_HAL_CAN_LEGACY_H */

View File

@ -0,0 +1,859 @@
/**
******************************************************************************
* @file stm32f1xx_hal_can.h
* @author MCD Application Team
* @brief Header file of CAN HAL module.
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32F1xx_HAL_CAN_H
#define STM32F1xx_HAL_CAN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal_def.h"
/** @addtogroup STM32F1xx_HAL_Driver
* @{
*/
#if defined (CAN1)
/** @addtogroup CAN
* @{
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup CAN_Exported_Types CAN Exported Types
* @{
*/
/**
* @brief HAL State structures definition
*/
typedef enum
{
HAL_CAN_STATE_RESET = 0x00U, /*!< CAN not yet initialized or disabled */
HAL_CAN_STATE_READY = 0x01U, /*!< CAN initialized and ready for use */
HAL_CAN_STATE_LISTENING = 0x02U, /*!< CAN receive process is ongoing */
HAL_CAN_STATE_SLEEP_PENDING = 0x03U, /*!< CAN sleep request is pending */
HAL_CAN_STATE_SLEEP_ACTIVE = 0x04U, /*!< CAN sleep mode is active */
HAL_CAN_STATE_ERROR = 0x05U /*!< CAN error state */
} HAL_CAN_StateTypeDef;
/**
* @brief CAN init structure definition
*/
typedef struct
{
uint32_t Prescaler; /*!< Specifies the length of a time quantum.
This parameter must be a number between Min_Data = 1 and Max_Data = 1024. */
uint32_t Mode; /*!< Specifies the CAN operating mode.
This parameter can be a value of @ref CAN_operating_mode */
uint32_t SyncJumpWidth; /*!< Specifies the maximum number of time quanta the CAN hardware
is allowed to lengthen or shorten a bit to perform resynchronization.
This parameter can be a value of @ref CAN_synchronisation_jump_width */
uint32_t TimeSeg1; /*!< Specifies the number of time quanta in Bit Segment 1.
This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_1 */
uint32_t TimeSeg2; /*!< Specifies the number of time quanta in Bit Segment 2.
This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_2 */
FunctionalState TimeTriggeredMode; /*!< Enable or disable the time triggered communication mode.
This parameter can be set to ENABLE or DISABLE. */
FunctionalState AutoBusOff; /*!< Enable or disable the automatic bus-off management.
This parameter can be set to ENABLE or DISABLE. */
FunctionalState AutoWakeUp; /*!< Enable or disable the automatic wake-up mode.
This parameter can be set to ENABLE or DISABLE. */
FunctionalState AutoRetransmission; /*!< Enable or disable the non-automatic retransmission mode.
This parameter can be set to ENABLE or DISABLE. */
FunctionalState ReceiveFifoLocked; /*!< Enable or disable the Receive FIFO Locked mode.
This parameter can be set to ENABLE or DISABLE. */
FunctionalState TransmitFifoPriority;/*!< Enable or disable the transmit FIFO priority.
This parameter can be set to ENABLE or DISABLE. */
} CAN_InitTypeDef;
/**
* @brief CAN filter configuration structure definition
*/
typedef struct
{
uint32_t FilterIdHigh; /*!< Specifies the filter identification number (MSBs for a 32-bit
configuration, first one for a 16-bit configuration).
This parameter must be a number between
Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterIdLow; /*!< Specifies the filter identification number (LSBs for a 32-bit
configuration, second one for a 16-bit configuration).
This parameter must be a number between
Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterMaskIdHigh; /*!< Specifies the filter mask number or identification number,
according to the mode (MSBs for a 32-bit configuration,
first one for a 16-bit configuration).
This parameter must be a number between
Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterMaskIdLow; /*!< Specifies the filter mask number or identification number,
according to the mode (LSBs for a 32-bit configuration,
second one for a 16-bit configuration).
This parameter must be a number between
Min_Data = 0x0000 and Max_Data = 0xFFFF. */
uint32_t FilterFIFOAssignment; /*!< Specifies the FIFO (0 or 1U) which will be assigned to the filter.
This parameter can be a value of @ref CAN_filter_FIFO */
uint32_t FilterBank; /*!< Specifies the filter bank which will be initialized.
For single CAN instance(14 dedicated filter banks),
this parameter must be a number between Min_Data = 0 and Max_Data = 13.
For dual CAN instances(28 filter banks shared),
this parameter must be a number between Min_Data = 0 and Max_Data = 27. */
uint32_t FilterMode; /*!< Specifies the filter mode to be initialized.
This parameter can be a value of @ref CAN_filter_mode */
uint32_t FilterScale; /*!< Specifies the filter scale.
This parameter can be a value of @ref CAN_filter_scale */
uint32_t FilterActivation; /*!< Enable or disable the filter.
This parameter can be a value of @ref CAN_filter_activation */
uint32_t SlaveStartFilterBank; /*!< Select the start filter bank for the slave CAN instance.
For single CAN instances, this parameter is meaningless.
For dual CAN instances, all filter banks with lower index are assigned to master
CAN instance, whereas all filter banks with greater index are assigned to slave
CAN instance.
This parameter must be a number between Min_Data = 0 and Max_Data = 27. */
} CAN_FilterTypeDef;
/**
* @brief CAN Tx message header structure definition
*/
typedef struct
{
uint32_t StdId; /*!< Specifies the standard identifier.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */
uint32_t ExtId; /*!< Specifies the extended identifier.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */
uint32_t IDE; /*!< Specifies the type of identifier for the message that will be transmitted.
This parameter can be a value of @ref CAN_identifier_type */
uint32_t RTR; /*!< Specifies the type of frame for the message that will be transmitted.
This parameter can be a value of @ref CAN_remote_transmission_request */
uint32_t DLC; /*!< Specifies the length of the frame that will be transmitted.
This parameter must be a number between Min_Data = 0 and Max_Data = 8. */
FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start
of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].
@note: Time Triggered Communication Mode must be enabled.
@note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.
This parameter can be set to ENABLE or DISABLE. */
} CAN_TxHeaderTypeDef;
/**
* @brief CAN Rx message header structure definition
*/
typedef struct
{
uint32_t StdId; /*!< Specifies the standard identifier.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */
uint32_t ExtId; /*!< Specifies the extended identifier.
This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */
uint32_t IDE; /*!< Specifies the type of identifier for the message that will be transmitted.
This parameter can be a value of @ref CAN_identifier_type */
uint32_t RTR; /*!< Specifies the type of frame for the message that will be transmitted.
This parameter can be a value of @ref CAN_remote_transmission_request */
uint32_t DLC; /*!< Specifies the length of the frame that will be transmitted.
This parameter must be a number between Min_Data = 0 and Max_Data = 8. */
uint32_t Timestamp; /*!< Specifies the timestamp counter value captured on start of frame reception.
@note: Time Triggered Communication Mode must be enabled.
This parameter must be a number between Min_Data = 0 and Max_Data = 0xFFFF. */
uint32_t FilterMatchIndex; /*!< Specifies the index of matching acceptance filter element.
This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF. */
} CAN_RxHeaderTypeDef;
/**
* @brief CAN handle Structure definition
*/
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
typedef struct __CAN_HandleTypeDef
#else
typedef struct
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
{
CAN_TypeDef *Instance; /*!< Register base address */
CAN_InitTypeDef Init; /*!< CAN required parameters */
__IO HAL_CAN_StateTypeDef State; /*!< CAN communication state */
__IO uint32_t ErrorCode; /*!< CAN Error code.
This parameter can be a value of @ref CAN_Error_Code */
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
void (* TxMailbox0CompleteCallback)(struct __CAN_HandleTypeDef *hcan);/*!< CAN Tx Mailbox 0 complete callback */
void (* TxMailbox1CompleteCallback)(struct __CAN_HandleTypeDef *hcan);/*!< CAN Tx Mailbox 1 complete callback */
void (* TxMailbox2CompleteCallback)(struct __CAN_HandleTypeDef *hcan);/*!< CAN Tx Mailbox 2 complete callback */
void (* TxMailbox0AbortCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Tx Mailbox 0 abort callback */
void (* TxMailbox1AbortCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Tx Mailbox 1 abort callback */
void (* TxMailbox2AbortCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Tx Mailbox 2 abort callback */
void (* RxFifo0MsgPendingCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Rx FIFO 0 msg pending callback */
void (* RxFifo0FullCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Rx FIFO 0 full callback */
void (* RxFifo1MsgPendingCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Rx FIFO 1 msg pending callback */
void (* RxFifo1FullCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Rx FIFO 1 full callback */
void (* SleepCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Sleep callback */
void (* WakeUpFromRxMsgCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Wake Up from Rx msg callback */
void (* ErrorCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Error callback */
void (* MspInitCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Msp Init callback */
void (* MspDeInitCallback)(struct __CAN_HandleTypeDef *hcan); /*!< CAN Msp DeInit callback */
#endif /* (USE_HAL_CAN_REGISTER_CALLBACKS) */
} CAN_HandleTypeDef;
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
/**
* @brief HAL CAN common Callback ID enumeration definition
*/
typedef enum
{
HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID = 0x00U, /*!< CAN Tx Mailbox 0 complete callback ID */
HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID = 0x01U, /*!< CAN Tx Mailbox 1 complete callback ID */
HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID = 0x02U, /*!< CAN Tx Mailbox 2 complete callback ID */
HAL_CAN_TX_MAILBOX0_ABORT_CB_ID = 0x03U, /*!< CAN Tx Mailbox 0 abort callback ID */
HAL_CAN_TX_MAILBOX1_ABORT_CB_ID = 0x04U, /*!< CAN Tx Mailbox 1 abort callback ID */
HAL_CAN_TX_MAILBOX2_ABORT_CB_ID = 0x05U, /*!< CAN Tx Mailbox 2 abort callback ID */
HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID = 0x06U, /*!< CAN Rx FIFO 0 message pending callback ID */
HAL_CAN_RX_FIFO0_FULL_CB_ID = 0x07U, /*!< CAN Rx FIFO 0 full callback ID */
HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID = 0x08U, /*!< CAN Rx FIFO 1 message pending callback ID */
HAL_CAN_RX_FIFO1_FULL_CB_ID = 0x09U, /*!< CAN Rx FIFO 1 full callback ID */
HAL_CAN_SLEEP_CB_ID = 0x0AU, /*!< CAN Sleep callback ID */
HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID = 0x0BU, /*!< CAN Wake Up from Rx msg callback ID */
HAL_CAN_ERROR_CB_ID = 0x0CU, /*!< CAN Error callback ID */
HAL_CAN_MSPINIT_CB_ID = 0x0DU, /*!< CAN MspInit callback ID */
HAL_CAN_MSPDEINIT_CB_ID = 0x0EU, /*!< CAN MspDeInit callback ID */
} HAL_CAN_CallbackIDTypeDef;
/**
* @brief HAL CAN Callback pointer definition
*/
typedef void (*pCAN_CallbackTypeDef)(CAN_HandleTypeDef *hcan); /*!< pointer to a CAN callback function */
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
/**
* @}
*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup CAN_Exported_Constants CAN Exported Constants
* @{
*/
/** @defgroup CAN_Error_Code CAN Error Code
* @{
*/
#define HAL_CAN_ERROR_NONE (0x00000000U) /*!< No error */
#define HAL_CAN_ERROR_EWG (0x00000001U) /*!< Protocol Error Warning */
#define HAL_CAN_ERROR_EPV (0x00000002U) /*!< Error Passive */
#define HAL_CAN_ERROR_BOF (0x00000004U) /*!< Bus-off error */
#define HAL_CAN_ERROR_STF (0x00000008U) /*!< Stuff error */
#define HAL_CAN_ERROR_FOR (0x00000010U) /*!< Form error */
#define HAL_CAN_ERROR_ACK (0x00000020U) /*!< Acknowledgment error */
#define HAL_CAN_ERROR_BR (0x00000040U) /*!< Bit recessive error */
#define HAL_CAN_ERROR_BD (0x00000080U) /*!< Bit dominant error */
#define HAL_CAN_ERROR_CRC (0x00000100U) /*!< CRC error */
#define HAL_CAN_ERROR_RX_FOV0 (0x00000200U) /*!< Rx FIFO0 overrun error */
#define HAL_CAN_ERROR_RX_FOV1 (0x00000400U) /*!< Rx FIFO1 overrun error */
#define HAL_CAN_ERROR_TX_ALST0 (0x00000800U) /*!< TxMailbox 0 transmit failure due to arbitration lost */
#define HAL_CAN_ERROR_TX_TERR0 (0x00001000U) /*!< TxMailbox 0 transmit failure due to transmit error */
#define HAL_CAN_ERROR_TX_ALST1 (0x00002000U) /*!< TxMailbox 1 transmit failure due to arbitration lost */
#define HAL_CAN_ERROR_TX_TERR1 (0x00004000U) /*!< TxMailbox 1 transmit failure due to transmit error */
#define HAL_CAN_ERROR_TX_ALST2 (0x00008000U) /*!< TxMailbox 2 transmit failure due to arbitration lost */
#define HAL_CAN_ERROR_TX_TERR2 (0x00010000U) /*!< TxMailbox 2 transmit failure due to transmit error */
#define HAL_CAN_ERROR_TIMEOUT (0x00020000U) /*!< Timeout error */
#define HAL_CAN_ERROR_NOT_INITIALIZED (0x00040000U) /*!< Peripheral not initialized */
#define HAL_CAN_ERROR_NOT_READY (0x00080000U) /*!< Peripheral not ready */
#define HAL_CAN_ERROR_NOT_STARTED (0x00100000U) /*!< Peripheral not started */
#define HAL_CAN_ERROR_PARAM (0x00200000U) /*!< Parameter error */
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
#define HAL_CAN_ERROR_INVALID_CALLBACK (0x00400000U) /*!< Invalid Callback error */
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
#define HAL_CAN_ERROR_INTERNAL (0x00800000U) /*!< Internal error */
/**
* @}
*/
/** @defgroup CAN_InitStatus CAN InitStatus
* @{
*/
#define CAN_INITSTATUS_FAILED (0x00000000U) /*!< CAN initialization failed */
#define CAN_INITSTATUS_SUCCESS (0x00000001U) /*!< CAN initialization OK */
/**
* @}
*/
/** @defgroup CAN_operating_mode CAN Operating Mode
* @{
*/
#define CAN_MODE_NORMAL (0x00000000U) /*!< Normal mode */
#define CAN_MODE_LOOPBACK ((uint32_t)CAN_BTR_LBKM) /*!< Loopback mode */
#define CAN_MODE_SILENT ((uint32_t)CAN_BTR_SILM) /*!< Silent mode */
#define CAN_MODE_SILENT_LOOPBACK ((uint32_t)(CAN_BTR_LBKM | CAN_BTR_SILM)) /*!< Loopback combined with
silent mode */
/**
* @}
*/
/** @defgroup CAN_synchronisation_jump_width CAN Synchronization Jump Width
* @{
*/
#define CAN_SJW_1TQ (0x00000000U) /*!< 1 time quantum */
#define CAN_SJW_2TQ ((uint32_t)CAN_BTR_SJW_0) /*!< 2 time quantum */
#define CAN_SJW_3TQ ((uint32_t)CAN_BTR_SJW_1) /*!< 3 time quantum */
#define CAN_SJW_4TQ ((uint32_t)CAN_BTR_SJW) /*!< 4 time quantum */
/**
* @}
*/
/** @defgroup CAN_time_quantum_in_bit_segment_1 CAN Time Quantum in Bit Segment 1
* @{
*/
#define CAN_BS1_1TQ (0x00000000U) /*!< 1 time quantum */
#define CAN_BS1_2TQ ((uint32_t)CAN_BTR_TS1_0) /*!< 2 time quantum */
#define CAN_BS1_3TQ ((uint32_t)CAN_BTR_TS1_1) /*!< 3 time quantum */
#define CAN_BS1_4TQ ((uint32_t)(CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 4 time quantum */
#define CAN_BS1_5TQ ((uint32_t)CAN_BTR_TS1_2) /*!< 5 time quantum */
#define CAN_BS1_6TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_0)) /*!< 6 time quantum */
#define CAN_BS1_7TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_1)) /*!< 7 time quantum */
#define CAN_BS1_8TQ ((uint32_t)(CAN_BTR_TS1_2 | CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 8 time quantum */
#define CAN_BS1_9TQ ((uint32_t)CAN_BTR_TS1_3) /*!< 9 time quantum */
#define CAN_BS1_10TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_0)) /*!< 10 time quantum */
#define CAN_BS1_11TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_1)) /*!< 11 time quantum */
#define CAN_BS1_12TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_1 | CAN_BTR_TS1_0)) /*!< 12 time quantum */
#define CAN_BS1_13TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2)) /*!< 13 time quantum */
#define CAN_BS1_14TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2 | CAN_BTR_TS1_0)) /*!< 14 time quantum */
#define CAN_BS1_15TQ ((uint32_t)(CAN_BTR_TS1_3 | CAN_BTR_TS1_2 | CAN_BTR_TS1_1)) /*!< 15 time quantum */
#define CAN_BS1_16TQ ((uint32_t)CAN_BTR_TS1) /*!< 16 time quantum */
/**
* @}
*/
/** @defgroup CAN_time_quantum_in_bit_segment_2 CAN Time Quantum in Bit Segment 2
* @{
*/
#define CAN_BS2_1TQ (0x00000000U) /*!< 1 time quantum */
#define CAN_BS2_2TQ ((uint32_t)CAN_BTR_TS2_0) /*!< 2 time quantum */
#define CAN_BS2_3TQ ((uint32_t)CAN_BTR_TS2_1) /*!< 3 time quantum */
#define CAN_BS2_4TQ ((uint32_t)(CAN_BTR_TS2_1 | CAN_BTR_TS2_0)) /*!< 4 time quantum */
#define CAN_BS2_5TQ ((uint32_t)CAN_BTR_TS2_2) /*!< 5 time quantum */
#define CAN_BS2_6TQ ((uint32_t)(CAN_BTR_TS2_2 | CAN_BTR_TS2_0)) /*!< 6 time quantum */
#define CAN_BS2_7TQ ((uint32_t)(CAN_BTR_TS2_2 | CAN_BTR_TS2_1)) /*!< 7 time quantum */
#define CAN_BS2_8TQ ((uint32_t)CAN_BTR_TS2) /*!< 8 time quantum */
/**
* @}
*/
/** @defgroup CAN_filter_mode CAN Filter Mode
* @{
*/
#define CAN_FILTERMODE_IDMASK (0x00000000U) /*!< Identifier mask mode */
#define CAN_FILTERMODE_IDLIST (0x00000001U) /*!< Identifier list mode */
/**
* @}
*/
/** @defgroup CAN_filter_scale CAN Filter Scale
* @{
*/
#define CAN_FILTERSCALE_16BIT (0x00000000U) /*!< Two 16-bit filters */
#define CAN_FILTERSCALE_32BIT (0x00000001U) /*!< One 32-bit filter */
/**
* @}
*/
/** @defgroup CAN_filter_activation CAN Filter Activation
* @{
*/
#define CAN_FILTER_DISABLE (0x00000000U) /*!< Disable filter */
#define CAN_FILTER_ENABLE (0x00000001U) /*!< Enable filter */
/**
* @}
*/
/** @defgroup CAN_filter_FIFO CAN Filter FIFO
* @{
*/
#define CAN_FILTER_FIFO0 (0x00000000U) /*!< Filter FIFO 0 assignment for filter x */
#define CAN_FILTER_FIFO1 (0x00000001U) /*!< Filter FIFO 1 assignment for filter x */
/**
* @}
*/
/** @defgroup CAN_identifier_type CAN Identifier Type
* @{
*/
#define CAN_ID_STD (0x00000000U) /*!< Standard Id */
#define CAN_ID_EXT (0x00000004U) /*!< Extended Id */
/**
* @}
*/
/** @defgroup CAN_remote_transmission_request CAN Remote Transmission Request
* @{
*/
#define CAN_RTR_DATA (0x00000000U) /*!< Data frame */
#define CAN_RTR_REMOTE (0x00000002U) /*!< Remote frame */
/**
* @}
*/
/** @defgroup CAN_receive_FIFO_number CAN Receive FIFO Number
* @{
*/
#define CAN_RX_FIFO0 (0x00000000U) /*!< CAN receive FIFO 0 */
#define CAN_RX_FIFO1 (0x00000001U) /*!< CAN receive FIFO 1 */
/**
* @}
*/
/** @defgroup CAN_Tx_Mailboxes CAN Tx Mailboxes
* @{
*/
#define CAN_TX_MAILBOX0 (0x00000001U) /*!< Tx Mailbox 0 */
#define CAN_TX_MAILBOX1 (0x00000002U) /*!< Tx Mailbox 1 */
#define CAN_TX_MAILBOX2 (0x00000004U) /*!< Tx Mailbox 2 */
/**
* @}
*/
/** @defgroup CAN_flags CAN Flags
* @{
*/
/* Transmit Flags */
#define CAN_FLAG_RQCP0 (0x00000500U) /*!< Request complete MailBox 0 flag */
#define CAN_FLAG_TXOK0 (0x00000501U) /*!< Transmission OK MailBox 0 flag */
#define CAN_FLAG_ALST0 (0x00000502U) /*!< Arbitration Lost MailBox 0 flag */
#define CAN_FLAG_TERR0 (0x00000503U) /*!< Transmission error MailBox 0 flag */
#define CAN_FLAG_RQCP1 (0x00000508U) /*!< Request complete MailBox1 flag */
#define CAN_FLAG_TXOK1 (0x00000509U) /*!< Transmission OK MailBox 1 flag */
#define CAN_FLAG_ALST1 (0x0000050AU) /*!< Arbitration Lost MailBox 1 flag */
#define CAN_FLAG_TERR1 (0x0000050BU) /*!< Transmission error MailBox 1 flag */
#define CAN_FLAG_RQCP2 (0x00000510U) /*!< Request complete MailBox2 flag */
#define CAN_FLAG_TXOK2 (0x00000511U) /*!< Transmission OK MailBox 2 flag */
#define CAN_FLAG_ALST2 (0x00000512U) /*!< Arbitration Lost MailBox 2 flag */
#define CAN_FLAG_TERR2 (0x00000513U) /*!< Transmission error MailBox 2 flag */
#define CAN_FLAG_TME0 (0x0000051AU) /*!< Transmit mailbox 0 empty flag */
#define CAN_FLAG_TME1 (0x0000051BU) /*!< Transmit mailbox 1 empty flag */
#define CAN_FLAG_TME2 (0x0000051CU) /*!< Transmit mailbox 2 empty flag */
#define CAN_FLAG_LOW0 (0x0000051DU) /*!< Lowest priority mailbox 0 flag */
#define CAN_FLAG_LOW1 (0x0000051EU) /*!< Lowest priority mailbox 1 flag */
#define CAN_FLAG_LOW2 (0x0000051FU) /*!< Lowest priority mailbox 2 flag */
/* Receive Flags */
#define CAN_FLAG_FF0 (0x00000203U) /*!< RX FIFO 0 Full flag */
#define CAN_FLAG_FOV0 (0x00000204U) /*!< RX FIFO 0 Overrun flag */
#define CAN_FLAG_FF1 (0x00000403U) /*!< RX FIFO 1 Full flag */
#define CAN_FLAG_FOV1 (0x00000404U) /*!< RX FIFO 1 Overrun flag */
/* Operating Mode Flags */
#define CAN_FLAG_INAK (0x00000100U) /*!< Initialization acknowledge flag */
#define CAN_FLAG_SLAK (0x00000101U) /*!< Sleep acknowledge flag */
#define CAN_FLAG_ERRI (0x00000102U) /*!< Error flag */
#define CAN_FLAG_WKU (0x00000103U) /*!< Wake up interrupt flag */
#define CAN_FLAG_SLAKI (0x00000104U) /*!< Sleep acknowledge interrupt flag */
/* Error Flags */
#define CAN_FLAG_EWG (0x00000300U) /*!< Error warning flag */
#define CAN_FLAG_EPV (0x00000301U) /*!< Error passive flag */
#define CAN_FLAG_BOF (0x00000302U) /*!< Bus-Off flag */
/**
* @}
*/
/** @defgroup CAN_Interrupts CAN Interrupts
* @{
*/
/* Transmit Interrupt */
#define CAN_IT_TX_MAILBOX_EMPTY ((uint32_t)CAN_IER_TMEIE) /*!< Transmit mailbox empty interrupt */
/* Receive Interrupts */
#define CAN_IT_RX_FIFO0_MSG_PENDING ((uint32_t)CAN_IER_FMPIE0) /*!< FIFO 0 message pending interrupt */
#define CAN_IT_RX_FIFO0_FULL ((uint32_t)CAN_IER_FFIE0) /*!< FIFO 0 full interrupt */
#define CAN_IT_RX_FIFO0_OVERRUN ((uint32_t)CAN_IER_FOVIE0) /*!< FIFO 0 overrun interrupt */
#define CAN_IT_RX_FIFO1_MSG_PENDING ((uint32_t)CAN_IER_FMPIE1) /*!< FIFO 1 message pending interrupt */
#define CAN_IT_RX_FIFO1_FULL ((uint32_t)CAN_IER_FFIE1) /*!< FIFO 1 full interrupt */
#define CAN_IT_RX_FIFO1_OVERRUN ((uint32_t)CAN_IER_FOVIE1) /*!< FIFO 1 overrun interrupt */
/* Operating Mode Interrupts */
#define CAN_IT_WAKEUP ((uint32_t)CAN_IER_WKUIE) /*!< Wake-up interrupt */
#define CAN_IT_SLEEP_ACK ((uint32_t)CAN_IER_SLKIE) /*!< Sleep acknowledge interrupt */
/* Error Interrupts */
#define CAN_IT_ERROR_WARNING ((uint32_t)CAN_IER_EWGIE) /*!< Error warning interrupt */
#define CAN_IT_ERROR_PASSIVE ((uint32_t)CAN_IER_EPVIE) /*!< Error passive interrupt */
#define CAN_IT_BUSOFF ((uint32_t)CAN_IER_BOFIE) /*!< Bus-off interrupt */
#define CAN_IT_LAST_ERROR_CODE ((uint32_t)CAN_IER_LECIE) /*!< Last error code interrupt */
#define CAN_IT_ERROR ((uint32_t)CAN_IER_ERRIE) /*!< Error Interrupt */
/**
* @}
*/
/**
* @}
*/
/* Exported macros -----------------------------------------------------------*/
/** @defgroup CAN_Exported_Macros CAN Exported Macros
* @{
*/
/** @brief Reset CAN handle state
* @param __HANDLE__ CAN handle.
* @retval None
*/
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
#define __HAL_CAN_RESET_HANDLE_STATE(__HANDLE__) do{ \
(__HANDLE__)->State = HAL_CAN_STATE_RESET; \
(__HANDLE__)->MspInitCallback = NULL; \
(__HANDLE__)->MspDeInitCallback = NULL; \
} while(0)
#else
#define __HAL_CAN_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_CAN_STATE_RESET)
#endif /*USE_HAL_CAN_REGISTER_CALLBACKS */
/**
* @brief Enable the specified CAN interrupts.
* @param __HANDLE__ CAN handle.
* @param __INTERRUPT__ CAN Interrupt sources to enable.
* This parameter can be any combination of @arg CAN_Interrupts
* @retval None
*/
#define __HAL_CAN_ENABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) |= (__INTERRUPT__))
/**
* @brief Disable the specified CAN interrupts.
* @param __HANDLE__ CAN handle.
* @param __INTERRUPT__ CAN Interrupt sources to disable.
* This parameter can be any combination of @arg CAN_Interrupts
* @retval None
*/
#define __HAL_CAN_DISABLE_IT(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) &= ~(__INTERRUPT__))
/** @brief Check if the specified CAN interrupt source is enabled or disabled.
* @param __HANDLE__ specifies the CAN Handle.
* @param __INTERRUPT__ specifies the CAN interrupt source to check.
* This parameter can be a value of @arg CAN_Interrupts
* @retval The state of __IT__ (TRUE or FALSE).
*/
#define __HAL_CAN_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (((__HANDLE__)->Instance->IER) & (__INTERRUPT__))
/** @brief Check whether the specified CAN flag is set or not.
* @param __HANDLE__ specifies the CAN Handle.
* @param __FLAG__ specifies the flag to check.
* This parameter can be one of @arg CAN_flags
* @retval The state of __FLAG__ (TRUE or FALSE).
*/
#define __HAL_CAN_GET_FLAG(__HANDLE__, __FLAG__) \
((((__FLAG__) >> 8U) == 5U)? ((((__HANDLE__)->Instance->TSR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 2U)? ((((__HANDLE__)->Instance->RF0R) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 4U)? ((((__HANDLE__)->Instance->RF1R) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 1U)? ((((__HANDLE__)->Instance->MSR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 3U)? ((((__HANDLE__)->Instance->ESR) & (1U << ((__FLAG__) & CAN_FLAG_MASK))) == (1U << ((__FLAG__) & CAN_FLAG_MASK))): 0U)
/** @brief Clear the specified CAN pending flag.
* @param __HANDLE__ specifies the CAN Handle.
* @param __FLAG__ specifies the flag to check.
* This parameter can be one of the following values:
* @arg CAN_FLAG_RQCP0: Request complete MailBox 0 Flag
* @arg CAN_FLAG_TXOK0: Transmission OK MailBox 0 Flag
* @arg CAN_FLAG_ALST0: Arbitration Lost MailBox 0 Flag
* @arg CAN_FLAG_TERR0: Transmission error MailBox 0 Flag
* @arg CAN_FLAG_RQCP1: Request complete MailBox 1 Flag
* @arg CAN_FLAG_TXOK1: Transmission OK MailBox 1 Flag
* @arg CAN_FLAG_ALST1: Arbitration Lost MailBox 1 Flag
* @arg CAN_FLAG_TERR1: Transmission error MailBox 1 Flag
* @arg CAN_FLAG_RQCP2: Request complete MailBox 2 Flag
* @arg CAN_FLAG_TXOK2: Transmission OK MailBox 2 Flag
* @arg CAN_FLAG_ALST2: Arbitration Lost MailBox 2 Flag
* @arg CAN_FLAG_TERR2: Transmission error MailBox 2 Flag
* @arg CAN_FLAG_FF0: RX FIFO 0 Full Flag
* @arg CAN_FLAG_FOV0: RX FIFO 0 Overrun Flag
* @arg CAN_FLAG_FF1: RX FIFO 1 Full Flag
* @arg CAN_FLAG_FOV1: RX FIFO 1 Overrun Flag
* @arg CAN_FLAG_WKUI: Wake up Interrupt Flag
* @arg CAN_FLAG_SLAKI: Sleep acknowledge Interrupt Flag
* @retval None
*/
#define __HAL_CAN_CLEAR_FLAG(__HANDLE__, __FLAG__) \
((((__FLAG__) >> 8U) == 5U)? (((__HANDLE__)->Instance->TSR) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 2U)? (((__HANDLE__)->Instance->RF0R) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 4U)? (((__HANDLE__)->Instance->RF1R) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): \
(((__FLAG__) >> 8U) == 1U)? (((__HANDLE__)->Instance->MSR) = (1U << ((__FLAG__) & CAN_FLAG_MASK))): 0U)
/**
* @}
*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup CAN_Exported_Functions CAN Exported Functions
* @{
*/
/** @addtogroup CAN_Exported_Functions_Group1 Initialization and de-initialization functions
* @brief Initialization and Configuration functions
* @{
*/
/* Initialization and de-initialization functions *****************************/
HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef *hcan);
void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan);
void HAL_CAN_MspDeInit(CAN_HandleTypeDef *hcan);
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
/* Callbacks Register/UnRegister functions ***********************************/
HAL_StatusTypeDef HAL_CAN_RegisterCallback(CAN_HandleTypeDef *hcan, HAL_CAN_CallbackIDTypeDef CallbackID,
void (* pCallback)(CAN_HandleTypeDef *_hcan));
HAL_StatusTypeDef HAL_CAN_UnRegisterCallback(CAN_HandleTypeDef *hcan, HAL_CAN_CallbackIDTypeDef CallbackID);
#endif /* (USE_HAL_CAN_REGISTER_CALLBACKS) */
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group2 Configuration functions
* @brief Configuration functions
* @{
*/
/* Configuration functions ****************************************************/
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, const CAN_FilterTypeDef *sFilterConfig);
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group3 Control functions
* @brief Control functions
* @{
*/
/* Control functions **********************************************************/
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_Stop(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_RequestSleep(CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef *hcan);
uint32_t HAL_CAN_IsSleepActive(const CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, const CAN_TxHeaderTypeDef *pHeader,
const uint8_t aData[], uint32_t *pTxMailbox);
HAL_StatusTypeDef HAL_CAN_AbortTxRequest(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes);
uint32_t HAL_CAN_GetTxMailboxesFreeLevel(const CAN_HandleTypeDef *hcan);
uint32_t HAL_CAN_IsTxMessagePending(const CAN_HandleTypeDef *hcan, uint32_t TxMailboxes);
uint32_t HAL_CAN_GetTxTimestamp(const CAN_HandleTypeDef *hcan, uint32_t TxMailbox);
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo,
CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);
uint32_t HAL_CAN_GetRxFifoFillLevel(const CAN_HandleTypeDef *hcan, uint32_t RxFifo);
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group4 Interrupts management
* @brief Interrupts management
* @{
*/
/* Interrupts management ******************************************************/
HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs);
HAL_StatusTypeDef HAL_CAN_DeactivateNotification(CAN_HandleTypeDef *hcan, uint32_t InactiveITs);
void HAL_CAN_IRQHandler(CAN_HandleTypeDef *hcan);
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group5 Callback functions
* @brief Callback functions
* @{
*/
/* Callbacks functions ********************************************************/
void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan);
/**
* @}
*/
/** @addtogroup CAN_Exported_Functions_Group6 Peripheral State and Error functions
* @brief CAN Peripheral State functions
* @{
*/
/* Peripheral State and Error functions ***************************************/
HAL_CAN_StateTypeDef HAL_CAN_GetState(const CAN_HandleTypeDef *hcan);
uint32_t HAL_CAN_GetError(const CAN_HandleTypeDef *hcan);
HAL_StatusTypeDef HAL_CAN_ResetError(CAN_HandleTypeDef *hcan);
/**
* @}
*/
/**
* @}
*/
/* Private types -------------------------------------------------------------*/
/** @defgroup CAN_Private_Types CAN Private Types
* @{
*/
/**
* @}
*/
/* Private variables ---------------------------------------------------------*/
/** @defgroup CAN_Private_Variables CAN Private Variables
* @{
*/
/**
* @}
*/
/* Private constants ---------------------------------------------------------*/
/** @defgroup CAN_Private_Constants CAN Private Constants
* @{
*/
#define CAN_FLAG_MASK (0x000000FFU)
/**
* @}
*/
/* Private Macros -----------------------------------------------------------*/
/** @defgroup CAN_Private_Macros CAN Private Macros
* @{
*/
#define IS_CAN_MODE(MODE) (((MODE) == CAN_MODE_NORMAL) || \
((MODE) == CAN_MODE_LOOPBACK)|| \
((MODE) == CAN_MODE_SILENT) || \
((MODE) == CAN_MODE_SILENT_LOOPBACK))
#define IS_CAN_SJW(SJW) (((SJW) == CAN_SJW_1TQ) || ((SJW) == CAN_SJW_2TQ) || \
((SJW) == CAN_SJW_3TQ) || ((SJW) == CAN_SJW_4TQ))
#define IS_CAN_BS1(BS1) (((BS1) == CAN_BS1_1TQ) || ((BS1) == CAN_BS1_2TQ) || \
((BS1) == CAN_BS1_3TQ) || ((BS1) == CAN_BS1_4TQ) || \
((BS1) == CAN_BS1_5TQ) || ((BS1) == CAN_BS1_6TQ) || \
((BS1) == CAN_BS1_7TQ) || ((BS1) == CAN_BS1_8TQ) || \
((BS1) == CAN_BS1_9TQ) || ((BS1) == CAN_BS1_10TQ)|| \
((BS1) == CAN_BS1_11TQ)|| ((BS1) == CAN_BS1_12TQ)|| \
((BS1) == CAN_BS1_13TQ)|| ((BS1) == CAN_BS1_14TQ)|| \
((BS1) == CAN_BS1_15TQ)|| ((BS1) == CAN_BS1_16TQ))
#define IS_CAN_BS2(BS2) (((BS2) == CAN_BS2_1TQ) || ((BS2) == CAN_BS2_2TQ) || \
((BS2) == CAN_BS2_3TQ) || ((BS2) == CAN_BS2_4TQ) || \
((BS2) == CAN_BS2_5TQ) || ((BS2) == CAN_BS2_6TQ) || \
((BS2) == CAN_BS2_7TQ) || ((BS2) == CAN_BS2_8TQ))
#define IS_CAN_PRESCALER(PRESCALER) (((PRESCALER) >= 1U) && ((PRESCALER) <= 1024U))
#define IS_CAN_FILTER_ID_HALFWORD(HALFWORD) ((HALFWORD) <= 0xFFFFU)
#if defined(CAN2)
#define IS_CAN_FILTER_BANK_DUAL(BANK) ((BANK) <= 27U)
#endif
#define IS_CAN_FILTER_BANK_SINGLE(BANK) ((BANK) <= 13U)
#define IS_CAN_FILTER_MODE(MODE) (((MODE) == CAN_FILTERMODE_IDMASK) || \
((MODE) == CAN_FILTERMODE_IDLIST))
#define IS_CAN_FILTER_SCALE(SCALE) (((SCALE) == CAN_FILTERSCALE_16BIT) || \
((SCALE) == CAN_FILTERSCALE_32BIT))
#define IS_CAN_FILTER_ACTIVATION(ACTIVATION) (((ACTIVATION) == CAN_FILTER_DISABLE) || \
((ACTIVATION) == CAN_FILTER_ENABLE))
#define IS_CAN_FILTER_FIFO(FIFO) (((FIFO) == CAN_FILTER_FIFO0) || \
((FIFO) == CAN_FILTER_FIFO1))
#define IS_CAN_TX_MAILBOX(TRANSMITMAILBOX) (((TRANSMITMAILBOX) == CAN_TX_MAILBOX0 ) || \
((TRANSMITMAILBOX) == CAN_TX_MAILBOX1 ) || \
((TRANSMITMAILBOX) == CAN_TX_MAILBOX2 ))
#define IS_CAN_TX_MAILBOX_LIST(TRANSMITMAILBOX) ((TRANSMITMAILBOX) <= (CAN_TX_MAILBOX0 | CAN_TX_MAILBOX1 | \
CAN_TX_MAILBOX2))
#define IS_CAN_STDID(STDID) ((STDID) <= 0x7FFU)
#define IS_CAN_EXTID(EXTID) ((EXTID) <= 0x1FFFFFFFU)
#define IS_CAN_DLC(DLC) ((DLC) <= 8U)
#define IS_CAN_IDTYPE(IDTYPE) (((IDTYPE) == CAN_ID_STD) || \
((IDTYPE) == CAN_ID_EXT))
#define IS_CAN_RTR(RTR) (((RTR) == CAN_RTR_DATA) || ((RTR) == CAN_RTR_REMOTE))
#define IS_CAN_RX_FIFO(FIFO) (((FIFO) == CAN_RX_FIFO0) || ((FIFO) == CAN_RX_FIFO1))
#define IS_CAN_IT(IT) ((IT) <= (CAN_IT_TX_MAILBOX_EMPTY | CAN_IT_RX_FIFO0_MSG_PENDING | \
CAN_IT_RX_FIFO0_FULL | CAN_IT_RX_FIFO0_OVERRUN | \
CAN_IT_RX_FIFO1_MSG_PENDING | CAN_IT_RX_FIFO1_FULL | \
CAN_IT_RX_FIFO1_OVERRUN | CAN_IT_WAKEUP | \
CAN_IT_SLEEP_ACK | CAN_IT_ERROR_WARNING | \
CAN_IT_ERROR_PASSIVE | CAN_IT_BUSOFF | \
CAN_IT_LAST_ERROR_CODE | CAN_IT_ERROR))
/**
* @}
*/
/* End of private macros -----------------------------------------------------*/
/**
* @}
*/
#endif /* CAN1 */
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* STM32F1xx_HAL_CAN_H */

View File

@ -51,7 +51,7 @@
#define HAL_MODULE_ENABLED
/*#define HAL_ADC_MODULE_ENABLED */
/*#define HAL_CRYP_MODULE_ENABLED */
/*#define HAL_CAN_MODULE_ENABLED */
#define HAL_CAN_MODULE_ENABLED
/*#define HAL_CEC_MODULE_ENABLED */
/*#define HAL_CORTEX_MODULE_ENABLED */
/*#define HAL_CRC_MODULE_ENABLED */

View File

@ -1,3 +1,14 @@
SRC_FILES := stm32f1xx_hal.c stm32f1xx_hal_uart.c stm32f1xx_hal_usart.c stm32f1xx_hal_cortex.c stm32f1xx_hal_rcc.c stm32f1xx_hal_rcc_ex.c stm32f1xx_hal_gpio.c stm32f1xx_hal_msp.c stm32f1xx_hal_flash.c stm32f1xx_hal_flash_ex.c stm32f1xx_hal_dma.c
SRC_FILES := stm32f1xx_hal.c \
stm32f1xx_hal_uart.c \
stm32f1xx_hal_usart.c \
stm32f1xx_hal_cortex.c \
stm32f1xx_hal_rcc.c \
stm32f1xx_hal_rcc_ex.c \
stm32f1xx_hal_gpio.c \
stm32f1xx_hal_msp.c \
stm32f1xx_hal_flash.c \
stm32f1xx_hal_flash_ex.c \
stm32f1xx_hal_dma.c \
stm32f1xx_hal_can.c
include $(KERNEL_ROOT)/compiler.mk

View File

@ -41,6 +41,7 @@
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include "stm32f1xx_hal_can.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
@ -505,6 +506,80 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
}
/**
* @brief CAN MSP Initialization
* This function configures the hardware resources used in this example
* @param hcan: CAN handle pointer
* @retval None
*/
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hcan->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspInit 0 */
/* USER CODE END CAN1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**CAN GPIO Configuration
PA11 ------> CAN_RX
PA12 ------> CAN_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* CAN1 interrupt Init */
HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
/* USER CODE BEGIN CAN1_MspInit 1 */
/* USER CODE END CAN1_MspInit 1 */
}
}
/**
* @brief CAN MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hcan: CAN handle pointer
* @retval None
*/
void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan)
{
if(hcan->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspDeInit 0 */
/* USER CODE END CAN1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_CAN1_CLK_DISABLE();
/**CAN GPIO Configuration
PA11 ------> CAN_RX
PA12 ------> CAN_TX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);
/* CAN1 interrupt DeInit */
HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
/* USER CODE BEGIN CAN1_MspDeInit 1 */
/* USER CODE END CAN1_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

50
Ubiquitous/XiZi_IIoT/easydo.sh Executable file
View File

@ -0,0 +1,50 @@
#!/bin/bash
# 定义目标目录
target_dir="/mnt/hgfs/share"
# 检查目标目录是否存在
if [ ! -d "$target_dir" ]; then
echo "错误: 目标目录 $target_dir 不存在,脚本将退出。"
exit 1
fi
# 执行 make clean 操作
# echo "执行 make BOARD=stm32f103-nano clean..."
# make BOARD=stm32f103-nano clean
# if [ $? -ne 0 ]; then
# echo "错误: make BOARD=stm32f103-nano clean 失败,脚本将退出。"
# exit 1
# fi
# 执行 make 操作
echo "执行 make BOARD=stm32f103-nano ..."
make BOARD=stm32f103-nano
if [ $? -ne 0 ]; then
echo "错误: make BOARD=stm32f103-nano 失败,脚本将退出。"
exit 1
fi
arm-none-eabi-objdump -d ./build/XiZi-stm32f103-nano.elf > ./build/obj.S
# 定义源文件路径和名称
source_files=(
"./build/obj.S"
"./build/XiZi-stm32f103-nano.bin"
"./build/XiZi-stm32f103-nano.elf"
"./build/XiZi-stm32f103-nano.hex"
"./build/XiZi-stm32f103-nano.map"
)
# 复制文件,如果有同名文件则覆盖
for file in "${source_files[@]}"; do
if [ -f "$file" ]; then
cp -f "$file" "$target_dir"
echo "文件 $file 已复制到 $target_dir(如果已存在则被覆盖)"
else
echo "警告: 文件 $file 不存在,跳过复制操作。"
fi
done

View File

@ -18,7 +18,9 @@ static void GetBusName(const char *path, char *bus_name)
static void GetDrvName(char *bus_name, char *drv_name)
{
snprintf(drv_name, strlen(bus_name) + 5, "%s_drv", bus_name);
//snprintf(drv_name, strlen(bus_name) + 5, "%s_drv", bus_name);
strcpy(drv_name, bus_name);
strcat(drv_name, "_drv");
}
static int DevicefileOpen(struct FileDescriptor *fdp, const char *path)

View File

@ -24,6 +24,7 @@
/* import board special configuration */
#include <xsconfig.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
@ -123,9 +124,10 @@ typedef x_base x_OffPos;
#endif
#define WAITING_FOREVER -1
// #define KPrintf printf
void KPrintf(const char *fmt, ...);
#ifdef __cplusplus
}
#endif

View File

@ -150,6 +150,8 @@ static int _CanTestRecv(const char *bus_name, const char *driver_name, const c
for(i = 0; i<len;i++)
KPrintf("0x%02x ", rx_buf[i]);
KPrintf("\n");
return 0;
}
else
{

View File

@ -252,7 +252,7 @@ extern int InitUserspace(void);
#endif
StartupOsAssign();
ymodem_fun();
return 0;
}

View File

@ -49,14 +49,6 @@ static void ZombieKTaskEntry(void *parameter)
lock = CriticalAreaLock();
if (JudgeZombieKTaskIsNotEmpty()) {
task = SYS_DOUBLE_LINKLIST_ENTRY(KTaskZombie.node_next, struct TaskDescriptor, task_dync_sched_member.sched_link);
if(0 == strcmp("main", task->task_base_info.name))
{
// KPrintf("Zombie KTask Is main\n");
SuspendKTask(zombie_recycle);
CriticalAreaUnLock(lock);
DO_KTASK_ASSIGN;
}
else
{
DoubleLinkListRmNode(&(task->task_dync_sched_member.sched_link));
CriticalAreaUnLock(lock);

View File

@ -373,6 +373,7 @@ KERNELPATHS += \
-I$(KERNEL_ROOT)/arch/arm/cortex-m3 \
-I$(BSP_ROOT)/third_party_driver/include \
-I$(BSP_ROOT)/third_party_driver/libraries/STM32F1xx_HAL/inc \
-I$(BSP_ROOT)/third_party_driver/libraries/STM32F1xx_HAL/inc/Legacy \
-I$(BSP_ROOT)/third_party_driver/libraries/CMSIS \
-I$(KERNEL_ROOT)/include \
-I$(BSP_ROOT)/include #

View File

@ -1,5 +1,6 @@
menu "Tool feature"
source "$KERNEL_DIR/tool/bootloader/Kconfig"
source "$KERNEL_DIR/tool/libcanard/Kconfig"
endmenu

View File

@ -8,4 +8,9 @@ ifeq ($(CONFIG_TOOL_USING_OTA),y)
SRC_DIR += bootloader
endif
ifeq ($(CONFIG_TOOL_USING_UVCAN),y)
SRC_DIR += libcanard
endif
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,7 @@
menu "UVCAN"
menuconfig TOOL_USING_UVCAN
bool "Enable UVCAN function"
default y
endmenu

View File

@ -0,0 +1,3 @@
SRC_FILES :=
include $(KERNEL_ROOT)/compiler.mk

View File

@ -0,0 +1,337 @@
/// Source: https://github.com/pavel-kirienko/cavl
///
/// Cavl is a single-header C library providing an implementation of AVL tree suitable for deeply embedded systems.
/// To integrate it into your project, simply copy this file into your source tree. Read the API docs below.
///
/// See also O1Heap <https://github.com/pavel-kirienko/o1heap> -- a deterministic memory manager for hard-real-time
/// high-integrity embedded systems.
///
/// Copyright (c) 2021 Pavel Kirienko <pavel@opencyphal.org>
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
/// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
/// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
/// and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all copies or substantial portions of
/// the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
/// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
/// OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
/// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#pragma once
#include "canard.h"
/// Modified for use with Libcanard: use the same assertion check macro if provided.
#ifdef CANARD_ASSERT
# define CAVL_ASSERT CANARD_ASSERT
#else
// Intentional violation of MISRA: inclusion not at the top of the file to eliminate unnecessary dependency on assert.h.
# include <assert.h> // NOSONAR
# define CAVL_ASSERT assert
#endif
#ifdef __cplusplus
// This is, strictly speaking, useless because we do not define any functions with external linkage here,
// but it tells static analyzers that what follows should be interpreted as C code rather than C++.
extern "C" {
#endif
// ---------------------------------------- PUBLIC API SECTION ----------------------------------------
/// Modified for use with Libcanard: expose the Cavl structure via public API as CanardTreeNode.
typedef CanardTreeNode Cavl;
/// Returns POSITIVE if the search target is GREATER than the provided node, negative if smaller, zero on match (found).
/// Values other than {-1, 0, +1} are not recommended to avoid overflow during the narrowing conversion of the result.
typedef int8_t (*CavlPredicate)(void* user_reference, const Cavl* node);
/// If provided, the factory will be invoked when the sought node does not exist in the tree.
/// It is expected to return a new node that will be inserted immediately (without the need to traverse the tree again).
/// If the factory returns NULL or is not provided, the tree is not modified.
typedef Cavl* (*CavlFactory)(void* user_reference);
/// Look for a node in the tree using the specified search predicate. The worst-case complexity is O(log n).
/// - If the node is found, return it.
/// - If the node is not found and the factory is NULL, return NULL.
/// - Otherwise, construct a new node using the factory; if the result is not NULL, insert it; return the result.
/// The user_reference is passed into the predicate & factory unmodified.
/// The root node may be replaced in the process.
/// If predicate is NULL, returns NULL.
static inline Cavl* cavlSearch(Cavl** const root,
void* const user_reference,
const CavlPredicate predicate,
const CavlFactory factory);
/// Remove the specified node from its tree. The root node may be replaced in the process.
/// The worst-case complexity is O(log n).
/// The function has no effect if either of the pointers are NULL.
/// If the node is not in the tree, the behavior is undefined; it may create cycles in the tree which is deadly.
/// It is safe to pass the result of cavlSearch() directly as the second argument:
/// cavlRemove(&root, cavlSearch(&root, user_reference, search_predicate, NULL));
/// It is recommended to invalidate the pointers stored in the node after its removal.
static inline void cavlRemove(Cavl** const root, const Cavl* const node);
/// Return the min-/max-valued node stored in the tree, depending on the flag. This is an extremely fast query.
/// Returns NULL iff the argument is NULL (i.e., the tree is empty). The worst-case complexity is O(log n).
static inline Cavl* cavlFindExtremum(Cavl* const root, const bool maximum)
{
Cavl* result = NULL;
Cavl* c = root;
while (c != NULL)
{
result = c;
c = c->lr[maximum];
}
return result;
}
// ---------------------------------------- END OF PUBLIC API SECTION ----------------------------------------
// ---------------------------------------- POLICE LINE DO NOT CROSS ----------------------------------------
/// INTERNAL USE ONLY. Makes the '!r' child of node 'x' its parent; i.e., rotates 'x' toward 'r'.
static inline void cavlPrivateRotate(Cavl* const x, const bool r)
{
CAVL_ASSERT((x != NULL) && (x->lr[!r] != NULL) && ((x->bf >= -1) && (x->bf <= +1)));
Cavl* const z = x->lr[!r];
if (x->up != NULL)
{
x->up->lr[x->up->lr[1] == x] = z;
}
z->up = x->up;
x->up = z;
x->lr[!r] = z->lr[r];
if (x->lr[!r] != NULL)
{
x->lr[!r]->up = x;
}
z->lr[r] = x;
}
/// INTERNAL USE ONLY.
/// Accepts a node and how its balance factor needs to be changed -- either +1 or -1.
/// Returns the new node to replace the old one if tree rotation took place, same node otherwise.
static inline Cavl* cavlPrivateAdjustBalance(Cavl* const x, const bool increment)
{
CAVL_ASSERT((x != NULL) && ((x->bf >= -1) && (x->bf <= +1)));
Cavl* out = x;
const int8_t new_bf = (int8_t) (x->bf + (increment ? +1 : -1));
if ((new_bf < -1) || (new_bf > 1))
{
const bool r = new_bf < 0; // bf<0 if left-heavy --> right rotation is needed.
const int8_t sign = r ? +1 : -1; // Positive if we are rotating right.
Cavl* const z = x->lr[!r];
CAVL_ASSERT(z != NULL); // Heavy side cannot be empty.
if ((z->bf * sign) <= 0) // Parent and child are heavy on the same side or the child is balanced.
{
out = z;
cavlPrivateRotate(x, r);
if (0 == z->bf)
{
x->bf = (int8_t) (-sign);
z->bf = (int8_t) (+sign);
}
else
{
x->bf = 0;
z->bf = 0;
}
}
else // Otherwise, the child needs to be rotated in the opposite direction first.
{
Cavl* const y = z->lr[r];
CAVL_ASSERT(y != NULL); // Heavy side cannot be empty.
out = y;
cavlPrivateRotate(z, !r);
cavlPrivateRotate(x, r);
if ((y->bf * sign) < 0)
{
x->bf = (int8_t) (+sign);
y->bf = 0;
z->bf = 0;
}
else if ((y->bf * sign) > 0)
{
x->bf = 0;
y->bf = 0;
z->bf = (int8_t) (-sign);
}
else
{
x->bf = 0;
z->bf = 0;
}
}
}
else
{
x->bf = new_bf; // Balancing not needed, just update the balance factor and call it a day.
}
return out;
}
/// INTERNAL USE ONLY.
/// Takes the culprit node (the one that is added); returns NULL or the root of the tree (possibly new one).
/// When adding a new node, set its balance factor to zero and call this function to propagate the changes upward.
static inline Cavl* cavlPrivateRetraceOnGrowth(Cavl* const added)
{
CAVL_ASSERT((added != NULL) && (0 == added->bf));
Cavl* c = added; // Child
Cavl* p = added->up; // Parent
while (p != NULL)
{
const bool r = p->lr[1] == c; // c is the right child of parent
CAVL_ASSERT(p->lr[r] == c);
c = cavlPrivateAdjustBalance(p, r);
p = c->up;
if (0 == c->bf)
{ // The height change of the subtree made this parent perfectly balanced (as all things should be),
break; // hence, the height of the outer subtree is unchanged, so upper balance factors are unchanged.
}
}
CAVL_ASSERT(c != NULL);
return (NULL == p) ? c : NULL; // New root or nothing.
}
static inline Cavl* cavlSearch(Cavl** const root,
void* const user_reference,
const CavlPredicate predicate,
const CavlFactory factory)
{
Cavl* out = NULL;
if ((root != NULL) && (predicate != NULL))
{
Cavl* up = *root;
Cavl** n = root;
while (*n != NULL)
{
const int8_t cmp = predicate(user_reference, *n);
if (0 == cmp)
{
out = *n;
break;
}
up = *n;
n = &(*n)->lr[cmp > 0];
CAVL_ASSERT((NULL == *n) || ((*n)->up == up));
}
if (NULL == out)
{
out = (NULL == factory) ? NULL : factory(user_reference);
if (out != NULL)
{
*n = out; // Overwrite the pointer to the new node in the parent node.
out->lr[0] = NULL;
out->lr[1] = NULL;
out->up = up;
out->bf = 0;
Cavl* const rt = cavlPrivateRetraceOnGrowth(out);
if (rt != NULL)
{
*root = rt;
}
}
}
}
return out;
}
static inline void cavlRemove(Cavl** const root, const Cavl* const node)
{
if ((root != NULL) && (node != NULL))
{
CAVL_ASSERT(*root != NULL); // Otherwise, the node would have to be NULL.
CAVL_ASSERT((node->up != NULL) || (node == *root));
Cavl* p = NULL; // The lowest parent node that suffered a shortening of its subtree.
bool r = false; // Which side of the above was shortened.
// The first step is to update the topology and remember the node where to start the retracing from later.
// Balancing is not performed yet so we may end up with an unbalanced tree.
if ((node->lr[0] != NULL) && (node->lr[1] != NULL))
{
Cavl* const re = cavlFindExtremum(node->lr[1], false);
CAVL_ASSERT((re != NULL) && (NULL == re->lr[0]) && (re->up != NULL));
re->bf = node->bf;
re->lr[0] = node->lr[0];
re->lr[0]->up = re;
if (re->up != node)
{
p = re->up; // Retracing starts with the ex-parent of our replacement node.
CAVL_ASSERT(p->lr[0] == re);
p->lr[0] = re->lr[1]; // Reducing the height of the left subtree here.
if (p->lr[0] != NULL)
{
p->lr[0]->up = p;
}
re->lr[1] = node->lr[1];
re->lr[1]->up = re;
r = false;
}
else // In this case, we are reducing the height of the right subtree, so r=1.
{
p = re; // Retracing starts with the replacement node itself as we are deleting its parent.
r = true; // The right child of the replacement node remains the same so we don't bother relinking it.
}
re->up = node->up;
if (re->up != NULL)
{
re->up->lr[re->up->lr[1] == node] = re; // Replace link in the parent of node.
}
else
{
*root = re;
}
}
else // Either or both of the children are NULL.
{
p = node->up;
const bool rr = node->lr[1] != NULL;
if (node->lr[rr] != NULL)
{
node->lr[rr]->up = p;
}
if (p != NULL)
{
r = p->lr[1] == node;
p->lr[r] = node->lr[rr];
if (p->lr[r] != NULL)
{
p->lr[r]->up = p;
}
}
else
{
*root = node->lr[rr];
}
}
// Now that the topology is updated, perform the retracing to restore balance. We climb up adjusting the
// balance factors until we reach the root or a parent whose balance factor becomes plus/minus one, which
// means that that parent was able to absorb the balance delta; in other words, the height of the outer
// subtree is unchanged, so upper balance factors shall be kept unchanged.
if (p != NULL)
{
Cavl* c = NULL;
for (;;)
{
c = cavlPrivateAdjustBalance(p, !r);
p = c->up;
if ((c->bf != 0) || (NULL == p)) // Reached the root or the height difference is absorbed by c.
{
break;
}
r = p->lr[1] == c;
}
if (NULL == p)
{
CAVL_ASSERT(c != NULL);
*root = c;
}
}
}
}
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,714 @@
/// ____ ______ __ __
/// / __ `____ ___ ____ / ____/_ ______ / /_ ____ / /
/// / / / / __ `/ _ `/ __ `/ / / / / / __ `/ __ `/ __ `/ /
/// / /_/ / /_/ / __/ / / / /___/ /_/ / /_/ / / / / /_/ / /
/// `____/ .___/`___/_/ /_/`____/`__, / .___/_/ /_/`__,_/_/
/// /_/ /____/_/
///
/// Libcanard is a compact implementation of the Cyphal/CAN protocol for high-integrity real-time embedded systems.
/// It is designed for use in robust deterministic embedded systems equipped with at least 32K ROM and 8K RAM.
/// The codebase follows the MISRA C rules, has 100% test coverage, and is validated by at least two static analyzers.
/// The library is designed to be compatible with any target platform and instruction set architecture, from 8 to 64
/// bit, little- and big-endian, RTOS-based or baremetal, etc., as long as there is a standards-compliant compiler.
///
/// INTEGRATION
///
/// The library is intended to be integrated into the end application by simply copying its source files into the
/// source tree of the project; it does not require any special compilation options and should work out of the box.
/// There are build-time configuration parameters defined near the top of canard.c, but they are safe to ignore.
///
/// As explained in this documentation, the library requires a deterministic constant-time bounded-fragmentation dynamic
/// memory allocator. If your target platform does not provide a deterministic memory manager (most platforms don't),
/// it is recommended to use O1Heap (MIT licensed): https://github.com/pavel-kirienko/o1heap.
///
/// There are no specific requirements to the underlying I/O layer. Some low-level drivers maintained by the
/// OpenCyphal team may be found at https://github.com/OpenCyphal-Garage/platform_specific_components.
///
/// If your application requires a MISRA C compliance report, please get in touch with the maintainers via the forum
/// at https://forum.opencyphal.org.
///
/// ARCHITECTURE
///
/// Cyphal, as a protocol stack, is composed of two layers: TRANSPORT and PRESENTATION. The transport layer is portable
/// across different transport protocols, one of which is CAN (FD), formally referred to as Cyphal/CAN. This library
/// is focused on Cyphal/CAN only and it will not support other transports. The presentation layer is implemented
/// through the DSDL language and the associated data type regulation policies; these parts are out of the scope of
/// this library as it is focused purely on the transport.
///
/// This library consists of two components: the transmission (TX) pipeline and the reception (RX) pipeline.
/// The pipelines are completely independent from each other except that they both rely on the same dynamic memory
/// manager. The TX pipeline uses the dynamic memory to store outgoing CAN frames in the prioritized transmission
/// queue. The RX pipeline uses the dynamic memory to store contiguous payload buffers for received transfers and
/// for keeping the transfer reassembly state machine data. The exact memory consumption model is defined for both
/// pipelines, so it is possible to statically determine the minimum size of the dynamic memory pool required to
/// guarantee that a given application will never encounter an out-of-memory error at runtime.
///
/// Much like with dynamic memory, the time complexity of every API function is well-characterized, allowing the
/// application to guarantee predictable real-time performance.
///
/// The TX pipeline is managed with the help of four API functions. The first one -- canardTxInit() -- is used for
/// constructing a new TX queue, of which there should be as many as there are redundant CAN interfaces;
/// each queue is managed independently. When the application needs to emit a transfer, it invokes canardTxPush()
/// on each queue separately. The function splits the transfer into CAN frames and stores them into the queue.
/// The application then picks the produced CAN frames from the queue one-by-one by calling canardTxPeek() followed
/// by canardTxPop() -- the former allows the application to look at the next frame scheduled for transmission,
/// and the latter tells the library that the frame shall be removed from the queue.
/// Popped frames need to be manually deallocated by the application upon transmission.
///
/// The RX pipeline is managed with the help of three API functions; unlike the TX pipeline, there is one shared
/// state for all redundant interfaces that manages deduplication transparently. The main function canardRxAccept()
/// takes a received CAN frame and updates the appropriate transfer reassembly state machine. The functions
/// canardRxSubscribe() and its counterpart canardRxUnsubscribe() instruct the library which transfers should be
/// received (by default, all transfers are ignored); also, the subscription function specifies vital transfer
/// reassembly parameters such as the maximum payload size (i.e., the maximum size of a serialized representation
/// of a DSDL object) and the transfer-ID timeout. Transfers that carry more payload than the configured maximum per
/// subscription are truncated following the Implicit Truncation Rule (ITR) defined by the Cyphal Specification --
/// the rule is implemented to facilitate backward-compatible DSDL data type extensibility.
///
/// The library supports a practically unlimited number of redundant interfaces.
///
/// The library is not thread-safe: if used in a concurrent environment, it is the responsibility of the application
/// to provide adequate synchronization.
///
/// The library is purely reactive: it does not perform any background processing and does not require periodic
/// servicing. Its internal state is only updated as a response to well-specified external events.
///
/// --------------------------------------------------------------------------------------------------------------------
///
/// This software is distributed under the terms of the MIT License.
/// Copyright (c) 2016 OpenCyphal.
/// Author: Pavel Kirienko <pavel@opencyphal.org>
/// Contributors: https://github.com/OpenCyphal/libcanard/contributors.
#ifndef CANARD_H_INCLUDED
#define CANARD_H_INCLUDED
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/// Semantic version of this library (not the Cyphal specification).
/// API will be backward compatible within the same major version.
#define CANARD_VERSION_MAJOR 3
#define CANARD_VERSION_MINOR 3
/// The version number of the Cyphal specification implemented by this library.
#define CANARD_CYPHAL_SPECIFICATION_VERSION_MAJOR 1
#define CANARD_CYPHAL_SPECIFICATION_VERSION_MINOR 0
/// These error codes may be returned from the library API calls whose return type is a signed integer in the negated
/// form (e.g., error code 2 returned as -2). A non-negative return value represents success.
/// API calls whose return type is not a signed integer cannot fail by contract.
/// No other error states may occur in the library.
/// By contract, a well-characterized application with a properly sized memory pool will never encounter errors.
/// The error code 1 is not used because -1 is often used as a generic error code in 3rd-party code.
#define CANARD_ERROR_INVALID_ARGUMENT 2
#define CANARD_ERROR_OUT_OF_MEMORY 3
/// MTU values for the supported protocols.
/// Per the recommendations given in the Cyphal/CAN Specification, other MTU values should not be used.
#define CANARD_MTU_CAN_CLASSIC 8U
#define CANARD_MTU_CAN_FD 64U
#define CANARD_MTU_MAX CANARD_MTU_CAN_FD
/// Parameter ranges are inclusive; the lower bound is zero for all. See Cyphal/CAN Specification for background.
#define CANARD_SUBJECT_ID_MAX 8191U
#define CANARD_SERVICE_ID_MAX 511U
#define CANARD_NODE_ID_MAX 127U
#define CANARD_PRIORITY_MAX 7U
#define CANARD_TRANSFER_ID_BIT_LENGTH 5U
#define CANARD_TRANSFER_ID_MAX ((1U << CANARD_TRANSFER_ID_BIT_LENGTH) - 1U)
/// This value represents an undefined node-ID: broadcast destination or anonymous source.
/// Library functions treat all values above CANARD_NODE_ID_MAX as anonymous.
#define CANARD_NODE_ID_UNSET 255U
/// This is the recommended transfer-ID timeout value given in the Cyphal Specification. The application may choose
/// different values per subscription (i.e., per data specifier) depending on its timing requirements.
#define CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC 2000000UL
// Forward declarations.
typedef struct CanardInstance CanardInstance;
typedef struct CanardTreeNode CanardTreeNode;
typedef struct CanardTxQueueItem CanardTxQueueItem;
typedef uint64_t CanardMicrosecond;
typedef uint16_t CanardPortID;
typedef uint8_t CanardNodeID;
typedef uint8_t CanardTransferID;
/// Transfer priority level mnemonics per the recommendations given in the Cyphal Specification.
typedef enum
{
CanardPriorityExceptional = 0,
CanardPriorityImmediate = 1,
CanardPriorityFast = 2,
CanardPriorityHigh = 3,
CanardPriorityNominal = 4, ///< Nominal priority level should be the default.
CanardPriorityLow = 5,
CanardPrioritySlow = 6,
CanardPriorityOptional = 7,
} CanardPriority;
/// Transfer kinds as defined by the Cyphal Specification.
typedef enum
{
CanardTransferKindMessage = 0, ///< Multicast, from publisher to all subscribers.
CanardTransferKindResponse = 1, ///< Point-to-point, from server to client.
CanardTransferKindRequest = 2, ///< Point-to-point, from client to server.
} CanardTransferKind;
#define CANARD_NUM_TRANSFER_KINDS 3
/// The AVL tree node structure is exposed here to avoid pointer casting/arithmetics inside the library.
/// The user code is not expected to interact with this type except if advanced introspection is required.
struct CanardTreeNode
{
CanardTreeNode* up; ///< Do not access this field.
CanardTreeNode* lr[2]; ///< Left and right children of this node may be accessed for tree traversal.
int8_t bf; ///< Do not access this field.
};
/// CAN data frame with an extended 29-bit ID. RTR/Error frames are not used and therefore not modeled here.
/// CAN frames with 11-bit ID are not used by Cyphal/CAN and so they are not supported by the library.
typedef struct
{
/// 29-bit extended ID. The bits above 29-th shall be zero.
uint32_t extended_can_id;
/// The useful data in the frame. The length value is not to be confused with DLC!
/// If the payload is empty (payload_size = 0), the payload pointer may be NULL.
/// For RX frames: the library does not expect the lifetime of the pointee to extend beyond the point of return
/// from the API function. That is, the pointee can be invalidated immediately after the frame has been processed.
/// For TX frames: the frame and the payload are allocated within the same dynamic memory fragment, so their
/// lifetimes are identical; when the frame is freed, the payload is invalidated.
/// A more detailed overview of the dataflow and related resource management issues is provided in the API docs.
size_t payload_size;
const void* payload;
} CanardFrame;
/// Conversion look-up table from CAN DLC to data length.
extern const uint8_t CanardCANDLCToLength[16];
/// Conversion look-up table from data length to CAN DLC; the length is rounded up.
extern const uint8_t CanardCANLengthToDLC[65];
/// A Cyphal transfer metadata (everything except the payload).
/// Per Specification, a transfer is represented on the wire as a non-empty set of transport frames (i.e., CAN frames).
/// The library is responsible for serializing transfers into transport frames when transmitting, and reassembling
/// transfers from an incoming stream of frames (possibly duplicated if redundant interfaces are used) during reception.
typedef struct
{
/// Per the Specification, all frames belonging to a given transfer shall share the same priority level.
/// If this is not the case, then this field contains the priority level of the last frame to arrive.
CanardPriority priority;
CanardTransferKind transfer_kind;
/// Subject-ID for message publications; service-ID for service requests/responses.
CanardPortID port_id;
/// For outgoing message transfers the value shall be CANARD_NODE_ID_UNSET (otherwise the state is invalid).
/// For outgoing service transfers this is the destination address (invalid if unset).
/// For incoming non-anonymous transfers this is the node-ID of the origin.
/// For incoming anonymous transfers the value is reported as CANARD_NODE_ID_UNSET.
CanardNodeID remote_node_id;
/// When responding to a service request, the response transfer SHALL have the same transfer-ID value as the
/// request because the client will match the response with the request based on that.
///
/// When publishing a message transfer, the value SHALL be one greater than the previous transfer under the same
/// subject-ID; the initial value should be zero.
///
/// When publishing a service request transfer, the value SHALL be one greater than the previous transfer under
/// the same service-ID addressed to the same server node-ID; the initial value should be zero.
///
/// Upon overflow, the value SHALL be reset back to zero.
/// Values above CANARD_TRANSFER_ID_MAX are permitted -- the library will compute the modulo automatically.
/// For received transfers, the values never exceed CANARD_TRANSFER_ID_MAX.
///
/// A simple and robust way of managing transfer-ID counters is to keep a separate static variable per subject-ID
/// and per (service-ID, server-node-ID) pair.
CanardTransferID transfer_id;
} CanardTransferMetadata;
/// Prioritized transmission queue that keeps CAN frames destined for transmission via one CAN interface.
/// Applications with redundant interfaces are expected to have one instance of this type per interface.
/// Applications that are not interested in transmission may have zero queues.
/// All operations (push, peek, pop) are O(log n); there is exactly one heap allocation per element.
/// API functions that work with this type are named "canardTx*()", find them below.
typedef struct CanardTxQueue
{
/// The maximum number of frames this queue is allowed to contain. An attempt to push more will fail with an
/// out-of-memory error even if the memory is not exhausted. This value can be changed by the user at any moment.
/// The purpose of this limitation is to ensure that a blocked queue does not exhaust the heap memory.
size_t capacity;
/// The transport-layer maximum transmission unit (MTU). The value can be changed arbitrarily at any time between
/// pushes. It defines the maximum number of data bytes per CAN data frame in outgoing transfers via this queue.
///
/// Only the standard values should be used as recommended by the specification;
/// otherwise, networking interoperability issues may arise. See recommended values CANARD_MTU_*.
///
/// Valid values are any valid CAN frame data length value not smaller than 8.
/// Invalid values are treated as the nearest valid value. The default is the maximum valid value.
size_t mtu_bytes;
/// The number of frames that are currently contained in the queue, initially zero.
/// Do not modify this field!
size_t size;
/// The root of the priority queue is NULL if the queue is empty. Do not modify this field!
CanardTreeNode* root;
/// This field can be arbitrarily mutated by the user. It is never accessed by the library.
/// Its purpose is to simplify integration with OOP interfaces.
void* user_reference;
} CanardTxQueue;
/// One frame stored in the transmission queue along with its metadata.
struct CanardTxQueueItem
{
/// Internal use only; do not access this field.
CanardTreeNode base;
/// Points to the next frame in this transfer or NULL. This field is mostly intended for own needs of the library.
/// Normally, the application would not use it because transfer frame ordering is orthogonal to global TX ordering.
/// It can be useful though for pulling pending frames from the TX queue if at least one frame of their transfer
/// failed to transmit; the idea is that if at least one frame is missing, the transfer will not be received by
/// remote nodes anyway, so all its remaining frames can be dropped from the queue at once using canardTxPop().
CanardTxQueueItem* next_in_transfer;
/// This is the same value that is passed to canardTxPush().
/// Frames whose transmission deadline is in the past shall be dropped.
CanardMicrosecond tx_deadline_usec;
/// The actual CAN frame data.
CanardFrame frame;
};
/// Transfer subscription state. The application can register its interest in a particular kind of data exchanged
/// over the bus by creating such subscription objects. Frames that carry data for which there is no active
/// subscription will be silently dropped by the library. The entire RX pipeline is invariant to the number of
/// redundant CAN interfaces used.
///
/// SUBSCRIPTION INSTANCES SHALL NOT BE MOVED WHILE IN USE.
///
/// The memory footprint of a subscription is large. On a 32-bit platform it slightly exceeds half a KiB.
/// This is an intentional time-memory trade-off: use a large look-up table to ensure predictable temporal properties.
typedef struct CanardRxSubscription
{
CanardTreeNode base; ///< Read-only DO NOT MODIFY THIS
CanardMicrosecond transfer_id_timeout_usec;
size_t extent; ///< Read-only DO NOT MODIFY THIS
CanardPortID port_id; ///< Read-only DO NOT MODIFY THIS
/// This field can be arbitrarily mutated by the user. It is never accessed by the library.
/// Its purpose is to simplify integration with OOP interfaces.
void* user_reference;
/// The current architecture is an acceptable middle ground between worst-case execution time and memory
/// consumption. Instead of statically pre-allocating a dedicated RX session for each remote node-ID here in
/// this table, we only keep pointers, which are NULL by default, populating a new RX session dynamically
/// on an ad-hoc basis when we first receive a transfer from that node. This is O(1) because our memory
/// allocation routines are assumed to be O(1) and we make at most one allocation per remote node.
///
/// A more predictable and simpler approach is to pre-allocate states here statically instead of keeping
/// just pointers, but it would push the size of this instance from about 0.5 KiB to ~3 KiB for a typical 32-bit
/// system. Since this is a general-purpose library, we have to pick a middle ground so we use the more complex
/// but more memory-efficient approach.
struct CanardInternalRxSession* sessions[CANARD_NODE_ID_MAX + 1U]; ///< Read-only DO NOT MODIFY THIS
} CanardRxSubscription;
/// Reassembled incoming transfer returned by canardRxAccept().
typedef struct CanardRxTransfer
{
CanardTransferMetadata metadata;
/// The timestamp of the first received CAN frame of this transfer.
/// The time system may be arbitrary as long as the clock is monotonic (steady).
CanardMicrosecond timestamp_usec;
/// If the payload is empty (payload_size = 0), the payload pointer may be NULL.
/// The application is required to deallocate the payload buffer after the transfer is processed.
size_t payload_size;
void* payload;
} CanardRxTransfer;
/// A pointer to the memory allocation function. The semantics are similar to malloc():
/// - The returned pointer shall point to an uninitialized block of memory that is at least "amount" bytes large.
/// - If there is not enough memory, the returned pointer shall be NULL.
/// - The memory shall be aligned at least at max_align_t.
/// - The execution time should be constant (O(1)).
/// - The worst-case memory fragmentation should be bounded and easily predictable.
/// If the standard dynamic memory manager of the target platform does not satisfy the above requirements,
/// consider using O1Heap: https://github.com/pavel-kirienko/o1heap.
typedef void* (*CanardMemoryAllocate)(CanardInstance* ins, size_t amount);
/// The counterpart of the above -- this function is invoked to return previously allocated memory to the allocator.
/// The semantics are similar to free():
/// - The pointer was previously returned by the allocation function.
/// - The pointer may be NULL, in which case the function shall have no effect.
/// - The execution time should be constant (O(1)).
typedef void (*CanardMemoryFree)(CanardInstance* ins, void* pointer);
/// This is the core structure that keeps all of the states and allocated resources of the library instance.
struct CanardInstance
{
/// User pointer that can link this instance with other objects.
/// This field can be changed arbitrarily, the library does not access it after initialization.
/// The default value is NULL.
void* user_reference;
/// The node-ID of the local node.
/// Per the Cyphal Specification, the node-ID should not be assigned more than once.
/// Invalid values are treated as CANARD_NODE_ID_UNSET. The default value is CANARD_NODE_ID_UNSET.
CanardNodeID node_id;
/// Dynamic memory management callbacks. See their type documentation for details.
/// They SHALL be valid function pointers at all times.
/// The time complexity models given in the API documentation are made on the assumption that the memory management
/// functions have constant complexity O(1).
///
/// The following API functions may allocate memory: canardRxAccept(), canardTxPush().
/// The following API functions may deallocate memory: canardRxAccept(), canardRxSubscribe(), canardRxUnsubscribe().
/// The exact memory requirement and usage model is specified for each function in its documentation.
CanardMemoryAllocate memory_allocate;
CanardMemoryFree memory_free;
/// Read-only DO NOT MODIFY THIS
CanardTreeNode* rx_subscriptions[CANARD_NUM_TRANSFER_KINDS];
};
/// CAN acceptance filter configuration with an extended 29-bit ID utilizing an ID + mask filter scheme.
/// Filter configuration can be programmed into a CAN controller to filter out irrelevant messages in hardware.
/// This allows the software application to reduce CPU load spent on processing irrelevant messages.
typedef struct CanardFilter
{
/// 29-bit extended ID. Defines the extended CAN ID to filter incoming frames against.
/// The bits above 29-th shall be zero.
uint32_t extended_can_id;
/// 29-bit extended mask. Defines the bitmask used to enable/disable bits used to filter messages.
/// Only bits that are enabled are compared to the extended_can_id for filtering.
/// The bits above 29-th shall be zero.
uint32_t extended_mask;
} CanardFilter;
/// Construct a new library instance.
/// The default values will be assigned as specified in the structure field documentation.
/// If any of the pointers are NULL, the behavior is undefined.
///
/// The instance does not hold any resources itself except for the allocated memory.
/// To safely discard it, simply remove all existing subscriptions, and don't forget about the TX queues.
///
/// The time complexity is constant. This function does not invoke the dynamic memory manager.
CanardInstance canardInit(const CanardMemoryAllocate memory_allocate, const CanardMemoryFree memory_free);
/// Construct a new transmission queue instance with the specified values for capacity and mtu_bytes.
/// No memory allocation is going to take place until the queue is actually pushed to.
/// Applications are expected to have one instance of this type per redundant interface.
///
/// The instance does not hold any resources itself except for the allocated memory.
/// To safely discard it, simply pop all items from the queue.
///
/// The time complexity is constant. This function does not invoke the dynamic memory manager.
CanardTxQueue canardTxInit(const size_t capacity, const size_t mtu_bytes);
/// This function serializes a transfer into a sequence of transport frames and inserts them into the prioritized
/// transmission queue at the appropriate position. Afterwards, the application is supposed to take the enqueued frames
/// from the transmission queue using the function canardTxPeek() and transmit them. Each transmitted (or otherwise
/// discarded, e.g., due to timeout) frame should be removed from the queue using canardTxPop(). The queue is
/// prioritized following the normal CAN frame arbitration rules to avoid the inner priority inversion. The transfer
/// payload will be copied into the transmission queue so that the lifetime of the frames is not related to the
/// lifetime of the input payload buffer.
///
/// The MTU of the generated frames is dependent on the value of the MTU setting at the time when this function
/// is invoked. The MTU setting can be changed arbitrarily between invocations.
///
/// The tx_deadline_usec will be used to populate the timestamp values of the resulting transport
/// frames (so all frames will have the same timestamp value). This feature is intended to facilitate transmission
/// deadline tracking, i.e., aborting frames that could not be transmitted before the specified deadline.
/// Therefore, normally, the timestamp value should be in the future.
/// The library itself, however, does not use or check this value in any way, so it can be zero if not needed.
///
/// The function returns the number of frames enqueued into the prioritized TX queue (which is always a positive
/// number) in case of success (so that the application can track the number of items in the TX queue if necessary).
/// In case of failure, the function returns a negated error code: either invalid argument or out-of-memory.
///
/// An invalid argument error may be returned in the following cases:
/// - Any of the input arguments are NULL.
/// - The remote node-ID is not CANARD_NODE_ID_UNSET and the transfer is a message transfer.
/// - The remote node-ID is above CANARD_NODE_ID_MAX and the transfer is a service transfer.
/// - The priority, subject-ID, or service-ID exceed their respective maximums.
/// - The transfer kind is invalid.
/// - The payload pointer is NULL while the payload size is nonzero.
/// - The local node is anonymous and a message transfer is requested that requires a multi-frame transfer.
/// - The local node is anonymous and a service transfer is requested.
/// The following cases are handled without raising an invalid argument error:
/// - If the transfer-ID is above the maximum, the excessive bits are silently masked away
/// (i.e., the modulo is computed automatically, so the caller doesn't have to bother).
///
/// An out-of-memory error is returned if a TX frame could not be allocated due to the memory being exhausted,
/// or if the capacity of the queue would be exhausted by this operation. In such cases, all frames allocated for
/// this transfer (if any) will be deallocated automatically. In other words, either all frames of the transfer are
/// enqueued successfully, or none are.
///
/// The time complexity is O(p + log e), where p is the amount of payload in the transfer, and e is the number of
/// frames already enqueued in the transmission queue.
///
/// The memory allocation requirement is one allocation per transport frame. A single-frame transfer takes one
/// allocation; a multi-frame transfer of N frames takes N allocations. The size of each allocation is
/// (sizeof(CanardTxQueueItem) + MTU).
int32_t canardTxPush(CanardTxQueue* const que,
CanardInstance* const ins,
const CanardMicrosecond tx_deadline_usec,
const CanardTransferMetadata* const metadata,
const size_t payload_size,
const void* const payload);
/// This function accesses the top element of the prioritized transmission queue. The queue itself is not modified
/// (i.e., the accessed element is not removed). The application should invoke this function to collect the transport
/// frames of serialized transfers pushed into the prioritized transmission queue by canardTxPush().
///
/// The timestamp values of returned frames are initialized with tx_deadline_usec from canardTxPush().
/// Timestamps are used to specify the transmission deadline. It is up to the application and/or the media layer
/// to implement the discardment of timed-out transport frames. The library does not check it, so a frame that is
/// already timed out may be returned here.
///
/// If the queue is empty or if the argument is NULL, the returned value is NULL.
///
/// If the queue is non-empty, the returned value is a pointer to its top element (i.e., the next frame to transmit).
/// The returned pointer points to an object allocated in the dynamic storage; it should be eventually freed by the
/// application by calling CanardInstance::memory_free(). The memory shall not be freed before the entry is removed
/// from the queue by calling canardTxPop(); this is because until canardTxPop() is executed, the library retains
/// ownership of the object. The pointer retains validity until explicitly freed by the application; in other words,
/// calling canardTxPop() does not invalidate the object.
///
/// The payload buffer is located shortly after the object itself, in the same memory fragment. The application shall
/// not attempt to free it.
///
/// The time complexity is logarithmic of the queue size. This function does not invoke the dynamic memory manager.
const CanardTxQueueItem* canardTxPeek(const CanardTxQueue* const que);
/// This function transfers the ownership of the specified element of the prioritized transmission queue from the queue
/// to the application. The element does not necessarily need to be the top one -- it is safe to dequeue any element.
/// The element is dequeued but not invalidated; it is the responsibility of the application to deallocate the
/// memory used by the object later. The memory SHALL NOT be deallocated UNTIL this function is invoked.
/// The function returns the same pointer that it is given except that it becomes mutable.
///
/// If any of the arguments are NULL, the function has no effect and returns NULL.
///
/// The time complexity is logarithmic of the queue size. This function does not invoke the dynamic memory manager.
CanardTxQueueItem* canardTxPop(CanardTxQueue* const que, const CanardTxQueueItem* const item);
/// This function implements the transfer reassembly logic. It accepts a transport frame from any of the redundant
/// interfaces, locates the appropriate subscription state, and, if found, updates it. If the frame completed a
/// transfer, the return value is 1 (one) and the out_transfer pointer is populated with the parameters of the
/// newly reassembled transfer. The transfer reassembly logic is defined in the Cyphal specification.
///
/// The MTU of the accepted frame can be arbitrary; that is, any MTU is accepted. The DLC validity is irrelevant.
///
/// Any value of redundant_iface_index is accepted; that is, up to 256 redundant interfaces are supported.
/// The index of the interface from which the transfer is accepted is always the same as redundant_iface_index
/// of the current invocation, so the application can always determine which interface has delivered the transfer.
///
/// Upon return, the out_subscription pointer will point to the instance of CanardRxSubscription that accepted this
/// frame; if no matching subscription exists (i.e., frame discarded), the pointer will be NULL.
/// If this information is not relevant, set out_subscription to NULL.
/// The purpose of this argument is to allow integration with OOP adapters built on top of libcanard; see also the
/// user_reference provided in CanardRxSubscription.
///
/// The function invokes the dynamic memory manager in the following cases only:
///
/// 1. New memory for a session state object is allocated when a new session is initiated.
/// This event occurs when a transport frame that matches a known subscription is received from a node that
/// did not emit matching frames since the subscription was created.
/// Once a new session is created, it is not destroyed until the subscription is terminated by invoking
/// canardRxUnsubscribe(). The number of sessions is bounded and the bound is low (at most the number of nodes
/// in the network minus one), also the size of a session instance is very small, so the removal is unnecessary.
/// Real-time networks typically do not change their configuration at runtime, so it is possible to reduce
/// the time complexity by never deallocating sessions.
/// The size of a session instance is at most 48 bytes on any conventional platform (typically much smaller).
///
/// 2. New memory for the transfer payload buffer is allocated when a new transfer is initiated, unless the buffer
/// was already allocated at the time.
/// This event occurs when a transport frame that matches a known subscription is received and it begins a
/// new transfer (that is, the start-of-frame flag is set and it is not a duplicate).
/// The amount of the allocated memory equals the extent as configured via canardRxSubscribe(); please read
/// its documentation for further information about the extent and related edge cases.
/// The worst case occurs when every node on the bus initiates a multi-frame transfer for which there is a
/// matching subscription: in this case, the library will allocate number_of_nodes allocations, where each
/// allocation is the same size as the configured extent.
///
/// 3. Memory allocated for the transfer payload buffer may be deallocated at the discretion of the library.
/// This operation does not increase the worst case execution time and does not improve the worst case memory
/// consumption, so a deterministic application need not consider this behavior in the resource analysis.
/// This behavior is implemented for the benefit of applications where rigorous characterization is unnecessary.
///
/// The worst case dynamic memory consumption per subscription is:
///
/// (sizeof(session instance) + extent) * number_of_nodes
///
/// Where sizeof(session instance) and extent are defined above, and number_of_nodes is the number of remote
/// nodes emitting transfers that match the subscription (which cannot exceed (CANARD_NODE_ID_MAX-1) by design).
/// If the dynamic memory pool is sized correctly, the application is guaranteed to never encounter an
/// out-of-memory (OOM) error at runtime. The actual size of the dynamic memory pool is typically larger;
/// for a detailed treatment of the problem and the related theory please refer to the documentation of O1Heap --
/// a deterministic memory allocator for hard real-time embedded systems.
///
/// The time complexity is O(p + log n) where n is the number of subject-IDs or service-IDs subscribed to by the
/// application, depending on the transfer kind of the supplied frame, and p is the amount of payload in the received
/// frame (because it will be copied into an internal contiguous buffer). Observe that the time complexity is
/// invariant to the network configuration (such as the number of online nodes) -- this is a very important
/// design guarantee for real-time applications because the execution time is dependent only on the number of
/// active subscriptions for a given transfer kind, and the MTU, both of which are easy to predict and account for.
/// Excepting the subscription search and the payload data copying, the entire RX pipeline contains neither loops
/// nor recursion.
/// Misaddressed and malformed frames are discarded in constant time.
///
/// The function returns 1 (one) if the new frame completed a transfer. In this case, the details of the transfer
/// are stored into out_transfer, and the transfer payload buffer ownership is passed to that object. The lifetime
/// of the resulting transfer object is not related to the lifetime of the input transport frame (that is, even if
/// it is a single-frame transfer, its payload is copied out into a new dynamically allocated buffer storage).
/// If the extent is zero, the payload pointer may be NULL, since there is no data to store and so a
/// buffer is not needed. The application is responsible for deallocating the payload buffer when the processing
/// is done by invoking memory_free on the transfer payload pointer.
///
/// The function returns a negated out-of-memory error if it was unable to allocate dynamic memory.
///
/// The function does nothing and returns a negated invalid argument error immediately if any condition is true:
/// - Any of the input arguments that are pointers are NULL.
/// - The payload pointer of the input frame is NULL while its size is non-zero.
/// - The CAN ID of the input frame is not less than 2**29=0x20000000.
///
/// The function returns zero if any of the following conditions are true (the general policy is that protocol
/// errors are not escalated because they do not construe a node-local error):
/// - The received frame is not a valid Cyphal/CAN transport frame.
/// - The received frame is a valid Cyphal/CAN transport frame, but there is no matching subscription,
/// the frame did not complete a transfer, the frame forms an invalid frame sequence, the frame is a duplicate,
/// the frame is unicast to a different node (address mismatch).
int8_t canardRxAccept(CanardInstance* const ins,
const CanardMicrosecond timestamp_usec,
const CanardFrame* const frame,
const uint8_t redundant_iface_index,
CanardRxTransfer* const out_transfer,
CanardRxSubscription** const out_subscription);
/// This function creates a new subscription, allowing the application to register its interest in a particular
/// category of transfers. The library will reject all transport frames for which there is no active subscription.
/// The reference out_subscription shall retain validity until the subscription is terminated (the referred object
/// cannot be moved or destroyed).
///
/// If such subscription already exists, it will be removed first as if canardRxUnsubscribe() was
/// invoked by the application, and then re-created anew with the new parameters.
///
/// The extent defines the size of the transfer payload memory buffer; or, in other words, the maximum possible size
/// of received objects, considering also possible future versions with new fields. It is safe to pick larger values.
/// Note well that the extent is not the same thing as the maximum size of the object, it is usually larger!
/// Transfers that carry payloads that exceed the specified extent will be accepted anyway but the excess payload
/// will be truncated away, as mandated by the Specification. The transfer CRC is always validated regardless of
/// whether its payload is truncated.
///
/// The default transfer-ID timeout value is defined as CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC; use it if not sure.
/// The redundant interface fail-over timeout (if redundant interfaces are used) is the same as the transfer-ID timeout.
/// It may be reduced in a future release of the library, but it will not affect the backward compatibility.
///
/// The return value is 1 if a new subscription has been created as requested.
/// The return value is 0 if such subscription existed at the time the function was invoked. In this case,
/// the existing subscription is terminated and then a new one is created in its place. Pending transfers may be lost.
/// The return value is a negated invalid argument error if any of the input arguments are invalid.
///
/// The time complexity is logarithmic from the number of current subscriptions under the specified transfer kind.
/// This function does not allocate new memory. The function may deallocate memory if such subscription already
/// existed; the deallocation behavior is specified in the documentation for canardRxUnsubscribe().
///
/// Subscription instances have large look-up tables to ensure that the temporal properties of the algorithms are
/// invariant to the network configuration (i.e., a node that is validated on a network containing one other node
/// will provably perform identically on a network that contains X nodes). This is a conscious time-memory trade-off.
int8_t canardRxSubscribe(CanardInstance* const ins,
const CanardTransferKind transfer_kind,
const CanardPortID port_id,
const size_t extent,
const CanardMicrosecond transfer_id_timeout_usec,
CanardRxSubscription* const out_subscription);
/// This function reverses the effect of canardRxSubscribe().
/// If the subscription is found, all its memory is de-allocated (session states and payload buffers); to determine
/// the amount of memory freed, please refer to the memory allocation requirement model of canardRxAccept().
///
/// The return value is 1 if such subscription existed (and, therefore, it was removed).
/// The return value is 0 if such subscription does not exist. In this case, the function has no effect.
/// The return value is a negated invalid argument error if any of the input arguments are invalid.
///
/// The time complexity is logarithmic from the number of current subscriptions under the specified transfer kind.
/// This function does not allocate new memory.
int8_t canardRxUnsubscribe(CanardInstance* const ins,
const CanardTransferKind transfer_kind,
const CanardPortID port_id);
/// This function allows to check the effect of canardRxSubscribe() and canardRxUnsubscribe().
///
/// The return value is 1 if the specified subscription exists, 0 otherwise.
/// The return value is a negated invalid argument error if any of the input arguments are invalid.
/// Output out_subscription could be NULL, but if it is not, it will be populated with the pointer to the existing
/// subscription. In case the subscription does not exist (or error), out_subscription won't be touched.
/// Result pointer to the subscription is valid until the subscription is terminated.
///
/// The time complexity is logarithmic from the number of current subscriptions under the specified transfer kind.
/// This function does not allocate new memory.
int8_t canardRxGetSubscription(CanardInstance* const ins,
const CanardTransferKind transfer_kind,
const CanardPortID port_id,
CanardRxSubscription** const out_subscription);
/// Utilities for generating CAN controller hardware acceptance filter configurations
/// to accept specific subjects, services, or nodes.
///
/// Complex applications will likely subscribe to more subject IDs than there are
/// acceptance filters available in the CAN hardware. In this case, the application
/// should implement filter consolidation. See canardConsolidateFilters()
/// as well as the Cyphal specification for details.
/// Generate an acceptance filter configuration to accept a specific subject ID.
CanardFilter canardMakeFilterForSubject(const CanardPortID subject_id);
/// Generate an acceptance filter configuration to accept both requests and responses for a specific service.
///
/// Users may prefer to instead use a catch-all acceptance filter configuration for accepting
/// all service requests and responses targeted at the specified local node ID.
/// See canardMakeFilterForServices() for this.
CanardFilter canardMakeFilterForService(const CanardPortID service_id, const CanardNodeID local_node_id);
/// Generate an acceptance filter configuration to accept all service
/// requests and responses targeted to the specified local node ID.
///
/// Due to the relatively low frequency of service transfers expected on a network,
/// and the fact that a service directed at a specific node is not likely to be rejected by that node,
/// a user may prefer to use this over canardMakeFilterForService()
/// in order to simplify the API usage and reduce the number of required hardware CAN acceptance filters.
CanardFilter canardMakeFilterForServices(const CanardNodeID local_node_id);
/// Consolidate two acceptance filter configurations into a single configuration.
///
/// Complex applications will likely subscribe to more subject IDs than there are
/// acceptance filters available in the CAN hardware. In this case, the application
/// should implement filter consolidation. While this may make it impossible to create
/// a 'perfect' filter that only accepts desired subject IDs, the application should apply
/// consolidation in a manner that minimizes the number of undesired messages that pass
/// through the hardware acceptance filters and require software filtering (implemented by canardRxSubscribe).
///
/// While optimal choice of filter consolidation is a function of the number of available hardware filters,
/// the set of transfers needed by the application, and the expected frequency of occurrence
/// of all possible distinct transfers on the bus, it is possible to generate a quasi-optimal configuration
/// if information about the frequency of occurrence of different transfers is not known.
/// For details, see the "Automatic hardware acceptance filter configuration" note under the Cyphal/CAN section
/// in the Transport Layer chapter of the Cyphal specification.
CanardFilter canardConsolidateFilters(const CanardFilter* const a, const CanardFilter* const b);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,118 @@
#include "canard.h"
#include <stdlib.h>
CanardInstance canard;
CanardTxQueue txQueue;
void* canard_memAllocate(CanardInstance* const canard, const size_t amount)
{
(void) canard;
return x_malloc(amount);
}
void canard_memFree(CanardInstance* const canard, void* const pointer)
{
(void) canard;
free(pointer);
}
void slave_comm_init()
{
canard = canardInit(&canard_memAllocate, &canard_memFree);
canard.node_id = savePara.id;
txQueue = canardTxInit(1536, CANARD_MTU_CAN_CLASSIC); // Set MTU = 64 bytes. There is also CANARD_MTU_CAN_CLASSIC.
}
void slave_comm_tx_process()
{
for (const CanardTxQueueItem* ti = NULL; (ti = canardTxPeek(&txQueue)) != NULL;) // Peek at the top of the queue.
{
if ((0U == ti->tx_deadline_usec) || (ti->tx_deadline_usec > rt_tick_get_millisecond()*1000)) // Check the deadline.
{
if (!slave_send_ext(ti->frame.extended_can_id,(void *)ti->frame.payload,ti->frame.payload_size)) // Send the frame over this redundant CAN iface.
{
break; // If the driver is busy, break and retry later.
}
}
// After the frame is transmitted or if it has timed out while waiting, pop it from the queue and deallocate:
canard.memory_free(&canard, canardTxPop(&txQueue, ti));
}
}
rt_inline uint8_t slave_send_ext(uint32_t id,uint8_t *sendBuf,uint8_t len)
{
struct rt_can_msg txMsg = {0};
txMsg.id = id;
txMsg.ide = RT_CAN_EXTID;
txMsg.rtr = RT_CAN_DTR;
txMsg.len = len;
for(rt_uint8_t i=0;i<len;i++)
{
txMsg.data[i] = sendBuf[i];
}
return rt_device_write(slaveDev,0,&txMsg,sizeof(txMsg));
}
void slave_comm_rx_process()
{
CanardRxTransfer transfer;
CanardFrame receivedFrame;
struct rt_can_msg canRxMsg = {0};
uint32_t rxTimestampUsec;
int8_t result;
while(rt_mq_recv(&slave_rec_msgq,&canRxMsg,sizeof(canRxMsg),RT_WAITING_NO) == RT_EOK)
{
receivedFrame.extended_can_id = canRxMsg.id;
receivedFrame.payload_size = canRxMsg.len;
receivedFrame.payload = canRxMsg.data;
rxTimestampUsec = rt_tick_get_millisecond()*1000;
result = canardRxAccept(&canard,
rxTimestampUsec, // When the frame was received, in microseconds.
&receivedFrame, // The CAN frame received from the bus.
0, // If the transport is not redundant, use 0.
&transfer,
NULL);
if (result < 0)
{
// An error has occurred: either an argument is invalid or we've ran out of memory.
// It is possible to statically prove that an out-of-memory will never occur for a given application if
// the heap is sized correctly; for background, refer to the Robson's Proof and the documentation for O1Heap.
// Reception of an invalid frame is NOT an error.
}
else if (result == 1)
{
void process_received_transfer(const uint8_t index,CanardRxTransfer* const transfer);
process_received_transfer(0, &transfer); // A transfer has been received, process it.
canard.memory_free(&canard, transfer.payload); // Deallocate the dynamic memory afterwards.
}
else
{
// Nothing to do.
// The received frame is either invalid or it's a non-last frame of a multi-frame transfer.
// Reception of an invalid frame is NOT reported as an error because it is not an error.
}
}
}
void process_received_transfer(const uint8_t index,CanardRxTransfer* const transfer)
{
LOG_D("slave rec id:%d size:%d",transfer->metadata.remote_node_id,transfer->payload_size);
if(transfer->metadata.remote_node_id == canard.node_id)
{
slavePackDef *p = (slavePackDef *)transfer->payload;
recCmd = p->packCmd;
}
}