可以收发,开始写自动生成接口

This commit is contained in:
yxming66 2025-12-27 20:29:07 +08:00
parent ef1f6d6642
commit 9db1394184
21 changed files with 2582 additions and 2905 deletions

File diff suppressed because one or more lines are too long

View File

@ -207,7 +207,7 @@ ProjectManager.ProjectName=FDCAN
ProjectManager.ProjectStructure=
ProjectManager.RegisterCallBack=
ProjectManager.StackSize=0x2000
ProjectManager.TargetToolchain=MDK-ARM V5.32
ProjectManager.TargetToolchain=CMake
ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath=

File diff suppressed because one or more lines are too long

View File

@ -157,9 +157,25 @@
<Bp>
<Number>0</Number>
<Type>0</Type>
<LineNumber>249</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>134224724</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>
<SizeOfObject>0</SizeOfObject>
<BreakByAccess>0</BreakByAccess>
<BreakIfRCount>1</BreakIfRCount>
<Filename>..\User\bsp\fdcan.c</Filename>
<ExecCommand></ExecCommand>
<Expression>\\FDCAN\../User/bsp/fdcan.c\249</Expression>
</Bp>
<Bp>
<Number>1</Number>
<Type>0</Type>
<LineNumber>217</LineNumber>
<EnabledFlag>1</EnabledFlag>
<Address>134224716</Address>
<Address>134224896</Address>
<ByteObject>0</ByteObject>
<HtxType>0</HtxType>
<ManyObjects>0</ManyObjects>

Binary file not shown.

View File

@ -28,6 +28,10 @@ Project File Date: 12/27/2025
*** Using Compiler 'V5.06 update 7 (build 960)', folder: 'D:\cangming\ARM\ARMCC\Bin'
Build target 'FDCAN'
Note: source file '..\User\bsp\fdcan.c' - object file renamed from 'FDCAN\fdcan.o' to 'FDCAN\fdcan_1.o'.
compiling fdcan.c...
linking...
Program Size: Code=23940 RO-data=996 RW-data=176 ZI-data=41576
FromELF: creating hex file...
"FDCAN\FDCAN.axf" - 0 Error(s), 0 Warning(s).
<h2>Software Packages used:</h2>
@ -51,7 +55,7 @@ Package Vendor: Keil
* Component: ARM::CMSIS:CORE:5.4.0
Include file: CMSIS\Core\Include\tz_context.h
Build Time Elapsed: 00:00:01
Build Time Elapsed: 00:00:05
</pre>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
<title>Static Call Graph - [FDCAN\FDCAN.axf]</title></head>
<body><HR>
<H1>Static Call Graph for image FDCAN\FDCAN.axf</H1><HR>
<BR><P>#&#060CALLGRAPH&#062# ARM Linker, 5060960: Last Updated: Sat Dec 27 03:17:48 2025
<BR><P>#&#060CALLGRAPH&#062# ARM Linker, 5060960: Last Updated: Sat Dec 27 03:49:53 2025
<BR><P>
<H3>Maximum Stack Usage = 352 bytes + Unknown(Functions without stacksize, Cycles, Untraceable Function Pointers)</H3><H3>
Call chain for Maximum Stack Depth:</H3>
@ -880,7 +880,7 @@ Global Symbols
<BR>[Called By]<UL><LI><a href="#[9e]">&gt;&gt;</a>&nbsp;&nbsp;&nbsp;Task_blink
</UL>
<P><STRONG><a name="[c7]"></a>BSP_FDCAN_Init</STRONG> (Thumb, 434 bytes, Stack size 56 bytes, fdcan_1.o(i.BSP_FDCAN_Init))
<P><STRONG><a name="[c7]"></a>BSP_FDCAN_Init</STRONG> (Thumb, 428 bytes, Stack size 56 bytes, fdcan_1.o(i.BSP_FDCAN_Init))
<BR><BR>[Stack]<UL><LI>Max Depth = 200<LI>Call Chain = BSP_FDCAN_Init &rArr; osMutexNew &rArr; xQueueCreateMutexStatic &rArr; prvInitialiseMutex &rArr; xQueueGenericSend &rArr; xTaskResumeAll &rArr; xTaskIncrementTick
</UL>
<BR>[Calls]<UL><LI><a href="#[cd]">&gt;&gt;</a>&nbsp;&nbsp;&nbsp;HAL_FDCAN_Start
@ -911,7 +911,7 @@ Global Symbols
<BR>[Called By]<UL><LI><a href="#[9e]">&gt;&gt;</a>&nbsp;&nbsp;&nbsp;Task_blink
</UL>
<P><STRONG><a name="[d7]"></a>BSP_FDCAN_Transmit</STRONG> (Thumb, 318 bytes, Stack size 136 bytes, fdcan_1.o(i.BSP_FDCAN_Transmit))
<P><STRONG><a name="[d7]"></a>BSP_FDCAN_Transmit</STRONG> (Thumb, 320 bytes, Stack size 136 bytes, fdcan_1.o(i.BSP_FDCAN_Transmit))
<BR><BR>[Stack]<UL><LI>Max Depth = 172<LI>Call Chain = BSP_FDCAN_Transmit &rArr; HAL_FDCAN_AddMessageToTxFifoQ &rArr; FDCAN_CopyMessageToRAM
</UL>
<BR>[Calls]<UL><LI><a href="#[d8]">&gt;&gt;</a>&nbsp;&nbsp;&nbsp;HAL_FDCAN_GetTxFifoFreeLevel
@ -1563,7 +1563,7 @@ Global Symbols
</UL>
<BR>[Address Reference Count : 1]<UL><LI> freertos.o(i.MX_FREERTOS_Init)
</UL>
<P><STRONG><a name="[9e]"></a>Task_blink</STRONG> (Thumb, 308 bytes, Stack size 32 bytes, blink.o(i.Task_blink))
<P><STRONG><a name="[9e]"></a>Task_blink</STRONG> (Thumb, 298 bytes, Stack size 32 bytes, blink.o(i.Task_blink))
<BR><BR>[Stack]<UL><LI>Max Depth = 232<LI>Call Chain = Task_blink &rArr; BSP_FDCAN_Init &rArr; osMutexNew &rArr; xQueueCreateMutexStatic &rArr; prvInitialiseMutex &rArr; xQueueGenericSend &rArr; xTaskResumeAll &rArr; xTaskIncrementTick
</UL>
<BR>[Calls]<UL><LI><a href="#[11e]">&gt;&gt;</a>&nbsp;&nbsp;&nbsp;osDelay

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
Dependencies for Project 'FDCAN', Target 'FDCAN': (DO NOT MODIFY !)
CompilerVersion: 5060960::V5.06 update 7 (build 960)::.\ARMCC
F (startup_stm32h723xx.s)(0x694ED3B7)(--cpu Cortex-M7.fp.dp -g --apcs=interwork -I ../Drivers/CMSIS/Include -I.\RTE\_FDCAN -ID:\cangming\ARM\CMSIS\5.7.0\CMSIS\Core\Include --pd "__UVISION_VERSION SETA 534" --pd "_RTE_ SETA 1" --pd "STM32H723xx SETA 1" --pd "_RTE_ SETA 1" --list startup_stm32h723xx.lst --xref -o fdcan\startup_stm32h723xx.o --depend fdcan\startup_stm32h723xx.d)
F (startup_stm32h723xx.s)(0x694EE382)(--cpu Cortex-M7.fp.dp -g --apcs=interwork -I ../Drivers/CMSIS/Include -I.\RTE\_FDCAN -ID:\cangming\ARM\CMSIS\5.7.0\CMSIS\Core\Include --pd "__UVISION_VERSION SETA 534" --pd "_RTE_ SETA 1" --pd "STM32H723xx SETA 1" --pd "_RTE_ SETA 1" --list startup_stm32h723xx.lst --xref -o fdcan\startup_stm32h723xx.o --depend fdcan\startup_stm32h723xx.d)
F (../Core/Src/main.c)(0x694E2F79)(--c99 --gnu -c --cpu Cortex-M7.fp.dp -g -O3 --apcs=interwork --split_sections -I ../Core/Inc -I ../Drivers/STM32H7xx_HAL_Driver/Inc -I ../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy -I ../Drivers/CMSIS/Device/ST/STM32H7xx/Include -I ../Drivers/CMSIS/Include -I ../Middlewares/Third_Party/FreeRTOS/Source/include -I ../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 -I ../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F -I ../User -I.\RTE\_FDCAN -ID:\cangming\ARM\CMSIS\5.7.0\CMSIS\Core\Include -D__UVISION_VERSION="534" -D_RTE_ -DSTM32H723xx -D_RTE_ -DUSE_PWR_LDO_SUPPLY -DUSE_HAL_DRIVER -DSTM32H723xx -o fdcan\main.o --omf_browse fdcan\main.crf --depend fdcan\main.d)
I (../Core/Inc/main.h)(0x694E28D6)
I (../Drivers/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal.h)(0x6944350B)
@ -1158,7 +1158,7 @@ I (../Middlewares/Third_Party/FreeRTOS/Source/include/mpu_wrappers.h)(0x694434DA
I (../Middlewares/Third_Party/FreeRTOS/Source/include/task.h)(0x694434DA)
I (../Middlewares/Third_Party/FreeRTOS/Source/include/list.h)(0x694434DA)
F (..\User\bsp\bsp.h)(0x694E34A2)()
F (..\User\bsp\fdcan.c)(0x694EDF57)(--c99 --gnu -c --cpu Cortex-M7.fp.dp -g -O3 --apcs=interwork --split_sections -I ../Core/Inc -I ../Drivers/STM32H7xx_HAL_Driver/Inc -I ../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy -I ../Drivers/CMSIS/Device/ST/STM32H7xx/Include -I ../Drivers/CMSIS/Include -I ../Middlewares/Third_Party/FreeRTOS/Source/include -I ../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 -I ../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F -I ../User -I.\RTE\_FDCAN -ID:\cangming\ARM\CMSIS\5.7.0\CMSIS\Core\Include -D__UVISION_VERSION="534" -D_RTE_ -DSTM32H723xx -D_RTE_ -DUSE_PWR_LDO_SUPPLY -DUSE_HAL_DRIVER -DSTM32H723xx -o fdcan\fdcan_1.o --omf_browse fdcan\fdcan_1.crf --depend fdcan\fdcan_1.d)
F (..\User\bsp\fdcan.c)(0x694EE6C6)(--c99 --gnu -c --cpu Cortex-M7.fp.dp -g -O3 --apcs=interwork --split_sections -I ../Core/Inc -I ../Drivers/STM32H7xx_HAL_Driver/Inc -I ../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy -I ../Drivers/CMSIS/Device/ST/STM32H7xx/Include -I ../Drivers/CMSIS/Include -I ../Middlewares/Third_Party/FreeRTOS/Source/include -I ../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 -I ../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F -I ../User -I.\RTE\_FDCAN -ID:\cangming\ARM\CMSIS\5.7.0\CMSIS\Core\Include -D__UVISION_VERSION="534" -D_RTE_ -DSTM32H723xx -D_RTE_ -DUSE_PWR_LDO_SUPPLY -DUSE_HAL_DRIVER -DSTM32H723xx -o fdcan\fdcan_1.o --omf_browse fdcan\fdcan_1.crf --depend fdcan\fdcan_1.d)
I (..\User\bsp\fdcan.h)(0x694ED994)
I (D:\cangming\ARM\ARMCC\include\stdint.h)(0x5E8E3CC2)
I (D:\cangming\ARM\ARMCC\include\stdbool.h)(0x5E8E3CC2)
@ -1352,7 +1352,7 @@ I (D:\cangming\ARM\ARMCC\include\stdint.h)(0x5E8E3CC2)
I (D:\cangming\ARM\ARMCC\include\stddef.h)(0x5E8E3CC2)
I (D:\cangming\ARM\ARMCC\include\string.h)(0x5E8E3CC2)
F (..\User\component\user_math.h)(0x690DD4C7)()
F (..\User\task\blink.c)(0x694ED995)(--c99 --gnu -c --cpu Cortex-M7.fp.dp -g -O3 --apcs=interwork --split_sections -I ../Core/Inc -I ../Drivers/STM32H7xx_HAL_Driver/Inc -I ../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy -I ../Drivers/CMSIS/Device/ST/STM32H7xx/Include -I ../Drivers/CMSIS/Include -I ../Middlewares/Third_Party/FreeRTOS/Source/include -I ../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 -I ../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F -I ../User -I.\RTE\_FDCAN -ID:\cangming\ARM\CMSIS\5.7.0\CMSIS\Core\Include -D__UVISION_VERSION="534" -D_RTE_ -DSTM32H723xx -D_RTE_ -DUSE_PWR_LDO_SUPPLY -DUSE_HAL_DRIVER -DSTM32H723xx -o fdcan\blink.o --omf_browse fdcan\blink.crf --depend fdcan\blink.d)
F (..\User\task\blink.c)(0x694EE409)(--c99 --gnu -c --cpu Cortex-M7.fp.dp -g -O3 --apcs=interwork --split_sections -I ../Core/Inc -I ../Drivers/STM32H7xx_HAL_Driver/Inc -I ../Drivers/STM32H7xx_HAL_Driver/Inc/Legacy -I ../Drivers/CMSIS/Device/ST/STM32H7xx/Include -I ../Drivers/CMSIS/Include -I ../Middlewares/Third_Party/FreeRTOS/Source/include -I ../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2 -I ../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F -I ../User -I.\RTE\_FDCAN -ID:\cangming\ARM\CMSIS\5.7.0\CMSIS\Core\Include -D__UVISION_VERSION="534" -D_RTE_ -DSTM32H723xx -D_RTE_ -DUSE_PWR_LDO_SUPPLY -DUSE_HAL_DRIVER -DSTM32H723xx -o fdcan\blink.o --omf_browse fdcan\blink.crf --depend fdcan\blink.d)
I (../User/task/user_task.h)(0x693967A8)
I (../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h)(0x694434DA)
I (D:\cangming\ARM\ARMCC\include\stdint.h)(0x5E8E3CC2)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -33,14 +33,10 @@
#include "FreeRTOS.h"
#include "task.h"
#ifndef __TARGET_FPU_VFP
#ifndef __VFP_FP__
#error This port can only be used when the project options are configured to enable hardware floating point support.
#endif
#if configMAX_SYSCALL_INTERRUPT_PRIORITY == 0
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
#endif
#ifndef configSYSTICK_CLOCK_HZ
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
/* Ensure the SysTick is clocked at the same frequency as the core. */
@ -51,15 +47,6 @@
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
#endif
/* Legacy macro for backward compatibility only. This macro used to be used to
replace the function that configures the clock used to generate the tick
interrupt (prvSetupTimerInterrupt()), but now the function is declared weak so
the application writer can override it by simply defining a function of the
same name (vApplicationSetupTickInterrupt()). */
#ifndef configOVERRIDE_DEFAULT_TICK_CONFIGURATION
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 0
#endif
/* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
@ -95,25 +82,34 @@ r0p1 port. */
#define portVECTACTIVE_MASK ( 0xFFUL )
/* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 )
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
#define portINITIAL_XPSR ( 0x01000000 )
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
/* The systick is a 24-bit counter. */
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
/* A fiddle factor to estimate the number of SysTick counts that would have
occurred while the SysTick counter is stopped during tickless idle
calculations. */
#define portMISSED_COUNTS_FACTOR ( 45UL )
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
/* For strict compliance with the Cortex-M spec the task start address should
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
/* A fiddle factor to estimate the number of SysTick counts that would have
occurred while the SysTick counter is stopped during tickless idle
calculations. */
#define portMISSED_COUNTS_FACTOR ( 45UL )
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case it messes up unwinding of the stack in the
debugger. */
#ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
/*
* Setup the timer to generate the tick interrupts. The implementation in this
* file is weak to allow application writers to change the timer used to
@ -124,19 +120,19 @@ void vPortSetupTimerInterrupt( void );
/*
* Exception handlers.
*/
void xPortPendSVHandler( void );
void xPortPendSVHandler( void ) __attribute__ (( naked ));
void xPortSysTickHandler( void );
void vPortSVCHandler( void );
void vPortSVCHandler( void ) __attribute__ (( naked ));
/*
* Start first task is a separate function so it can be tested in isolation.
*/
static void prvStartFirstTask( void );
static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
/*
* Functions defined in portasm.s to enable the VFP.
* Function to enable the VFP.
*/
static void prvEnableVFP( void );
static void vPortEnableVFP( void ) __attribute__ (( naked ));
/*
* Used to catch tasks that attempt to return from their implementing function.
@ -177,10 +173,10 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
* FreeRTOS API functions are not called from interrupts that have been assigned
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/
#if ( configASSERT_DEFINED == 1 )
#if( configASSERT_DEFINED == 1 )
static uint8_t ucMaxSysCallPriority = 0;
static uint32_t ulMaxPRIGROUPValue = 0;
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16;
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
#endif /* configASSERT_DEFINED */
/*-----------------------------------------------------------*/
@ -201,7 +197,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
pxTopOfStack--;
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
/* Save code space by skipping register initialisation. */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
@ -220,6 +216,8 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
static void prvTaskExitError( void )
{
volatile uint32_t ulDummy = 0;
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
@ -228,69 +226,58 @@ static void prvTaskExitError( void )
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
while( ulDummy == 0 )
{
/* This file calls prvTaskExitError() after the scheduler has been
started to remove a compiler warning about the function being defined
but never called. ulDummy is used purely to quieten other warnings
about code appearing after this function is called - making ulDummy
volatile makes the compiler think the function could return and
therefore not output an 'unreachable code' warning for code that appears
after it. */
}
}
/*-----------------------------------------------------------*/
__asm void vPortSVCHandler( void )
void vPortSVCHandler( void )
{
PRESERVE8
/* Get the location of the current TCB. */
ldr r3, =pxCurrentTCB
ldr r1, [r3]
ldr r0, [r1]
/* Pop the core registers. */
ldmia r0!, {r4-r11, r14}
msr psp, r0
isb
mov r0, #0
msr basepri, r0
bx r14
__asm volatile (
" ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */
" ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n" /* Restore the task stack pointer. */
" isb \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" bx r14 \n"
" \n"
" .align 4 \n"
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
);
}
/*-----------------------------------------------------------*/
__asm void prvStartFirstTask( void )
static void prvPortStartFirstTask( void )
{
PRESERVE8
/* Use the NVIC offset register to locate the stack. */
ldr r0, =0xE000ED08
ldr r0, [r0]
ldr r0, [r0]
/* Set the msp back to the start of the stack. */
msr msp, r0
/* Clear the bit that indicates the FPU is in use in case the FPU was used
before the scheduler was started - which would otherwise result in the
unnecessary leaving of space in the SVC stack for lazy saving of FPU
registers. */
mov r0, #0
msr control, r0
/* Globally enable interrupts. */
cpsie i
cpsie f
dsb
isb
/* Call SVC to start the first task. */
svc 0
nop
nop
}
/*-----------------------------------------------------------*/
__asm void prvEnableVFP( void )
{
PRESERVE8
/* The FPU enable bits are in the CPACR. */
ldr.w r0, =0xE000ED88
ldr r1, [r0]
/* Enable CP10 and CP11 coprocessors, then save back. */
orr r1, r1, #( 0xf << 20 )
str r1, [r0]
bx r14
nop
/* Start the first task. This also clears the bit that indicates the FPU is
in use in case the FPU was used before the scheduler was started - which
would otherwise result in the unnecessary leaving of space in the SVC stack
for lazy saving of FPU registers. */
__asm volatile(
" ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \n"
" ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" mov r0, #0 \n" /* Clear the bit that indicates the FPU is in use, see comment above. */
" msr control, r0 \n"
" cpsie i \n" /* Globally enable interrupts. */
" cpsie f \n"
" dsb \n"
" isb \n"
" svc 0 \n" /* System call to start first task. */
" nop \n"
);
}
/*-----------------------------------------------------------*/
@ -312,7 +299,7 @@ BaseType_t xPortStartScheduler( void )
#if( configASSERT_DEFINED == 1 )
{
volatile uint32_t ulOriginalPriority;
volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile uint8_t ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API
@ -330,10 +317,6 @@ BaseType_t xPortStartScheduler( void )
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
/* The kernel interrupt priority should be set to the lowest
priority. */
configASSERT( ucMaxPriorityValue == ( configKERNEL_INTERRUPT_PRIORITY & ucMaxPriorityValue ) );
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
@ -387,13 +370,22 @@ BaseType_t xPortStartScheduler( void )
uxCriticalNesting = 0;
/* Ensure the VFP is enabled - it should be anyway. */
prvEnableVFP();
vPortEnableVFP();
/* Lazy save always. */
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
/* Start the first task. */
prvStartFirstTask();
prvPortStartFirstTask();
/* Should never get here as the tasks will now be executing! Call the task
exit error function to prevent compiler warnings about a static function
not being called in the case that the application writer overrides this
functionality by defining configTASK_RETURN_ADDRESS. Call
vTaskSwitchContext() so link time optimisation does not remove the
symbol. */
vTaskSwitchContext();
prvTaskExitError();
/* Should not get here! */
return 0;
@ -436,65 +428,60 @@ void vPortExitCritical( void )
}
/*-----------------------------------------------------------*/
__asm void xPortPendSVHandler( void )
void xPortPendSVHandler( void )
{
extern uxCriticalNesting;
extern pxCurrentTCB;
extern vTaskSwitchContext;
/* This is a naked function. */
PRESERVE8
mrs r0, psp
isb
/* Get the location of the current TCB. */
ldr r3, =pxCurrentTCB
ldr r2, [r3]
/* Is the task using the FPU context? If so, push high vfp registers. */
tst r14, #0x10
it eq
vstmdbeq r0!, {s16-s31}
/* Save the core registers. */
stmdb r0!, {r4-r11, r14}
/* Save the new top of stack into the first member of the TCB. */
str r0, [r2]
stmdb sp!, {r0, r3}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0
dsb
isb
bl vTaskSwitchContext
mov r0, #0
msr basepri, r0
ldmia sp!, {r0, r3}
/* The first item in pxCurrentTCB is the task top of stack. */
ldr r1, [r3]
ldr r0, [r1]
/* Pop the core registers. */
ldmia r0!, {r4-r11, r14}
/* Is the task using the FPU context? If so, pop the high vfp registers
too. */
tst r14, #0x10
it eq
vldmiaeq r0!, {s16-s31}
msr psp, r0
isb
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
__asm volatile
(
" mrs r0, psp \n"
" isb \n"
" \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */
" it eq \n"
" vstmdbeq r0!, {s16-s31} \n"
" \n"
" stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
" stmdb sp!, {r0, r3} \n"
" mov r0, %0 \n"
" msr basepri, r0 \n"
" dsb \n"
" isb \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" ldmia sp!, {r0, r3} \n"
" \n"
" ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldr r0, [r1] \n"
" \n"
" ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */
" \n"
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */
" it eq \n"
" vldmiaeq r0!, {s16-s31} \n"
" \n"
" msr psp, r0 \n"
" isb \n"
" \n"
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */
#if WORKAROUND_PMU_CM001 == 1
push { r14 }
pop { pc }
nop
" push { r14 } \n"
" pop { pc } \n"
#endif
#endif
bx r14
" \n"
" bx r14 \n"
" \n"
" .align 4 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n"
::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY)
);
}
/*-----------------------------------------------------------*/
@ -503,9 +490,8 @@ void xPortSysTickHandler( void )
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
executes all interrupts must be unmasked. There is therefore no need to
save and then restore the interrupt mask value as its value is already
known - therefore the slightly faster vPortRaiseBASEPRI() function is used
in place of portSET_INTERRUPT_MASK_FROM_ISR(). */
vPortRaiseBASEPRI();
known. */
portDISABLE_INTERRUPTS();
{
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
@ -515,13 +501,13 @@ void xPortSysTickHandler( void )
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
vPortClearBASEPRIFromISR();
portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
#if( configUSE_TICKLESS_IDLE == 1 )
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
__attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
TickType_t xModifiableIdleTime;
@ -549,9 +535,9 @@ void xPortSysTickHandler( void )
/* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */
__disable_irq();
__dsb( portSY_FULL_READ_WRITE );
__isb( portSY_FULL_READ_WRITE );
__asm volatile( "cpsid i" ::: "memory" );
__asm volatile( "dsb" );
__asm volatile( "isb" );
/* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */
@ -568,9 +554,9 @@ void xPortSysTickHandler( void )
periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above __disable_irq() call
/* Re-enable interrupts - see comments above the cpsid instruction()
above. */
__enable_irq();
__asm volatile( "cpsie i" ::: "memory" );
}
else
{
@ -593,26 +579,26 @@ void xPortSysTickHandler( void )
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
if( xModifiableIdleTime > 0 )
{
__dsb( portSY_FULL_READ_WRITE );
__wfi();
__isb( portSY_FULL_READ_WRITE );
__asm volatile( "dsb" ::: "memory" );
__asm volatile( "wfi" );
__asm volatile( "isb" );
}
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
/* Re-enable interrupts to allow the interrupt that brought the MCU
out of sleep mode to execute immediately. see comments above
__disable_interrupt() call above. */
__enable_irq();
__dsb( portSY_FULL_READ_WRITE );
__isb( portSY_FULL_READ_WRITE );
__asm volatile( "cpsie i" ::: "memory" );
__asm volatile( "dsb" );
__asm volatile( "isb" );
/* Disable interrupts again because the clock is about to be stopped
and interrupts that execute while the clock is stopped will increase
any slippage between the time maintained by the RTOS and calendar
time. */
__disable_irq();
__dsb( portSY_FULL_READ_WRITE );
__isb( portSY_FULL_READ_WRITE );
__asm volatile( "cpsid i" ::: "memory" );
__asm volatile( "dsb" );
__asm volatile( "isb" );
/* Disable the SysTick clock without reading the
portNVIC_SYSTICK_CTRL_REG register to ensure the
@ -679,49 +665,50 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Exit with interrupts enabled. */
__enable_irq();
__asm volatile( "cpsie i" ::: "memory" );
}
}
#endif /* #if configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
/*
* Setup the SysTick timer to generate the tick interrupts at the required
* Setup the systick timer to generate the tick interrupts at the required
* frequency.
*/
#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
__weak void vPortSetupTimerInterrupt( void )
__attribute__(( weak )) void vPortSetupTimerInterrupt( void )
{
/* Calculate the constants required to configure the tick interrupt. */
#if( configUSE_TICKLESS_IDLE == 1 )
{
/* Calculate the constants required to configure the tick interrupt. */
#if( configUSE_TICKLESS_IDLE == 1 )
{
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
}
#endif /* configUSE_TICKLESS_IDLE */
/* Stop and clear the SysTick. */
portNVIC_SYSTICK_CTRL_REG = 0UL;
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
}
#endif /* configUSE_TICKLESS_IDLE */
#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */
/* Stop and clear the SysTick. */
portNVIC_SYSTICK_CTRL_REG = 0UL;
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
}
/*-----------------------------------------------------------*/
__asm uint32_t vPortGetIPSR( void )
/* This is a naked function. */
static void vPortEnableVFP( void )
{
PRESERVE8
mrs r0, ipsr
bx r14
__asm volatile
(
" ldr.w r0, =0xE000ED88 \n" /* The FPU enable bits are in the CPACR. */
" ldr r1, [r0] \n"
" \n"
" orr r1, r1, #( 0xf << 20 ) \n" /* Enable CP10 and CP11 coprocessors, then save back. */
" str r1, [r0] \n"
" bx r14 "
);
}
/*-----------------------------------------------------------*/
@ -733,7 +720,7 @@ __asm uint32_t vPortGetIPSR( void )
uint8_t ucCurrentPriority;
/* Obtain the number of the currently executing interrupt. */
ulCurrentInterrupt = vPortGetIPSR();
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
/* Is the interrupt number a user defined interrupt? */
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )

View File

@ -73,24 +73,19 @@ typedef unsigned long UBaseType_t;
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
/* Constants used with memory barrier intrinsics. */
#define portSY_FULL_READ_WRITE ( 15 )
/*-----------------------------------------------------------*/
/* Scheduler utilities. */
#define portYIELD() \
#define portYIELD() \
{ \
/* Set a PendSV to request a context switch. */ \
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
\
/* Barriers are normally not required but do ensure the code is completely \
within the specified behaviour for the architecture. */ \
__dsb( portSY_FULL_READ_WRITE ); \
__isb( portSY_FULL_READ_WRITE ); \
__asm volatile( "dsb" ::: "memory" ); \
__asm volatile( "isb" ); \
}
/*-----------------------------------------------------------*/
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
@ -101,16 +96,22 @@ typedef unsigned long UBaseType_t;
/* Critical section management. */
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x)
#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0)
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/
/* Tickless idle/low power functionality. */
#ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
@ -118,13 +119,22 @@ extern void vPortExitCritical( void );
#endif
/*-----------------------------------------------------------*/
/* Port specific optimisations. */
/* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Generic helper function. */
__attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap )
{
uint8_t ucReturn;
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
return ucReturn;
}
/* Check the configuration. */
#if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
@ -136,16 +146,10 @@ extern void vPortExitCritical( void );
/*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __clz( ( uxReadyPriorities ) ) )
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) )
#endif /* taskRECORD_READY_PRIORITY */
/*-----------------------------------------------------------*/
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* Task function macros as described on the FreeRTOS.org WEB site. These are
not necessary for to use this port. They are defined so the common demo files
(which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/*-----------------------------------------------------------*/
#ifdef configASSERT
@ -156,80 +160,19 @@ not necessary for to use this port. They are defined so the common demo files
/* portNOP() is not required by this port. */
#define portNOP()
#define portINLINE __inline
#define portINLINE __inline
#ifndef portFORCE_INLINE
#define portFORCE_INLINE __forceinline
#define portFORCE_INLINE inline __attribute__(( always_inline))
#endif
/*-----------------------------------------------------------*/
static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI )
{
__asm
{
/* Barrier instructions are not used as this function is only used to
lower the BASEPRI value. */
msr basepri, ulBASEPRI
}
}
/*-----------------------------------------------------------*/
static portFORCE_INLINE void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
__asm
{
/* Set BASEPRI to the max syscall priority to effect a critical
section. */
msr basepri, ulNewBASEPRI
dsb
isb
}
}
/*-----------------------------------------------------------*/
static portFORCE_INLINE void vPortClearBASEPRIFromISR( void )
{
__asm
{
/* Set BASEPRI to 0 so no interrupts are masked. This function is only
used to lower the mask in an interrupt, so memory barriers are not
used. */
msr basepri, #0
}
}
/*-----------------------------------------------------------*/
static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI( void )
{
uint32_t ulReturn, ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;
__asm
{
/* Set BASEPRI to the max syscall priority to effect a critical
section. */
mrs ulReturn, basepri
msr basepri, ulNewBASEPRI
dsb
isb
}
return ulReturn;
}
/*-----------------------------------------------------------*/
static portFORCE_INLINE BaseType_t xPortIsInsideInterrupt( void )
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
{
uint32_t ulCurrentInterrupt;
BaseType_t xReturn;
/* Obtain the number of the currently executing interrupt. */
__asm
{
mrs ulCurrentInterrupt, ipsr
}
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
if( ulCurrentInterrupt == 0 )
{
@ -243,6 +186,54 @@ BaseType_t xReturn;
return xReturn;
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI;
__asm volatile
(
" mov %0, %1 \n" \
" msr basepri, %0 \n" \
" isb \n" \
" dsb \n" \
:"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
);
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void )
{
uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
__asm volatile
(
" mrs %0, basepri \n" \
" mov %1, %2 \n" \
" msr basepri, %1 \n" \
" isb \n" \
" dsb \n" \
:"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
);
/* This return will not be reached but is necessary to prevent compiler
warnings. */
return ulOriginalBASEPRI;
}
/*-----------------------------------------------------------*/
portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
{
__asm volatile
(
" msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory"
);
}
/*-----------------------------------------------------------*/
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
#ifdef __cplusplus
}

View File

@ -1,234 +0,0 @@
#include "bsp_can.h"
#include "main.h"
#include <string.h>
#include "bsp/bsp.h"
#include <stdint.h>
#include <stdbool.h>
typedef struct {
FDCAN_RxHeaderTypeDef header;
uint8_t data[64];
} can_raw_rx_t;
typedef struct {
FDCAN_HandleTypeDef header;
uint8_t data[8];
} can_raw_tx_t;
typedef struct {
void (*fn)(bsp_can_t can, uint32_t id, uint8_t *data, void *arg);
void *arg;
} can_callback_t;
extern FDCAN_HandleTypeDef hfdcan1;
extern FDCAN_HandleTypeDef hfdcan2;
static can_callback_t callback_list[BSP_CAN_NUM][BSP_CAN_CB_NUM];
static bool bsp_can_initd = false;
static can_raw_rx_t rx_buff[BSP_CAN_NUM];
FDCAN_HandleTypeDef *bsp_can_get_handle(bsp_can_t can) {
switch (can) {
case BSP_CAN_1:
return &hfdcan1;
case BSP_CAN_2:
return &hfdcan2;
default:
return NULL;
}
}
static bsp_can_t can_get(FDCAN_HandleTypeDef *hcan) {
if (hcan->Instance == FDCAN1) {
return BSP_CAN_1;
} else if (hcan->Instance == FDCAN2) {
return BSP_CAN_2;
} else {
return BSP_CAN_ERR;
}
}
void bsp_can_init(void) {
FDCAN_FilterTypeDef can_filter = {0};
can_filter.IdType = FDCAN_STANDARD_ID;
can_filter.FilterIndex = 0;
can_filter.FilterType = FDCAN_FILTER_MASK;
can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
can_filter.FilterID1 = 0x0000;
can_filter.FilterID2 = 0x0000;
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &can_filter) != HAL_OK) {
// XB_ASSERT(false);
}
can_filter.IdType = FDCAN_EXTENDED_ID;
can_filter.FilterIndex = 1;
can_filter.FilterType = FDCAN_FILTER_MASK;
can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
can_filter.FilterID1 = 0x0000;
can_filter.FilterID2 = 0x0000;
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &can_filter) != HAL_OK) {
// XB_ASSERT(false);
}
can_filter.IdType = FDCAN_STANDARD_ID;
can_filter.FilterIndex = 2;
can_filter.FilterType = FDCAN_FILTER_MASK;
can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
can_filter.FilterID1 = 0x0000;
can_filter.FilterID2 = 0x0000;
if (HAL_FDCAN_ConfigFilter(&hfdcan2, &can_filter) != HAL_OK) {
// XB_ASSERT(false);
}
can_filter.IdType = FDCAN_EXTENDED_ID;
can_filter.FilterIndex = 3;
can_filter.FilterType = FDCAN_FILTER_MASK;
can_filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
can_filter.FilterID1 = 0x0000;
can_filter.FilterID2 = 0x0000;
if (HAL_FDCAN_ConfigFilter(&hfdcan2, &can_filter) != HAL_OK) {
// XB_ASSERT(false);
}
HAL_FDCAN_Start(&hfdcan1); //开启FDCAN
HAL_FDCAN_Start(&hfdcan2); //开启FDCAN
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_TX_FIFO_EMPTY, 0);
HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_TX_FIFO_EMPTY, 0);
bsp_can_initd = true;
}
static const uint8_t DLCtoBytes[] = {0, 1, 2, 3, 4, 5, 6, 7,
8, 12, 16, 20, 24, 32, 48, 64};
static void can_rx_cb_fn(bsp_can_t can, uint32_t fifo) {
while (HAL_FDCAN_GetRxMessage(bsp_can_get_handle(can), fifo,
&rx_buff[can].header,
rx_buff[can].data) == HAL_OK) {
if (rx_buff[can].header.FDFormat == FDCAN_CLASSIC_CAN) {
if (callback_list[can][CAN_RX_MSG_CALLBACK].fn) {
callback_list[can][CAN_RX_MSG_CALLBACK].fn(
can, rx_buff[can].header.Identifier, rx_buff[can].data,
callback_list[can][CAN_RX_MSG_CALLBACK].arg);
}
} else {
if (callback_list[can][CANFD_RX_MSG_CALLBACK].fn) {
bsp_canfd_data_t data = {
.data = rx_buff[can].data,
.size = DLCtoBytes[rx_buff[can].header.DataLength >> 16U]};
callback_list[can][CANFD_RX_MSG_CALLBACK].fn(
can, rx_buff[can].header.Identifier, (uint8_t *)&data,
callback_list[can][CANFD_RX_MSG_CALLBACK].arg);
}
}
}
}
// void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hcan, uint32_t RxFifo0ITs) {
// (void)RxFifo0ITs;
// can_rx_cb_fn(can_get(hcan), FDCAN_RX_FIFO0);
// }
// void HAL_FDCAN_RxFifo1Callback(FDCAN_HandleTypeDef *hcan, uint32_t RxFifo1ITs) {
// (void)RxFifo1ITs;
// can_rx_cb_fn(can_get(hcan), FDCAN_RX_FIFO1);
// }
int8_t bsp_can_register_callback(
bsp_can_t can, bsp_can_callback_t type,
void (*callback)(bsp_can_t can, uint32_t id, uint8_t *data, void *arg),
void *callback_arg) {
assert_param(callback);
assert_param(type != BSP_CAN_CB_NUM);
callback_list[can][type].fn = callback;
callback_list[can][type].arg = callback_arg;
return BSP_OK;
}
int8_t bsp_can_trans_packet(bsp_can_t can, bsp_can_format_t format,
uint32_t id, uint8_t *data) {
FDCAN_TxHeaderTypeDef header;
header.Identifier = id;
if (format == CAN_FORMAT_STD) {
header.IdType = FDCAN_STANDARD_ID;
} else {
header.IdType = FDCAN_EXTENDED_ID;
}
header.TxFrameType = FDCAN_DATA_FRAME;
header.DataLength = FDCAN_DLC_BYTES_8;
header.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
header.BitRateSwitch = FDCAN_BRS_OFF;
header.FDFormat = FDCAN_CLASSIC_CAN;
header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;
header.MessageMarker = 0x01;
while ((bsp_can_get_handle(can)->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U) {
__NOP();
}
return HAL_FDCAN_AddMessageToTxFifoQ(bsp_can_get_handle(can), &header,
data) == HAL_OK
? BSP_OK
: BSP_ERR;
}
static const uint32_t FDCAN_PACK_LEN_MAP[16] = {
FDCAN_DLC_BYTES_0, FDCAN_DLC_BYTES_1, FDCAN_DLC_BYTES_2,
FDCAN_DLC_BYTES_3, FDCAN_DLC_BYTES_4, FDCAN_DLC_BYTES_5,
FDCAN_DLC_BYTES_6, FDCAN_DLC_BYTES_7, FDCAN_DLC_BYTES_8,
FDCAN_DLC_BYTES_12, FDCAN_DLC_BYTES_16, FDCAN_DLC_BYTES_20,
FDCAN_DLC_BYTES_24, FDCAN_DLC_BYTES_32, FDCAN_DLC_BYTES_48,
FDCAN_DLC_BYTES_64,
};
int8_t bsp_canfd_trans_packet(bsp_can_t can, bsp_can_format_t format,
uint32_t id, uint8_t *data, size_t size) {
FDCAN_TxHeaderTypeDef header;
// XB_ASSERT(size <= 64);
header.Identifier = id;
if (format == CAN_FORMAT_STD) {
header.IdType = FDCAN_STANDARD_ID;
} else {
header.IdType = FDCAN_EXTENDED_ID;
}
header.TxFrameType = FDCAN_DATA_FRAME;
if (size <= 8) {
header.DataLength = FDCAN_PACK_LEN_MAP[size];
} else if (size <= 24) {
header.DataLength = FDCAN_PACK_LEN_MAP[(size - 9) / 4 + 1 + 8];
} else if (size < 32) {
header.DataLength = FDCAN_DLC_BYTES_32;
} else if (size < 48) {
header.DataLength = FDCAN_DLC_BYTES_48;
} else {
header.DataLength = FDCAN_DLC_BYTES_64;
}
header.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
header.BitRateSwitch = FDCAN_BRS_OFF;
header.FDFormat = FDCAN_FD_CAN;
header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;
header.MessageMarker = 0x01;
while ((bsp_can_get_handle(can)->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U) {
__NOP();
}
return HAL_FDCAN_AddMessageToTxFifoQ(bsp_can_get_handle(can), &header,
data) == HAL_OK
? BSP_OK
: BSP_ERR;
}

View File

@ -1,53 +0,0 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "bsp.h"
typedef enum {
BSP_CAN_1,
BSP_CAN_2,
BSP_CAN_NUM,
BSP_CAN_ERR,
} bsp_can_t;
typedef enum {
CAN_RX_MSG_CALLBACK,
CAN_TX_CPLT_CALLBACK,
CANFD_RX_MSG_CALLBACK,
CANFD_TX_CPLT_CALLBACK,
BSP_CAN_CB_NUM
} bsp_can_callback_t;
typedef enum {
CAN_FORMAT_STD,
CAN_FORMAT_EXT,
} bsp_can_format_t;
typedef struct {
uint8_t data[8];
} bsp_can_data_t;
typedef struct {
size_t size;
uint8_t *data;
} bsp_canfd_data_t;
void bsp_can_init(void);
int8_t bsp_can_register_callback(
bsp_can_t can, bsp_can_callback_t type,
void (*callback)(bsp_can_t can, uint32_t id, uint8_t *data, void *arg),
void *callback_arg);
int8_t bsp_can_trans_packet(bsp_can_t can, bsp_can_format_t format,
uint32_t id, uint8_t *data);
int8_t bsp_canfd_trans_packet(bsp_can_t can, bsp_can_format_t format,
uint32_t id, uint8_t *data, size_t size);
int8_t bsp_can_get_msg(bsp_can_t can, uint8_t *data, uint32_t *index);
#ifdef __cplusplus
}
#endif

View File

@ -2,7 +2,6 @@
#include "fdcan.h"
#include "bsp/fdcan.h"
#include "bsp/bsp.h"
#include "stm32h7xx_hal_gpio.h"
#include <fdcan.h>
#include <cmsis_os2.h>
#include <string.h>
@ -38,7 +37,7 @@ static osMessageQueueId_t BSP_FDCAN_FindQueue(BSP_FDCAN_t fdcan, uint32_t can_id
static int8_t BSP_FDCAN_CreateIdQueue(BSP_FDCAN_t fdcan, uint32_t can_id, uint8_t queue_size);
static void BSP_FDCAN_RxFifo0Callback(void);
static void BSP_FDCAN_RxFifo1Callback(void);
static void BSP_FDCAN_TxCompleteCallback(void);
// static void BSP_FDCAN_TxCompleteCallback(void);
static BSP_FDCAN_FrameType_t BSP_FDCAN_GetFrameType(FDCAN_RxHeaderTypeDef *header);
static uint32_t BSP_FDCAN_DefaultIdParser(uint32_t original_id, BSP_FDCAN_FrameType_t frame_type);
static void BSP_FDCAN_TxQueueInit(BSP_FDCAN_t fdcan);
@ -102,6 +101,17 @@ static uint32_t BSP_FDCAN_DefaultIdParser(uint32_t original_id, BSP_FDCAN_FrameT
return original_id;
}
static uint32_t BSP_FDCAN_EncodeDLC(uint8_t dlc) {
if (dlc <= 8) return dlc;
if (dlc <= 12) return FDCAN_DLC_BYTES_12;
if (dlc <= 16) return FDCAN_DLC_BYTES_16;
if (dlc <= 20) return FDCAN_DLC_BYTES_20;
if (dlc <= 24) return FDCAN_DLC_BYTES_24;
if (dlc <= 32) return FDCAN_DLC_BYTES_32;
if (dlc <= 48) return FDCAN_DLC_BYTES_48;
return FDCAN_DLC_BYTES_64;
}
static void BSP_FDCAN_TxQueueInit(BSP_FDCAN_t fdcan) {
if (fdcan >= BSP_FDCAN_NUM) return;
tx_queues[fdcan].head = 0;
@ -131,8 +141,8 @@ static bool BSP_FDCAN_TxQueueIsEmpty(BSP_FDCAN_t fdcan) {
if (fdcan >= BSP_FDCAN_NUM) return true;
return tx_queues[fdcan].head == tx_queues[fdcan].tail;
}
void BSP_FDCAN_TxCompleteCallback(void) {
//static void BSP_FDCAN_TxCompleteCallback(void) {
static void BSP_FDCAN_TxCompleteCallback(void) {
for (int i = 0; i < BSP_FDCAN_NUM; i++) {
BSP_FDCAN_t fdcan = (BSP_FDCAN_t)i;
FDCAN_HandleTypeDef *hfdcan = BSP_FDCAN_GetHandle(fdcan);
@ -154,6 +164,7 @@ static bool BSP_FDCAN_TxQueueIsEmpty(BSP_FDCAN_t fdcan) {
}
}
}
static const uint8_t fdcan_dlc2len[16] = {0,1,2,3,4,5,6,7,8,12,16,20,24,32,48,64};
static void BSP_FDCAN_RxFifo0Callback(void) {
FDCAN_RxHeaderTypeDef rx_header;
@ -172,8 +183,10 @@ static void BSP_FDCAN_RxFifo0Callback(void) {
msg.frame_type = frame_type;
msg.original_id = original_id;
msg.parsed_id = parsed_id;
msg.dlc = rx_header.DataLength;
uint8_t real_len = fdcan_dlc2len[rx_header.DataLength & 0xF];
msg.dlc = real_len;
if (msg.dlc > BSP_FDCAN_MAX_DLC) msg.dlc = BSP_FDCAN_MAX_DLC;
memset(msg.data, 0, BSP_FDCAN_MAX_DLC);//现在是最大缓冲区写法所以全清零
memcpy(msg.data, rx_data, msg.dlc);
osMessageQueuePut(queue, &msg, 0, 0);
}
@ -187,6 +200,7 @@ static void BSP_FDCAN_RxFifo0Callback(void) {
static void BSP_FDCAN_RxFifo1Callback(void) {
FDCAN_RxHeaderTypeDef rx_header;
uint8_t rx_data[BSP_FDCAN_MAX_DLC];
static const uint8_t fdcan_dlc2len[16] = {0,1,2,3,4,5,6,7,8,12,16,20,24,32,48,64};
for (int fdcan_idx = 0; fdcan_idx < BSP_FDCAN_NUM; fdcan_idx++) {
FDCAN_HandleTypeDef *hfdcan = BSP_FDCAN_GetHandle((BSP_FDCAN_t)fdcan_idx);
if (hfdcan == NULL) continue;
@ -201,8 +215,10 @@ static void BSP_FDCAN_RxFifo1Callback(void) {
msg.frame_type = frame_type;
msg.original_id = original_id;
msg.parsed_id = parsed_id;
msg.dlc = rx_header.DataLength;
uint8_t real_len = fdcan_dlc2len[rx_header.DataLength & 0xF];
msg.dlc = real_len;
if (msg.dlc > BSP_FDCAN_MAX_DLC) msg.dlc = BSP_FDCAN_MAX_DLC;
memset(msg.data, 0, BSP_FDCAN_MAX_DLC);//现在是最大缓冲区写法所以全清零
memcpy(msg.data, rx_data, msg.dlc);
osMessageQueuePut(queue, &msg, 0, 0);
}
@ -330,19 +346,9 @@ int8_t BSP_FDCAN_Init(void) {
sFilterConfig.RxBufferIndex = 0;
HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig);
HAL_FDCAN_ConfigGlobalFilter(&hfdcan1,FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE);
sFilterConfig.FilterIndex = 1;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x000;
sFilterConfig.FilterID2 = 0x000;
sFilterConfig.RxBufferIndex = 0;
HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig);
HAL_FDCAN_ConfigGlobalFilter(&hfdcan1,FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE);
/* 配置 FDCAN2 过滤器 */
/* 索引0;标准ID;掩码模式;存入 FIFO 1普通优先级;不过滤; */
sFilterConfig.FilterIndex = 2;
sFilterConfig.FilterIndex = 0;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
@ -350,20 +356,10 @@ int8_t BSP_FDCAN_Init(void) {
sFilterConfig.FilterID2 = 0x000;
sFilterConfig.RxBufferIndex = 0;
HAL_FDCAN_ConfigFilter(&hfdcan2, &sFilterConfig);
HAL_FDCAN_ConfigGlobalFilter(&hfdcan2,FDCAN_REJECT, FDCAN_REJECT, DISABLE, DISABLE);
sFilterConfig.FilterIndex = 3;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
sFilterConfig.FilterID1 = 0x000;
sFilterConfig.FilterID2 = 0x000;
sFilterConfig.RxBufferIndex = 0;
HAL_FDCAN_ConfigFilter(&hfdcan2, &sFilterConfig);
HAL_FDCAN_ConfigGlobalFilter(&hfdcan2,FDCAN_REJECT, FDCAN_REJECT, DISABLE, DISABLE);
HAL_FDCAN_ConfigGlobalFilter(&hfdcan2,FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE);
/* 配置 FDCAN3 过滤器 */
/* 索引0;标准ID;掩码模式;存入 FIFO 1普通优先级;不过滤; */
sFilterConfig.FilterIndex = 4;
sFilterConfig.FilterIndex = 0;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
@ -371,25 +367,8 @@ int8_t BSP_FDCAN_Init(void) {
sFilterConfig.FilterID2 = 0x000;
sFilterConfig.RxBufferIndex = 0;
HAL_FDCAN_ConfigFilter(&hfdcan3, &sFilterConfig);
HAL_FDCAN_ConfigGlobalFilter(&hfdcan3,FDCAN_REJECT, FDCAN_REJECT, DISABLE, DISABLE);
HAL_FDCAN_ConfigGlobalFilter(&hfdcan3,FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE);
sFilterConfig.FilterIndex = 5;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
sFilterConfig.FilterID1 = 0x000;
sFilterConfig.FilterID2 = 0x000;
sFilterConfig.RxBufferIndex = 0;
HAL_FDCAN_ConfigFilter(&hfdcan3, &sFilterConfig);
HAL_FDCAN_ConfigGlobalFilter(&hfdcan3,FDCAN_REJECT, FDCAN_REJECT, DISABLE, DISABLE);
// HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
// HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_TX_FIFO_EMPTY, 0);
// HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
// HAL_FDCAN_ActivateNotification(&hfdcan2, FDCAN_IT_TX_FIFO_EMPTY, 0);
// HAL_FDCAN_ActivateNotification(&hfdcan3, FDCAN_IT_RX_FIFO1_NEW_MESSAGE, 0);
// HAL_FDCAN_ActivateNotification(&hfdcan3, FDCAN_IT_TX_FIFO_EMPTY, 0);
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE
| FDCAN_IT_TX_EVT_FIFO_NEW_DATA
| FDCAN_IT_RAM_ACCESS_FAILURE, 0);//加一个RAM访问失败中断
@ -400,11 +379,6 @@ int8_t BSP_FDCAN_Init(void) {
| FDCAN_IT_TX_EVT_FIFO_NEW_DATA
| FDCAN_IT_RAM_ACCESS_FAILURE, 0);
/* __ ,启动! */
HAL_FDCAN_Start(&hfdcan1);
HAL_FDCAN_Start(&hfdcan2);
HAL_FDCAN_Start(&hfdcan3);
BSP_FDCAN_RegisterCallback(BSP_FDCAN_1, HAL_FDCAN_RX_FIFO0_MSG_PENDING_CB, BSP_FDCAN_RxFifo0Callback);
BSP_FDCAN_RegisterCallback(BSP_FDCAN_1, HAL_FDCAN_TX_EVENT_FIFO_CB, BSP_FDCAN_TxCompleteCallback);
@ -414,10 +388,10 @@ int8_t BSP_FDCAN_Init(void) {
BSP_FDCAN_RegisterCallback(BSP_FDCAN_3, HAL_FDCAN_RX_FIFO1_MSG_PENDING_CB, BSP_FDCAN_RxFifo1Callback);
BSP_FDCAN_RegisterCallback(BSP_FDCAN_3, HAL_FDCAN_TX_EVENT_FIFO_CB, BSP_FDCAN_TxCompleteCallback);
//POWER ENABLE
// HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
/* __ ,启动! */
HAL_FDCAN_Start(&hfdcan1);
HAL_FDCAN_Start(&hfdcan2);
HAL_FDCAN_Start(&hfdcan3);
return BSP_OK;
}
@ -475,24 +449,22 @@ int8_t BSP_FDCAN_Transmit(BSP_FDCAN_t fdcan, BSP_FDCAN_Format_t format, uint32_t
return BSP_ERR;
}
tx_msg.header.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
tx_msg.header.BitRateSwitch = FDCAN_BRS_OFF;
tx_msg.header.FDFormat = FDCAN_CLASSIC_CAN;
// tx_msg.header.BitRateSwitch = FDCAN_BRS_OFF;
// tx_msg.header.FDFormat = FDCAN_CLASSIC_CAN;
// tx_msg.header.BitRateSwitch = FDCAN_BRS_ON;
// tx_msg.header.FDFormat = FDCAN_FD_CAN;
tx_msg.header.BitRateSwitch = FDCAN_BRS_OFF;
tx_msg.header.FDFormat = FDCAN_FD_CAN;
tx_msg.header.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;
tx_msg.header.MessageMarker = 0x01;
// tx_msg.header.DataLength = FDCAN_DLC_BYTES_64;
if (dlc <= 8) {
tx_msg.header.DataLength = FDCAN_DLC_BYTES_8;
} else if (dlc <= 24) {
tx_msg.header.DataLength = FDCAN_DLC_BYTES_24;
} else if (dlc < 32) {
tx_msg.header.DataLength = FDCAN_DLC_BYTES_32;
} else if (dlc < 48) {
tx_msg.header.DataLength = FDCAN_DLC_BYTES_48;
} else {
tx_msg.header.DataLength = FDCAN_DLC_BYTES_64;
}
if (data != NULL && dlc > 0)
memcpy(tx_msg.data, data, dlc);
tx_msg.header.DataLength = BSP_FDCAN_EncodeDLC(dlc);
memset(tx_msg.data, 0, dlc);
if (data != NULL && dlc > 0) {
memcpy(tx_msg.data, data, dlc);}
fifolevel=HAL_FDCAN_GetTxFifoFreeLevel(hfdcan);
if (HAL_FDCAN_GetTxFifoFreeLevel(hfdcan) > 0) {
if (HAL_FDCAN_AddMessageToTxFifoQ(hfdcan, &tx_msg.header, tx_msg.data) == HAL_OK) return BSP_OK;

View File

@ -111,9 +111,6 @@ int32_t BSP_FDCAN_GetQueueCount(BSP_FDCAN_t can, uint32_t can_id);
int8_t BSP_FDCAN_FlushQueue(BSP_FDCAN_t can, uint32_t can_id);
int8_t BSP_FDCAN_RegisterIdParser(BSP_FDCAN_IdParser_t parser);
uint32_t BSP_FDCAN_ParseId(uint32_t original_id, BSP_FDCAN_FrameType_t frame_type);
void BSP_FDCAN_TxCompleteCallback(void);
#ifdef __cplusplus
}
#endif

View File

@ -10,7 +10,6 @@
#include "bsp/bsp.h"
#include "bsp/fdcan.h"
// #include "bsp/pwm.h"
#include "bsp/bsp_can.h"
#include <math.h>
/* USER INCLUDE END */
@ -19,13 +18,13 @@
/* Private macro ------------------------------------------------------------ */
/* Private variables -------------------------------------------------------- */
/* USER STRUCT BEGIN */
BSP_FDCAN_Message_t msg;
BSP_FDCAN_Message_t msg1={0};
BSP_FDCAN_Message_t msg2={0};
BSP_FDCAN_Message_t msg3={0};
/* USER STRUCT END */
float rxlevel=0;
/* Private function --------------------------------------------------------- */
void can_rx_callback(bsp_can_t can, uint32_t id, uint8_t *data, void *arg) {
// 这里可以打印、断点或设置标志位
}
/* Exported functions ------------------------------------------------------- */
void Task_blink(void *argument) {
(void)argument; /* 未使用argument消除警告 */
@ -44,7 +43,7 @@ void Task_blink(void *argument) {
// BSP_PWM_Start(BSP_PWM_LED_G);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_14, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_15, GPIO_PIN_SET);
BSP_FDCAN_Init();
@ -53,10 +52,6 @@ void Task_blink(void *argument) {
BSP_FDCAN_RegisterId(BSP_FDCAN_2, 0x102, 8);
BSP_FDCAN_RegisterId(BSP_FDCAN_3, 0x103, 8);
// bsp_can_init();
// bsp_can_register_callback(BSP_CAN_1, CAN_RX_MSG_CALLBACK, can_rx_callback, NULL);
/* USER CODE INIT END */
while (1) {
@ -65,30 +60,33 @@ void Task_blink(void *argument) {
// 呼吸灯 - 基于tick的正弦波
// float duty = (sinf(tick * 0.003f) + 1.0f) * 0.5f; // 0到1之间的正弦波加快频率
// BSP_PWM_SetComp(BSP_PWM_LED_G, duty);
// uint8_t tx_data[8] = {1,2,3,4,5,6,7,8};
// bsp_can_trans_packet(BSP_CAN_1, CAN_FORMAT_STD, 0x123, tx_data);
// 测试:向三路 CAN 周期性发送电机控制帧(示例数据),并轮询接收
{
uint8_t data1[8] = {0xA1, 0x01, 0x34, 0x12, 0x10, 0x00, 0x00, 0x00};
uint8_t data2[8] = {0xA1, 0x02, 0x78, 0x56, 0x20, 0x00, 0x00, 0x00};
uint8_t data3[8] = {0xA1, 0x03, 0x00, 0x01, 0x30, 0x00, 0x00, 0x00};
uint8_t data1[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
uint8_t data2[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
uint8_t data3[32] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20};
// 简单 CRC/校验(可选)
data1[7] = data1[0] ^ data1[1] ^ data1[2];
data2[7] = data2[0] ^ data2[1] ^ data2[2];
data3[7] = data3[0] ^ data3[1] ^ data3[2];
// data3[7] = data3[0] ^ data3[1] ^ data3[2];
// 使用 BSP 封装的发送接口(非阻塞,若硬件 FIFO 满则内部入队)
BSP_FDCAN_Transmit(BSP_FDCAN_1, BSP_FDCAN_FORMAT_STD_DATA, 0x101, data1, 8);
BSP_FDCAN_Transmit(BSP_FDCAN_2, BSP_FDCAN_FORMAT_STD_DATA, 0x102, data2, 8);
BSP_FDCAN_Transmit(BSP_FDCAN_3, BSP_FDCAN_FORMAT_STD_DATA, 0x103, data3, 8);
// BSP_FDCAN_Transmit(BSP_FDCAN_1, BSP_FDCAN_FORMAT_STD_DATA, 0x101, data1, 8);
// BSP_FDCAN_Transmit(BSP_FDCAN_2, BSP_FDCAN_FORMAT_STD_DATA, 0x102, data2, 8);
BSP_FDCAN_Transmit(BSP_FDCAN_3, BSP_FDCAN_FORMAT_STD_DATA, 0x103, data3, 13);
if (BSP_FDCAN_GetMessage(BSP_FDCAN_1, 0x101, &msg, BSP_FDCAN_TIMEOUT_IMMEDIATE) == BSP_OK) {
if (BSP_FDCAN_GetMessage(BSP_FDCAN_1, 0x101, &msg1, BSP_FDCAN_TIMEOUT_IMMEDIATE) == BSP_OK) {
}
if (BSP_FDCAN_GetMessage(BSP_FDCAN_2, 0x102, &msg, BSP_FDCAN_TIMEOUT_IMMEDIATE) == BSP_OK) {
if (BSP_FDCAN_GetMessage(BSP_FDCAN_2, 0x102, &msg2, BSP_FDCAN_TIMEOUT_IMMEDIATE) == BSP_OK) {
}
if (BSP_FDCAN_GetMessage(BSP_FDCAN_3, 0x103, &msg, BSP_FDCAN_TIMEOUT_IMMEDIATE) == BSP_OK) {
if (BSP_FDCAN_GetMessage(BSP_FDCAN_3, 0x103, &msg3, BSP_FDCAN_TIMEOUT_IMMEDIATE) == BSP_OK) {
}
rxlevel=HAL_FDCAN_GetRxFifoFillLevel(BSP_FDCAN_GetHandle(BSP_FDCAN_2), FDCAN_RX_FIFO1);
}
// osDelay(10);
/* USER CODE END */