增加了等级日志和RTT viewer的支持

This commit is contained in:
NeoZng 2023-03-18 20:36:21 +08:00
parent 68ac340c5a
commit 6f7bf8e9d7
9 changed files with 110 additions and 19 deletions

1
.vscode/launch.json vendored
View File

@ -35,6 +35,7 @@
"servertype": "jlink",
"interface": "swd",
"svdFile": "STM32F407.svd",
"rtos": "FreeRTOS",
// "preLaunchTask": "build task",//Build,使
},
],

7
.vscode/tasks.json vendored
View File

@ -30,5 +30,12 @@
"isDefault": false,
}
},
{
"label": "log",
"type": "shell",
"command":"JlinkRTTClient",
"args": [],
"problemMatcher": [],
}
]
}

View File

@ -8,7 +8,6 @@
>
> 1. 添加一键编译+启用ozone调试脚本使得整个进一步流程自动化
> 2. 增加更多的背景知识介绍
> 3. 增加VSCode下RTT viewer的支持
@ -481,6 +480,12 @@ VSCode `ctrl+,`进入设置,通过`搜索`找到cortex-debug插件的设置。
### RTT Viewer日志功能
本框架添加了vscode下Segger RTT client的支持。在`.vscode/task.json`中已经添加了启动rtt viewer client的任务。你也可以将此任务作为附加启动任务和调试一起启动方便查看日志。要使用日志请包含`bsp_log.h`。注意需要将jlink的安装目录添加到环境变量中。
### 更好的编辑体验
建议安装以下插件:

View File

@ -15,7 +15,7 @@ int PrintLog(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
int n = SEGGER_RTT_vprintf(BUFFER_INDEX, fmt, &args);
int n = SEGGER_RTT_vprintf(BUFFER_INDEX, fmt, &args); // 一次可以开启多个buffer(多个终端),我们只用一个
va_end(args);
return n;
}
@ -31,4 +31,5 @@ void Float2Str(char *str, float va)
sprintf(str, "-%d.%d", head, point);
else
sprintf(str, "%d.%d", head, point);
}
}

View File

@ -2,17 +2,34 @@
#define _BSP_LOG_H
/**
* @brief ,
* @brief ,LOGI,LOGW,LOGE等使
*
*/
void BSPLogInit();
#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(format,...) LOG_PROTO("","",format,##__VA_ARGS__)
/* 有颜色格式日志输出 */
#define LOGINFO(format,...) LOG_PROTO("I: ", RTT_CTRL_TEXT_BRIGHT_GREEN , format, ##__VA_ARGS__)
#define LOGWARNING(format,...) LOG_PROTO("W: ", RTT_CTRL_TEXT_BRIGHT_YELLOW, format, ##__VA_ARGS__)
#define LOGERROR(format,...) LOG_PROTO("E: ", RTT_CTRL_TEXT_BRIGHT_RED , format, ##__VA_ARGS__)
/**
* @brief segger RTT打印日志,,printf
*
* @param fmt
* @param ...
* @return int
* @param fmt
* @param ...
* @return int log字符数
*/
int PrintLog(const char *fmt, ...);

View File

@ -25,7 +25,7 @@ static USARTInstance *usart_instance[DEVICE_USART_CNT] = {NULL};
*
* @param _instance instance owned by module,
*/
static void USARTServiceInit(USARTInstance *_instance)
void USARTServiceInit(USARTInstance *_instance)
{
HAL_UARTEx_ReceiveToIdle_DMA(_instance->usart_handle, _instance->recv_buff, _instance->recv_buff_size);
// 关闭dma half transfer中断防止两次进入HAL_UARTEx_RxEventCallback()
@ -67,11 +67,24 @@ void USARTSend(USARTInstance *_instance, uint8_t *send_buf, uint16_t send_size,
break;
default:
while (1)
; // illegal mode! check your code context!
; // illegal mode! check your code context! 检查定义instance的代码上下文,可能出现指针越界
break;
}
}
/* 串口发送时,gstate会被设为BUSY_TX */
uint8_t USARTIsReady(USARTInstance *_instance)
{
if(_instance->usart_handle->gState | HAL_UART_STATE_BUSY_TX)
{
return 0;
}
else
{
return 1;
}
}
/**
* @brief dma/idle中断发生时.uart实例会调用对应的回调进行进一步的处理
* ://

View File

@ -10,6 +10,7 @@
// 模块回调函数,用于解析协议
typedef void (*usart_module_callback)();
/* 发送模式枚举 */
typedef enum
{
USART_TRANSFER_NONE=0,
@ -37,17 +38,25 @@ typedef struct
} USART_Init_Config_s;
/**
* @brief .
* @brief ,
*
* @param init_config
*/
USARTInstance *USARTRegister(USART_Init_Config_s *init_config);
/**
* @brief ,usart实例.lost callback的情况(使daemon)
*
* @param _instance
*/
void USARTServiceInit(USARTInstance *_instance);
/**
* @brief ,usart实例,buff以及这一帧的长度
* DMA发送,
* @todo DMA发送,
* ,
* @note ,IT/DMA会导致上一次的发送未完成而新的发送取消.
* @note 使DMA/IT进行发送,USARTIsReady()使,module实现一个发送队列和任务.
* @todo USARTInstance增加发送队列以进行连续发送?
*
* @param _instance
* @param send_buf buffer
@ -55,4 +64,12 @@ USARTInstance *USARTRegister(USART_Init_Config_s *init_config);
*/
void USARTSend(USARTInstance *_instance, uint8_t *send_buf, uint16_t send_size,USART_TRANSFER_MODE mode);
/**
* @brief ,IT/DMA发送
*
* @param _instance
* @return uint8_t ready 1, busy 0
*/
uint8_t USARTIsReady(USARTInstance *_instance);
#endif

View File

@ -12,12 +12,15 @@
#include "bsp_usart.h"
#include "usart.h"
#include "seasky_protocol.h"
#include "daemon.h"
#include "bsp_log.h"
static Vision_Recv_s recv_data;
// @todo:由于后续需要进行IMU-Cam的硬件触发采集控制,因此可能需要将发送设置为定时任务,或由IMU采集完成产生的中断唤醒的任务,
// 后者显然更nice,使得时间戳对齐. 因此,在send_data中设定其他的标志位数据,让ins_task填充姿态值.
// static Vision_Send_s send_data;
static USARTInstance *vision_usart_instance;
static DaemonInstance *vision_daemon_instance;
/**
* @brief ,bsp_usart.c中被usart rx callback调用
@ -27,8 +30,23 @@ static USARTInstance *vision_usart_instance;
static void DecodeVision()
{
static uint16_t flag_register;
DaemonReload(vision_daemon_instance); // 喂狗
get_protocol_info(vision_usart_instance->recv_buff, &flag_register, (uint8_t *)&recv_data.pitch);
// TODO: code to resolve flag_register;
PrintLog("decode vision");
}
/**
* @brief 线,daemon.c中被daemon task调用
* @attention HAL库的设计问题,DMA接收之后同时发送有概率出现__HAL_LOCK(),使
* .daemon判断数据更新,.
*
* @param id vision_usart_instance的地址,.
*/
static void VisionOfflineCallback(void *id)
{
USARTServiceInit(vision_usart_instance);
}
/* 视觉通信初始化 */
@ -38,8 +56,16 @@ Vision_Recv_s *VisionInit(UART_HandleTypeDef *_handle)
conf.module_callback = DecodeVision;
conf.recv_buff_size = VISION_RECV_SIZE;
conf.usart_handle = _handle;
vision_usart_instance = USARTRegister(&conf);
// 为master process注册daemon,用于判断视觉通信是否离线
Daemon_Init_Config_s daemon_conf = {
.callback = VisionOfflineCallback, // 离线时调用的回调函数,会重启串口接收
.owner_id = vision_usart_instance,
.reload_count = 10,
};
vision_daemon_instance = DaemonRegister(&daemon_conf);
return &recv_data;
}
@ -58,11 +84,11 @@ void VisionSend(Vision_Send_s *send)
static uint8_t send_buff[VISION_SEND_SIZE];
static uint16_t tx_len;
// TODO: code to set flag_register
// 将数据转化为seasky协议的数据包
get_protocol_send_data(0x02, flag_register, &send->yaw, 3, send_buff, &tx_len);
USARTSend(vision_usart_instance, send_buff, tx_len,USART_TRANSFER_IT); // 和视觉通信使用IT,防止和接收使用的DMA冲突
USARTSend(vision_usart_instance, send_buff, tx_len, USART_TRANSFER_DMA); // 和视觉通信使用IT,防止和接收使用的DMA冲突
// 此处为HAL设计的缺陷,DMASTOP会停止发送和接收,导致再也无法进入接收中断.
// 也可在发送完成中断中重新启动DMA接收,但较为复杂.因此,此处使用IT发送.
// 若使用了daemon,则也可以使用DMA发送.
}

View File

@ -7,6 +7,10 @@
> 1. 给不同的电机设置不同的低通滤波器惯性系数而不是统一使用宏
> 2. 为M2006和M3508增加开环的零位校准函数
---
> 建议将电机的反馈频率通过RoboMaster Assistant统一设置为500Hz。当前默认的`MotorTask()`执行频率为500Hz若不修改电机反馈频率可能导致单条总线挂载的电机数量有限且容易出现帧错误和仲裁失败的情况。
## 总览和封装说明
> 如果你不需要理解该模块的工作原理,你只需要查看这一小节。
@ -19,7 +23,7 @@ dji_motor模块对DJI智能电机包括M2006M3508以及GM6020进行了详
2. ==速度环为角速度,单位为**度/每秒**deg/sec==
3. ==电流环为mA==
3. ==电流环为A==
4. ==GM6020的输入设定为**力矩**,待测量(-30000~30000==