init commit

This commit is contained in:
NeoZng
2022-10-20 17:13:02 +08:00
commit 78f85b7fda
518 changed files with 409143 additions and 0 deletions

13
bsp/bsp_buzzer.c Normal file
View File

@@ -0,0 +1,13 @@
#include "bsp_buzzer.h"
#include "main.h"
extern TIM_HandleTypeDef htim4;
void buzzer_on(uint16_t psc, uint16_t pwm)
{
__HAL_TIM_PRESCALER(&htim4, psc);
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, pwm);
}
void buzzer_off(void)
{
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 0);
}

9
bsp/bsp_buzzer.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef BSP_BUZZER_H
#define BSP_BUZZER_H
#include "struct_typedef.h"
extern void buzzer_on(uint16_t psc, uint16_t pwm);
extern void buzzer_off(void);
#endif

122
bsp/bsp_can.c Normal file
View File

@@ -0,0 +1,122 @@
#include "bsp_can.h"
#include "main.h"
#include <stdlib.h>
#include "memory.h"
static can_instance* instance[MX_REGISTER_DEVICE_CNT];
/**
* @brief add filter to receive mesg with specific ID,called by CANRegister()
*
* @note there are total 28 filter and 2 FIFO in bxCAN of STM32F4 series product.
* here, we assign the former 14 to CAN1 and the rest for CAN2
* when initializing, module with odd ID will be assigned to FIFO0 while even one to FIFO1
* those modules which registered in CAN1 would use Filter0-13, while CAN2 use Filter14-27
*
* @attention you don't have to fully understand what this function done, cause it is basically
* for initialization.Enjoy developing without caring about the infrastructure!
* if you really want to know what is happeng, contact author.
*
* @param _instance can instance owned by specific module
*/
static void CANAddFilter(can_instance* _instance)
{
CAN_FilterTypeDef can_filter_conf;
static uint8_t can1_filter_idx=0,can2_filter_idx=14;
can_filter_conf.FilterMode = CAN_FILTERMODE_IDLIST;
can_filter_conf.FilterScale = CAN_FILTERSCALE_16BIT;
can_filter_conf.FilterFIFOAssignment = (_instance->rx_id & 1) ? CAN_RX_FIFO0 : CAN_RX_FIFO1;
can_filter_conf.SlaveStartFilterBank = 14;
can_filter_conf.FilterIdLow = _instance->rx_id << 5;
can_filter_conf.FilterBank = _instance->can_handle==&hcan1?(can1_filter_idx++):(can2_filter_idx++);
can_filter_conf.FilterActivation = CAN_FILTER_ENABLE;
HAL_CAN_ConfigFilter(_instance->can_handle, &can_filter_conf);
}
/**
* @brief called by CANRegister before the first module being registered
*
* @note this func will handle all these thing automatically
* there is no need to worry about hardware initialization, we do these for you!
*
*/
static void CANServiceInit()
{
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO1_MSG_PENDING);
HAL_CAN_Start(&hcan2);
HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING);
HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO1_MSG_PENDING);
}
void CANRegister(can_instance* _instance)
{
static uint8_t instance_idx;
if(!instance_idx)
{
CANServiceInit();
}
_instance->rx_buff=(uint8_t*)malloc(8*sizeof(uint8_t));
_instance->tx_buff=(uint8_t*)malloc(8*sizeof(uint8_t));
CANAddFilter(_instance);
instance[instance_idx++]=_instance;
}
void CANTransmit(can_instance* _instance)
{
CAN_TxHeaderTypeDef txconf;
txconf.StdId=_instance->tx_id;
txconf.IDE=CAN_ID_STD;
txconf.RTR=CAN_RTR_DATA;
txconf.DLC=0x08;
while (HAL_CAN_GetTxMailboxesFreeLevel(_instance->can_handle) == 0);
HAL_CAN_AddTxMessage(_instance->can_handle, &txconf, _instance->tx_buff, &_instance->tx_mailbox);
}
/**
* @brief this func will recv data from @param:fifox to a tmp can_rx_buff
* then, all the instances will be polling to check which should recv this pack of data
*
* @param _hcan
* @param fifox passed to HAL_CAN_GetRxMessage() to get mesg from a specific fifo
*/
static void CANFIFOxCallback(CAN_HandleTypeDef* _hcan,uint32_t fifox)
{
uint8_t can_rx_buff[8];
CAN_RxHeaderTypeDef rxconf;
HAL_CAN_GetRxMessage(_hcan,fifox,&rxconf,can_rx_buff);
for (size_t i = 0; i < DEVICE_CAN_CNT; i++)
{
if(_hcan==instance[i]->can_handle && rxconf.StdId==instance[i]->rx_id)
{
memcpy(instance[i]->rx_buff,can_rx_buff,8);
instance[i]->can_module_callback(instance[i]);
break;
}
}
}
/* ATTENTION: two CAN device in STM32 share two FIFO */
/* functions below will call CANFIFOxCallback() to further process message from a specific CAN device */
/**
* @brief rx fifo callback. Once FIFO_0 is full,this func would be called
*
* @param hcan CAN handle indicate which device the oddest mesg in FIFO_0 comes from
*/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CANFIFOxCallback(hcan, CAN_RX_FIFO0);
}
/**
* @brief rx fifo callback. Once FIFO_1 is full,this func would be called
*
* @param hcan CAN handle indicate which device the oddest mesg in FIFO_1 comes from
*/
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
CANFIFOxCallback(hcan, CAN_RX_FIFO1);
}

46
bsp/bsp_can.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef BSP_CAN_H
#define BSP_CAN_H
#include "struct_typedef.h"
#include "can.h"
#define MX_REGISTER_DEVICE_CNT 12 // maximum number of device can be registered to CAN service
// this number depends on the load of CAN bus.
#define MX_CAN_FILTER_CNT (4 * 14) // temporarily useless
#define DEVICE_CAN_CNT 2 // CAN1,CAN2
/* module callback,which resolve protocol when new mesg arrives*/
/* can instance typedef, every module registered to CAN should have this variable */
typedef struct tmp
{
CAN_HandleTypeDef* can_handle;
uint32_t tx_id;
uint32_t tx_mailbox;
uint8_t* tx_buff;
uint8_t* rx_buff;
uint32_t rx_id;
void (*can_module_callback)(struct tmp*); // callback needs an instance to tell among registered ones
} can_instance;
/**
* @brief transmit mesg through CAN device
*
* @param _instance can instance owned by module
*/
void CANTransmit(can_instance* _instance);
/**
* @brief Register a module to CAN service,remember to call this before using a CAN device
*
* @attention tx_id, rx_id, can_handle and module_callback should be set before calling this func
* for the rest configs, this func will do for you
*
* @param _instance can instance owned by a specific device, remember to initialize it!
*
*/
void CANRegister(can_instance* _instance);
#endif

122
bsp/bsp_dwt.c Normal file
View File

@@ -0,0 +1,122 @@
/**
******************************************************************************
* @file bsp_dwt.c
* @author Wang Hongxi
* @version V1.1.0
* @date 2022/3/8
* @brief
******************************************************************************
* @attention
*
******************************************************************************
*/
#include "bsp_dwt.h"
DWT_Time_t SysTime;
static uint32_t CPU_FREQ_Hz, CPU_FREQ_Hz_ms, CPU_FREQ_Hz_us;
static uint32_t CYCCNT_RountCount;
static uint32_t CYCCNT_LAST;
uint64_t CYCCNT64;
static void DWT_CNT_Update(void);
void DWT_Init(uint32_t CPU_Freq_mHz)
{
/* 使能DWT外设 */
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
/* DWT CYCCNT寄存器计数清0 */
DWT->CYCCNT = (uint32_t)0u;
/* 使能Cortex-M DWT CYCCNT寄存器 */
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
CPU_FREQ_Hz = CPU_Freq_mHz * 1000000;
CPU_FREQ_Hz_ms = CPU_FREQ_Hz / 1000;
CPU_FREQ_Hz_us = CPU_FREQ_Hz / 1000000;
CYCCNT_RountCount = 0;
}
float DWT_GetDeltaT(uint32_t *cnt_last)
{
volatile uint32_t cnt_now = DWT->CYCCNT;
float dt = ((uint32_t)(cnt_now - *cnt_last)) / ((float)(CPU_FREQ_Hz));
*cnt_last = cnt_now;
DWT_CNT_Update();
return dt;
}
double DWT_GetDeltaT64(uint32_t *cnt_last)
{
volatile uint32_t cnt_now = DWT->CYCCNT;
double dt = ((uint32_t)(cnt_now - *cnt_last)) / ((double)(CPU_FREQ_Hz));
*cnt_last = cnt_now;
DWT_CNT_Update();
return dt;
}
void DWT_SysTimeUpdate(void)
{
volatile uint32_t cnt_now = DWT->CYCCNT;
static uint64_t CNT_TEMP1, CNT_TEMP2, CNT_TEMP3;
DWT_CNT_Update();
CYCCNT64 = (uint64_t)CYCCNT_RountCount * (uint64_t)UINT32_MAX + (uint64_t)cnt_now;
CNT_TEMP1 = CYCCNT64 / CPU_FREQ_Hz;
CNT_TEMP2 = CYCCNT64 - CNT_TEMP1 * CPU_FREQ_Hz;
SysTime.s = CNT_TEMP1;
SysTime.ms = CNT_TEMP2 / CPU_FREQ_Hz_ms;
CNT_TEMP3 = CNT_TEMP2 - SysTime.ms * CPU_FREQ_Hz_ms;
SysTime.us = CNT_TEMP3 / CPU_FREQ_Hz_us;
}
float DWT_GetTimeline_s(void)
{
DWT_SysTimeUpdate();
float DWT_Timelinef32 = SysTime.s + SysTime.ms * 0.001f + SysTime.us * 0.000001f;
return DWT_Timelinef32;
}
float DWT_GetTimeline_ms(void)
{
DWT_SysTimeUpdate();
float DWT_Timelinef32 = SysTime.s * 1000 + SysTime.ms + SysTime.us * 0.001f;
return DWT_Timelinef32;
}
uint64_t DWT_GetTimeline_us(void)
{
DWT_SysTimeUpdate();
uint64_t DWT_Timelinef32 = SysTime.s * 1000000 + SysTime.ms * 1000 + SysTime.us;
return DWT_Timelinef32;
}
static void DWT_CNT_Update(void)
{
volatile uint32_t cnt_now = DWT->CYCCNT;
if (cnt_now < CYCCNT_LAST)
CYCCNT_RountCount++;
CYCCNT_LAST = cnt_now;
}
void DWT_Delay(float Delay)
{
uint32_t tickstart = DWT->CYCCNT;
float wait = Delay;
while ((DWT->CYCCNT - tickstart) < wait * (float)CPU_FREQ_Hz)
{
}
}

39
bsp/bsp_dwt.h Normal file
View File

@@ -0,0 +1,39 @@
/**
******************************************************************************
* @file bsp_dwt.h
* @author Wang Hongxi
* @version V1.1.0
* @date 2022/3/8
* @brief
******************************************************************************
* @attention
*
******************************************************************************
*/
#ifndef _BSP_DWT_H
#define _BSP_DWT_H
#include "main.h"
#include "stdint.h"
typedef struct
{
uint32_t s;
uint16_t ms;
uint16_t us;
} DWT_Time_t;
extern DWT_Time_t SysTime;
void DWT_Init(uint32_t CPU_Freq_mHz);
float DWT_GetDeltaT(uint32_t *cnt_last);
double DWT_GetDeltaT64(uint32_t *cnt_last);
float DWT_GetTimeline_s(void);
float DWT_GetTimeline_ms(void);
uint64_t DWT_GetTimeline_us(void);
void DWT_Delay(float Delay);
void DWT_SysTimeUpdate(void);
#endif /* BSP_DWT_H_ */

21
bsp/bsp_led.c Normal file
View File

@@ -0,0 +1,21 @@
#include "bsp_led.h"
#include "main.h"
extern TIM_HandleTypeDef htim5;
void aRGB_led_show(uint32_t aRGB)
{
static uint8_t alpha;
static uint16_t red,green,blue;
alpha = (aRGB & 0xFF000000) >> 24;
red = ((aRGB & 0x00FF0000) >> 16) * alpha;
green = ((aRGB & 0x0000FF00) >> 8) * alpha;
blue = ((aRGB & 0x000000FF) >> 0) * alpha;
__HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_1, blue);
__HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_2, green);
__HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_3, red);
}

8
bsp/bsp_led.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef BSP_LED_H
#define BSP_LED_H
#include "struct_typedef.h"
extern void aRGB_led_show(uint32_t aRGB);
#endif

0
bsp/bsp_log.c Normal file
View File

0
bsp/bsp_log.h Normal file
View File

9
bsp/bsp_temperature.c Normal file
View File

@@ -0,0 +1,9 @@
#include "bsp_temperature.h"
extern TIM_HandleTypeDef htim10;
void imu_pwm_set(uint16_t pwm)
{
__HAL_TIM_SetCompare(&htim10, TIM_CHANNEL_1, pwm);
}

9
bsp/bsp_temperature.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef __BSP_IMU_PWM_H
#define __BSP_IMU_PWM_H
#include "stdint.h"
#include "tim.h"
extern void imu_pwm_set(uint16_t pwm);
#endif

75
bsp/bsp_usart.c Normal file
View File

@@ -0,0 +1,75 @@
#include "bsp_usart.h"
#include "stdlib.h"
/* usart service instance,modules' info would be recoreded here using ModuleRegister() */
static usart_instance* instance[DEVICE_USART_CNT];
/**
* @brief usart service will start automatically, after each module registered
*
* @param _instance instance owned by module
*/
static void USARTServiceInit(usart_instance* _instance)
{
HAL_UARTEx_ReceiveToIdle_DMA(_instance->usart_handle, _instance->recv_buff, _instance->recv_buff_size);
__HAL_DMA_DISABLE_IT(_instance->usart_handle->hdmarx, DMA_IT_HT);
}
void USARTRegister(usart_instance* _instance)
{
static instance_idx;
_instance->recv_buff=(uint8_t*)malloc(_instance->recv_buff_size*sizeof(uint8_t));
USARTServiceInit(_instance);
instance[instance_idx++]=_instance;
}
void USARTSend(usart_instance* _instance,uint8_t* send_buf, uint16_t send_size)
{
HAL_UART_Transmit_DMA(_instance->usart_handle, send_buf,send_size);
}
/**
* @brief everytiem when dma/idle happens,this function will be called
* here, for each uart, specific callback is refered for further process
* etc:visual protocol resolve/remote control resolve/referee protocol resolve
*
* @note because DMA half transfer iterrupt(DMA_IT_HT) would call this function too, so we just
* disable it when transfer complete using macro: __HAL_DMA_DISABLE_IT(huart->hdmarx,DMA_IT_HT)
*
* @param huart uart handle indicate which uart is being handled
* @param Size not used temporarily
*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
for (uint8_t i = 0; i < 3; i++)
{
if (huart == instance[i]->usart_handle)
{
instance[i]->module_callback();
HAL_UARTEx_ReceiveToIdle_DMA(instance[i]->usart_handle, instance[i]->recv_buff, instance[i]->recv_buff_size);
__HAL_DMA_DISABLE_IT(instance[i]->usart_handle->hdmarx, DMA_IT_HT);
break;
}
}
}
/**
* @brief when error occurs in the process of send/receive,this function will be called
* then just simply restart send/receive.
*
* @note most frequent error ex: parity/overrrun/frame error
*
* @param huart uart handle type,indicate where error comes from
*/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
for (uint8_t i = 0; i < 3; i++)
{
if (huart == instance[i]->usart_handle)
{
HAL_UARTEx_ReceiveToIdle_DMA(instance[i]->usart_handle, instance[i]->recv_buff, instance[i]->recv_buff_size);
__HAL_DMA_DISABLE_IT(instance[i]->usart_handle->hdmarx, DMA_IT_HT);
break;
}
}
}

43
bsp/bsp_usart.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef BSP_RC_H
#define BSP_RC_H
#include "struct_typedef.h"
#include "main.h"
#define DEVICE_USART_CNT 3
/* application callback,which resolves specific protocol */
typedef void (*usart_module_callback)();
/* usart_instance struct,each app would have one instance */
typedef struct
{
uint8_t *recv_buff;
uint8_t recv_buff_size;
UART_HandleTypeDef *usart_handle;
usart_module_callback module_callback;
} usart_instance;
/**
* @brief calling this func would regiter a module to usart_service
* this function provides completely wrap and abstract for those module who use usart as commu method
*
* @param id module id.attention,each id is mapped to a specific usart port(ex:remote control->usart3)
* @param prbuff pointer to where the raw recv data stored
* @param rbuffsize size of recv data buff
* @param psbuff pointer to where the data to be sent stored
* @param callback func pointer,this func would be called in USART_service.c/HAL_UARTEx_RxEventCallback()
* to resolve raw data using protocol provides by specific app calling Moduleregister()
*
*/
void USARTRegister(usart_instance* _instance);
/**
* @brief api for sending data through a specific serial port,indicated by the first parameter:id
*
* @param id specify which usart would be used
* @param send_size how many bytes to send
*/
void USARTSend(usart_instance* _instance, uint8_t* send_buf,uint16_t send_size);
#endif

35
bsp/struct_typedef.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef STRUCT_TYPEDEF_H
#define STRUCT_TYPEDEF_H
#ifndef __packed
#define __packed
#endif
typedef signed char int8_t;
typedef signed short int int16_t;
#ifndef _INT32_T_DECLARED
typedef signed int int32_t;
#define _INT32_T_DECLARED
#endif
typedef signed long long int64_t;
/* exact-width unsigned integer types */
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
#ifndef _UINT32_T_DECLARED
typedef unsigned int uint32_t;
#define _UINT32_T_DECLARED
#endif
typedef unsigned long long uint64_t;
typedef unsigned char bool_t;
typedef float fp32;
typedef double fp64;
#endif