mirror of
https://gitee.com/dlmu-cone/bf_original_balance_chassis
synced 2026-07-24 03:27:45 +08:00
Merge branch 'master' of https://gitee.com/hnuyuelurm/basic_framework
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
#include "bsp_log.h"
|
||||
#include "bsp_dwt.h"
|
||||
#include "bsp_usb.h"
|
||||
#include "bsp_buzzer.h"
|
||||
#include "buzzer.h"
|
||||
#include "bsp_led.h"
|
||||
#include "bsp_temperature.h"
|
||||
|
||||
@@ -15,5 +15,5 @@ void BSPInit()
|
||||
// legacy support,待删除,将在实现了led/tempctrl/buzzer的module之后移动到app层进行XXXRegister()
|
||||
LEDInit();
|
||||
IMUTempInit();
|
||||
BuzzerInit();
|
||||
buzzer_init();
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#include "bsp_buzzer.h"
|
||||
#include "main.h"
|
||||
|
||||
#warning this is a legacy support file, please use the new version
|
||||
|
||||
extern TIM_HandleTypeDef htim4;
|
||||
static uint8_t tmp_warning_level = 0;
|
||||
|
||||
void BuzzerInit()
|
||||
{
|
||||
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3);
|
||||
}
|
||||
|
||||
void BuzzerOn(uint16_t psc, uint16_t pwm, uint8_t level)
|
||||
{
|
||||
if (level > tmp_warning_level)
|
||||
{
|
||||
tmp_warning_level = level;
|
||||
__HAL_TIM_PRESCALER(&htim4, psc);
|
||||
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, pwm);
|
||||
}
|
||||
}
|
||||
|
||||
void BuzzerOff(void)
|
||||
{
|
||||
__HAL_TIM_SetCompare(&htim4, TIM_CHANNEL_3, 0);
|
||||
tmp_warning_level = 0;
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#ifndef BSP_BUZZER_H
|
||||
#define BSP_BUZZER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void BuzzerInit();
|
||||
extern void BuzzerOn(uint16_t psc, uint16_t pwm, uint8_t level);
|
||||
extern void BuzzerOff(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -65,15 +65,20 @@ CANInstance *CANRegister(CAN_Init_Config_s *config)
|
||||
if (!idx)
|
||||
{
|
||||
CANServiceInit(); // 第一次注册,先进行硬件初始化
|
||||
LOGINFO("[bsp_can] CAN Service Init");
|
||||
}
|
||||
if (idx >= CAN_MX_REGISTER_CNT) // 超过最大实例数
|
||||
{
|
||||
while (1)
|
||||
;
|
||||
LOGERROR("[bsp_can] CAN instance exceeded MAX num, consider balance the load of CAN bus");
|
||||
}
|
||||
for (size_t i = 0; i < idx; i++)
|
||||
{ // 重复注册 | id重复
|
||||
if (can_instance[i]->rx_id == config->rx_id && can_instance[i]->can_handle == config->can_handle)
|
||||
{
|
||||
while (1)
|
||||
;
|
||||
LOGERROR("[}bsp_can] CAN id crash ,tx [%d] or rx [%d] already registered", &config->tx_id, &config->rx_id);
|
||||
}
|
||||
}
|
||||
|
||||
CANInstance *instance = (CANInstance *)malloc(sizeof(CANInstance)); // 分配空间
|
||||
@@ -107,7 +112,7 @@ uint8_t CANTransmit(CANInstance *_instance, float timeout)
|
||||
{
|
||||
if (DWT_GetTimeline_ms() - dwt_start > timeout) // 超时
|
||||
{
|
||||
LOGWARNING("CAN BUSY sending! cnt:%d", busy_count);
|
||||
LOGWARNING("[bsp_can] CAN MAILbox full! failed to add msg to mailbox. Cnt [%d]", busy_count);
|
||||
busy_count++;
|
||||
return 0;
|
||||
}
|
||||
@@ -116,7 +121,7 @@ uint8_t CANTransmit(CANInstance *_instance, float timeout)
|
||||
// tx_mailbox会保存实际填入了这一帧消息的邮箱,但是知道是哪个邮箱发的似乎也没啥用
|
||||
if (HAL_CAN_AddTxMessage(_instance->can_handle, &_instance->txconf, _instance->tx_buff, &_instance->tx_mailbox))
|
||||
{
|
||||
LOGWARNING("CAN BUSY bus! cnt:%d", busy_count);
|
||||
LOGWARNING("[bsp_can] CAN bus BUS! cnt:%d", busy_count);
|
||||
busy_count++;
|
||||
return 0;
|
||||
}
|
||||
@@ -125,9 +130,10 @@ uint8_t CANTransmit(CANInstance *_instance, float timeout)
|
||||
|
||||
void CANSetDLC(CANInstance *_instance, uint8_t length)
|
||||
{
|
||||
// 发送长度错误!检查调用参数是否出错,或出现野指针/越界访问
|
||||
if (length > 8 || length == 0) // 安全检查
|
||||
while (1)
|
||||
; // 发送长度错误!检查调用参数是否出错,或出现野指针/越界访问
|
||||
LOGERROR("[bsp_can] CAN DLC error! check your code or wild pointer");
|
||||
_instance->txconf.DLC = length;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ static osMutexId DWT_MUTEX;
|
||||
/**
|
||||
* @brief 私有函数,用于检查DWT CYCCNT寄存器是否溢出,并更新CYCCNT_RountCount
|
||||
* @attention 此函数假设两次调用之间的时间间隔不超过一次溢出
|
||||
*
|
||||
* @todo 更好的方案是为dwt的时间更新单独设置一个任务
|
||||
*
|
||||
* @todo 更好的方案是为dwt的时间更新单独设置一个任务?
|
||||
* 不过,使用dwt的初衷是定时不被中断/任务等因素影响,因此该实现仍然有其存在的意义
|
||||
*
|
||||
*/
|
||||
@@ -31,7 +31,7 @@ static void DWT_CNT_Update(void)
|
||||
if (__get_CONTROL()) // 不在中断中,使用互斥锁;在中断则直接执行即可,本框架将所有中断优先级设置为相同,故不会被其他中断重入
|
||||
if (osOK != osMutexWait(DWT_MUTEX, 0))
|
||||
return;
|
||||
|
||||
|
||||
volatile uint32_t cnt_now = DWT->CYCCNT;
|
||||
if (cnt_now < CYCCNT_LAST)
|
||||
CYCCNT_RountCount++;
|
||||
@@ -131,6 +131,5 @@ void DWT_Delay(float Delay)
|
||||
float wait = Delay;
|
||||
|
||||
while ((DWT->CYCCNT - tickstart) < wait * (float)CPU_FREQ_Hz)
|
||||
{
|
||||
}
|
||||
;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
******************************************************************************
|
||||
* @file bsp_dwt.h
|
||||
* @author Wang Hongxi
|
||||
* @version V1.1.0
|
||||
* @author modified by NeoZng
|
||||
* @version V1.2.0
|
||||
* @date 2022/3/8
|
||||
* @brief
|
||||
******************************************************************************
|
||||
@@ -15,6 +16,7 @@
|
||||
|
||||
#include "main.h"
|
||||
#include "stdint.h"
|
||||
#include "bsp_log.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -23,17 +25,30 @@ typedef struct
|
||||
uint16_t us;
|
||||
} DWT_Time_t;
|
||||
|
||||
/**
|
||||
* @brief 该宏用于计算代码段执行时间,单位为秒/s,返回值为float类型
|
||||
* 首先需要创建一个float类型的变量,用于存储时间间隔
|
||||
* 计算得到的时间间隔同时还会通过RTT打印到日志终端,你也可以将你的dt变量添加到查看
|
||||
*/
|
||||
#define TIME_ELAPSE(dt, code) \
|
||||
do \
|
||||
{ \
|
||||
float tstart = DWT_GetTimeline_s(); \
|
||||
code; \
|
||||
dt = DWT_GetTimeline_s() - tstart; \
|
||||
LOGINFO("[DWT] " #dt " = %f s\r\n", dt); \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief 初始化DWT,传入参数为CPU频率,单位MHz
|
||||
*
|
||||
*
|
||||
* @param CPU_Freq_mHz c板为168MHz,A板为180MHz
|
||||
*/
|
||||
void DWT_Init(uint32_t CPU_Freq_mHz);
|
||||
|
||||
/**
|
||||
* @brief 获取两次调用之间的时间间隔,单位为秒/s
|
||||
*
|
||||
*
|
||||
* @param cnt_last 上一次调用的时间戳
|
||||
* @return float 时间间隔,单位为秒/s
|
||||
*/
|
||||
@@ -41,7 +56,7 @@ float DWT_GetDeltaT(uint32_t *cnt_last);
|
||||
|
||||
/**
|
||||
* @brief 获取两次调用之间的时间间隔,单位为秒/s,高精度
|
||||
*
|
||||
*
|
||||
* @param cnt_last 上一次调用的时间戳
|
||||
* @return double 时间间隔,单位为秒/s
|
||||
*/
|
||||
@@ -49,22 +64,22 @@ double DWT_GetDeltaT64(uint32_t *cnt_last);
|
||||
|
||||
/**
|
||||
* @brief 获取当前时间,单位为秒/s,即初始化后的时间
|
||||
*
|
||||
*
|
||||
* @return float 时间轴
|
||||
*/
|
||||
float DWT_GetTimeline_s(void);
|
||||
|
||||
/**
|
||||
* @brief 获取当前时间,单位为毫秒/ms,即初始化后的时间
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
float DWT_GetTimeline_ms(void);
|
||||
|
||||
/**
|
||||
* @brief 获取当前时间,单位为微秒/us,即初始化后的时间
|
||||
*
|
||||
* @return uint64_t
|
||||
*
|
||||
* @return uint64_t
|
||||
*/
|
||||
uint64_t DWT_GetTimeline_us(void);
|
||||
|
||||
@@ -72,7 +87,7 @@ uint64_t DWT_GetTimeline_us(void);
|
||||
* @brief DWT延时函数,单位为秒/s
|
||||
* @attention 该函数不受中断是否开启的影响,可以在临界区和关闭中断时使用
|
||||
* @note 禁止在__disable_irq()和__enable_irq()之间使用HAL_Delay()函数,应使用本函数
|
||||
*
|
||||
*
|
||||
* @param Delay 延时时间,单位为秒/s
|
||||
*/
|
||||
void DWT_Delay(float Delay);
|
||||
@@ -83,6 +98,4 @@ void DWT_Delay(float Delay);
|
||||
*/
|
||||
void DWT_SysTimeUpdate(void);
|
||||
|
||||
|
||||
|
||||
#endif /* BSP_DWT_H_ */
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
DWT是stm32内部的一个"隐藏资源",他的用途是给下载器提供准确的定时,从而为调试信息加上时间戳.并在固定的时间间隔将调试数据发送到你的xxlink上.
|
||||
|
||||
|
||||
|
||||
## 常用功能
|
||||
|
||||
### 计算两次进入同一个函数的时间间隔
|
||||
@@ -23,8 +21,34 @@ start=DWT_DetTimeline_ms();
|
||||
|
||||
// some proc to go...
|
||||
for(uint8_t i=0;i<10;i++)
|
||||
foo();
|
||||
foo();
|
||||
|
||||
end = DWT_DetTimeline_ms()-start;
|
||||
```
|
||||
|
||||
我们还提供了一个宏用于调试计时:
|
||||
|
||||
```c
|
||||
#define TIME_ELAPSE(dt, code) \
|
||||
do \
|
||||
{ \
|
||||
float tstart = DWT_GetTimeline_s(); \
|
||||
code; \
|
||||
dt = DWT_GetTimeline_s() - tstart; \
|
||||
LOGINFO("[DWT] " #dt " = %f s\r\n", dt); \
|
||||
} while (0)
|
||||
|
||||
```
|
||||
|
||||
传入一个float类型的变量,并将你要执行的代码写入第二个参数:
|
||||
|
||||
```c
|
||||
static float my_func_dt;
|
||||
TIME_ELAPSE(my_func_dt,
|
||||
Function1(vara);
|
||||
Function2(some, var);
|
||||
Function3(your,param);
|
||||
// something more
|
||||
);
|
||||
// my_func_dt can be used for other purpose then;
|
||||
```
|
||||
|
||||
289
bsp/flash/bsp_flash.c
Normal file
289
bsp/flash/bsp_flash.c
Normal file
@@ -0,0 +1,289 @@
|
||||
#include "bsp_flash.h"
|
||||
#include "main.h"
|
||||
#include "string.h"
|
||||
|
||||
static uint32_t ger_sector(uint32_t address);
|
||||
|
||||
/**
|
||||
* @brief erase flash
|
||||
* @param[in] address: flash address
|
||||
* @param[in] len: page num
|
||||
* @retval none
|
||||
*/
|
||||
/**
|
||||
* @brief <20><><EFBFBD><EFBFBD>flash
|
||||
* @param[in] address: flash <20><>ַ
|
||||
* @param[in] len: ҳ<><D2B3><EFBFBD><EFBFBD>
|
||||
* @retval none
|
||||
*/
|
||||
void flash_erase_address(uint32_t address, uint16_t len)
|
||||
{
|
||||
FLASH_EraseInitTypeDef flash_erase;
|
||||
uint32_t error;
|
||||
|
||||
flash_erase.Sector = ger_sector(address);
|
||||
flash_erase.TypeErase = FLASH_TYPEERASE_SECTORS;
|
||||
flash_erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
|
||||
flash_erase.NbSectors = len;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
HAL_FLASHEx_Erase(&flash_erase, &error);
|
||||
HAL_FLASH_Lock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write data to one page of flash
|
||||
* @param[in] start_address: flash address
|
||||
* @param[in] buf: data point
|
||||
* @param[in] len: data num
|
||||
* @retval success 0, fail -1
|
||||
*/
|
||||
/**
|
||||
* @brief <20><>һҳflashд<68><D0B4><EFBFBD><EFBFBD>
|
||||
* @param[in] start_address: flash <20><>ַ
|
||||
* @param[in] buf: <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
|
||||
* @param[in] len: <20><><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
|
||||
* @retval success 0, fail -1
|
||||
*/
|
||||
int8_t flash_write_single_address(uint32_t start_address, uint32_t *buf, uint32_t len)
|
||||
{
|
||||
static uint32_t uw_address;
|
||||
static uint32_t end_address;
|
||||
static uint32_t *data_buf;
|
||||
static uint32_t data_len;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
|
||||
uw_address = start_address;
|
||||
end_address = get_next_flash_address(start_address);
|
||||
data_buf = buf;
|
||||
data_len = 0;
|
||||
|
||||
while (uw_address <= end_address)
|
||||
{
|
||||
|
||||
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,uw_address, *data_buf) == HAL_OK)
|
||||
{
|
||||
uw_address += 4;
|
||||
data_buf++;
|
||||
data_len++;
|
||||
if (data_len == len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_FLASH_Lock();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_FLASH_Lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief write data to some pages of flash
|
||||
* @param[in] start_address: flash start address
|
||||
* @param[in] end_address: flash end address
|
||||
* @param[in] buf: data point
|
||||
* @param[in] len: data num
|
||||
* @retval success 0, fail -1
|
||||
*/
|
||||
/**
|
||||
* @brief <20><><EFBFBD><EFBFBD>ҳflashд<68><D0B4><EFBFBD><EFBFBD>
|
||||
* @param[in] start_address: flash <20><>ʼ<EFBFBD><CABC>ַ
|
||||
* @param[in] end_address: flash <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
|
||||
* @param[in] buf: <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
|
||||
* @param[in] len: <20><><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
|
||||
* @retval success 0, fail -1
|
||||
*/
|
||||
int8_t flash_write_muli_address(uint32_t start_address, uint32_t end_address, uint32_t *buf, uint32_t len)
|
||||
{
|
||||
uint32_t uw_address = 0;
|
||||
uint32_t *data_buf;
|
||||
uint32_t data_len;
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
|
||||
uw_address = start_address;
|
||||
data_buf = buf;
|
||||
data_len = 0;
|
||||
while (uw_address <= end_address)
|
||||
{
|
||||
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,uw_address, *data_buf) == HAL_OK)
|
||||
{
|
||||
uw_address += 4;
|
||||
data_buf++;
|
||||
data_len++;
|
||||
if (data_len == len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_FLASH_Lock();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_FLASH_Lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief read data for flash
|
||||
* @param[in] address: flash address
|
||||
* @param[out] buf: data point
|
||||
* @param[in] len: data num
|
||||
* @retval none
|
||||
*/
|
||||
/**
|
||||
* @brief <20><>flash<73><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
* @param[in] start_address: flash <20><>ַ
|
||||
* @param[out] buf: <20><><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>
|
||||
* @param[in] len: <20><><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
|
||||
* @retval none
|
||||
*/
|
||||
void flash_read(uint32_t address, uint32_t *buf, uint32_t len)
|
||||
{
|
||||
memcpy(buf, (void*)address, len *4);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief get the sector number of flash
|
||||
* @param[in] address: flash address
|
||||
* @retval sector number
|
||||
*/
|
||||
/**
|
||||
* @brief <20><>ȡflash<73><68>sector<6F><72>
|
||||
* @param[in] address: flash <20><>ַ
|
||||
* @retval sector<6F><72>
|
||||
*/
|
||||
static uint32_t ger_sector(uint32_t address)
|
||||
{
|
||||
uint32_t sector = 0;
|
||||
if ((address < ADDR_FLASH_SECTOR_1) && (address >= ADDR_FLASH_SECTOR_0))
|
||||
{
|
||||
sector = FLASH_SECTOR_0;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_2) && (address >= ADDR_FLASH_SECTOR_1))
|
||||
{
|
||||
sector = FLASH_SECTOR_1;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_3) && (address >= ADDR_FLASH_SECTOR_2))
|
||||
{
|
||||
sector = FLASH_SECTOR_2;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_4) && (address >= ADDR_FLASH_SECTOR_3))
|
||||
{
|
||||
sector = FLASH_SECTOR_3;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_5) && (address >= ADDR_FLASH_SECTOR_4))
|
||||
{
|
||||
sector = FLASH_SECTOR_4;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_6) && (address >= ADDR_FLASH_SECTOR_5))
|
||||
{
|
||||
sector = FLASH_SECTOR_5;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_7) && (address >= ADDR_FLASH_SECTOR_6))
|
||||
{
|
||||
sector = FLASH_SECTOR_6;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_8) && (address >= ADDR_FLASH_SECTOR_7))
|
||||
{
|
||||
sector = FLASH_SECTOR_7;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_9) && (address >= ADDR_FLASH_SECTOR_8))
|
||||
{
|
||||
sector = FLASH_SECTOR_8;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_10) && (address >= ADDR_FLASH_SECTOR_9))
|
||||
{
|
||||
sector = FLASH_SECTOR_9;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_11) && (address >= ADDR_FLASH_SECTOR_10))
|
||||
{
|
||||
sector = FLASH_SECTOR_10;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_12) && (address >= ADDR_FLASH_SECTOR_11))
|
||||
{
|
||||
sector = FLASH_SECTOR_11;
|
||||
}
|
||||
else
|
||||
{
|
||||
sector = FLASH_SECTOR_11;
|
||||
}
|
||||
|
||||
return sector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get the next page flash address
|
||||
* @param[in] address: flash address
|
||||
* @retval next page flash address
|
||||
*/
|
||||
/**
|
||||
* @brief <20><>ȡ<EFBFBD><C8A1>һҳflash<73><68>ַ
|
||||
* @param[in] address: flash <20><>ַ
|
||||
* @retval <20><>һҳflash<73><68>ַ
|
||||
*/
|
||||
uint32_t get_next_flash_address(uint32_t address)
|
||||
{
|
||||
uint32_t sector = 0;
|
||||
|
||||
if ((address < ADDR_FLASH_SECTOR_1) && (address >= ADDR_FLASH_SECTOR_0))
|
||||
{
|
||||
sector = ADDR_FLASH_SECTOR_1;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_2) && (address >= ADDR_FLASH_SECTOR_1))
|
||||
{
|
||||
sector = ADDR_FLASH_SECTOR_2;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_3) && (address >= ADDR_FLASH_SECTOR_2))
|
||||
{
|
||||
sector = ADDR_FLASH_SECTOR_3;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_4) && (address >= ADDR_FLASH_SECTOR_3))
|
||||
{
|
||||
sector = ADDR_FLASH_SECTOR_4;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_5) && (address >= ADDR_FLASH_SECTOR_4))
|
||||
{
|
||||
sector = ADDR_FLASH_SECTOR_5;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_6) && (address >= ADDR_FLASH_SECTOR_5))
|
||||
{
|
||||
sector = ADDR_FLASH_SECTOR_6;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_7) && (address >= ADDR_FLASH_SECTOR_6))
|
||||
{
|
||||
sector = ADDR_FLASH_SECTOR_7;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_8) && (address >= ADDR_FLASH_SECTOR_7))
|
||||
{
|
||||
sector = ADDR_FLASH_SECTOR_8;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_9) && (address >= ADDR_FLASH_SECTOR_8))
|
||||
{
|
||||
sector = ADDR_FLASH_SECTOR_9;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_10) && (address >= ADDR_FLASH_SECTOR_9))
|
||||
{
|
||||
sector = ADDR_FLASH_SECTOR_10;
|
||||
}
|
||||
else if ((address < ADDR_FLASH_SECTOR_11) && (address >= ADDR_FLASH_SECTOR_10))
|
||||
{
|
||||
sector = ADDR_FLASH_SECTOR_11;
|
||||
}
|
||||
else /*(address < FLASH_END_ADDR) && (address >= ADDR_FLASH_SECTOR_23))*/
|
||||
{
|
||||
sector = FLASH_END_ADDR;
|
||||
}
|
||||
return sector;
|
||||
}
|
||||
80
bsp/flash/bsp_flash.h
Normal file
80
bsp/flash/bsp_flash.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef _BSP_FLASH_H
|
||||
#define _BSP_FLASH_H
|
||||
#include "main.h"
|
||||
|
||||
/* Base address of the Flash sectors */
|
||||
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 16 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base address of Sector 1, 16 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base address of Sector 2, 16 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base address of Sector 3, 16 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base address of Sector 4, 64 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base address of Sector 5, 128 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base address of Sector 6, 128 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base address of Sector 7, 128 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_8 ((uint32_t)0x08080000) /* Base address of Sector 8, 128 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_9 ((uint32_t)0x080A0000) /* Base address of Sector 9, 128 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_10 ((uint32_t)0x080C0000) /* Base address of Sector 10, 128 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_11 ((uint32_t)0x080E0000) /* Base address of Sector 11, 128 Kbytes */
|
||||
|
||||
#define FLASH_END_ADDR ((uint32_t)0x08100000) /* Base address of Sector 23, 128 Kbytes */
|
||||
|
||||
|
||||
#define ADDR_FLASH_SECTOR_12 ((uint32_t)0x08100000) /* Base address of Sector 12, 16 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_13 ((uint32_t)0x08104000) /* Base address of Sector 13, 16 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_14 ((uint32_t)0x08108000) /* Base address of Sector 14, 16 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_15 ((uint32_t)0x0810C000) /* Base address of Sector 15, 16 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_16 ((uint32_t)0x08110000) /* Base address of Sector 16, 64 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_17 ((uint32_t)0x08120000) /* Base address of Sector 17, 128 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_18 ((uint32_t)0x08140000) /* Base address of Sector 18, 128 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_19 ((uint32_t)0x08160000) /* Base address of Sector 19, 128 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_20 ((uint32_t)0x08180000) /* Base address of Sector 20, 128 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_21 ((uint32_t)0x081A0000) /* Base address of Sector 21, 128 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_22 ((uint32_t)0x081C0000) /* Base address of Sector 22, 128 Kbytes */
|
||||
#define ADDR_FLASH_SECTOR_23 ((uint32_t)0x081E0000) /* Base address of Sector 23, 128 Kbytes */
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief erase flash
|
||||
* @param[in] address: flash address
|
||||
* @param[in] len: page num
|
||||
* @retval none
|
||||
*/
|
||||
void flash_erase_address(uint32_t address, uint16_t len);
|
||||
|
||||
/**
|
||||
* @brief write data to one page of flash
|
||||
* @param[in] start_address: flash address
|
||||
* @param[in] buf: data point
|
||||
* @param[in] len: data num
|
||||
* @retval success 0, fail -1
|
||||
*/
|
||||
int8_t flash_write_single_address(uint32_t start_address, uint32_t *buf, uint32_t len);
|
||||
|
||||
|
||||
/**
|
||||
* @brief write data to some pages of flash
|
||||
* @param[in] start_address: flash start address
|
||||
* @param[in] end_address: flash end address
|
||||
* @param[in] buf: data point
|
||||
* @param[in] len: data num
|
||||
* @retval success 0, fail -1
|
||||
*/
|
||||
int8_t flash_write_muli_address(uint32_t start_address, uint32_t end_address, uint32_t *buf, uint32_t len);
|
||||
|
||||
/**
|
||||
* @brief read data for flash
|
||||
* @param[in] address: flash address
|
||||
* @param[out] buf: data point
|
||||
* @param[in] len: data num
|
||||
* @retval none
|
||||
*/
|
||||
void flash_read(uint32_t address, uint32_t *buf, uint32_t len);
|
||||
|
||||
/**
|
||||
* @brief get the next page flash address
|
||||
* @param[in] address: flash address
|
||||
* @retval next page flash address
|
||||
*/
|
||||
uint32_t get_next_flash_address(uint32_t address);
|
||||
#endif
|
||||
0
bsp/flash/bsp_flash.md
Normal file
0
bsp/flash/bsp_flash.md
Normal file
@@ -7,44 +7,46 @@
|
||||
|
||||
#define BUFFER_INDEX 0
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief 日志系统初始化
|
||||
*
|
||||
*
|
||||
*/
|
||||
void BSPLogInit();
|
||||
|
||||
/**
|
||||
* @brief 日志功能原型,供下面的LOGI,LOGW,LOGE等使用
|
||||
*
|
||||
*
|
||||
*/
|
||||
#define LOG_PROTO(type,color,format,...) \
|
||||
SEGGER_RTT_printf(BUFFER_INDEX," %s%s"format"\r\n%s", \
|
||||
color, \
|
||||
type, \
|
||||
##__VA_ARGS__, \
|
||||
#define LOG_PROTO(type, color, format, ...) \
|
||||
SEGGER_RTT_printf(BUFFER_INDEX, " %s%s" format "\r\n%s", \
|
||||
color, \
|
||||
type, \
|
||||
##__VA_ARGS__, \
|
||||
RTT_CTRL_RESET)
|
||||
|
||||
/*------下面是日志输出的接口--------*/
|
||||
/*----------------------------------------下面是日志输出的接口-------------------------------------------------*/
|
||||
|
||||
/* 清屏 */
|
||||
#define LOG_CLEAR() SEGGER_RTT_WriteString(0, " "RTT_CTRL_CLEAR)
|
||||
#define LOG_CLEAR() SEGGER_RTT_WriteString(0, " " RTT_CTRL_CLEAR)
|
||||
|
||||
/* 无颜色日志输出 */
|
||||
#define LOG(format,...) LOG_PROTO("","",format,##__VA_ARGS__)
|
||||
#define LOG(format, ...) LOG_PROTO("", "", format, ##__VA_ARGS__)
|
||||
|
||||
/* 有颜色格式日志输出,建议使用这些宏来输出日志 */
|
||||
/**
|
||||
* 有颜色格式日志输出,建议使用这些宏来输出日志
|
||||
* @attention 注意这些接口不支持浮点格式化输出,若有需要,请使用Float2Str()函数进行转换后再打印
|
||||
*/
|
||||
// information level
|
||||
#define LOGINFO(format,...) LOG_PROTO("I", RTT_CTRL_TEXT_BRIGHT_GREEN , format, ##__VA_ARGS__)
|
||||
#define LOGINFO(format, ...) LOG_PROTO("I:", RTT_CTRL_TEXT_BRIGHT_GREEN, format, ##__VA_ARGS__)
|
||||
// warning level
|
||||
#define LOGWARNING(format,...) LOG_PROTO("W", RTT_CTRL_TEXT_BRIGHT_YELLOW, format, ##__VA_ARGS__)
|
||||
#define LOGWARNING(format, ...) LOG_PROTO("W:", RTT_CTRL_TEXT_BRIGHT_YELLOW, format, ##__VA_ARGS__)
|
||||
// error level
|
||||
#define LOGERROR(format,...) LOG_PROTO("E", RTT_CTRL_TEXT_BRIGHT_RED , format, ##__VA_ARGS__)
|
||||
#define LOGERROR(format, ...) LOG_PROTO("E:", RTT_CTRL_TEXT_BRIGHT_RED, format, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief 通过segger RTT打印日志,支持格式化输出,格式化输出的实现参考printf.
|
||||
*
|
||||
* @attention !! 此函数不支持浮点格式化,若有需要,请使用Float2Str()函数进行转换后再打印 !!
|
||||
*
|
||||
* @param fmt 格式字符串
|
||||
* @param ... 参数列表
|
||||
* @return int 打印的log字符数
|
||||
@@ -53,7 +55,8 @@ int PrintLog(const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* @brief 利用sprintf(),将float转换为字符串进行打印
|
||||
*
|
||||
* @attention 浮点数需要转换为字符串后才能通过RTT打印
|
||||
*
|
||||
* @param str 转换后的字符串
|
||||
* @param va 待转换的float
|
||||
*/
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
|
||||
<p align='right'>neozng1@hnu.edu.cn</p>
|
||||
|
||||
> TODO:
|
||||
>
|
||||
> 1. 在未接入调试器的时候,将日志写入flash中,并提供接口读取
|
||||
> 2. 增加日志分级,提供info、warning、error三个等级的日志
|
||||
|
||||
## 使用说明
|
||||
|
||||
bsp_log是基于segger RTT实现的日志打印模块。
|
||||
@@ -19,11 +14,11 @@ bsp_log是基于segger RTT实现的日志打印模块。
|
||||
#define LOGERROR(format,...)
|
||||
```
|
||||
|
||||
分别用于输出不同等级的日志。
|
||||
分别用于输出不同等级的日志。注意RTT不支持直接使用`%f`进行浮点格式化,要使用`void Float2Str(char *str, float va);`转化成字符串之后再发送。
|
||||
|
||||
**若想启用RTT,必须通过`launch.json`的`debug-jlink`启动调试(不论使用什么调试器)。**
|
||||
**若想启用RTT,必须通过`launch.json`的`debug-jlink`启动调试(不论使用什么调试器)。** 按照`VSCode+Ozone环境配置`完成配置之后的cmsis dap和daplink是可以支持Jlink全家桶的。
|
||||
|
||||
注意,若你使用的是cmsis-dap和daplink,**请在调试任务启动之后再打开`log`任务。**(均在项目文件夹下的.vsocde/task.json中,有注释自行查看)。
|
||||
另外,若你使用的是cmsis-dap和daplink,**请在 *jlink* 调试任务启动之后再打开`log`任务。**(均在项目文件夹下的.vsocde/task.json中,有注释自行查看)。否则可能出线RTT viewer无法连接客户端的情况。
|
||||
|
||||
在ozone中查看log输出,直接打开console调试任务台和terminal调试中断便可看到调试输出。
|
||||
|
||||
@@ -35,7 +30,7 @@ bsp_log是基于segger RTT实现的日志打印模块。
|
||||
|
||||
```c
|
||||
int printf_log(const char *fmt, ...);
|
||||
void Float2Str(char *str, float va);
|
||||
void Float2Str(char *str, float va); // 输出浮点需要先用此函数进行转换
|
||||
```
|
||||
|
||||
调用第一个函数,可以通过jlink或dap-link向调试器连接的上位机发送信息,格式和printf相同,示例如下:
|
||||
@@ -53,8 +48,3 @@ char* str_buff[64];
|
||||
Float2Str(str_buff,current_feedback);
|
||||
printf_log("Motor %d met some problem, error code %d!\n",3,1);
|
||||
```
|
||||
|
||||
或直接通过`%f`格式符直接使用`printf_log()`发送日志,可以设置小数点位数以降低带宽开销。
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ static PWMInstance *pwm_instance[PWM_DEVICE_CNT] = {NULL}; // 所有的pwm insta
|
||||
|
||||
/**
|
||||
* @brief pwm dma传输完成回调函数
|
||||
* @attention 由于HAL库的设计问题,当一个pulse完成(即tim的计数超过比较寄存器)也会调用此函数
|
||||
* 故对于那些开启了PWM的TIM,务必关闭其全局中断,仅保持DMA传输完成中断打开
|
||||
*
|
||||
* @param htim 发生中断的定时器句柄
|
||||
*/
|
||||
@@ -15,7 +17,7 @@ void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
for (uint8_t i = 0; i < idx; i++)
|
||||
{ // 来自同一个定时器的中断且通道相同
|
||||
if (pwm_instance[i]->htim == htim && htim->Channel == pwm_instance[i]->channel)
|
||||
if (pwm_instance[i]->htim == htim && htim->Channel == (1<<(pwm_instance[i]->channel/4)))
|
||||
{
|
||||
if (pwm_instance[i]->callback) // 如果有回调函数
|
||||
pwm_instance[i]->callback(pwm_instance[i]);
|
||||
@@ -39,7 +41,7 @@ PWMInstance *PWMRegister(PWM_Init_Config_s *config)
|
||||
pwm->callback = config->callback;
|
||||
pwm->id = config->id;
|
||||
// 启动PWM
|
||||
HAL_TIM_PWM_Start(pwm->htim, pwm->channel);
|
||||
HAL_TIM_PWM_Start_IT(pwm->htim, pwm->channel);
|
||||
__HAL_TIM_SetCompare(pwm->htim, pwm->channel, pwm->pulse); // 设置占空比
|
||||
|
||||
pwm_instance[idx++] = pwm;
|
||||
@@ -65,7 +67,11 @@ void PWMSetPulse(PWMInstance *pwm, uint32_t pulse)
|
||||
pwm->pulse = pulse;
|
||||
__HAL_TIM_SetCompare(pwm->htim, pwm->channel, pwm->pulse);
|
||||
}
|
||||
|
||||
void PWMSetPeriod(PWMInstance *pwm, uint32_t period)
|
||||
{
|
||||
pwm->period = period;
|
||||
__HAL_TIM_PRESCALER(pwm->htim, pwm->period);
|
||||
}
|
||||
/* 只是对HAL的函数进行了形式上的封装 */
|
||||
void PWMStartDMA(PWMInstance *pwm, uint32_t *pData, uint32_t Size)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*
|
||||
*/
|
||||
#include "bsp_usart.h"
|
||||
#include "bsp_log.h"
|
||||
#include "stdlib.h"
|
||||
#include "memory.h"
|
||||
|
||||
@@ -38,7 +39,13 @@ USARTInstance *USARTRegister(USART_Init_Config_s *init_config)
|
||||
{
|
||||
if (idx >= DEVICE_USART_CNT) // 超过最大实例数
|
||||
while (1)
|
||||
;
|
||||
LOGERROR("[bsp_usart] USART exceed max instance count!");
|
||||
|
||||
for (uint8_t i = 0; i < idx; i++) // 检查是否已经注册过
|
||||
if (usart_instance[i]->usart_handle == init_config->usart_handle)
|
||||
while (1)
|
||||
LOGERROR("[bsp_usart] USART instance already registered!");
|
||||
|
||||
USARTInstance *instance = (USARTInstance *)malloc(sizeof(USARTInstance));
|
||||
memset(instance, 0, sizeof(USARTInstance));
|
||||
|
||||
@@ -75,14 +82,10 @@ void USARTSend(USARTInstance *_instance, uint8_t *send_buf, uint16_t send_size,
|
||||
/* 串口发送时,gstate会被设为BUSY_TX */
|
||||
uint8_t USARTIsReady(USARTInstance *_instance)
|
||||
{
|
||||
if(_instance->usart_handle->gState | HAL_UART_STATE_BUSY_TX)
|
||||
{
|
||||
if (_instance->usart_handle->gState | HAL_UART_STATE_BUSY_TX)
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,6 +132,7 @@ void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
HAL_UARTEx_ReceiveToIdle_DMA(usart_instance[i]->usart_handle, usart_instance[i]->recv_buff, usart_instance[i]->recv_buff_size);
|
||||
__HAL_DMA_DISABLE_IT(usart_instance[i]->usart_handle->hdmarx, DMA_IT_HT);
|
||||
LOGWARNING("[bsp_usart] USART error callback triggered, instance idx [%d]", i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
|
||||
需要在串口实例下设定接收的数据包的长度,实例对应的串口硬件(通过`UART_HandleTypeDef`指定,如`&huart1`),解析接收数据对应的回调函数这三个参数。然后,调用`USARTRegister()`并传入配置好的`usart_instance`指针即可。
|
||||
|
||||
若要发送数据,调用`USARTSend()`。注意buffsize务必小于buff的大小,否则造成指针越界后果未知。
|
||||
若要发送数据,调用`USARTSend()`。注意buffsize务必小于你创建的buff的大小,否则造成指针越界后果未知。
|
||||
|
||||
串口硬件收到数据时,会将其存入`usart_instance.recv_buff[]`中,当收到完整一包数据,会调用设定的回调函数`module_callback`(即你提供的解析函数)。在此函数中,你可以通过`usart_instance.recv_buff[]`访问串口收到的数据。
|
||||
串口硬件收到数据时,会将其存入`usart_instance.recv_buff[]`中,当收到完整一包数据,会调用设定的回调函数`module_callback`(即你注册时提供的解析函数)。在此函数中,你可以通过`usart_instance.recv_buff[]`访问串口收到的数据。
|
||||
|
||||
## 代码结构
|
||||
|
||||
|
||||
@@ -11,16 +11,17 @@
|
||||
|
||||
#include "bsp_usb.h"
|
||||
#include "bsp_log.h"
|
||||
#include "bsp_dwt.h"
|
||||
|
||||
static uint8_t *bsp_usb_rx_buffer; // 接收到的数据会被放在这里,buffer size为2048
|
||||
// 注意usb单个数据包(Full speed模式下)最大为64byte,超出可能会出现丢包情况
|
||||
|
||||
uint8_t *USBInit(USB_Init_Config_s usb_conf)
|
||||
{
|
||||
// 上电后重新枚举usb设备
|
||||
LOGINFO("USB init success");
|
||||
// usb的软件复位(模拟拔插)在usbd_conf.c中的HAL_PCD_MspInit()中
|
||||
bsp_usb_rx_buffer = CDCInitRxbufferNcallback(usb_conf.tx_cbk, usb_conf.rx_cbk); // 获取接收数据指针
|
||||
// usb的接收回调函数会在这里被设置,并将数据保存在bsp_usb_rx_buffer中
|
||||
LOGINFO("USB init success");
|
||||
return bsp_usb_rx_buffer;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user