第一次提交
This commit is contained in:
1289
app_cail/app_calibration.c
Normal file
1289
app_cail/app_calibration.c
Normal file
File diff suppressed because it is too large
Load Diff
231
app_cail/app_calibration.h
Normal file
231
app_cail/app_calibration.h
Normal file
@@ -0,0 +1,231 @@
|
||||
#ifndef __APP_CALIBRATION_H
|
||||
#define __APP_CALIBRATION_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mx_log.h"
|
||||
#include "resi_math_lib.h"
|
||||
#include "mozen_protocol.h"
|
||||
#include "cali_process.h"
|
||||
|
||||
#include "main.h"
|
||||
//#include "bsp_config.h"
|
||||
|
||||
/****************************<2A><>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD> <20><>********************************/
|
||||
|
||||
//<2F><><EFBFBD><EFBFBD>Ŀ<EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д
|
||||
#define MT_AX_NUM (AX_NUM)
|
||||
#define MT_AY_NUM (AY_NUM)
|
||||
|
||||
#ifdef CALI_POINT_NUM
|
||||
#undef CALI_POINT_NUM
|
||||
#endif
|
||||
#define CALI_POINT_NUM (3) //<2F>궨<EFBFBD><EAB6A8>λ<EFBFBD><CEBB><EFBFBD><EFBFBD>
|
||||
|
||||
#ifdef MAX_PRESSURE_POINTS
|
||||
#undef MAX_PRESSURE_POINTS
|
||||
#endif
|
||||
#define MAX_PRESSURE_POINTS CALI_POINT_NUM
|
||||
|
||||
//δ<><CEB4><EFBFBD>б궨ǰ<EAB6A8><C7B0><EFBFBD>㷨<EFBFBD><E3B7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD>ϲ<EFBFBD><CFB2><EFBFBD>
|
||||
#define DEFAULT_MIN_TRIGGER_RES_VALUE (1000)
|
||||
#define DEFAULT_MAX_TRIGGER_RES_VALUE (10000)
|
||||
#define DEFAULT_DIV_TRIGGER_RES_VALUE (1300) // <20><><EFBFBD>ݾ<EFBFBD><DDBE><EFBFBD><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF>Ӳ<EFBFBD><D3B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5>д
|
||||
#define DEFAULT_MAX_DISPLAY_VALUE (255) // (255U)
|
||||
|
||||
/****************************<2A><>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD> <20><> ********************************/
|
||||
|
||||
#define MAX_DISPLAY_ADC_VALUE (4096) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾֵ
|
||||
|
||||
#ifndef APP_CALI_USE_PROJECT_RUNTIME_FLAGS
|
||||
#define APP_CALI_USE_PROJECT_RUNTIME_FLAGS 1U //<2F>Ƿ<EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>־ (0:<3A><>ʹ<EFBFBD><CAB9> 1:ʹ<><CAB9>)
|
||||
#endif
|
||||
|
||||
#ifndef APP_CALI_ENABLE_LEGACY_API
|
||||
#define APP_CALI_ENABLE_LEGACY_API 0U //<2F>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>þɰ<C3BE>API (0:<3A><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1:<3A><><EFBFBD><EFBFBD>)
|
||||
#endif
|
||||
|
||||
#define APP_MATH_PARAM_FRAME_SIZE 8U //<2F>㷨<EFBFBD><E3B7A8>ѧ<EFBFBD><D1A7><EFBFBD><EFBFBD>֡<EFBFBD><D6A1>С
|
||||
#define APP_MAP_MATRIX_WORDS ((uint32_t)MT_AX_NUM * (uint32_t)MT_AY_NUM * (uint32_t)CALI_POINT_NUM) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
#define APP_MAP_MATRIX_BYTES (APP_MAP_MATRIX_WORDS * sizeof(uint16_t)) //<2F><><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> * 2)
|
||||
#define APP_SENSOR_FRAME_PAYLOAD_MAX_BYTES (1U + ((uint32_t)MT_AX_NUM * (uint32_t)MT_AY_NUM * sizeof(uint16_t))) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֡<EFBFBD><D6A1><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
|
||||
#define APP_CALI_STATUS_UNCALIBRATED 0x0000U // δ<>궨״̬
|
||||
#define APP_CALI_STATUS_CALIBRATED 0xA55AU // <20>ѱ궨״̬
|
||||
|
||||
// <20>豸<EFBFBD><E8B1B8>ϢSN
|
||||
#define DEFAULT_PN "JJ009"
|
||||
#define DEFAULT_SN "FA0060G1A7100001"
|
||||
#define DEFAULT_SW_VER "V1.0.1"
|
||||
#define DEFAULT_HW_VER "V1.0_20250627"
|
||||
|
||||
#define APP_DEVICE_PROTOCOL_VER "V1.0" // Protocol Version
|
||||
|
||||
//У<D0A3><D7BC><EFBFBD>ݽṹ
|
||||
typedef struct _app_math_cali_t
|
||||
{
|
||||
uint16_t check_cail; // У<><D0A3>ֵ
|
||||
uint16_t sensor_data_type; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
uint16_t min_trigger_res_value; // <20><>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
|
||||
uint16_t max_trigger_res_value; // <20><><EFBFBD><EFBFBD><F3B4A5B7><EFBFBD><EFBFBD><EFBFBD>ֵ
|
||||
uint16_t div_trigger_res_value; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD>
|
||||
uint16_t max_display_value; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾֵ
|
||||
uint16_t num_points; // <20>궨<EFBFBD><EAB6A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
uint16_t pressure_points[MAX_PRESSURE_POINTS]; // <20>궨<EFBFBD><EAB6A8>ѹ<EFBFBD><D1B9>ֵ
|
||||
} app_math_cali_t;
|
||||
|
||||
typedef struct _app_creep_params
|
||||
{
|
||||
uint8_t creep_strength;
|
||||
uint8_t creep_level;
|
||||
}app_creep_params;
|
||||
|
||||
|
||||
typedef struct _app_device_info
|
||||
{
|
||||
uint8_t pn[33]; // <20>ͺŴ洢
|
||||
char sn[17]; // <20><><EFBFBD>кŴ洢
|
||||
uint8_t sw_ver[sizeof(DEFAULT_SW_VER)+1]; // <20><><EFBFBD><EFBFBD><EFBFBD>汾<EFBFBD>洢
|
||||
uint8_t hw_ver[sizeof(DEFAULT_HW_VER)+1]; // Ӳ<><D3B2><EFBFBD>汾<EFBFBD>洢
|
||||
uint8_t sensor_size[10]; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD>
|
||||
uint8_t protocol_ver[10]; // Э<><D0AD><EFBFBD>汾<EFBFBD>洢
|
||||
} app_dev_info;
|
||||
|
||||
typedef struct {
|
||||
uint16_t max_cal;
|
||||
uint16_t min_cal;
|
||||
uint16_t ref_value;
|
||||
uint16_t adc_max;
|
||||
uint16_t max_display;
|
||||
} app_legacy_math_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t creep_strength;
|
||||
uint8_t creep_level;
|
||||
} app_legacy_creep_t;
|
||||
|
||||
// <20>豸״̬ old
|
||||
typedef struct
|
||||
{
|
||||
uint8_t led_sw;
|
||||
uint8_t sensor_tx_sw;
|
||||
uint8_t tx_stopping;
|
||||
uint8_t output_pick;
|
||||
} app_device_status_t;
|
||||
|
||||
/* Compatibility typedefs after merge */
|
||||
typedef app_math_cali_t app_math_params_t;
|
||||
typedef app_math_cali_t pressure_params_t;
|
||||
|
||||
extern volatile bool g_check_cali ;
|
||||
extern volatile bool g_reset_takeEffect ;
|
||||
extern volatile bool g_is_active_reporting;
|
||||
extern pressure_params_t* pressure_params;
|
||||
extern volatile bool g_is_creep_enable ;
|
||||
|
||||
/* Algorithm (math) parameter interfaces */
|
||||
uint8_t app_math_init(uint16_t *min_trigger_res_value,
|
||||
uint16_t *max_trigger_res_value,
|
||||
uint16_t *div_trigger_res_value,
|
||||
uint16_t *max_display_value,uint16_t *sensor_data_type);
|
||||
uint8_t app_math_get_temp_params(app_math_cali_t *out_params);
|
||||
uint8_t app_math_set_temp_params(const app_math_cali_t *params);
|
||||
|
||||
uint8_t app_math_write_temp_params(const uint8_t *data, uint16_t len);
|
||||
uint8_t app_math_save_params(const uint8_t *data, uint16_t len);
|
||||
uint8_t app_math_clear_params(void);
|
||||
uint8_t app_math_read_temp_params(uint8_t *response_buf, uint16_t *response_len);
|
||||
uint8_t app_math_read_solidified_params(uint8_t *response_buf, uint16_t *response_len);
|
||||
|
||||
/* Pressure parameter interfaces */
|
||||
pressure_params_t *app_pressure_init(void);
|
||||
uint8_t app_pressure_write_temp_params(const uint8_t *data, uint16_t len);
|
||||
uint8_t app_pressure_read_temp_params(uint8_t *response_buf, uint16_t *response_len);
|
||||
uint8_t app_pressure_save_params(const uint8_t *data, uint16_t len);
|
||||
uint8_t app_pressure_read_solidified_params(uint8_t *response_buf, uint16_t *response_len);
|
||||
uint8_t app_pressure_clear_params(void);
|
||||
|
||||
/* N-point map interfaces */
|
||||
uint8_t app_map_init(void);
|
||||
uint8_t app_map_write_temp_params(const uint8_t *data, uint16_t len);
|
||||
uint8_t app_map_save_params(const uint8_t *data, uint16_t len);
|
||||
uint8_t app_map_clear_params(void);
|
||||
uint8_t app_map_read_temp_params(uint8_t *response_buf, uint16_t *response_len);
|
||||
uint8_t *app_map_data_ptr(void);
|
||||
uint32_t app_map_data_size(void);
|
||||
|
||||
/* Creep parameter interfaces */
|
||||
uint8_t app_creep_write_temp_params(app_creep_params *creep_params);
|
||||
uint8_t app_creep_save_params(app_creep_params *creep_params);
|
||||
uint8_t app_creep_read_params(app_creep_params *creep_params);
|
||||
uint8_t app_creep_clear_params(void);
|
||||
|
||||
/* Device information interfaces */
|
||||
uint8_t app_device_get_info(app_dev_info *dev_info);
|
||||
uint8_t app_device_set_info(const app_dev_info *dev_info);
|
||||
|
||||
/* Legacy device status interfaces */
|
||||
app_device_status_t* app_device_status_get(void);
|
||||
void app_device_status_set(const app_device_status_t *status);
|
||||
void app_device_status_init(void);
|
||||
|
||||
/* Runtime state hooks for protocol layer */
|
||||
void app_calibration_invalidate_runtime(void);
|
||||
void app_calibration_request_reset_effect(void);
|
||||
uint8_t app_calibration_check(void);
|
||||
uint8_t app_calibration_get_cail_status(void);
|
||||
uint8_t app_calibration_set(uint8_t calibrated);
|
||||
|
||||
/* Forward declaration for flash operations */
|
||||
struct flash_port_ops_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the calibration module and underlying flash port.
|
||||
* @param flash_ops Pointer to flash operations mapping.
|
||||
*/
|
||||
void app_calibration_init(const struct flash_port_ops_t *flash_ops);
|
||||
|
||||
void app_calibration_reset_init(void);
|
||||
|
||||
/**
|
||||
* @brief Process raw 16-bit sensor data against calibration map
|
||||
* @param in_raw_data Input raw sensor data matrix (MT_AX_NUM x MT_AY_NUM)
|
||||
* @param out_cali_data Output buffer to store processed data
|
||||
* @return 1 on success, 0 on invalid parameters
|
||||
*/
|
||||
void process_calibration_frame(const uint16_t in_raw_data[MT_AX_NUM][MT_AY_NUM],
|
||||
uint16_t out_cali_data[MT_AX_NUM][MT_AY_NUM]);
|
||||
|
||||
uint8_t send_sensor_frame_8bit(const uint8_t (*sensor_data)[MT_AY_NUM]);
|
||||
uint8_t send_sensor_frame_16bit(const uint16_t (*sensor_data)[MT_AY_NUM]);
|
||||
|
||||
uint8_t app_calibration_build_sensor8bit_payload(const uint8_t (*sensor_data)[MT_AY_NUM],
|
||||
uint8_t *payload,
|
||||
uint16_t payload_size,
|
||||
uint16_t *payload_len);
|
||||
uint8_t app_calibration_build_sensor16bit_payload(const uint16_t (*sensor_data)[MT_AY_NUM],
|
||||
uint8_t *payload,
|
||||
uint16_t payload_size,
|
||||
uint16_t *payload_len);
|
||||
|
||||
/* Legacy compatibility interfaces */
|
||||
#if APP_CALI_ENABLE_LEGACY_API
|
||||
uint8_t array_resi_params_write(const uint8_t *data, uint16_t len);
|
||||
uint8_t array_resi_params_save(const uint8_t *data, uint16_t len);
|
||||
uint8_t clear_array_init_info(void);
|
||||
uint8_t return_array_resi_init_info(uint8_t *response_buf, uint16_t *response_len);
|
||||
uint8_t return_flash_array_resi_init_info(uint8_t *response_buf, uint16_t *response_len);
|
||||
|
||||
pressure_params_t *init_pressure_params(void);
|
||||
uint8_t write_temp_pressure_params(const uint8_t *data, uint16_t len);
|
||||
uint8_t read_temp_pressure_params(uint8_t *response_buf, uint16_t *response_len);
|
||||
uint8_t write_solidified_pressure_params(const uint8_t *data, uint16_t len);
|
||||
uint8_t read_solidified_pressure_params(uint8_t *response_buf, uint16_t *response_len);
|
||||
uint8_t clear_pressure_params_from_flash(void);
|
||||
|
||||
void write_cali_params_to_ram(const uint8_t *data, uint16_t len);
|
||||
uint8_t save_cali_params_to_flash(const uint8_t *data, uint16_t len);
|
||||
uint8_t clear_cali_params_from_flash(void);
|
||||
uint8_t read_cali_params_from_ram(uint8_t *response_buf, uint16_t *response_len);
|
||||
#endif
|
||||
|
||||
#endif /* __APP_CALIBRATION_H */
|
||||
83
app_cail/demo_main.c
Normal file
83
app_cail/demo_main.c
Normal file
@@ -0,0 +1,83 @@
|
||||
#include "app_calibration.h"
|
||||
#include "mx_log.h"
|
||||
|
||||
/* 最简移植模板*/
|
||||
|
||||
// 接收上位机下发的数据处理函数
|
||||
void process_rx(void)
|
||||
{
|
||||
uint8_t rx_chunk[64];
|
||||
uint16_t recv_len = 0;
|
||||
|
||||
//如果是串口通信,则在串口接收到数据的地方,调用mozen_protocol_receive_byte 喂入字节流
|
||||
//recv_len = usart_rx_recv(USART_3_TR, rx_chunk, sizeof(rx_chunk));
|
||||
|
||||
//如果是usb cdc 通信,则在usb cdc 接收到数据的地方,调用mozen_protocol_receive_byte 喂入字节流
|
||||
//recv_len = usbcdc_rx_recv(rx_chunk, sizeof(rx_chunk));
|
||||
|
||||
for(uint16_t i = 0; i < recv_len; i++) {
|
||||
mozen_protocol_receive_byte(rx_chunk[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//新协议需要调用的发送函数,需要外部自己实现一下函数定义
|
||||
static int mozen_tx(const uint8_t *frame, uint16_t len)
|
||||
{
|
||||
if ((frame == NULL) || (len == 0U)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
//这里替换具体项目平台的发送函数,例如:
|
||||
// usart_dma_send_data(USART_0_TR, (uint8_t *)frame, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t adc_channel_cache[AX_BUF_NUM];
|
||||
uint16_t g_sensor_raw_value[AX_NUM];
|
||||
uint16_t g_sensor_ref_value[AX_NUM];
|
||||
uint16_t sensor1_resi_output[AX_NUM];
|
||||
uint16_t sensor1_display_output[AX_NUM];
|
||||
uint16_t sensor1_voltage[AX_NUM][AY_NUM];
|
||||
} Hc4051AdcValue;
|
||||
Hc4051AdcValue temp_adc_value;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
//项目中的外设初始化
|
||||
//...
|
||||
|
||||
/*Step 1 */
|
||||
//把这三个函数放在外设初始化之后,然后设置一下发送回调,
|
||||
mozen_protocol_set_tx(mozen_tx);
|
||||
mozen_protocol_init();
|
||||
app_calibration_reset_init();
|
||||
|
||||
uint16_t count_ay = 0;
|
||||
|
||||
while(1)
|
||||
{
|
||||
|
||||
/*Step 2 处理上位机下发的数据,内部调用mozen_protocol_receive_byte会解析协议 */
|
||||
process_rx();
|
||||
|
||||
scan_y(&temp_adc_value, count_ay); // scan_y 就是熟悉的正扫反扫的函数
|
||||
count_ay++;
|
||||
if (count_ay >= AY_NUM) { //扫完一帧
|
||||
count_ay = 0;
|
||||
|
||||
/*Step 3 将原始帧数据传入,返回标定后二维结果。 */
|
||||
uint16_t (*cailed_sensor_data)[MT_AY_NUM];
|
||||
cailed_sensor_data = process_calibration_frame(temp_adc_value.sensor1_voltage);
|
||||
|
||||
// 预留给外部算法扩展: 可在此处继续处理 cailed_sensor_data 比如拿到cailed_sensor_data 做抗蠕变等其他算法
|
||||
//...
|
||||
|
||||
//发走
|
||||
send_sensor_frame(cailed_sensor_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
156
app_cail/lib_math_cail/cali_process.c
Normal file
156
app_cail/lib_math_cail/cali_process.c
Normal file
@@ -0,0 +1,156 @@
|
||||
#include "cali_process.h"
|
||||
|
||||
//ʵ<><CAB5>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD>ʹ<EFBFBD><CAB9><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD>ֵ<EFBFBD><D6B5>ʽ y = y1 + (x-x1)*(y2-y1)/(x2-x1)
|
||||
uint16_t linear_fuction_double_byte(uint16_t x, uint16_t x1, uint16_t x2, uint16_t y1, uint16_t y2)
|
||||
{
|
||||
uint16_t y = 0;
|
||||
uint32_t cal_y = 0;
|
||||
if(x2==x1) return y1;
|
||||
|
||||
if(x >= x1)
|
||||
{
|
||||
cal_y = (uint32_t)(x - x1) * (uint32_t)(y2 - y1) / (uint32_t)(x2 - x1) + y1;
|
||||
if(cal_y > UINT16_MAX)
|
||||
{
|
||||
cal_y = UINT16_MAX;
|
||||
}
|
||||
y = (uint16_t)cal_y;
|
||||
return y;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t linear_fuction_single_byte(uint16_t x, uint16_t x1, uint16_t x2, uint8_t y1, uint8_t y2)
|
||||
{
|
||||
uint8_t y = 0;
|
||||
uint32_t cal_y = 0;
|
||||
if(x2==x1) return y1;
|
||||
|
||||
if(x >= x1)
|
||||
{
|
||||
cal_y = (uint32_t)(x - x1) * (uint32_t)(y2 - y1) / (uint32_t)(x2 - x1) + y1;
|
||||
if(cal_y > UINT8_MAX)
|
||||
{
|
||||
cal_y = UINT8_MAX;
|
||||
}
|
||||
y = (uint8_t)cal_y;
|
||||
return y;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void math_resi_cali(uint16_t *raw_value, CALI_INFO_T *cali_info, void *processed_value, uint16_t math_cali_buffer_size)
|
||||
{
|
||||
uint8_t *processed_value_single_pointer = NULL;
|
||||
uint16_t *processed_value_double_pointer = NULL;
|
||||
|
||||
if(cali_info->cali_pressure_num < 2 || raw_value == NULL || cali_info == NULL || processed_value ==NULL || math_cali_buffer_size == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch(cali_info->cali_data_out_bit_size)
|
||||
{
|
||||
case UINT8_SINGLE:
|
||||
processed_value_single_pointer = (uint8_t*)processed_value;
|
||||
for(uint16_t count = 0; count < math_cali_buffer_size; ++count)
|
||||
{
|
||||
uint16_t min_press_idx = count;
|
||||
uint16_t max_press_idx = count + (cali_info->cali_pressure_num - 1) * math_cali_buffer_size;
|
||||
|
||||
if(raw_value[count] > cali_info->cali_params[max_press_idx])
|
||||
raw_value[count] = cali_info->cali_params[max_press_idx];
|
||||
if(raw_value[count] < cali_info->cali_params[min_press_idx])
|
||||
raw_value[count] = cali_info->cali_params[min_press_idx];
|
||||
|
||||
uint8_t found_flag = 0;
|
||||
for(uint8_t press_idx = 0; press_idx < cali_info->cali_pressure_num-1; ++press_idx)
|
||||
{
|
||||
uint16_t current_press_idx = count + press_idx * math_cali_buffer_size;
|
||||
uint16_t next_press_idx = count + (press_idx + 1) * math_cali_buffer_size;
|
||||
|
||||
if(raw_value[count] >= cali_info->cali_params[current_press_idx] && raw_value[count] <= cali_info->cali_params[next_press_idx])
|
||||
{
|
||||
if(raw_value[count] == cali_info->cali_params[current_press_idx]) {
|
||||
processed_value_single_pointer[count] = cali_info->real_pressure_value[press_idx];
|
||||
}
|
||||
else if(raw_value[count] == cali_info->cali_params[next_press_idx]) {
|
||||
processed_value_single_pointer[count] = cali_info->real_pressure_value[press_idx + 1];
|
||||
}
|
||||
else {
|
||||
processed_value_single_pointer[count] = linear_fuction_single_byte(
|
||||
raw_value[count],
|
||||
cali_info->cali_params[current_press_idx],
|
||||
cali_info->cali_params[next_press_idx],
|
||||
cali_info->real_pressure_value[press_idx],
|
||||
cali_info->real_pressure_value[press_idx + 1]);
|
||||
}
|
||||
found_flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found_flag)
|
||||
{
|
||||
processed_value_single_pointer[count] = cali_info->real_pressure_value[0];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case UINT16_DOUBLE:
|
||||
processed_value_double_pointer = (uint16_t*)processed_value;
|
||||
for(uint16_t count = 0; count < math_cali_buffer_size; ++count)
|
||||
{
|
||||
uint16_t min_press_idx = count;
|
||||
uint16_t max_press_idx = count + (cali_info->cali_pressure_num - 1) * math_cali_buffer_size;
|
||||
|
||||
if(raw_value[count] > cali_info->cali_params[max_press_idx])
|
||||
raw_value[count] = cali_info->cali_params[max_press_idx];
|
||||
if(raw_value[count] < cali_info->cali_params[min_press_idx])
|
||||
raw_value[count] = cali_info->cali_params[min_press_idx];
|
||||
|
||||
uint8_t found_flag = 0;
|
||||
for(uint8_t press_idx = 0; press_idx < cali_info->cali_pressure_num-1; ++press_idx)
|
||||
{
|
||||
uint16_t current_press_idx = count + press_idx * math_cali_buffer_size;
|
||||
uint16_t next_press_idx = count + (press_idx + 1) * math_cali_buffer_size;
|
||||
|
||||
if(raw_value[count] >= cali_info->cali_params[current_press_idx] && raw_value[count] <= cali_info->cali_params[next_press_idx])
|
||||
{
|
||||
if(raw_value[count] == cali_info->cali_params[current_press_idx]) {
|
||||
processed_value_double_pointer[count] = cali_info->real_pressure_value[press_idx];
|
||||
}
|
||||
else if(raw_value[count] == cali_info->cali_params[next_press_idx]) {
|
||||
processed_value_double_pointer[count] = cali_info->real_pressure_value[press_idx + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
processed_value_double_pointer[count] = linear_fuction_double_byte(
|
||||
raw_value[count],
|
||||
cali_info->cali_params[current_press_idx],
|
||||
cali_info->cali_params[next_press_idx],
|
||||
cali_info->real_pressure_value[press_idx],
|
||||
cali_info->real_pressure_value[press_idx + 1]);
|
||||
}
|
||||
found_flag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found_flag)
|
||||
{
|
||||
processed_value_double_pointer[count] = cali_info->real_pressure_value[0];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
26
app_cail/lib_math_cail/cali_process.h
Normal file
26
app_cail/lib_math_cail/cali_process.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _CALI_PROCESS_H
|
||||
#define _CALI_PROCESS_H
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef enum{
|
||||
UINT8_SINGLE,
|
||||
UINT16_DOUBLE
|
||||
} OUT_DATA_BIT_SIZE_T;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct{
|
||||
uint16_t *real_pressure_value;
|
||||
uint16_t *cali_params;
|
||||
uint8_t cali_pressure_num;
|
||||
OUT_DATA_BIT_SIZE_T cali_data_out_bit_size;
|
||||
} CALI_INFO_T;
|
||||
#pragma pack()
|
||||
|
||||
|
||||
void math_resi_cali(uint16_t *raw_value, CALI_INFO_T *cali_info, void *processed_value, uint16_t math_cali_buffer_size);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
754
app_cail/moxzen_protocol/app_mozen_handler.c
Normal file
754
app_cail/moxzen_protocol/app_mozen_handler.c
Normal file
@@ -0,0 +1,754 @@
|
||||
#include "app_mozen_handler.h"
|
||||
#include "mozen_tunnel.h"
|
||||
#include "mx_log.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "app_calibration.h"
|
||||
#include "main.h"
|
||||
#include "cJSON.h"
|
||||
|
||||
// Define logs if not using MX_LOG directly
|
||||
#ifndef MX_LOGD
|
||||
#define MX_LOGD MOZEN_LOGD
|
||||
#define MX_LOGI MOZEN_LOGI
|
||||
#define MX_LOGW MOZEN_LOGW
|
||||
#define MX_LOGE MOZEN_LOGE
|
||||
#endif
|
||||
|
||||
#define MX_PTO_TAG "MOZEN_APP"
|
||||
|
||||
volatile uint16_t g_sensor_frames_to_send = 0;
|
||||
volatile uint8_t g_sensor_data_type = SENSOR_BIT_16;
|
||||
|
||||
static mozen_protocol_t *s_prot_instance = NULL;
|
||||
static mozen_tunnel_t s_tunnel_instance;
|
||||
|
||||
// --- Tunnel Stream State ---
|
||||
static struct
|
||||
{
|
||||
bool is_streaming_write;
|
||||
uint8_t* write_ptr;
|
||||
uint8_t target_cmd;
|
||||
uint8_t target_sub_class;
|
||||
} s_stream_state;
|
||||
|
||||
// --- Response Utilities ---
|
||||
#pragma pack(1)
|
||||
typedef struct
|
||||
{
|
||||
uint8_t target_id;
|
||||
uint8_t sub_class;
|
||||
uint8_t operation;
|
||||
} mozen_cmd_header_t;
|
||||
#pragma pack()
|
||||
|
||||
typedef void (*cmd_sub_handler_t)(const mozen_cmd_header_t* header, const uint8_t* payload, uint16_t payload_len);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t target_id;
|
||||
cmd_sub_handler_t handler;
|
||||
} cmd_handler_entry_t;
|
||||
|
||||
// --- Forward Declarations ---
|
||||
static void param_handle_report_mode(const mozen_cmd_header_t* header, const uint8_t* payload, uint16_t payload_len);
|
||||
static void param_handle_device_info(const mozen_cmd_header_t* header, const uint8_t* payload, uint16_t payload_len);
|
||||
static void param_handle_cali_display(const mozen_cmd_header_t* header, const uint8_t* payload, uint16_t payload_len);
|
||||
static void prod_handle_sys_cmd(const mozen_cmd_header_t* header, const uint8_t* payload, uint16_t payload_len);
|
||||
static void prod_handle_map_cali_cmd(const mozen_cmd_header_t* header, const uint8_t* payload, uint16_t payload_len);
|
||||
|
||||
// --- param setters ---
|
||||
static const cmd_handler_entry_t s_param_handlers[] =
|
||||
{
|
||||
{MOZEN_PARAM_TGT_REPORT_MODE, param_handle_report_mode}, // 0x01
|
||||
{MOZEN_PARAM_TGT_DEVICE_INFO, param_handle_device_info}, // 0x02
|
||||
{MOZEN_PARAM_TGT_CALI_DISPLAY, param_handle_cali_display}, // 0x03
|
||||
};
|
||||
|
||||
// --- Production Test Targets ---
|
||||
static const cmd_handler_entry_t s_prod_handlers[] =
|
||||
{
|
||||
{MOZEN_PROD_TGT_SYS, prod_handle_sys_cmd},
|
||||
{MOZEN_PROD_TGT_MAP_CALI, prod_handle_map_cali_cmd},
|
||||
};
|
||||
|
||||
// --- Init ---
|
||||
mozen_protocol_t g_mozen_prot; // Global mozen protocol instance
|
||||
#define RX_BUFFER_SIZE 1024 // RX buffer size
|
||||
#define TX_BUFFER_SIZE 1024 // TX buffer size
|
||||
static uint8_t s_rx_buf[RX_BUFFER_SIZE]; // RX buffer
|
||||
static uint8_t s_tx_buf_main[TX_BUFFER_SIZE]; // TX buffer
|
||||
static uint8_t s_tx_buf_irq[TX_BUFFER_SIZE]; // TX buffer
|
||||
|
||||
// --- Legacy Compatibility Functions ---
|
||||
static uint8_t is_legacy_config_payload(const uint8_t *data, uint16_t len)
|
||||
{
|
||||
if ((data == NULL) || (len < 3U)) return 0U;
|
||||
if ((data[0] != 0x3DU) && (data[0] != 0x3FU)) return 0U;
|
||||
if ((data[1] != '{') || (data[len - 1U] != '}')) return 0U;
|
||||
|
||||
return 1U;
|
||||
}
|
||||
|
||||
static int handle_old_protocol_device_status(uint8_t *data, uint16_t length)
|
||||
{
|
||||
if ((data == NULL) || (length < 2U)) return -1;
|
||||
|
||||
if (data[0] == 0x3D) // "=" <20><><EFBFBD>ò<EFBFBD><C3B2><EFBFBD>
|
||||
{
|
||||
cJSON *root = cJSON_Parse((char *)&data[1]);
|
||||
if (!root)
|
||||
{
|
||||
MX_LOGE(MX_PTO_TAG, "old protocol json parse failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
MX_LOGD(MX_PTO_TAG, "old protocol json parsed");
|
||||
|
||||
// 1. <20><>Ӧ<EFBFBD>ò<EFBFBD><C3B2><EFBFBD>ȡ<EFBFBD><C8A1>ǰ״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>и<EFBFBD><D0B8><EFBFBD>
|
||||
app_device_status_t new_status = *app_device_status_get();
|
||||
|
||||
// 2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>
|
||||
cJSON *led_sw = cJSON_GetObjectItem(root, "led_sw");
|
||||
if (led_sw) new_status.led_sw = (uint8_t)led_sw->valueint;
|
||||
|
||||
cJSON *tx_sw = cJSON_GetObjectItem(root, "tx_sw");
|
||||
if (tx_sw)
|
||||
{
|
||||
int tx_sw_val = tx_sw->valueint;
|
||||
if (new_status.sensor_tx_sw == 1 && tx_sw_val == 0)
|
||||
{
|
||||
new_status.tx_stopping = 1;
|
||||
}
|
||||
new_status.sensor_tx_sw = (uint8_t)tx_sw_val;
|
||||
}
|
||||
|
||||
cJSON *pick_sw = cJSON_GetObjectItem(root, "pick_sw");
|
||||
if (pick_sw) new_status.output_pick = (uint8_t)pick_sw->valueint;
|
||||
// printf("pick_sw: %d\n", new_status.output_pick);
|
||||
|
||||
// 3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѧ<EFBFBD>궨<EFBFBD><EAB6A8><EFBFBD><EFBFBD> (math / math_full)
|
||||
cJSON *math_arr = cJSON_GetObjectItem(root, "math");
|
||||
cJSON *extra_flag = cJSON_GetObjectItem(root, "math_full");
|
||||
|
||||
if (math_arr && cJSON_IsArray(math_arr))
|
||||
{
|
||||
int size = cJSON_GetArraySize(math_arr);
|
||||
app_math_cali_t temp_params;
|
||||
|
||||
if (app_math_get_temp_params(&temp_params))
|
||||
{
|
||||
if (size >= 1) {
|
||||
temp_params.max_trigger_res_value = (uint16_t)cJSON_GetArrayItem(math_arr, 0)->valueint;
|
||||
}
|
||||
if (size >= 2) {
|
||||
temp_params.min_trigger_res_value = (uint16_t)cJSON_GetArrayItem(math_arr, 1)->valueint;
|
||||
}
|
||||
|
||||
if (extra_flag && extra_flag->valueint && size >= 5) {
|
||||
temp_params.max_display_value = (uint16_t)cJSON_GetArrayItem(math_arr, 4)->valueint;
|
||||
}
|
||||
|
||||
app_math_set_temp_params(&temp_params);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
cJSON *creep_strength = cJSON_GetObjectItem(root, "creep_strength");
|
||||
cJSON *creep_level = cJSON_GetObjectItem(root, "creep_level");
|
||||
|
||||
if (creep_strength || creep_level)
|
||||
{
|
||||
app_creep_params temp_creep;
|
||||
app_creep_read_params(&temp_creep);
|
||||
|
||||
if (creep_strength) {
|
||||
temp_creep.creep_strength = (uint8_t)creep_strength->valueint;
|
||||
}
|
||||
if (creep_level) {
|
||||
temp_creep.creep_level = (uint8_t)creep_level->valueint;
|
||||
}
|
||||
|
||||
app_creep_write_temp_params(&temp_creep);
|
||||
}
|
||||
|
||||
// 5. Flash <20>־û<D6BE><C3BB><EFBFBD><EFBFBD><EFBFBD>
|
||||
cJSON *flash_cmd = cJSON_GetObjectItem(root, "flash");
|
||||
if(flash_cmd && cJSON_IsString(flash_cmd))
|
||||
{
|
||||
if (strcmp(flash_cmd->valuestring, "creep_write") == 0)
|
||||
{
|
||||
app_creep_params temp_creep;
|
||||
app_creep_read_params(&temp_creep);
|
||||
app_creep_save_params(&temp_creep);
|
||||
}
|
||||
}
|
||||
|
||||
// 6. <20><><EFBFBD><EFBFBD><EFBFBD>º<EFBFBD><C2BA><EFBFBD> Legacy ״̬<D7B4><CCAC>д<EFBFBD><D0B4>Ӧ<EFBFBD>ò<EFBFBD>
|
||||
app_device_status_set(&new_status);
|
||||
|
||||
cJSON_Delete(root);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool app_mozen_raw_frame_handler(void *context, const uint8_t *raw_frame, uint16_t length)
|
||||
{
|
||||
mozen_frame_header_t header;
|
||||
if (length < sizeof(mozen_frame_header_t) + 2) return false;
|
||||
|
||||
memcpy(&header, raw_frame, sizeof(mozen_frame_header_t));
|
||||
if (header.command_id == MOZEN_CMD_ID_PARAM_CONFIG) // 0x02
|
||||
{
|
||||
uint16_t full_frame_len = header.frame_length;
|
||||
uint16_t data_len = full_frame_len - sizeof(mozen_frame_header_t);
|
||||
const uint8_t *data_ptr = raw_frame + sizeof(mozen_frame_header_t);
|
||||
uint16_t received_crc;
|
||||
memcpy(&received_crc, raw_frame + full_frame_len, sizeof(uint16_t));
|
||||
|
||||
uint16_t calc_crc = mozen_protocol_checksum(raw_frame, full_frame_len);
|
||||
if ((calc_crc == received_crc) || is_legacy_config_payload(data_ptr, data_len))
|
||||
{
|
||||
handle_old_protocol_device_status((uint8_t *)data_ptr, data_len);
|
||||
return true; // Handled
|
||||
}
|
||||
}
|
||||
return false; // Not handled, fallback to standard parsing
|
||||
}
|
||||
|
||||
// --- Command Handlers ---
|
||||
/*
|
||||
* @brief handle sensor data
|
||||
* @param context: context
|
||||
* @param cmd_id: command id
|
||||
* @param data: data
|
||||
* @param length: length
|
||||
* @retval none
|
||||
*/
|
||||
static void handle_sensor_data(void *context, uint8_t cmd_id, const uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (length < 3)
|
||||
{
|
||||
MX_LOGE(MX_PTO_TAG, "sensor command length invalid: %u", (unsigned int)length);
|
||||
return;
|
||||
}
|
||||
uint8_t new_data_type = data[0];
|
||||
if (new_data_type != g_sensor_data_type)
|
||||
{
|
||||
g_sensor_data_type = new_data_type;
|
||||
app_math_cali_t temp_params;
|
||||
bool got_params = false;
|
||||
|
||||
got_params = app_math_get_temp_params(&temp_params);
|
||||
|
||||
if (got_params)
|
||||
{
|
||||
temp_params.max_display_value = 4095;
|
||||
temp_params.sensor_data_type = g_sensor_data_type;
|
||||
|
||||
app_math_set_temp_params(&temp_params);
|
||||
}
|
||||
}
|
||||
g_sensor_frames_to_send = *(uint16_t*)(&data[1]);
|
||||
}
|
||||
|
||||
// --- Response Utilities ---
|
||||
/*
|
||||
* @brief send mozen command response
|
||||
* @param cmd_id: command id
|
||||
* @param req_header: request header
|
||||
* @param payload: payload
|
||||
* @param payload_len: payload length
|
||||
* @retval none
|
||||
*/
|
||||
static void send_mozen_cmd_response(uint8_t cmd_id, const mozen_cmd_header_t* req_header, const uint8_t* payload, uint16_t payload_len)
|
||||
{
|
||||
static uint8_t response_buf[1024];
|
||||
mozen_cmd_header_t* res_header = (mozen_cmd_header_t*)response_buf;
|
||||
res_header->target_id = req_header->target_id;
|
||||
res_header->sub_class = req_header->sub_class;
|
||||
res_header->operation = req_header->operation;
|
||||
if (payload && payload_len > 0)
|
||||
{
|
||||
memcpy(response_buf + sizeof(mozen_cmd_header_t), payload, payload_len);
|
||||
}
|
||||
mozen_protocol_send_frame(s_prot_instance, cmd_id, response_buf, sizeof(mozen_cmd_header_t) + payload_len, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief send mozen command ok or ng
|
||||
* @param cmd_id: command id
|
||||
* @param req_header: request header
|
||||
* @param success: success or not
|
||||
* @retval none
|
||||
*/
|
||||
static inline void send_mozen_cmd_ok_ng(uint8_t cmd_id, const mozen_cmd_header_t* req_header, bool success)
|
||||
{
|
||||
uint8_t payload[2] = { success ? 'o' : 'N', success ? 'k' : 'G' };
|
||||
send_mozen_cmd_response(cmd_id, req_header, payload, 2);
|
||||
}
|
||||
|
||||
// --- Parameter Config Handlers (Cmd ID: 0x02) ---
|
||||
/*
|
||||
* @brief handle report mode
|
||||
* @param header: header
|
||||
* @param payload: payload
|
||||
* @param payload_len: payload length
|
||||
* @retval none
|
||||
*/
|
||||
static void param_handle_report_mode(const mozen_cmd_header_t* header, const uint8_t* payload, uint16_t payload_len)
|
||||
{
|
||||
if (header->sub_class == 0x01 && header->operation == 0x01 && payload_len >= 1)
|
||||
{
|
||||
if (payload[0] == 0x00) g_is_active_reporting = false;
|
||||
else if (payload[0] == 0x01) g_is_active_reporting = true;
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PARAM_CONFIG, header, true);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* @brief handle device info
|
||||
* @param header: header
|
||||
* @param payload: payload
|
||||
* @param payload_len: payload length
|
||||
* @retval none
|
||||
*/
|
||||
static void param_handle_device_info(const mozen_cmd_header_t* header, const uint8_t* payload, uint16_t payload_len)
|
||||
{
|
||||
if (header->operation == 0x00)
|
||||
{
|
||||
app_dev_info dev_info;
|
||||
char sensor_size_text[sizeof(dev_info.sensor_size) + 1U] = {0};
|
||||
char protocol_ver_text[sizeof(dev_info.protocol_ver) + 1U] = {0};
|
||||
|
||||
if (app_device_get_info(&dev_info))
|
||||
{
|
||||
memcpy(sensor_size_text, dev_info.sensor_size, sizeof(dev_info.sensor_size));
|
||||
memcpy(protocol_ver_text, dev_info.protocol_ver, sizeof(dev_info.protocol_ver));
|
||||
|
||||
uint8_t resp_payload[256];
|
||||
resp_payload[0] = 'o';
|
||||
resp_payload[1] = 'k';
|
||||
int json_len = snprintf((char *)(resp_payload + 2),
|
||||
sizeof(resp_payload) - 2,
|
||||
"{\"PN\":\"%s\",\"SN\":\"%s\",\"SV\":\"%s\",\"HVI\":\"%s\",\"XY\":\"%s\",\"Protocol\":\"%s\"}",
|
||||
dev_info.pn, dev_info.sn, dev_info.sw_ver, dev_info.hw_ver, sensor_size_text, protocol_ver_text);
|
||||
if (json_len > 0) {
|
||||
send_mozen_cmd_response(MOZEN_CMD_ID_PARAM_CONFIG, header, resp_payload, 2 + (uint16_t)json_len);
|
||||
} else {
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PARAM_CONFIG, header, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PARAM_CONFIG, header, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* @brief handle calibration display
|
||||
* @param header: header
|
||||
* @param payload: payload
|
||||
* @param payload_len: payload length
|
||||
* @retval none
|
||||
*/
|
||||
static void param_handle_cali_display(const mozen_cmd_header_t* header, const uint8_t* payload, uint16_t payload_len)
|
||||
{
|
||||
if (header->operation == 0x00)
|
||||
{
|
||||
uint8_t success = 0;
|
||||
uint16_t data_len = 0;
|
||||
uint8_t resp_payload[256];
|
||||
|
||||
if (header->sub_class == 0x01)
|
||||
{
|
||||
success = app_math_read_temp_params(resp_payload + 2, &data_len);
|
||||
}
|
||||
else if (header->sub_class == 0x02)
|
||||
{
|
||||
success = app_math_read_solidified_params(resp_payload + 2, &data_len);
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
resp_payload[0] = 'o'; resp_payload[1] = 'k';
|
||||
send_mozen_cmd_response(MOZEN_CMD_ID_PARAM_CONFIG, header, resp_payload, 2 + data_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PARAM_CONFIG, header, false);
|
||||
}
|
||||
}
|
||||
else if (header->operation == 0x01)
|
||||
{
|
||||
uint8_t success = 0;
|
||||
if (header->sub_class == 0x01)
|
||||
{
|
||||
success = app_math_write_temp_params(payload, payload_len);
|
||||
}
|
||||
else if (header->sub_class == 0x02)
|
||||
{
|
||||
success = app_math_save_params(payload, payload_len);
|
||||
}
|
||||
else if (header->sub_class == 0x03)
|
||||
{
|
||||
success = app_math_clear_params();
|
||||
app_calibration_invalidate_runtime();
|
||||
}
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PARAM_CONFIG, header, success);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* @brief handle param config
|
||||
* @param context: context
|
||||
* @param cmd_id: cmd id
|
||||
* @param data: data
|
||||
* @param length: length
|
||||
* @retval none
|
||||
*/
|
||||
static void handle_param_config(void *context, uint8_t cmd_id, const uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (length < sizeof(mozen_cmd_header_t)) return;
|
||||
|
||||
const mozen_cmd_header_t* cmd_header = (const mozen_cmd_header_t*)data;
|
||||
const uint8_t* cmd_payload = data + sizeof(mozen_cmd_header_t);
|
||||
uint16_t payload_len = length - sizeof(mozen_cmd_header_t);
|
||||
|
||||
for (size_t i = 0; i < sizeof(s_param_handlers) / sizeof(s_param_handlers[0]); i++)
|
||||
{
|
||||
if (s_param_handlers[i].target_id == cmd_header->target_id)
|
||||
{
|
||||
s_param_handlers[i].handler(cmd_header, cmd_payload, payload_len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// --- Production Test Handlers (Cmd ID: 0xAA) ---
|
||||
|
||||
/*
|
||||
* @brief handle system command
|
||||
* @param header: header
|
||||
* @param payload: payload
|
||||
* @param payload_len: payload length
|
||||
* @retval none
|
||||
*/
|
||||
static void prod_handle_sys_cmd(const mozen_cmd_header_t* header, const uint8_t* payload, uint16_t payload_len)
|
||||
{
|
||||
if (header->operation == 0x01)
|
||||
{
|
||||
if (header->sub_class == 0x02)
|
||||
{
|
||||
if(payload_len > 0)
|
||||
{
|
||||
g_is_creep_enable = (payload[0] == 0x01);
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PROD_TEST, header, true);
|
||||
}
|
||||
}
|
||||
else if (header->sub_class == 0x01)
|
||||
{
|
||||
app_dev_info dev_info;
|
||||
if (payload_len == 0U || payload_len >= sizeof(dev_info.sn))
|
||||
{
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PROD_TEST, header, false);
|
||||
return;
|
||||
}
|
||||
if (!app_device_get_info(&dev_info))
|
||||
{
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PROD_TEST, header, false);
|
||||
return;
|
||||
}
|
||||
memset(dev_info.sn, 0, sizeof(dev_info.sn));
|
||||
memcpy(dev_info.sn, payload, payload_len);
|
||||
if (!app_device_set_info(&dev_info))
|
||||
{
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PROD_TEST, header, false);
|
||||
return;
|
||||
}
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PROD_TEST, header, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief handle map calibration
|
||||
* @param header: header
|
||||
* @param payload: payload
|
||||
* @param payload_len: payload length
|
||||
* @retval none
|
||||
*/
|
||||
static void prod_handle_map_cali_cmd(const mozen_cmd_header_t* header, const uint8_t* payload, uint16_t payload_len)
|
||||
{
|
||||
uint8_t resp_payload[260];
|
||||
|
||||
// First, handle map temp params (operation 0x01, sub_class 0x3F / 0x3D) which return no response
|
||||
// First, handle map temp params (operation 0x01, sub_class 0x3F / 0x3D) which return no response
|
||||
if (header->operation == 0x01)
|
||||
{
|
||||
if (header->sub_class == 0x3F)
|
||||
{
|
||||
app_map_write_temp_params(payload, payload_len);
|
||||
return;
|
||||
}
|
||||
else if (header->sub_class == 0x3D)
|
||||
{
|
||||
app_map_save_params(payload, payload_len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (header->sub_class)
|
||||
{
|
||||
case 0x4F:
|
||||
if (header->operation == 0x00)
|
||||
{
|
||||
uint16_t d_len;
|
||||
if(app_pressure_read_temp_params(resp_payload + 2, &d_len))
|
||||
{
|
||||
resp_payload[0] = 'o'; resp_payload[1] = 'k';
|
||||
send_mozen_cmd_response(MOZEN_CMD_ID_PROD_TEST, header, resp_payload, 2 + d_len);
|
||||
} else {
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PROD_TEST, header, false);
|
||||
}
|
||||
} else if (header->operation == 0x01) {
|
||||
bool success = app_pressure_write_temp_params(payload, payload_len);
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PROD_TEST, header, success);
|
||||
}
|
||||
break;
|
||||
case 0x4D:
|
||||
if (header->operation == 0x00)
|
||||
{
|
||||
uint16_t d_len;
|
||||
if(app_pressure_read_solidified_params(resp_payload + 2, &d_len))
|
||||
{
|
||||
resp_payload[0] = 'o'; resp_payload[1] = 'k';
|
||||
send_mozen_cmd_response(MOZEN_CMD_ID_PROD_TEST, header, resp_payload, 2 + d_len);
|
||||
} else {
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PROD_TEST, header, false);
|
||||
}
|
||||
} else if (header->operation == 0x01)
|
||||
{
|
||||
bool success = app_pressure_save_params(payload, payload_len);
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PROD_TEST, header, success);
|
||||
}
|
||||
break;
|
||||
case 0x3F:
|
||||
case 0x3D:
|
||||
if (header->operation == 0x00)
|
||||
{
|
||||
uint32_t total_data_len = app_map_data_size();
|
||||
uint16_t total_packets = (total_data_len + 240 - 1) / 240;
|
||||
memcpy(resp_payload, &total_data_len, sizeof(uint32_t));
|
||||
memcpy(resp_payload + 4, &total_packets, sizeof(uint16_t));
|
||||
send_mozen_cmd_response(MOZEN_CMD_ID_PROD_TEST, header, resp_payload, 6);
|
||||
}
|
||||
else if (header->operation == 0x02)
|
||||
{
|
||||
if (payload_len < 2)
|
||||
{
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PROD_TEST, header, false);
|
||||
break;
|
||||
}
|
||||
uint16_t packet_index;
|
||||
memcpy(&packet_index, payload, sizeof(uint16_t));
|
||||
uint32_t total_data_len = app_map_data_size();
|
||||
uint32_t offset = (packet_index - 1) * 240;
|
||||
|
||||
if (offset >= total_data_len)
|
||||
{
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PROD_TEST, header, false);
|
||||
break;
|
||||
}
|
||||
uint16_t chunk_len = 240;
|
||||
if (offset + chunk_len > total_data_len) chunk_len = total_data_len - offset;
|
||||
|
||||
memcpy(resp_payload, &packet_index, sizeof(uint16_t));
|
||||
memcpy(resp_payload + 2, app_map_data_ptr() + offset, chunk_len);
|
||||
send_mozen_cmd_response(MOZEN_CMD_ID_PROD_TEST, header, resp_payload, 2 + chunk_len);
|
||||
}
|
||||
break;
|
||||
case 0x00:
|
||||
if (header->operation == 0x01)
|
||||
{
|
||||
bool success = app_pressure_clear_params();
|
||||
success = success && app_map_clear_params();
|
||||
send_mozen_cmd_ok_ng(MOZEN_CMD_ID_PROD_TEST, header, success);
|
||||
app_calibration_invalidate_runtime();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the production test command.
|
||||
* It checks the target ID and calls the appropriate handler function.
|
||||
* @param context The context pointer.
|
||||
* @param cmd_id The command ID.
|
||||
* @param data The command data.
|
||||
* @param length The length of the command data.
|
||||
*/
|
||||
static void handle_production_test(void *context, uint8_t cmd_id, const uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (length < sizeof(mozen_cmd_header_t)) return;
|
||||
|
||||
const mozen_cmd_header_t* cmd_header = (const mozen_cmd_header_t*)data;
|
||||
const uint8_t* cmd_payload = data + sizeof(mozen_cmd_header_t);
|
||||
uint16_t payload_len = length - sizeof(mozen_cmd_header_t);
|
||||
|
||||
for (size_t i = 0; i < sizeof(s_prod_handlers) / sizeof(s_prod_handlers[0]); i++)
|
||||
{
|
||||
if (s_prod_handlers[i].target_id == cmd_header->target_id) {
|
||||
s_prod_handlers[i].handler(cmd_header, cmd_payload, payload_len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the tunnel command.
|
||||
* It calls the tunnel handle command function with the command data.
|
||||
* @param context The context pointer.
|
||||
* @param cmd_id The command ID.
|
||||
* @param data The command data.
|
||||
* @param length The length of the command data.
|
||||
*/
|
||||
static void handle_tunnel_command(void *context, uint8_t cmd_id, const uint8_t *data, uint16_t length)
|
||||
{
|
||||
mozen_tunnel_handle_command(&s_tunnel_instance, data, length);
|
||||
}
|
||||
|
||||
// --- Tunnel Callbacks ---
|
||||
/*
|
||||
* This function is called when a stream starts.
|
||||
* It checks if the target command is production test and the sub class is 0x3F or 0x3D.
|
||||
* If so, it sets the stream state to streaming write and initializes the write pointer.
|
||||
* @param context The context pointer.
|
||||
* @param target_cmd The target command.
|
||||
* @param first_chunk_data The first chunk of data.
|
||||
* @param chunk_len The length of the chunk.
|
||||
* @return true if the stream is started, false otherwise.
|
||||
*/
|
||||
static bool tunnel_on_stream_start(void *context, uint8_t target_cmd, const uint8_t *first_chunk_data, uint16_t chunk_len)
|
||||
{
|
||||
if (target_cmd == MOZEN_CMD_ID_PROD_TEST) {
|
||||
const mozen_cmd_header_t* pt_header = (const mozen_cmd_header_t*)first_chunk_data;
|
||||
if (chunk_len >= sizeof(mozen_cmd_header_t) && pt_header->target_id == MOZEN_PROD_TGT_MAP_CALI && pt_header->operation == 0x01)
|
||||
{
|
||||
if (pt_header->sub_class == 0x3F || pt_header->sub_class == 0x3D)
|
||||
{
|
||||
s_stream_state.is_streaming_write = true;
|
||||
s_stream_state.target_sub_class = pt_header->sub_class;
|
||||
s_stream_state.target_cmd = target_cmd;
|
||||
s_stream_state.write_ptr = app_map_data_ptr();
|
||||
|
||||
uint16_t data_offset = sizeof(mozen_cmd_header_t);
|
||||
uint16_t data_to_write = chunk_len - data_offset;
|
||||
uint8_t* end_ptr = (app_map_data_ptr() + app_map_data_size());
|
||||
|
||||
if (s_stream_state.write_ptr + data_to_write > end_ptr) {
|
||||
data_to_write = end_ptr - s_stream_state.write_ptr;
|
||||
}
|
||||
|
||||
if (data_to_write > 0) {
|
||||
memcpy(s_stream_state.write_ptr, first_chunk_data + data_offset, data_to_write);
|
||||
s_stream_state.write_ptr += data_to_write;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when data is received during a stream.
|
||||
* It checks if the stream is in streaming write mode and writes the data to the map data buffer.
|
||||
* @param context The context pointer.
|
||||
* @param data The data.
|
||||
* @param len The length of the data.
|
||||
* @return true if the data is handled, false otherwise.
|
||||
*/
|
||||
static bool tunnel_on_stream_data(void *context, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
if (s_stream_state.is_streaming_write) {
|
||||
uint8_t* end_ptr = (app_map_data_ptr() + app_map_data_size());
|
||||
uint16_t data_to_write = len;
|
||||
|
||||
if (s_stream_state.write_ptr >= end_ptr) {
|
||||
data_to_write = 0;
|
||||
} else if (s_stream_state.write_ptr + data_to_write > end_ptr) {
|
||||
data_to_write = end_ptr - s_stream_state.write_ptr;
|
||||
}
|
||||
|
||||
if (data_to_write > 0) {
|
||||
memcpy(s_stream_state.write_ptr, data, data_to_write);
|
||||
s_stream_state.write_ptr += data_to_write;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is called when a stream finishes.
|
||||
* It checks if the stream is in streaming write mode and saves the map parameters if the target command is production test and the sub class is 0x3F or 0x3D.
|
||||
* @param context The context pointer.
|
||||
* @param success The success flag.
|
||||
* @return None.
|
||||
*/
|
||||
static void tunnel_on_stream_finish(void *context, bool success)
|
||||
{
|
||||
if (s_stream_state.is_streaming_write && success)
|
||||
{
|
||||
uint32_t expected_bytes = app_map_data_size();
|
||||
uint32_t written_bytes = (uint32_t)(s_stream_state.write_ptr - app_map_data_ptr());
|
||||
|
||||
if (written_bytes >= expected_bytes)
|
||||
{
|
||||
if (s_stream_state.target_cmd == MOZEN_CMD_ID_PROD_TEST && s_stream_state.target_sub_class == 0x3D)
|
||||
{
|
||||
app_map_save_params(app_map_data_ptr(), (uint16_t)expected_bytes);
|
||||
app_calibration_request_reset_effect();
|
||||
}
|
||||
}
|
||||
}
|
||||
s_stream_state.is_streaming_write = false;
|
||||
s_stream_state.write_ptr = NULL;
|
||||
}
|
||||
|
||||
// --- Init ---
|
||||
|
||||
/*
|
||||
* @brief: Initialize the mozen handler.
|
||||
* @param tx_fn: The function to send data.
|
||||
* @return None.
|
||||
*/
|
||||
void app_mozen_init(mozen_tx_fn_t tx_fn)
|
||||
{
|
||||
mozen_protocol_init(&g_mozen_prot, s_rx_buf, sizeof(s_rx_buf),
|
||||
s_tx_buf_main, s_tx_buf_irq, sizeof(s_tx_buf_main),
|
||||
tx_fn, NULL);
|
||||
app_mozen_handler_init(&g_mozen_prot);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief: Handle raw frame from mozen protocol
|
||||
* @param: prot - Protocol instance
|
||||
* @return: None
|
||||
*/
|
||||
void app_mozen_handler_init(mozen_protocol_t *prot)
|
||||
{
|
||||
s_prot_instance = prot;
|
||||
|
||||
// Register commands
|
||||
mozen_protocol_register_handler(prot, MOZEN_CMD_ID_SENSOR_DATA, handle_sensor_data);
|
||||
mozen_protocol_register_handler(prot, MOZEN_CMD_ID_PARAM_CONFIG, handle_param_config);
|
||||
mozen_protocol_register_handler(prot, MOZEN_CMD_ID_PROD_TEST, handle_production_test);
|
||||
mozen_protocol_register_handler(prot, MOZEN_TUNNEL_COMMAND_ID, handle_tunnel_command);
|
||||
|
||||
// Legacy handler
|
||||
mozen_protocol_set_raw_handler(prot, app_mozen_raw_frame_handler);
|
||||
|
||||
// Init tunnel
|
||||
mozen_tunnel_init(&s_tunnel_instance, prot, 240, NULL);
|
||||
mozen_tunnel_set_callbacks(&s_tunnel_instance, tunnel_on_stream_start, tunnel_on_stream_data, tunnel_on_stream_finish);
|
||||
}
|
||||
48
app_cail/moxzen_protocol/app_mozen_handler.h
Normal file
48
app_cail/moxzen_protocol/app_mozen_handler.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef __APP_MOZEN_HANDLER_H
|
||||
#define __APP_MOZEN_HANDLER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mozen_protocol.h"
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>
|
||||
enum
|
||||
{
|
||||
SENSOR_BIT_8 = 0x01,
|
||||
SENSOR_BIT_16,
|
||||
};
|
||||
|
||||
// ȫ<><C8AB>״̬<D7B4><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD> mozen_protocol.h <20>ж<EFBFBD><D0B6>壬<EFBFBD><E5A3AC><EFBFBD><EFBFBD>Ӧ<EFBFBD>ò<EFBFBD><C3B2><EFBFBD><EFBFBD><EFBFBD>
|
||||
extern volatile uint16_t g_sensor_frames_to_send;
|
||||
extern volatile uint8_t g_sensor_data_type;
|
||||
|
||||
// --- Protocol Command IDs ---
|
||||
#define MOZEN_CMD_ID_SENSOR_DATA 0x01 // --- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---
|
||||
#define MOZEN_CMD_ID_PARAM_CONFIG 0x02 // --- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---
|
||||
#define MOZEN_CMD_ID_PROD_TEST 0xAA // --- <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---
|
||||
|
||||
// --- Param Config Target IDs (Command 0x02) ---
|
||||
#define MOZEN_PARAM_TGT_REPORT_MODE 0x01
|
||||
#define MOZEN_PARAM_TGT_CALI_DISPLAY 0x3D
|
||||
#define MOZEN_PARAM_TGT_DEVICE_INFO 0x3F
|
||||
|
||||
// --- Production Test Target IDs (Command 0xAA) ---
|
||||
#define MOZEN_PROD_TGT_SYS 0x01
|
||||
#define MOZEN_PROD_TGT_MAP_CALI 0x03
|
||||
|
||||
// Global protocol instance for application
|
||||
extern mozen_protocol_t g_mozen_prot;
|
||||
|
||||
/**
|
||||
* @brief Initialize the Mozen application handlers.
|
||||
* This will register all necessary command handlers to the protocol instance.
|
||||
* @param prot Protocol instance to bind to.
|
||||
*/
|
||||
void app_mozen_handler_init(mozen_protocol_t *prot);
|
||||
|
||||
/**
|
||||
* @brief Top level initialization for Mozen protocol and application handlers.
|
||||
* @param tx_fn The transmit callback function.
|
||||
*/
|
||||
void app_mozen_init(mozen_tx_fn_t tx_fn);
|
||||
|
||||
#endif // __APP_MOZEN_HANDLER_H
|
||||
315
app_cail/moxzen_protocol/mozen_protocol.c
Normal file
315
app_cail/moxzen_protocol/mozen_protocol.c
Normal file
@@ -0,0 +1,315 @@
|
||||
#include "mozen_protocol.h"
|
||||
#include <string.h>
|
||||
#include "bsp_uart.h"
|
||||
|
||||
// --- Helper Functions ---
|
||||
/*
|
||||
* Calculate CRC16 for data
|
||||
* @param data: Pointer to data
|
||||
* @param length: Length of data
|
||||
* @return: CRC16 value
|
||||
* @note: This function is used for Modbus CRC16
|
||||
*/
|
||||
uint16_t mozen_protocol_crc16_modbus(const uint8_t *data, uint16_t length)
|
||||
{
|
||||
uint16_t crc = 0xFFFF;
|
||||
for (uint16_t i = 0; i < length; i++)
|
||||
{
|
||||
crc ^= data[i];
|
||||
for (uint8_t j = 0; j < 8; j++)
|
||||
{
|
||||
if (crc & 0x0001) crc = (crc >> 1) ^ 0xA001;
|
||||
else crc >>= 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate checksum for data
|
||||
* @param data: Pointer to data
|
||||
* @param len: Length of data
|
||||
* @return: Checksum value
|
||||
* @note: This function is used for legacy checksum protocols
|
||||
*/
|
||||
uint16_t mozen_protocol_checksum(const uint8_t *data, uint32_t len)
|
||||
{
|
||||
uint16_t sum = 0;
|
||||
for (uint32_t i = 0; i < len; ++i)
|
||||
{
|
||||
sum += data[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
// --- Internal Functions ---
|
||||
|
||||
/*
|
||||
* Reset RX state
|
||||
* @param prot: Pointer to mozen_protocol_t structure
|
||||
* @note: This function is called automatically by mozen_protocol_process_rx
|
||||
*/
|
||||
static void mozen_protocol_reset_rx(mozen_protocol_t *prot)
|
||||
{
|
||||
prot->rx_state = MOZEN_RX_STATE_WAIT_SOF1; // Reset to wait for SOF1
|
||||
prot->rx_index = 0; // Reset index
|
||||
prot->expected_data_len = 0; // Reset expected data length
|
||||
}
|
||||
|
||||
/*
|
||||
* Dispatch received frame
|
||||
* @param prot: Pointer to mozen_protocol_t structure
|
||||
* @note: This function is called automatically by mozen_protocol_process_rx
|
||||
* when a complete frame is received
|
||||
*/
|
||||
static void mozen_protocol_dispatch(mozen_protocol_t *prot)
|
||||
{
|
||||
if (prot->rx_index < sizeof(mozen_frame_header_t) + 2) return; // Too short
|
||||
|
||||
uint16_t received_crc; // Extract CRC from frame
|
||||
mozen_frame_header_t header;
|
||||
memcpy(&header, prot->rx_buffer, sizeof(mozen_frame_header_t));
|
||||
|
||||
if (header.sof != MOZEN_PROTOCOL_SOF) return;
|
||||
|
||||
uint16_t full_frame_len = header.frame_length;
|
||||
uint32_t total_len = (uint32_t)full_frame_len + 2; // +2 for SOF and CRC
|
||||
if (total_len > prot->rx_index || total_len > prot->rx_buffer_size) return;
|
||||
|
||||
|
||||
uint16_t data_len = full_frame_len - sizeof(mozen_frame_header_t); // Exclude header
|
||||
const uint8_t *data_ptr = prot->rx_buffer + sizeof(mozen_frame_header_t); // Point to data
|
||||
|
||||
memcpy(&received_crc, prot->rx_buffer + full_frame_len, sizeof(uint16_t)); // Extract CRC from frame
|
||||
|
||||
// 1. Raw frame handler check (e.g. for legacy checksum protocols)
|
||||
if (prot->raw_frame_handler)
|
||||
{
|
||||
if (prot->raw_frame_handler(prot->user_context, prot->rx_buffer, total_len)) return; // Handled by custom raw handler
|
||||
}
|
||||
|
||||
// 2. Standard CRC16 check
|
||||
uint16_t calculated_crc = mozen_protocol_crc16_modbus(prot->rx_buffer, full_frame_len);
|
||||
if (received_crc != calculated_crc) return; // CRC Error
|
||||
|
||||
// 3. Dispatch to registered handlers
|
||||
for (uint8_t i = 0; i < prot->handler_count; i++)
|
||||
{
|
||||
if (prot->handlers[i].cmd_id == header.command_id)
|
||||
{
|
||||
prot->handlers[i].handler(prot->user_context, header.command_id, data_ptr, data_len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Default handler fallback
|
||||
if (prot->default_handler)
|
||||
{
|
||||
prot->default_handler(prot->user_context, header.command_id, data_ptr, data_len);
|
||||
}
|
||||
}
|
||||
|
||||
// --- API Functions ---
|
||||
/*
|
||||
* Initialize mozen_protocol_t structure
|
||||
* @param prot: Pointer to mozen_protocol_t structure
|
||||
* @param rx_buf: Pointer to RX buffer
|
||||
* @param rx_buf_size: Size of RX buffer
|
||||
* @param tx_buf_main: Pointer to TX buffer
|
||||
* @param tx_buf_irq: Pointer to IRQ TX buffer (optional)
|
||||
* @param tx_buf_size: Size of TX buffer
|
||||
* @param tx_fn: TX function
|
||||
* @param user_context: User context for TX function
|
||||
* @note: This function should be called once before using the protocol
|
||||
*/
|
||||
void mozen_protocol_init(mozen_protocol_t *prot,
|
||||
uint8_t *rx_buf, uint16_t rx_buf_size,
|
||||
uint8_t *tx_buf_main, uint8_t *tx_buf_irq, uint16_t tx_buf_size,
|
||||
mozen_tx_fn_t tx_fn, void *user_context)
|
||||
{
|
||||
if (!prot) return;
|
||||
|
||||
memset(prot, 0, sizeof(mozen_protocol_t));
|
||||
|
||||
prot->rx_buffer = rx_buf;
|
||||
prot->rx_buffer_size = rx_buf_size;
|
||||
prot->tx_buffer_main = tx_buf_main;
|
||||
prot->tx_buffer_irq = tx_buf_irq ? tx_buf_irq : tx_buf_main;
|
||||
prot->tx_buffer_size = tx_buf_size;
|
||||
prot->tx_fn = tx_fn;
|
||||
prot->user_context = user_context;
|
||||
|
||||
mozen_protocol_reset_rx(prot);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a command handler
|
||||
* @param prot: Pointer to mozen_protocol_t structure
|
||||
* @param cmd_id: Command ID
|
||||
* @param handler: Command handler function
|
||||
* @return: 0 on success, -1 on failure
|
||||
* @note: This function can be called multiple times to register multiple handlers
|
||||
*/
|
||||
int mozen_protocol_register_handler(mozen_protocol_t *prot, uint8_t cmd_id, mozen_cmd_handler_t handler)
|
||||
{
|
||||
if (!prot || !handler) return -1;
|
||||
if (prot->handler_count >= MOZEN_MAX_HANDLERS) return -1;
|
||||
|
||||
prot->handlers[prot->handler_count].cmd_id = cmd_id;
|
||||
prot->handlers[prot->handler_count].handler = handler;
|
||||
prot->handler_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process RX buffer
|
||||
* @param prot: Pointer to mozen_protocol_t structure
|
||||
* @param current_time_ms: Current time in milliseconds
|
||||
* @note: This function should be called periodically to process incoming data
|
||||
*/
|
||||
void mozen_protocol_set_default_handler(mozen_protocol_t *prot, mozen_cmd_handler_t handler)
|
||||
{
|
||||
if (prot) prot->default_handler = handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set raw frame handler
|
||||
* @param prot: Pointer to mozen_protocol_t structure
|
||||
* @param handler: Raw frame handler function
|
||||
* @note: This function can be used to handle legacy checksum protocols or custom protocols
|
||||
*/
|
||||
void mozen_protocol_set_raw_handler(mozen_protocol_t *prot, mozen_raw_frame_handler_t handler)
|
||||
{
|
||||
if (prot) prot->raw_frame_handler = handler;
|
||||
}
|
||||
|
||||
/*
|
||||
* Feed a byte to the protocol
|
||||
* @param prot: Pointer to mozen_protocol_t structure
|
||||
* @param byte: Byte to feed
|
||||
* @param current_time_ms: Current time in milliseconds
|
||||
* @note: This function should be called whenever a new byte is received
|
||||
*/
|
||||
void mozen_protocol_feed_byte(mozen_protocol_t *prot, uint8_t byte, uint32_t current_time_ms)
|
||||
{
|
||||
if (!prot || !prot->rx_buffer) return;
|
||||
|
||||
prot->last_rx_time_ms = current_time_ms;
|
||||
|
||||
switch (prot->rx_state)
|
||||
{
|
||||
case MOZEN_RX_STATE_WAIT_SOF1:
|
||||
if (byte == (MOZEN_PROTOCOL_SOF & 0xFF))
|
||||
{
|
||||
prot->rx_buffer[0] = byte;
|
||||
prot->rx_index = 1;
|
||||
prot->rx_state = MOZEN_RX_STATE_WAIT_SOF2;
|
||||
}
|
||||
break;
|
||||
|
||||
case MOZEN_RX_STATE_WAIT_SOF2:
|
||||
if (byte == (MOZEN_PROTOCOL_SOF >> 8))
|
||||
{
|
||||
prot->rx_buffer[1] = byte;
|
||||
prot->rx_index = 2;
|
||||
prot->rx_state = MOZEN_RX_STATE_WAIT_HEADER;
|
||||
}
|
||||
else { mozen_protocol_reset_rx(prot);}
|
||||
break;
|
||||
|
||||
case MOZEN_RX_STATE_WAIT_HEADER: // Wait for frame header
|
||||
prot->rx_buffer[prot->rx_index++] = byte;
|
||||
if (prot->rx_index >= sizeof(mozen_frame_header_t))
|
||||
{
|
||||
mozen_frame_header_t header;
|
||||
memcpy(&header, prot->rx_buffer, sizeof(mozen_frame_header_t));
|
||||
|
||||
prot->expected_data_len = header.frame_length - sizeof(mozen_frame_header_t) + 2; // +2 for CRC
|
||||
|
||||
if ((sizeof(mozen_frame_header_t) + prot->expected_data_len) > prot->rx_buffer_size)
|
||||
{
|
||||
mozen_protocol_reset_rx(prot);
|
||||
return;
|
||||
}
|
||||
prot->rx_state = MOZEN_RX_STATE_WAIT_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
case MOZEN_RX_STATE_WAIT_DATA:
|
||||
prot->rx_buffer[prot->rx_index++] = byte;
|
||||
if (prot->rx_index >= (sizeof(mozen_frame_header_t) + prot->expected_data_len))
|
||||
{
|
||||
mozen_protocol_dispatch(prot);
|
||||
mozen_protocol_reset_rx(prot);
|
||||
} else if (prot->rx_index >= prot->rx_buffer_size) {
|
||||
// Should not happen due to header check, but safe guard against buffer overflow
|
||||
mozen_protocol_reset_rx(prot);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset the protocol state
|
||||
* @param prot: Pointer to mozen_protocol_t structure
|
||||
* current_time_ms: Current time in milliseconds
|
||||
* timeout_ms: Timeout in milliseconds
|
||||
* @note: This function should be called when a timeout occurs or when a frame is received
|
||||
*/
|
||||
void mozen_protocol_tick(mozen_protocol_t *prot, uint32_t current_time_ms, uint32_t timeout_ms)
|
||||
{
|
||||
if (!prot) return;
|
||||
|
||||
if (prot->rx_state != MOZEN_RX_STATE_WAIT_SOF1)
|
||||
{
|
||||
// Calculate diff taking into account potential integer overflow/wraparound
|
||||
uint32_t time_diff = current_time_ms - prot->last_rx_time_ms;
|
||||
if (time_diff > timeout_ms)
|
||||
{
|
||||
mozen_protocol_reset_rx(prot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a frame
|
||||
* @param prot: Pointer to mozen_protocol_t structure
|
||||
* @param command_id: Command ID
|
||||
* @param data: Data to send
|
||||
* @param length: Length of data
|
||||
* @param use_irq_buffer: Use IRQ buffer for sending
|
||||
* @return: 0 on success, -1 on error
|
||||
* @note: This function sends a frame using the provided data and command ID
|
||||
*/
|
||||
int mozen_protocol_send_frame(mozen_protocol_t *prot, uint8_t command_id, const uint8_t* data, uint16_t length, bool use_irq_buffer)
|
||||
{
|
||||
if (!prot || !prot->tx_fn) return -1;
|
||||
|
||||
uint16_t frame_length = sizeof(mozen_frame_header_t) + length; //Total length after removing CRC
|
||||
uint16_t total_length = frame_length + 2; // Total length including CRC
|
||||
|
||||
if (total_length > prot->tx_buffer_size) return -1;
|
||||
|
||||
// During the transmission stage, double buffering is employed to prevent the data frames of the main loop from overlapping with the interrupt ACKs.
|
||||
// The sensor data frames and ACKs may be sent concurrently in different contexts.
|
||||
// The two static buffers can avoid overwriting and competition.
|
||||
// The ACKs use an independent buffer to prevent interference with large packet transmission.
|
||||
uint8_t *active_buffer = use_irq_buffer ? prot->tx_buffer_irq : prot->tx_buffer_main;
|
||||
|
||||
mozen_frame_header_t header;
|
||||
header.sof = MOZEN_PROTOCOL_SOF;
|
||||
header.command_id = command_id;
|
||||
header.frame_length = frame_length;
|
||||
|
||||
memcpy(active_buffer, &header, sizeof(mozen_frame_header_t));
|
||||
if (data && length > 0)
|
||||
{
|
||||
memcpy(active_buffer + sizeof(mozen_frame_header_t), data, length);
|
||||
}
|
||||
|
||||
uint16_t crc = mozen_protocol_crc16_modbus(active_buffer, frame_length);
|
||||
memcpy(active_buffer + frame_length, &crc, sizeof(uint16_t));
|
||||
|
||||
return prot->tx_fn(active_buffer, total_length);
|
||||
}
|
||||
120
app_cail/moxzen_protocol/mozen_protocol.h
Normal file
120
app_cail/moxzen_protocol/mozen_protocol.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#ifndef __MOZEN_PROTOCOL_H
|
||||
#define __MOZEN_PROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MOZEN_PROTOCOL_SOF 0x5AA5 // ֡ͷ
|
||||
|
||||
// --- Core Protocol Data Structures ---
|
||||
|
||||
#pragma pack(1)
|
||||
/**
|
||||
* @brief Represents the header of a Mozen protocol frame.
|
||||
* The payload data follows this header directly in the buffer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t sof;
|
||||
uint8_t command_id;
|
||||
uint16_t frame_length;
|
||||
} mozen_frame_header_t;
|
||||
#pragma pack()
|
||||
|
||||
/**
|
||||
* @brief Command handler callback type.
|
||||
* @param context User context provided during registration.
|
||||
* @param cmd_id The command ID of the received frame.
|
||||
* @param data Pointer to the 'Data' field of the received frame.
|
||||
* @param length The length of the 'Data' field.
|
||||
*/
|
||||
typedef void (*mozen_cmd_handler_t)(void *context, uint8_t cmd_id, const uint8_t *data, uint16_t length);
|
||||
|
||||
/**
|
||||
* @brief Custom raw frame handler, used for legacy protocol compatibility or custom validation.
|
||||
* @param context User context.
|
||||
* @param raw_frame The complete raw frame data.
|
||||
* @param length The length of the complete raw frame.
|
||||
* @return true if the frame is handled and should not be processed further, false otherwise.
|
||||
*/
|
||||
typedef bool (*mozen_raw_frame_handler_t)(void *context, const uint8_t *raw_frame, uint16_t length);
|
||||
|
||||
/**
|
||||
* @brief Transport TX callback type.
|
||||
* @param frame Complete protocol frame buffer (header + payload + crc).
|
||||
* @param len Frame length in bytes.
|
||||
* @return 0 on success, negative value on failure.
|
||||
*/
|
||||
typedef int (*mozen_tx_fn_t)(const uint8_t *frame, uint16_t len);
|
||||
|
||||
// Max number of registered command handlers
|
||||
#define MOZEN_MAX_HANDLERS 10
|
||||
|
||||
// RX State Machine States
|
||||
typedef enum
|
||||
{
|
||||
MOZEN_RX_STATE_WAIT_SOF1,
|
||||
MOZEN_RX_STATE_WAIT_SOF2,
|
||||
MOZEN_RX_STATE_WAIT_HEADER,
|
||||
MOZEN_RX_STATE_WAIT_DATA,
|
||||
} mozen_rx_state_t;
|
||||
|
||||
/**
|
||||
* @brief Mozen Protocol Instance Context
|
||||
* Contains state and configurations for a single protocol instance.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
// Buffers and configuration
|
||||
uint8_t *rx_buffer;
|
||||
uint16_t rx_buffer_size;
|
||||
uint8_t *tx_buffer_main; // Main TX buffer
|
||||
uint8_t *tx_buffer_irq; // IRQ TX buffer
|
||||
uint16_t tx_buffer_size;
|
||||
|
||||
// Callbacks
|
||||
mozen_tx_fn_t tx_fn;
|
||||
void *user_context;
|
||||
|
||||
// Command Handlers
|
||||
struct
|
||||
{
|
||||
uint8_t cmd_id;
|
||||
mozen_cmd_handler_t handler;
|
||||
} handlers[MOZEN_MAX_HANDLERS];
|
||||
uint8_t handler_count;
|
||||
|
||||
mozen_cmd_handler_t default_handler;
|
||||
mozen_raw_frame_handler_t raw_frame_handler;
|
||||
|
||||
// RX State Machine
|
||||
mozen_rx_state_t rx_state;
|
||||
uint16_t rx_index;
|
||||
uint16_t expected_data_len;
|
||||
uint32_t last_rx_time_ms; // For timeout handling
|
||||
} mozen_protocol_t;
|
||||
|
||||
// --- API Functions ---
|
||||
|
||||
void mozen_protocol_init(mozen_protocol_t *prot,
|
||||
uint8_t *rx_buf, uint16_t rx_buf_size,
|
||||
uint8_t *tx_buf_main, uint8_t *tx_buf_irq, uint16_t tx_buf_size,
|
||||
mozen_tx_fn_t tx_fn, void *user_context);
|
||||
|
||||
int mozen_protocol_register_handler(mozen_protocol_t *prot, uint8_t cmd_id, mozen_cmd_handler_t handler);
|
||||
|
||||
void mozen_protocol_set_default_handler(mozen_protocol_t *prot, mozen_cmd_handler_t handler);
|
||||
|
||||
void mozen_protocol_set_raw_handler(mozen_protocol_t *prot, mozen_raw_frame_handler_t handler);
|
||||
|
||||
void mozen_protocol_feed_byte(mozen_protocol_t *prot, uint8_t byte, uint32_t current_time_ms);
|
||||
|
||||
void mozen_protocol_tick(mozen_protocol_t *prot, uint32_t current_time_ms, uint32_t timeout_ms);
|
||||
|
||||
int mozen_protocol_send_frame(mozen_protocol_t *prot, uint8_t command_id, const uint8_t* data, uint16_t length, bool use_irq_buffer);
|
||||
|
||||
uint16_t mozen_protocol_crc16_modbus(const uint8_t *data, uint16_t length);
|
||||
|
||||
uint16_t mozen_protocol_checksum(const uint8_t *data, uint32_t len);
|
||||
|
||||
#endif // __MOZEN_PROTOCOL_H
|
||||
197
app_cail/moxzen_protocol/mozen_tunnel.c
Normal file
197
app_cail/moxzen_protocol/mozen_tunnel.c
Normal file
@@ -0,0 +1,197 @@
|
||||
#include "mozen_tunnel.h"
|
||||
#include <string.h>
|
||||
// <20>ְ<EFBFBD>
|
||||
|
||||
/*
|
||||
* Initialize tunnel
|
||||
* tunnel: tunnel context
|
||||
* prot: protocol context
|
||||
* mtu: maximum transmission unit
|
||||
* user_context: user context
|
||||
* returns: none
|
||||
*/
|
||||
void mozen_tunnel_init(mozen_tunnel_t *tunnel, mozen_protocol_t *prot, uint16_t mtu, void *user_context)
|
||||
{
|
||||
if (!tunnel) return;
|
||||
memset(tunnel, 0, sizeof(mozen_tunnel_t));
|
||||
tunnel->prot = prot;
|
||||
tunnel->mtu = mtu;
|
||||
tunnel->user_context = user_context;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a response to the tunnel command
|
||||
* tunnel: tunnel context
|
||||
* target_cmd: command id
|
||||
* is_ok: true if the command was successful, false otherwise
|
||||
* returns: none
|
||||
*/
|
||||
void mozen_tunnel_set_callbacks(mozen_tunnel_t *tunnel,
|
||||
mozen_tunnel_on_stream_start_t on_start,
|
||||
mozen_tunnel_on_stream_data_t on_data,
|
||||
mozen_tunnel_on_stream_finish_t on_finish)
|
||||
{
|
||||
if (!tunnel) return;
|
||||
tunnel->on_start = on_start;
|
||||
tunnel->on_data = on_data;
|
||||
tunnel->on_finish = on_finish;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a response to the tunnel command
|
||||
* tunnel: tunnel context
|
||||
* target_cmd: command id
|
||||
* is_ok: true if the command was successful, false otherwise
|
||||
* returns: none
|
||||
*/
|
||||
static void mozen_tunnel_send_response(mozen_tunnel_t *tunnel, uint8_t target_cmd, bool is_ok)
|
||||
{
|
||||
if (!tunnel || !tunnel->prot) return;
|
||||
|
||||
uint8_t res_buf[sizeof(mozen_tunnel_header_t) + 2];
|
||||
mozen_tunnel_header_t *res_header = (mozen_tunnel_header_t *)res_buf;
|
||||
|
||||
res_header->tunnel_type = TUNNEL_TYPE_DATA_TRANSFER;
|
||||
res_header->target_cmd = target_cmd;
|
||||
res_buf[sizeof(mozen_tunnel_header_t)] = is_ok ? 'o' : 'N';
|
||||
res_buf[sizeof(mozen_tunnel_header_t) + 1] = is_ok ? 'k' : 'G';
|
||||
// tunnel messages go through IRQ buffer context to avoid disrupting main buffer?
|
||||
// The previous implementation used the default send context.
|
||||
mozen_protocol_send_frame(tunnel->prot, MOZEN_TUNNEL_COMMAND_ID, res_buf, sizeof(res_buf), true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a received tunnel frame
|
||||
* tunnel: tunnel context
|
||||
* data: received data
|
||||
* length: received data length
|
||||
* returns: none
|
||||
*/
|
||||
static void mozen_tunnel_abort(mozen_tunnel_t *tunnel)
|
||||
{
|
||||
if (tunnel->is_active)
|
||||
{
|
||||
if (tunnel->on_finish)
|
||||
{
|
||||
tunnel->on_finish(tunnel->user_context, false);
|
||||
}
|
||||
tunnel->is_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a received tunnel frame
|
||||
* tunnel: tunnel context
|
||||
* data: received data
|
||||
* length: received data length
|
||||
* returns: none
|
||||
*/
|
||||
void mozen_tunnel_handle_command(mozen_tunnel_t *tunnel, const uint8_t *data, uint16_t length)
|
||||
{
|
||||
if (!tunnel || length < sizeof(mozen_tunnel_header_t)) return;
|
||||
|
||||
const mozen_tunnel_header_t *tunnel_header = (const mozen_tunnel_header_t *)data;
|
||||
const uint8_t *payload = data + sizeof(mozen_tunnel_header_t);
|
||||
uint16_t payload_len = length - sizeof(mozen_tunnel_header_t);
|
||||
|
||||
switch (tunnel_header->tunnel_type)
|
||||
{
|
||||
case TUNNEL_TYPE_HANDSHAKE: // handshake request
|
||||
{
|
||||
if (payload_len < sizeof(uint32_t) + sizeof(uint16_t)) return;
|
||||
|
||||
mozen_tunnel_abort(tunnel); // Abort any ongoing stream
|
||||
|
||||
tunnel->is_active = true;
|
||||
tunnel->target_cmd = tunnel_header->target_cmd;
|
||||
|
||||
memcpy(&tunnel->total_data_len, payload, sizeof(uint32_t));
|
||||
memcpy(&tunnel->total_packets, payload + sizeof(uint32_t), sizeof(uint16_t));
|
||||
|
||||
tunnel->next_packet_index = 1;
|
||||
tunnel->received_data_len = 0;
|
||||
|
||||
// Prepare and send handshake response
|
||||
uint8_t res_buf[sizeof(mozen_tunnel_handshake_res_t)];
|
||||
mozen_tunnel_handshake_res_t *res = (mozen_tunnel_handshake_res_t *)res_buf;
|
||||
res->header.tunnel_type = TUNNEL_TYPE_RESPONSE;
|
||||
res->header.target_cmd = tunnel_header->target_cmd;
|
||||
res->status = 0x6B6F; // 'ok' (little-endian: 'o' is 0x6F, 'k' is 0x6B)
|
||||
res->mtu = tunnel->mtu;
|
||||
|
||||
if (tunnel->prot)
|
||||
{
|
||||
mozen_protocol_send_frame(tunnel->prot, MOZEN_TUNNEL_COMMAND_ID, (uint8_t *)res, sizeof(mozen_tunnel_handshake_res_t), true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TUNNEL_TYPE_DATA_TRANSFER: // data transfer
|
||||
{
|
||||
if (!tunnel->is_active || tunnel_header->target_cmd != tunnel->target_cmd) return;
|
||||
if (payload_len < sizeof(uint16_t)) return;
|
||||
|
||||
uint16_t packet_index;
|
||||
memcpy(&packet_index, payload, sizeof(uint16_t));
|
||||
|
||||
if (packet_index != tunnel->next_packet_index)
|
||||
{
|
||||
mozen_tunnel_send_response(tunnel, tunnel->target_cmd, false);
|
||||
mozen_tunnel_abort(tunnel);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t *chunk_data = payload + sizeof(uint16_t);
|
||||
uint16_t chunk_len = payload_len - sizeof(uint16_t);
|
||||
|
||||
bool accepted = true;
|
||||
|
||||
if (packet_index == 1)
|
||||
{
|
||||
if (tunnel->on_start)
|
||||
{
|
||||
accepted = tunnel->on_start(tunnel->user_context, tunnel->target_cmd, chunk_data, chunk_len);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tunnel->on_data)
|
||||
{
|
||||
accepted = tunnel->on_data(tunnel->user_context, chunk_data, chunk_len);
|
||||
}
|
||||
}
|
||||
|
||||
if (!accepted)
|
||||
{
|
||||
mozen_tunnel_send_response(tunnel, tunnel->target_cmd, false);
|
||||
mozen_tunnel_abort(tunnel);
|
||||
return;
|
||||
}
|
||||
|
||||
tunnel->received_data_len += chunk_len;
|
||||
tunnel->next_packet_index++;
|
||||
|
||||
mozen_tunnel_send_response(tunnel, tunnel->target_cmd, true);
|
||||
|
||||
if (tunnel->next_packet_index > tunnel->total_packets)
|
||||
{
|
||||
if (tunnel->received_data_len == tunnel->total_data_len)
|
||||
{
|
||||
if (tunnel->on_finish)
|
||||
{
|
||||
tunnel->on_finish(tunnel->user_context, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tunnel->on_finish)
|
||||
{
|
||||
tunnel->on_finish(tunnel->user_context, false);
|
||||
}
|
||||
}
|
||||
tunnel->is_active = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
113
app_cail/moxzen_protocol/mozen_tunnel.h
Normal file
113
app_cail/moxzen_protocol/mozen_tunnel.h
Normal file
@@ -0,0 +1,113 @@
|
||||
#ifndef __MOZEN_TUNNEL_H
|
||||
#define __MOZEN_TUNNEL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "mozen_protocol.h"
|
||||
|
||||
// --- Tunnel Protocol Definitions ---
|
||||
|
||||
#define MOZEN_TUNNEL_COMMAND_ID 0xFB // Tunnel command ID
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TUNNEL_TYPE_HANDSHAKE = 0x01, // Handshake request
|
||||
TUNNEL_TYPE_DATA_TRANSFER = 0x02, // Data transfer
|
||||
TUNNEL_TYPE_RESPONSE = 0xFF, // Special type for responses
|
||||
} mozen_tunnel_type_t;
|
||||
|
||||
#pragma pack(1)
|
||||
// <20><><EFBFBD><EFBFBD>Э<EFBFBD><D0AD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD>
|
||||
typedef struct {
|
||||
uint8_t tunnel_type;
|
||||
uint8_t target_cmd;
|
||||
} mozen_tunnel_header_t;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṹ<EFBFBD><E1B9B9>
|
||||
typedef struct {
|
||||
mozen_tunnel_header_t header;
|
||||
uint32_t total_data_length;
|
||||
uint16_t total_packets;
|
||||
} mozen_tunnel_handshake_req_t;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݰ<EFBFBD><DDB0>ṹ<EFBFBD><E1B9B9>
|
||||
typedef struct {
|
||||
mozen_tunnel_header_t header;
|
||||
uint16_t status; // 'ok' or 'NG'
|
||||
uint16_t mtu;
|
||||
} mozen_tunnel_handshake_res_t;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ṹ<EFBFBD><E1B9B9>
|
||||
typedef struct {
|
||||
mozen_tunnel_header_t header;
|
||||
uint16_t packet_index;
|
||||
uint8_t data_chunk[]; // Flexible array member for data
|
||||
} mozen_tunnel_data_t;
|
||||
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD>ṹ<EFBFBD><E1B9B9>
|
||||
typedef struct {
|
||||
mozen_tunnel_header_t header;
|
||||
uint16_t status; // 'ok' or 'NG'
|
||||
} mozen_tunnel_response_t;
|
||||
#pragma pack()
|
||||
|
||||
// --- Tunnel Context and Callbacks ---
|
||||
|
||||
/**
|
||||
* @brief Callback for starting a stream write.
|
||||
* @param context User context.
|
||||
* @param target_cmd The command indicating the stream target.
|
||||
* @param first_chunk_data The first chunk of data, useful for analyzing sub-headers.
|
||||
* @param chunk_len Length of the first chunk.
|
||||
* @return True if streaming can begin, false to reject.
|
||||
*/
|
||||
typedef bool (*mozen_tunnel_on_stream_start_t)(void *context, uint8_t target_cmd, const uint8_t *first_chunk_data, uint16_t chunk_len);
|
||||
|
||||
/**
|
||||
* @brief Callback for continuing a stream write.
|
||||
* @param context User context.
|
||||
* @param data Chunk data.
|
||||
* @param len Chunk length.
|
||||
* @return True if chunk accepted, false to abort.
|
||||
*/
|
||||
typedef bool (*mozen_tunnel_on_stream_data_t)(void *context, const uint8_t *data, uint16_t len);
|
||||
|
||||
/**
|
||||
* @brief Callback for finishing a stream write.
|
||||
* @param context User context.
|
||||
* @param success True if the transfer completed successfully, false if aborted.
|
||||
*/
|
||||
typedef void (*mozen_tunnel_on_stream_finish_t)(void *context, bool success);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool is_active;
|
||||
uint8_t target_cmd;
|
||||
uint32_t total_data_len;
|
||||
uint16_t total_packets;
|
||||
uint16_t next_packet_index;
|
||||
uint32_t received_data_len;
|
||||
|
||||
// Config
|
||||
uint16_t mtu; // Max packet size
|
||||
mozen_protocol_t *prot; // For sending ACKs
|
||||
void *user_context; // For callbacks
|
||||
|
||||
// Callbacks
|
||||
mozen_tunnel_on_stream_start_t on_start;
|
||||
mozen_tunnel_on_stream_data_t on_data;
|
||||
mozen_tunnel_on_stream_finish_t on_finish;
|
||||
} mozen_tunnel_t;
|
||||
|
||||
// --- API ---
|
||||
|
||||
void mozen_tunnel_init(mozen_tunnel_t *tunnel, mozen_protocol_t *prot, uint16_t mtu, void *user_context);
|
||||
|
||||
void mozen_tunnel_set_callbacks(mozen_tunnel_t *tunnel,
|
||||
mozen_tunnel_on_stream_start_t on_start,
|
||||
mozen_tunnel_on_stream_data_t on_data,
|
||||
mozen_tunnel_on_stream_finish_t on_finish);
|
||||
|
||||
void mozen_tunnel_handle_command(mozen_tunnel_t *tunnel, const uint8_t *data, uint16_t length);
|
||||
|
||||
#endif // __MOZEN_TUNNEL_H
|
||||
429
app_cail/mx_log/logRTT/SEGGER_RTT_V782c/Config/SEGGER_RTT_Conf.h
Normal file
429
app_cail/mx_log/logRTT/SEGGER_RTT_V782c/Config/SEGGER_RTT_Conf.h
Normal file
@@ -0,0 +1,429 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.82c *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_Conf.h
|
||||
Purpose : Implementation of SEGGER real-time transfer (RTT) which
|
||||
allows real-time communication on targets which support
|
||||
debugger memory accesses while the CPU is running.
|
||||
Revision: $Rev: 24316 $
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_RTT_CONF_H
|
||||
#define SEGGER_RTT_CONF_H
|
||||
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
#include <intrinsics.h>
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// Take in and set to correct values for Cortex-A systems with CPU cache
|
||||
//
|
||||
//#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (32) // Largest cache line size (in bytes) in the current system
|
||||
//#define SEGGER_RTT_UNCACHED_OFF (0xFB000000) // Address alias where RTT CB and buffers can be accessed uncached
|
||||
//
|
||||
// Most common case:
|
||||
// Up-channel 0: RTT
|
||||
// Up-channel 1: SystemView
|
||||
//
|
||||
#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS
|
||||
#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (3) // Max. number of up-buffers (T->H) available on this target (Default: 3)
|
||||
#endif
|
||||
//
|
||||
// Most common case:
|
||||
// Down-channel 0: RTT
|
||||
// Down-channel 1: SystemView
|
||||
//
|
||||
#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS
|
||||
#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (3) // Max. number of down-buffers (H->T) available on this target (Default: 3)
|
||||
#endif
|
||||
|
||||
#ifndef BUFFER_SIZE_UP
|
||||
#define BUFFER_SIZE_UP (1024)// (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k)
|
||||
#endif
|
||||
|
||||
#ifndef BUFFER_SIZE_DOWN
|
||||
#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16)
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
|
||||
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64)
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_MODE_DEFAULT
|
||||
#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP//SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL // Mode for pre-initialized terminal channel (buffer 0)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT memcpy configuration
|
||||
*
|
||||
* memcpy() is good for large amounts of data,
|
||||
* but the overhead is big for small amounts, which are usually stored via RTT.
|
||||
* With SEGGER_RTT_MEMCPY_USE_BYTELOOP a simple byte loop can be used instead.
|
||||
*
|
||||
* SEGGER_RTT_MEMCPY() can be used to replace standard memcpy() in RTT functions.
|
||||
* This is may be required with memory access restrictions,
|
||||
* such as on Cortex-A devices with MMU.
|
||||
*/
|
||||
#ifndef SEGGER_RTT_MEMCPY_USE_BYTELOOP
|
||||
#define SEGGER_RTT_MEMCPY_USE_BYTELOOP 0 // 0: Use memcpy/SEGGER_RTT_MEMCPY, 1: Use a simple byte-loop
|
||||
#endif
|
||||
//
|
||||
// Example definition of SEGGER_RTT_MEMCPY to external memcpy with GCC toolchains and Cortex-A targets
|
||||
//
|
||||
//#if ((defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__)) && (defined (__ARM_ARCH_7A__))
|
||||
// #define SEGGER_RTT_MEMCPY(pDest, pSrc, NumBytes) SEGGER_memcpy((pDest), (pSrc), (NumBytes))
|
||||
//#endif
|
||||
|
||||
//
|
||||
// Target is not allowed to perform other RTT operations while string still has not been stored completely.
|
||||
// Otherwise we would probably end up with a mixed string in the buffer.
|
||||
// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here.
|
||||
//
|
||||
// SEGGER_RTT_MAX_INTERRUPT_PRIORITY can be used in the sample lock routines on Cortex-M3/4.
|
||||
// Make sure to mask all interrupts which can send RTT data, i.e. generate SystemView events, or cause task switches.
|
||||
// When high-priority interrupts must not be masked while sending RTT data, SEGGER_RTT_MAX_INTERRUPT_PRIORITY needs to be adjusted accordingly.
|
||||
// (Higher priority = lower priority number)
|
||||
// Default value for embOS: 128u
|
||||
// Default configuration in FreeRTOS: configMAX_SYSCALL_INTERRUPT_PRIORITY: ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
|
||||
// In case of doubt mask all interrupts: 1 << (8 - BASEPRI_PRIO_BITS) i.e. 1 << 5 when 3 bits are implemented in NVIC
|
||||
// or define SEGGER_RTT_LOCK() to completely disable interrupts.
|
||||
//
|
||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20) // Interrupt priority to lock on SEGGER_RTT_LOCK on Cortex-M3/4 (Default: 0x20)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for SEGGER Embedded Studio,
|
||||
* Rowley CrossStudio and GCC
|
||||
*/
|
||||
#if ((defined(__SES_ARM) || defined(__SES_RISCV) || defined(__CROSSWORKS_ARM) || defined(__GNUC__) || defined(__clang__)) && !defined (__CC_ARM) && !defined(WIN32))
|
||||
#if (defined(__ARM_ARCH_6M__) || defined(__ARM_ARCH_8M_BASE__))
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("mrs %0, primask \n\t" \
|
||||
"movs r1, #1 \n\t" \
|
||||
"msr primask, r1 \n\t" \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
: "r1", "cc" \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr primask, %0 \n\t" \
|
||||
: \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
); \
|
||||
}
|
||||
#elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_8M_MAIN__))
|
||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||
#endif
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("mrs %0, basepri \n\t" \
|
||||
"mov r1, %1 \n\t" \
|
||||
"msr basepri, r1 \n\t" \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: "i"(SEGGER_RTT_MAX_INTERRUPT_PRIORITY) \
|
||||
: "r1", "cc" \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("msr basepri, %0 \n\t" \
|
||||
: \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
); \
|
||||
}
|
||||
|
||||
#elif (defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__))
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("mrs r1, CPSR \n\t" \
|
||||
"mov %0, r1 \n\t" \
|
||||
"orr r1, r1, #0xC0 \n\t" \
|
||||
"msr CPSR_c, r1 \n\t" \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
: "r1", "cc" \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \
|
||||
"mrs r1, CPSR \n\t" \
|
||||
"bic r1, r1, #0xC0 \n\t" \
|
||||
"and r0, r0, #0xC0 \n\t" \
|
||||
"orr r1, r1, r0 \n\t" \
|
||||
"msr CPSR_c, r1 \n\t" \
|
||||
: \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: "r0", "r1", "cc" \
|
||||
); \
|
||||
}
|
||||
#elif defined(__riscv) || defined(__riscv_xlen)
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("csrr %0, mstatus \n\t" \
|
||||
"csrci mstatus, 8 \n\t" \
|
||||
"andi %0, %0, 8 \n\t" \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
: \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("csrr a1, mstatus \n\t" \
|
||||
"or %0, %0, a1 \n\t" \
|
||||
"csrs mstatus, %0 \n\t" \
|
||||
: \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: "a1" \
|
||||
); \
|
||||
}
|
||||
#else
|
||||
#define SEGGER_RTT_LOCK()
|
||||
#define SEGGER_RTT_UNLOCK()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for IAR EWARM
|
||||
*/
|
||||
#ifdef __ICCARM__
|
||||
#if (defined (__ARM6M__) && (__CORE__ == __ARM6M__)) || \
|
||||
(defined (__ARM8M_BASELINE__) && (__CORE__ == __ARM8M_BASELINE__))
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_PRIMASK(); \
|
||||
__set_PRIMASK(1);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) || \
|
||||
(defined (__ARM7M__) && (__CORE__ == __ARM7M__)) || \
|
||||
(defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__)) || \
|
||||
(defined (__ARM8M_MAINLINE__) && (__CORE__ == __ARM8M_MAINLINE__))
|
||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||
#endif
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_BASEPRI(); \
|
||||
__set_BASEPRI(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_BASEPRI(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#elif (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || \
|
||||
(defined (__ARM7R__) && (__CORE__ == __ARM7R__))
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
__asm volatile ("mrs r1, CPSR \n\t" \
|
||||
"mov %0, r1 \n\t" \
|
||||
"orr r1, r1, #0xC0 \n\t" \
|
||||
"msr CPSR_c, r1 \n\t" \
|
||||
: "=r" (_SEGGER_RTT__LockState) \
|
||||
: \
|
||||
: "r1", "cc" \
|
||||
);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __asm volatile ("mov r0, %0 \n\t" \
|
||||
"mrs r1, CPSR \n\t" \
|
||||
"bic r1, r1, #0xC0 \n\t" \
|
||||
"and r0, r0, #0xC0 \n\t" \
|
||||
"orr r1, r1, r0 \n\t" \
|
||||
"msr CPSR_c, r1 \n\t" \
|
||||
: \
|
||||
: "r" (_SEGGER_RTT__LockState) \
|
||||
: "r0", "r1", "cc" \
|
||||
); \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for IAR RX
|
||||
*/
|
||||
#ifdef __ICCRX__
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned long _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_interrupt_state(); \
|
||||
__disable_interrupt();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for IAR RL78
|
||||
*/
|
||||
#ifdef __ICCRL78__
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
__istate_t _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_interrupt_state(); \
|
||||
__disable_interrupt();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_interrupt_state(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for KEIL ARM
|
||||
*/
|
||||
#ifdef __CC_ARM
|
||||
#if (defined __TARGET_ARCH_6S_M)
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
register unsigned char _SEGGER_RTT__PRIMASK __asm( "primask"); \
|
||||
_SEGGER_RTT__LockState = _SEGGER_RTT__PRIMASK; \
|
||||
_SEGGER_RTT__PRIMASK = 1u; \
|
||||
__schedule_barrier();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() _SEGGER_RTT__PRIMASK = _SEGGER_RTT__LockState; \
|
||||
__schedule_barrier(); \
|
||||
}
|
||||
#elif (defined(__TARGET_ARCH_7_M) || defined(__TARGET_ARCH_7E_M))
|
||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||
#endif
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
register unsigned char BASEPRI __asm( "basepri"); \
|
||||
_SEGGER_RTT__LockState = BASEPRI; \
|
||||
BASEPRI = SEGGER_RTT_MAX_INTERRUPT_PRIORITY; \
|
||||
__schedule_barrier();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() BASEPRI = _SEGGER_RTT__LockState; \
|
||||
__schedule_barrier(); \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for TI ARM
|
||||
*/
|
||||
#ifdef __TI_ARM__
|
||||
#if defined (__TI_ARM_V6M0__)
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = __get_PRIMASK(); \
|
||||
__set_PRIMASK(1);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() __set_PRIMASK(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#elif (defined (__TI_ARM_V7M3__) || defined (__TI_ARM_V7M4__))
|
||||
#ifndef SEGGER_RTT_MAX_INTERRUPT_PRIORITY
|
||||
#define SEGGER_RTT_MAX_INTERRUPT_PRIORITY (0x20)
|
||||
#endif
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned int _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = _set_interrupt_priority(SEGGER_RTT_MAX_INTERRUPT_PRIORITY);
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() _set_interrupt_priority(_SEGGER_RTT__LockState); \
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for CCRX
|
||||
*/
|
||||
#ifdef __RX
|
||||
#include <machine.h>
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
unsigned long _SEGGER_RTT__LockState; \
|
||||
_SEGGER_RTT__LockState = get_psw() & 0x010000; \
|
||||
clrpsw_i();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() set_psw(get_psw() | _SEGGER_RTT__LockState); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration for embOS Simulation on Windows
|
||||
* (Can also be used for generic RTT locking with embOS)
|
||||
*/
|
||||
#if defined(WIN32) || defined(SEGGER_RTT_LOCK_EMBOS)
|
||||
|
||||
void OS_SIM_EnterCriticalSection(void);
|
||||
void OS_SIM_LeaveCriticalSection(void);
|
||||
|
||||
#define SEGGER_RTT_LOCK() { \
|
||||
OS_SIM_EnterCriticalSection();
|
||||
|
||||
#define SEGGER_RTT_UNLOCK() OS_SIM_LeaveCriticalSection(); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT lock configuration fallback
|
||||
*/
|
||||
#ifndef SEGGER_RTT_LOCK
|
||||
#define SEGGER_RTT_LOCK() // Lock RTT (nestable) (i.e. disable interrupts)
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_UNLOCK
|
||||
#define SEGGER_RTT_UNLOCK() // Unlock RTT (nestable) (i.e. enable previous interrupt lock state)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,80 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.82c *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
--------- END-OF-HEADER --------------------------------------------
|
||||
File : Main_RTT_MenuApp.c
|
||||
Purpose : Sample application to demonstrate RTT bi-directional functionality
|
||||
*/
|
||||
|
||||
#define MAIN_C
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
volatile int _Cnt;
|
||||
volatile int _Delay;
|
||||
|
||||
static char r;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* main
|
||||
*/
|
||||
void main(void) {
|
||||
|
||||
SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n");
|
||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
|
||||
do {
|
||||
r = SEGGER_RTT_WaitKey();
|
||||
SEGGER_RTT_Write(0, &r, 1);
|
||||
r++;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,108 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.82c *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
--------- END-OF-HEADER --------------------------------------------
|
||||
File : Main_RTT_MenuApp.c
|
||||
Purpose : Sample application to demonstrate RTT bi-directional functionality
|
||||
*/
|
||||
|
||||
#define MAIN_C
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
volatile int _Cnt;
|
||||
volatile int _Delay;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* main
|
||||
*/
|
||||
void main(void) {
|
||||
int r;
|
||||
int CancelOp;
|
||||
|
||||
do {
|
||||
_Cnt = 0;
|
||||
|
||||
SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n");
|
||||
SEGGER_RTT_WriteString(0, "Press <1> to continue in blocking mode (Application waits if necessary, no data lost)\r\n");
|
||||
SEGGER_RTT_WriteString(0, "Press <2> to continue in non-blocking mode (Application does not wait, data lost if fifo full)\r\n");
|
||||
do {
|
||||
r = SEGGER_RTT_WaitKey();
|
||||
} while ((r != '1') && (r != '2'));
|
||||
if (r == '1') {
|
||||
SEGGER_RTT_WriteString(0, "\r\nSelected <1>. Configuring RTT and starting...\r\n");
|
||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
|
||||
} else {
|
||||
SEGGER_RTT_WriteString(0, "\r\nSelected <2>. Configuring RTT and starting...\r\n");
|
||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
|
||||
}
|
||||
CancelOp = 0;
|
||||
do {
|
||||
//for (_Delay = 0; _Delay < 10000; _Delay++);
|
||||
SEGGER_RTT_printf(0, "Count: %d. Press <Space> to get back to menu.\r\n", _Cnt++);
|
||||
r = SEGGER_RTT_HasKey();
|
||||
if (r) {
|
||||
CancelOp = (SEGGER_RTT_GetKey() == ' ') ? 1 : 0;
|
||||
}
|
||||
//
|
||||
// Check if user selected to cancel the current operation
|
||||
//
|
||||
if (CancelOp) {
|
||||
SEGGER_RTT_WriteString(0, "Operation cancelled, going back to menu...\r\n");
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
SEGGER_RTT_GetKey();
|
||||
SEGGER_RTT_WriteString(0, "\r\n");
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,155 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.82c *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
--------- END-OF-HEADER --------------------------------------------
|
||||
File : Main_RTT_MenuApp.c
|
||||
Purpose : Sample application to demonstrate RTT bi-directional functionality
|
||||
*/
|
||||
|
||||
#define MAIN_C
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
volatile int _Cnt;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* main
|
||||
*/
|
||||
void main(void) {
|
||||
|
||||
SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
|
||||
|
||||
SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n\r\n");
|
||||
SEGGER_RTT_WriteString(0, "###### Testing SEGGER_printf() ######\r\n");
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%c, 'S' : %c.\r\n", 'S');
|
||||
SEGGER_RTT_printf(0, "printf Test: %%5c, 'E' : %5c.\r\n", 'E');
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-5c, 'G' : %-5c.\r\n", 'G');
|
||||
SEGGER_RTT_printf(0, "printf Test: %%5.3c, 'G' : %-5c.\r\n", 'G');
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.3c, 'E' : %-5c.\r\n", 'E');
|
||||
SEGGER_RTT_printf(0, "printf Test: %%c, 'R' : %c.\r\n", 'R');
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\" : %s.\r\n", "RTT");
|
||||
SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\\r\\nRocks.\" : %s.\r\n", "RTT\r\nRocks.");
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%u, 12345 : %u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%+u, 12345 : %+u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.3u, 12345 : %.3u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.6u, 12345 : %.6u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%6.3u, 12345 : %6.3u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%8.6u, 12345 : %8.6u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08u, 12345 : %08u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08.6u, 12345 : %08.6u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%0u, 12345 : %0u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-.6u, 12345 : %-.6u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-6.3u, 12345 : %-6.3u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-8.6u, 12345 : %-8.6u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08u, 12345 : %-08u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08.6u, 12345 : %-08.6u.\r\n", 12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-0u, 12345 : %-0u.\r\n", 12345);
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%u, -12345 : %u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%+u, -12345 : %+u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.3u, -12345 : %.3u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.6u, -12345 : %.6u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%6.3u, -12345 : %6.3u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%8.6u, -12345 : %8.6u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08u, -12345 : %08u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08.6u, -12345 : %08.6u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%0u, -12345 : %0u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-.6u, -12345 : %-.6u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-6.3u, -12345 : %-6.3u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-8.6u, -12345 : %-8.6u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08u, -12345 : %-08u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08.6u, -12345 : %-08.6u.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-0u, -12345 : %-0u.\r\n", -12345);
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%d, -12345 : %d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%+d, -12345 : %+d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.3d, -12345 : %.3d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.6d, -12345 : %.6d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%6.3d, -12345 : %6.3d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%8.6d, -12345 : %8.6d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08d, -12345 : %08d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08.6d, -12345 : %08.6d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%0d, -12345 : %0d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-.6d, -12345 : %-.6d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-6.3d, -12345 : %-6.3d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-8.6d, -12345 : %-8.6d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08d, -12345 : %-08d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08.6d, -12345 : %-08.6d.\r\n", -12345);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-0d, -12345 : %-0d.\r\n", -12345);
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%x, 0x1234ABC : %x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%+x, 0x1234ABC : %+x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.3x, 0x1234ABC : %.3x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%.6x, 0x1234ABC : %.6x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%6.3x, 0x1234ABC : %6.3x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%8.6x, 0x1234ABC : %8.6x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08x, 0x1234ABC : %08x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%08.6x, 0x1234ABC : %08.6x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%0x, 0x1234ABC : %0x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-.6x, 0x1234ABC : %-.6x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-6.3x, 0x1234ABC : %-6.3x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-8.6x, 0x1234ABC : %-8.6x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08x, 0x1234ABC : %-08x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-08.6x, 0x1234ABC : %-08.6x.\r\n", 0x1234ABC);
|
||||
SEGGER_RTT_printf(0, "printf Test: %%-0x, 0x1234ABC : %-0x.\r\n", 0x1234ABC);
|
||||
|
||||
SEGGER_RTT_printf(0, "printf Test: %%p, &_Cnt : %p.\r\n", &_Cnt);
|
||||
|
||||
SEGGER_RTT_WriteString(0, "###### SEGGER_printf() Tests done. ######\r\n");
|
||||
do {
|
||||
_Cnt++;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,106 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.82c *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
--------- END-OF-HEADER --------------------------------------------
|
||||
File : Main_RTT_SpeedTestApp.c
|
||||
Purpose : Sample program for measuring RTT performance.
|
||||
*/
|
||||
|
||||
#include "RTOS.h"
|
||||
#include "BSP.h"
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
#include <stdio.h>
|
||||
|
||||
OS_STACKPTR int StackHP[128], StackLP[128]; /* Task stacks */
|
||||
OS_TASK TCBHP, TCBLP; /* Task-control-blocks */
|
||||
|
||||
static void HPTask(void) {
|
||||
while (1) {
|
||||
//
|
||||
// Measure time needed for RTT output
|
||||
// Perform dummy write with 0 characters, so we know the overhead of toggling LEDs and RTT in general
|
||||
//
|
||||
// Set BP here. Then start sampling on scope
|
||||
BSP_ClrLED(0);
|
||||
SEGGER_RTT_Write(0, 0, 0);
|
||||
BSP_SetLED(0);
|
||||
BSP_ClrLED(0);
|
||||
SEGGER_RTT_Write(0, "01234567890123456789012345678901234567890123456789012345678901234567890123456789\r\n", 82);
|
||||
BSP_SetLED(0);
|
||||
// Set BP here. Then stop sampling on scope
|
||||
OS_Delay(200);
|
||||
}
|
||||
}
|
||||
|
||||
static void LPTask(void) {
|
||||
while (1) {
|
||||
BSP_ToggleLED(1);
|
||||
OS_Delay (500);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* main
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
int main(void) {
|
||||
OS_IncDI(); /* Initially disable interrupts */
|
||||
OS_InitKern(); /* Initialize OS */
|
||||
OS_InitHW(); /* Initialize Hardware for OS */
|
||||
BSP_Init(); /* Initialize LED ports */
|
||||
BSP_SetLED(0);
|
||||
/* You need to create at least one task before calling OS_Start() */
|
||||
OS_CREATETASK(&TCBHP, "HP Task", HPTask, 100, StackHP);
|
||||
OS_CREATETASK(&TCBLP, "LP Task", LPTask, 50, StackLP);
|
||||
OS_Start(); /* Start multitasking */
|
||||
return 0;
|
||||
}
|
||||
|
||||
36
app_cail/mx_log/logRTT/SEGGER_RTT_V782c/LICENSE.md
Normal file
36
app_cail/mx_log/logRTT/SEGGER_RTT_V782c/LICENSE.md
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
SEGGER Microcontroller GmbH
|
||||
The Embedded Experts
|
||||
|
||||
(c) 1995 - 2021 SEGGER Microcontroller GmbH
|
||||
www.segger.com Support: support@segger.com
|
||||
|
||||
SEGGER RTT Real Time Transfer for embedded targets
|
||||
|
||||
|
||||
All rights reserved.
|
||||
|
||||
SEGGER strongly recommends to not make any changes
|
||||
to or modify the source code of this software in order to stay
|
||||
compatible with the RTT protocol and J-Link.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, are permitted provided that the following
|
||||
condition is met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this condition and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGE.
|
||||
24
app_cail/mx_log/logRTT/SEGGER_RTT_V782c/README.md
Normal file
24
app_cail/mx_log/logRTT/SEGGER_RTT_V782c/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
RTT
|
||||
===
|
||||
|
||||
SEGGER RTT Sources
|
||||
|
||||
https://www.segger.com/products/debug-probes/j-link/technology/about-real-time-transfer
|
||||
https://wiki.segger.com/RTT
|
||||
|
||||
## Included files
|
||||
|
||||
* `RTT/`
|
||||
* `SEGGER_RTT.c` - Main module for RTT.
|
||||
* `SEGGER_RTT.h` - Main header for RTT.
|
||||
* `SEGGER_RTT_ASM_ARMv7M.S` - Assembly-optimized implementation of RTT functions for ARMv7M processors.
|
||||
* `SEGGER_RTT_Printf.c` - Simple implementation of printf (`SEGGER_RTT_Printf()`) to write formatted strings via RTT.
|
||||
* `Syscalls/`
|
||||
* `SEGGER_RTT_Syscalls_*.c` - Low-level syscalls to retarget `printf()` to RTT with different toolchains.
|
||||
* `Config/`
|
||||
* `SEGGER_RTT_Conf.h` - RTT configuration file.
|
||||
* `Examples/`
|
||||
* `Main_RTT_InputEchoApp.c` - Example application which echoes input on Channel 0.
|
||||
* `Main_RTT_MenuApp.c` - Example application to demonstrate RTT bi-directional functionality.
|
||||
* `Main_RTT_PrintfTest.c` - Example application to test RTT's simple printf implementation.
|
||||
* `Main_RTT_SpeedTestApp.c` - Example application to measure RTT performance. (Requires embOS)
|
||||
2103
app_cail/mx_log/logRTT/SEGGER_RTT_V782c/RTT/SEGGER_RTT.c
Normal file
2103
app_cail/mx_log/logRTT/SEGGER_RTT_V782c/RTT/SEGGER_RTT.c
Normal file
File diff suppressed because it is too large
Load Diff
493
app_cail/mx_log/logRTT/SEGGER_RTT_V782c/RTT/SEGGER_RTT.h
Normal file
493
app_cail/mx_log/logRTT/SEGGER_RTT_V782c/RTT/SEGGER_RTT.h
Normal file
@@ -0,0 +1,493 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.82c *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT.h
|
||||
Purpose : Implementation of SEGGER real-time transfer which allows
|
||||
real-time communication on targets which support debugger
|
||||
memory accesses while the CPU is running.
|
||||
Revision: $Rev: 25842 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_RTT_H
|
||||
#define SEGGER_RTT_H
|
||||
|
||||
#include "../Config/SEGGER_RTT_Conf.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, defaults
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef RTT_USE_ASM
|
||||
//
|
||||
// Some cores support out-of-order memory accesses (reordering of memory accesses in the core)
|
||||
// For such cores, we need to define a memory barrier to guarantee the order of certain accesses to the RTT ring buffers.
|
||||
// Needed for:
|
||||
// Cortex-M7 (ARMv7-M)
|
||||
// Cortex-M23 (ARM-v8M)
|
||||
// Cortex-M33 (ARM-v8M)
|
||||
// Cortex-A/R (ARM-v7A/R)
|
||||
//
|
||||
// We do not explicitly check for "Embedded Studio" as the compiler in use determines what we support.
|
||||
// You can use an external toolchain like IAR inside ES. So there is no point in checking for "Embedded Studio"
|
||||
//
|
||||
#if (defined __CROSSWORKS_ARM) // Rowley Crossworks
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#if (defined __ARM_ARCH_7M__) // Cortex-M3
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#else
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
#elif (defined __ARMCC_VERSION)
|
||||
//
|
||||
// ARM compiler
|
||||
// ARM compiler V6.0 and later is clang based.
|
||||
// Our ASM part is compatible to clang.
|
||||
//
|
||||
#if (__ARMCC_VERSION >= 6000000)
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#else
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
#if (defined __ARM_ARCH_6M__) // Cortex-M0 / M1
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0 // No ASM support for this architecture
|
||||
#elif (defined __ARM_ARCH_7M__) // Cortex-M3
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif ((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) // Cortex-A/R 32-bit ARMv7-A/R
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#else
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
#elif ((defined __GNUC__) || (defined __clang__))
|
||||
//
|
||||
// GCC / Clang
|
||||
//
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
// ARM 7/9: __ARM_ARCH_5__ / __ARM_ARCH_5E__ / __ARM_ARCH_5T__ / __ARM_ARCH_5T__ / __ARM_ARCH_5TE__
|
||||
#if (defined __ARM_ARCH_7M__) // Cortex-M3
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#elif (defined __ARM_ARCH_7EM__) // Cortex-M4/M7
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1 // Only Cortex-M7 needs a DMB but we cannot distinguish M4 and M7 here...
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_BASE__) // Cortex-M23
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif (defined __ARM_ARCH_8M_MAIN__) // Cortex-M33
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#elif ((defined __ARM_ARCH_7A__) || (defined __ARM_ARCH_7R__)) // Cortex-A/R 32-bit ARMv7-A/R
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() __asm volatile ("dmb\n" : : :);
|
||||
#else
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
#elif ((defined __IASMARM__) || (defined __ICCARM__))
|
||||
//
|
||||
// IAR assembler/compiler
|
||||
//
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 1
|
||||
#if (__VER__ < 6300000)
|
||||
#define VOLATILE
|
||||
#else
|
||||
#define VOLATILE volatile
|
||||
#endif
|
||||
#if (defined __ARM7M__) // Needed for old versions that do not know the define yet
|
||||
#if (__CORE__ == __ARM7M__) // Cortex-M3
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM7EM__)
|
||||
#if (__CORE__ == __ARM7EM__) // Cortex-M4/M7
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM8M_BASELINE__)
|
||||
#if (__CORE__ == __ARM8M_BASELINE__) // Cortex-M23
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM8M_MAINLINE__)
|
||||
#if (__CORE__ == __ARM8M_MAINLINE__) // Cortex-M33
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM8EM_MAINLINE__)
|
||||
#if (__CORE__ == __ARM8EM_MAINLINE__) // Cortex-???
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 1
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM7A__)
|
||||
#if (__CORE__ == __ARM7A__) // Cortex-A 32-bit ARMv7-A
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
#if (defined __ARM7R__)
|
||||
#if (__CORE__ == __ARM7R__) // Cortex-R 32-bit ARMv7-R
|
||||
#define _CORE_NEEDS_DMB 1
|
||||
#define RTT__DMB() asm VOLATILE ("DMB");
|
||||
#endif
|
||||
#endif
|
||||
// TBD: __ARM8A__ => Cortex-A 64-bit ARMv8-A
|
||||
// TBD: __ARM8R__ => Cortex-R 64-bit ARMv8-R
|
||||
#else
|
||||
//
|
||||
// Other compilers
|
||||
//
|
||||
#define _CC_HAS_RTT_ASM_SUPPORT 0
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0
|
||||
#endif
|
||||
//
|
||||
// If IDE and core support the ASM version, enable ASM version by default
|
||||
//
|
||||
#ifndef _CORE_HAS_RTT_ASM_SUPPORT
|
||||
#define _CORE_HAS_RTT_ASM_SUPPORT 0 // Default for unknown cores
|
||||
#endif
|
||||
#if (_CC_HAS_RTT_ASM_SUPPORT && _CORE_HAS_RTT_ASM_SUPPORT)
|
||||
#define RTT_USE_ASM (1)
|
||||
#else
|
||||
#define RTT_USE_ASM (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef _CORE_NEEDS_DMB
|
||||
#define _CORE_NEEDS_DMB 0
|
||||
#endif
|
||||
|
||||
#ifndef RTT__DMB
|
||||
#if _CORE_NEEDS_DMB
|
||||
#error "Don't know how to place inline assembly for DMB"
|
||||
#else
|
||||
#define RTT__DMB()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_CPU_CACHE_LINE_SIZE
|
||||
#define SEGGER_RTT_CPU_CACHE_LINE_SIZE (0) // On most target systems where RTT is used, we do not have a CPU cache, therefore 0 is a good default here
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_UNCACHED_OFF
|
||||
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE
|
||||
#error "SEGGER_RTT_UNCACHED_OFF must be defined when setting SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
|
||||
#else
|
||||
#define SEGGER_RTT_UNCACHED_OFF (0)
|
||||
#endif
|
||||
#endif
|
||||
#if RTT_USE_ASM
|
||||
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE
|
||||
#error "RTT_USE_ASM is not available if SEGGER_RTT_CPU_CACHE_LINE_SIZE != 0"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SEGGER_RTT_ASM // defined when SEGGER_RTT.h is included from assembly file
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, fixed
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// Determine how much we must pad the control block to make it a multiple of a cache line in size
|
||||
// Assuming: U8 = 1B
|
||||
// U16 = 2B
|
||||
// U32 = 4B
|
||||
// U8/U16/U32* = 4B
|
||||
//
|
||||
#if SEGGER_RTT_CPU_CACHE_LINE_SIZE // Avoid division by zero in case we do not have any cache
|
||||
#define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (((NumBytes + SEGGER_RTT_CPU_CACHE_LINE_SIZE - 1) / SEGGER_RTT_CPU_CACHE_LINE_SIZE) * SEGGER_RTT_CPU_CACHE_LINE_SIZE)
|
||||
#else
|
||||
#define SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(NumBytes) (NumBytes)
|
||||
#endif
|
||||
#define SEGGER_RTT__CB_SIZE (16 + 4 + 4 + (SEGGER_RTT_MAX_NUM_UP_BUFFERS * 24) + (SEGGER_RTT_MAX_NUM_DOWN_BUFFERS * 24))
|
||||
#define SEGGER_RTT__CB_PADDING (SEGGER_RTT__ROUND_UP_2_CACHE_LINE_SIZE(SEGGER_RTT__CB_SIZE) - SEGGER_RTT__CB_SIZE)
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Types
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// Description for a circular buffer (also called "ring buffer")
|
||||
// which is used as up-buffer (T->H)
|
||||
//
|
||||
typedef struct {
|
||||
const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
|
||||
char* pBuffer; // Pointer to start of buffer
|
||||
unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
|
||||
unsigned WrOff; // Position of next item to be written by either target.
|
||||
volatile unsigned RdOff; // Position of next item to be read by host. Must be volatile since it may be modified by host.
|
||||
unsigned Flags; // Contains configuration flags. Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
|
||||
} SEGGER_RTT_BUFFER_UP;
|
||||
|
||||
//
|
||||
// Description for a circular buffer (also called "ring buffer")
|
||||
// which is used as down-buffer (H->T)
|
||||
//
|
||||
typedef struct {
|
||||
const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4"
|
||||
char* pBuffer; // Pointer to start of buffer
|
||||
unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty.
|
||||
volatile unsigned WrOff; // Position of next item to be written by host. Must be volatile since it may be modified by host.
|
||||
unsigned RdOff; // Position of next item to be read by target (down-buffer).
|
||||
unsigned Flags; // Contains configuration flags. Flags[31:24] are used for validity check and must be zero. Flags[23:2] are reserved for future use. Flags[1:0] = RTT operating mode.
|
||||
} SEGGER_RTT_BUFFER_DOWN;
|
||||
|
||||
//
|
||||
// RTT control block which describes the number of buffers available
|
||||
// as well as the configuration for each buffer
|
||||
//
|
||||
//
|
||||
typedef struct {
|
||||
char acID[16]; // Initialized to "SEGGER RTT"
|
||||
int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2)
|
||||
int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2)
|
||||
SEGGER_RTT_BUFFER_UP aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host
|
||||
SEGGER_RTT_BUFFER_DOWN aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target
|
||||
#if SEGGER_RTT__CB_PADDING
|
||||
unsigned char aDummy[SEGGER_RTT__CB_PADDING];
|
||||
#endif
|
||||
} SEGGER_RTT_CB;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global data
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
extern SEGGER_RTT_CB _SEGGER_RTT;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT API functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int SEGGER_RTT_AllocDownBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
||||
int SEGGER_RTT_AllocUpBuffer (const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
||||
int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
||||
int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags);
|
||||
int SEGGER_RTT_GetKey (void);
|
||||
unsigned SEGGER_RTT_HasData (unsigned BufferIndex);
|
||||
int SEGGER_RTT_HasKey (void);
|
||||
unsigned SEGGER_RTT_HasDataUp (unsigned BufferIndex);
|
||||
void SEGGER_RTT_Init (void);
|
||||
unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize);
|
||||
unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize);
|
||||
int SEGGER_RTT_SetNameDownBuffer (unsigned BufferIndex, const char* sName);
|
||||
int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName);
|
||||
int SEGGER_RTT_SetFlagsDownBuffer (unsigned BufferIndex, unsigned Flags);
|
||||
int SEGGER_RTT_SetFlagsUpBuffer (unsigned BufferIndex, unsigned Flags);
|
||||
int SEGGER_RTT_WaitKey (void);
|
||||
unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_ASM_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s);
|
||||
void SEGGER_RTT_WriteWithOverwriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_PutChar (unsigned BufferIndex, char c);
|
||||
unsigned SEGGER_RTT_PutCharSkip (unsigned BufferIndex, char c);
|
||||
unsigned SEGGER_RTT_PutCharSkipNoLock (unsigned BufferIndex, char c);
|
||||
unsigned SEGGER_RTT_GetAvailWriteSpace (unsigned BufferIndex);
|
||||
unsigned SEGGER_RTT_GetBytesInBuffer (unsigned BufferIndex);
|
||||
//
|
||||
// Function macro for performance optimization
|
||||
//
|
||||
#define SEGGER_RTT_HASDATA(n) (((SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_DOWN*)((char*)&_SEGGER_RTT.aDown[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff)
|
||||
|
||||
#if RTT_USE_ASM
|
||||
#define SEGGER_RTT_WriteSkipNoLock SEGGER_RTT_ASM_WriteSkipNoLock
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT transfer functions to send RTT data via other channels.
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
unsigned SEGGER_RTT_ReadUpBuffer (unsigned BufferIndex, void* pBuffer, unsigned BufferSize);
|
||||
unsigned SEGGER_RTT_ReadUpBufferNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize);
|
||||
unsigned SEGGER_RTT_WriteDownBuffer (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
unsigned SEGGER_RTT_WriteDownBufferNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes);
|
||||
|
||||
#define SEGGER_RTT_HASDATA_UP(n) (((SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->WrOff - ((SEGGER_RTT_BUFFER_UP*)((char*)&_SEGGER_RTT.aUp[n] + SEGGER_RTT_UNCACHED_OFF))->RdOff) // Access uncached to make sure we see changes made by the J-Link side and all of our changes go into HW directly
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT "Terminal" API functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
int SEGGER_RTT_SetTerminal (unsigned char TerminalId);
|
||||
int SEGGER_RTT_TerminalOut (unsigned char TerminalId, const char* s);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* RTT printf functions (require SEGGER_RTT_printf.c)
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...);
|
||||
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ifndef(SEGGER_RTT_ASM)
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
//
|
||||
// Operating modes. Define behavior if buffer is full (not enough space for entire message)
|
||||
//
|
||||
#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0) // Skip. Do not block, output nothing. (Default)
|
||||
#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1) // Trim: Do not block, output as much as fits.
|
||||
#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2) // Block: Wait until there is space in the buffer.
|
||||
#define SEGGER_RTT_MODE_MASK (3)
|
||||
|
||||
//
|
||||
// Control sequences, based on ANSI.
|
||||
// Can be used to control color, and clear the screen
|
||||
//
|
||||
#define RTT_CTRL_RESET "\x1B[0m" // Reset to default colors
|
||||
#define RTT_CTRL_CLEAR "\x1B[2J" // Clear screen, reposition cursor to top left
|
||||
|
||||
#define RTT_CTRL_TEXT_BLACK "\x1B[2;30m"
|
||||
#define RTT_CTRL_TEXT_RED "\x1B[2;31m"
|
||||
#define RTT_CTRL_TEXT_GREEN "\x1B[2;32m"
|
||||
#define RTT_CTRL_TEXT_YELLOW "\x1B[2;33m"
|
||||
#define RTT_CTRL_TEXT_BLUE "\x1B[2;34m"
|
||||
#define RTT_CTRL_TEXT_MAGENTA "\x1B[2;35m"
|
||||
#define RTT_CTRL_TEXT_CYAN "\x1B[2;36m"
|
||||
#define RTT_CTRL_TEXT_WHITE "\x1B[2;37m"
|
||||
|
||||
#define RTT_CTRL_TEXT_BRIGHT_BLACK "\x1B[1;30m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_RED "\x1B[1;31m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_GREEN "\x1B[1;32m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\x1B[1;33m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_BLUE "\x1B[1;34m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\x1B[1;35m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_CYAN "\x1B[1;36m"
|
||||
#define RTT_CTRL_TEXT_BRIGHT_WHITE "\x1B[1;37m"
|
||||
|
||||
#define RTT_CTRL_BG_BLACK "\x1B[24;40m"
|
||||
#define RTT_CTRL_BG_RED "\x1B[24;41m"
|
||||
#define RTT_CTRL_BG_GREEN "\x1B[24;42m"
|
||||
#define RTT_CTRL_BG_YELLOW "\x1B[24;43m"
|
||||
#define RTT_CTRL_BG_BLUE "\x1B[24;44m"
|
||||
#define RTT_CTRL_BG_MAGENTA "\x1B[24;45m"
|
||||
#define RTT_CTRL_BG_CYAN "\x1B[24;46m"
|
||||
#define RTT_CTRL_BG_WHITE "\x1B[24;47m"
|
||||
|
||||
#define RTT_CTRL_BG_BRIGHT_BLACK "\x1B[4;40m"
|
||||
#define RTT_CTRL_BG_BRIGHT_RED "\x1B[4;41m"
|
||||
#define RTT_CTRL_BG_BRIGHT_GREEN "\x1B[4;42m"
|
||||
#define RTT_CTRL_BG_BRIGHT_YELLOW "\x1B[4;43m"
|
||||
#define RTT_CTRL_BG_BRIGHT_BLUE "\x1B[4;44m"
|
||||
#define RTT_CTRL_BG_BRIGHT_MAGENTA "\x1B[4;45m"
|
||||
#define RTT_CTRL_BG_BRIGHT_CYAN "\x1B[4;46m"
|
||||
#define RTT_CTRL_BG_BRIGHT_WHITE "\x1B[4;47m"
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,242 @@
|
||||
/*********************************************************************
|
||||
* (c) SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
* www.segger.com *
|
||||
**********************************************************************
|
||||
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
|
||||
File : SEGGER_RTT_ASM_ARMv7M.S
|
||||
Purpose : Assembler implementation of RTT functions for ARMv7M
|
||||
|
||||
Additional information:
|
||||
This module is written to be assembler-independent and works with
|
||||
GCC and clang (Embedded Studio) and IAR.
|
||||
*/
|
||||
|
||||
#define SEGGER_RTT_ASM // Used to control processed input from header file
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, fixed
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#define _CCIAR 0
|
||||
#define _CCCLANG 1
|
||||
|
||||
#if (defined __SES_ARM) || (defined __GNUC__) || (defined __clang__)
|
||||
#define _CC_TYPE _CCCLANG
|
||||
#define _PUB_SYM .global
|
||||
#define _EXT_SYM .extern
|
||||
#define _END .end
|
||||
#define _WEAK .weak
|
||||
#define _THUMB_FUNC .thumb_func
|
||||
#define _THUMB_CODE .code 16
|
||||
#define _WORD .word
|
||||
#define _SECTION(Sect, Type, AlignExp) .section Sect ##, "ax"
|
||||
#define _ALIGN(Exp) .align Exp
|
||||
#define _PLACE_LITS .ltorg
|
||||
#define _DATA_SECT_START
|
||||
#define _C_STARTUP _start
|
||||
#define _STACK_END __stack_end__
|
||||
#define _RAMFUNC
|
||||
//
|
||||
// .text => Link to flash
|
||||
// .fast => Link to RAM
|
||||
// OtherSect => Usually link to RAM
|
||||
// Alignment is 2^x
|
||||
//
|
||||
#elif defined (__IASMARM__)
|
||||
#define _CC_TYPE _CCIAR
|
||||
#define _PUB_SYM PUBLIC
|
||||
#define _EXT_SYM EXTERN
|
||||
#define _END END
|
||||
#define _WEAK _WEAK
|
||||
#define _THUMB_FUNC
|
||||
#define _THUMB_CODE THUMB
|
||||
#define _WORD DCD
|
||||
#define _SECTION(Sect, Type, AlignExp) SECTION Sect ## : ## Type ## :REORDER:NOROOT ## (AlignExp)
|
||||
#define _ALIGN(Exp) alignrom Exp
|
||||
#define _PLACE_LITS
|
||||
#define _DATA_SECT_START DATA
|
||||
#define _C_STARTUP __iar_program_start
|
||||
#define _STACK_END sfe(CSTACK)
|
||||
#define _RAMFUNC SECTION_TYPE SHT_PROGBITS, SHF_WRITE | SHF_EXECINSTR
|
||||
//
|
||||
// .text => Link to flash
|
||||
// .textrw => Link to RAM
|
||||
// OtherSect => Usually link to RAM
|
||||
// NOROOT => Allows linker to throw away the function, if not referenced
|
||||
// Alignment is 2^x
|
||||
//
|
||||
#endif
|
||||
|
||||
#if (_CC_TYPE == _CCIAR)
|
||||
NAME SEGGER_RTT_ASM_ARMv7M
|
||||
#else
|
||||
.syntax unified
|
||||
#endif
|
||||
|
||||
#if defined (RTT_USE_ASM) && (RTT_USE_ASM == 1)
|
||||
#define SHT_PROGBITS 0x1
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public / external symbols
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
_EXT_SYM __aeabi_memcpy
|
||||
_EXT_SYM __aeabi_memcpy4
|
||||
_EXT_SYM _SEGGER_RTT
|
||||
|
||||
_PUB_SYM SEGGER_RTT_ASM_WriteSkipNoLock
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_WriteSkipNoLock
|
||||
*
|
||||
* Function description
|
||||
* Stores a specified number of characters in SEGGER RTT
|
||||
* control block which is then read by the host.
|
||||
* SEGGER_RTT_WriteSkipNoLock does not lock the application and
|
||||
* skips all data, if the data does not fit into the buffer.
|
||||
*
|
||||
* Parameters
|
||||
* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal").
|
||||
* pBuffer Pointer to character array. Does not need to point to a \0 terminated string.
|
||||
* NumBytes Number of bytes to be stored in the SEGGER RTT control block.
|
||||
* MUST be > 0!!!
|
||||
* This is done for performance reasons, so no initial check has do be done.
|
||||
*
|
||||
* Return value
|
||||
* 1: Data has been copied
|
||||
* 0: No space, data has not been copied
|
||||
*
|
||||
* Notes
|
||||
* (1) If there is not enough space in the "Up"-buffer, all data is dropped.
|
||||
* (2) For performance reasons this function does not call Init()
|
||||
* and may only be called after RTT has been initialized.
|
||||
* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
|
||||
*/
|
||||
_SECTION(.text, CODE, 2)
|
||||
_ALIGN(2)
|
||||
_THUMB_FUNC
|
||||
SEGGER_RTT_ASM_WriteSkipNoLock: // unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pData, unsigned NumBytes) {
|
||||
//
|
||||
// Cases:
|
||||
// 1) RdOff <= WrOff => Space until wrap-around is sufficient
|
||||
// 2) RdOff <= WrOff => Space after wrap-around needed (copy in 2 chunks)
|
||||
// 3) RdOff < WrOff => No space in buf
|
||||
// 4) RdOff > WrOff => Space is sufficient
|
||||
// 5) RdOff > WrOff => No space in buf
|
||||
//
|
||||
// 1) is the most common case for large buffers and assuming that J-Link reads the data fast enough
|
||||
//
|
||||
// Register usage:
|
||||
// R0 Temporary needed as RdOff, <Tmp> register later on
|
||||
// R1 pData
|
||||
// R2 <NumBytes>
|
||||
// R3 <Tmp> register. Hold free for subroutine calls
|
||||
// R4 <Rem>
|
||||
// R5 pRing->pBuffer
|
||||
// R6 pRing (Points to active struct SEGGER_RTT_BUFFER_DOWN)
|
||||
// R7 WrOff
|
||||
//
|
||||
PUSH {R4-R7}
|
||||
ADD R3,R0,R0, LSL #+1
|
||||
LDR.W R0,=_SEGGER_RTT // pRing = &_SEGGER_RTT.aUp[BufferIndex];
|
||||
ADD R0,R0,R3, LSL #+3
|
||||
ADD R6,R0,#+24
|
||||
LDR R0,[R6, #+16] // RdOff = pRing->RdOff;
|
||||
LDR R7,[R6, #+12] // WrOff = pRing->WrOff;
|
||||
LDR R5,[R6, #+4] // pRing->pBuffer
|
||||
CMP R7,R0
|
||||
BCC.N _CheckCase4 // if (RdOff <= WrOff) { => Case 1), 2) or 3)
|
||||
//
|
||||
// Handling for case 1, later on identical to case 4
|
||||
//
|
||||
LDR R3,[R6, #+8] // Avail = pRing->SizeOfBuffer - WrOff - 1u; => Space until wrap-around (assume 1 byte not usable for case that RdOff == 0)
|
||||
SUBS R4,R3,R7 // <Rem> (Used in case we jump into case 2 afterwards)
|
||||
SUBS R3,R4,#+1 // <Avail>
|
||||
CMP R3,R2
|
||||
BCC.N _CheckCase2 // if (Avail >= NumBytes) { => Case 1)?
|
||||
_Case4:
|
||||
ADDS R5,R7,R5 // pBuffer += WrOff
|
||||
ADDS R0,R2,R7 // v = WrOff + NumBytes
|
||||
//
|
||||
// 2x unrolling for the copy loop that is used most of the time
|
||||
// This is a special optimization for small SystemView packets and makes them even faster
|
||||
//
|
||||
_ALIGN(2)
|
||||
_LoopCopyStraight: // memcpy(pRing->pBuffer + WrOff, pData, NumBytes);
|
||||
LDRB R3,[R1], #+1
|
||||
STRB R3,[R5], #+1 // *pDest++ = *pSrc++
|
||||
SUBS R2,R2,#+1
|
||||
BEQ _CSDone
|
||||
LDRB R3,[R1], #+1
|
||||
STRB R3,[R5], #+1 // *pDest++ = *pSrc++
|
||||
SUBS R2,R2,#+1
|
||||
BNE _LoopCopyStraight
|
||||
_CSDone:
|
||||
#if _CORE_NEEDS_DMB // Do not slow down cores that do not need a DMB instruction here
|
||||
DMB // Cortex-M7 may delay memory writes and also change the order in which the writes happen. Therefore, make sure that all buffer writes are finished, before updating the <WrOff> in the struct
|
||||
#endif
|
||||
STR R0,[R6, #+12] // pRing->WrOff = WrOff + NumBytes;
|
||||
MOVS R0,#+1
|
||||
POP {R4-R7}
|
||||
BX LR // Return 1
|
||||
_CheckCase2:
|
||||
ADDS R0,R0,R3 // Avail += RdOff; => Space incl. wrap-around
|
||||
CMP R0,R2
|
||||
BCC.N _Case3 // if (Avail >= NumBytes) { => Case 2? => If not, we have case 3) (does not fit)
|
||||
//
|
||||
// Handling for case 2
|
||||
//
|
||||
ADDS R0,R7,R5 // v = pRing->pBuffer + WrOff => Do not change pRing->pBuffer here because 2nd chunk needs org. value
|
||||
SUBS R2,R2,R4 // NumBytes -= Rem; (Rem = pRing->SizeOfBuffer - WrOff; => Space until end of buffer)
|
||||
_LoopCopyBeforeWrapAround: // memcpy(pRing->pBuffer + WrOff, pData, Rem); => Copy 1st chunk
|
||||
LDRB R3,[R1], #+1
|
||||
STRB R3,[R0], #+1 // *pDest++ = *pSrc++
|
||||
SUBS R4,R4,#+1
|
||||
BNE _LoopCopyBeforeWrapAround
|
||||
//
|
||||
// Special case: First check that assumed RdOff == 0 calculated that last element before wrap-around could not be used
|
||||
// But 2nd check (considering space until wrap-around and until RdOff) revealed that RdOff is not 0, so we can use the last element
|
||||
// In this case, we may use a copy straight until buffer end anyway without needing to copy 2 chunks
|
||||
// Therefore, check if 2nd memcpy is necessary at all
|
||||
//
|
||||
ADDS R4,R2,#+0 // Save <NumBytes> (needed as counter in loop but must be written to <WrOff> after the loop). Also use this inst to update the flags to skip 2nd loop if possible
|
||||
BEQ.N _No2ChunkNeeded // if (NumBytes) {
|
||||
_LoopCopyAfterWrapAround: // memcpy(pRing->pBuffer, pData + Rem, NumBytes);
|
||||
LDRB R3,[R1], #+1 // pData already points to the next src byte due to copy loop increment before this loop
|
||||
STRB R3,[R5], #+1 // *pDest++ = *pSrc++
|
||||
SUBS R2,R2,#+1
|
||||
BNE _LoopCopyAfterWrapAround
|
||||
_No2ChunkNeeded:
|
||||
#if _CORE_NEEDS_DMB // Do not slow down cores that do not need a DMB instruction here
|
||||
DMB // Cortex-M7 may delay memory writes and also change the order in which the writes happen. Therefore, make sure that all buffer writes are finished, before updating the <WrOff> in the struct
|
||||
#endif
|
||||
STR R4,[R6, #+12] // pRing->WrOff = NumBytes; => Must be written after copying data because J-Link may read control block asynchronously while writing into buffer
|
||||
MOVS R0,#+1
|
||||
POP {R4-R7}
|
||||
BX LR // Return 1
|
||||
_CheckCase4:
|
||||
SUBS R0,R0,R7
|
||||
SUBS R0,R0,#+1 // Avail = RdOff - WrOff - 1u;
|
||||
CMP R0,R2
|
||||
BCS.N _Case4 // if (Avail >= NumBytes) { => Case 4) == 1) ? => If not, we have case 5) == 3) (does not fit)
|
||||
_Case3:
|
||||
MOVS R0,#+0
|
||||
POP {R4-R7}
|
||||
BX LR // Return 0
|
||||
_PLACE_LITS
|
||||
|
||||
#endif // defined (RTT_USE_ASM) && (RTT_USE_ASM == 1)
|
||||
_END
|
||||
|
||||
/*************************** End of file ****************************/
|
||||
505
app_cail/mx_log/logRTT/SEGGER_RTT_V782c/RTT/SEGGER_RTT_printf.c
Normal file
505
app_cail/mx_log/logRTT/SEGGER_RTT_V782c/RTT/SEGGER_RTT_printf.c
Normal file
@@ -0,0 +1,505 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.82c *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_printf.c
|
||||
Purpose : Replacement for printf to write formatted data via RTT
|
||||
Revision: $Rev: 17697 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#include "SEGGER_RTT.h"
|
||||
#include "SEGGER_RTT_Conf.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE
|
||||
#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64)
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0)
|
||||
#define FORMAT_FLAG_PAD_ZERO (1u << 1)
|
||||
#define FORMAT_FLAG_PRINT_SIGN (1u << 2)
|
||||
#define FORMAT_FLAG_ALTERNATE (1u << 3)
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Types
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
char* pBuffer;
|
||||
unsigned BufferSize;
|
||||
unsigned Cnt;
|
||||
|
||||
int ReturnValue;
|
||||
|
||||
unsigned RTTBufferIndex;
|
||||
} SEGGER_RTT_PRINTF_DESC;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function prototypes
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Static code
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* _StoreChar
|
||||
*/
|
||||
static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) {
|
||||
unsigned Cnt;
|
||||
|
||||
Cnt = p->Cnt;
|
||||
if ((Cnt + 1u) <= p->BufferSize) {
|
||||
*(p->pBuffer + Cnt) = c;
|
||||
p->Cnt = Cnt + 1u;
|
||||
p->ReturnValue++;
|
||||
}
|
||||
//
|
||||
// Write part of string, when the buffer is full
|
||||
//
|
||||
if (p->Cnt == p->BufferSize) {
|
||||
if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) {
|
||||
p->ReturnValue = -1;
|
||||
} else {
|
||||
p->Cnt = 0u;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _PrintUnsigned
|
||||
*/
|
||||
static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
|
||||
static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
unsigned Div;
|
||||
unsigned Digit;
|
||||
unsigned Number;
|
||||
unsigned Width;
|
||||
char c;
|
||||
|
||||
Number = v;
|
||||
Digit = 1u;
|
||||
//
|
||||
// Get actual field width
|
||||
//
|
||||
Width = 1u;
|
||||
while (Number >= Base) {
|
||||
Number = (Number / Base);
|
||||
Width++;
|
||||
}
|
||||
if (NumDigits > Width) {
|
||||
Width = NumDigits;
|
||||
}
|
||||
//
|
||||
// Print leading chars if necessary
|
||||
//
|
||||
if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) {
|
||||
if (FieldWidth != 0u) {
|
||||
if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) {
|
||||
c = '0';
|
||||
} else {
|
||||
c = ' ';
|
||||
}
|
||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||
FieldWidth--;
|
||||
_StoreChar(pBufferDesc, c);
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pBufferDesc->ReturnValue >= 0) {
|
||||
//
|
||||
// Compute Digit.
|
||||
// Loop until Digit has the value of the highest digit required.
|
||||
// Example: If the output is 345 (Base 10), loop 2 times until Digit is 100.
|
||||
//
|
||||
while (1) {
|
||||
if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned)
|
||||
NumDigits--;
|
||||
} else {
|
||||
Div = v / Digit;
|
||||
if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done
|
||||
break;
|
||||
}
|
||||
}
|
||||
Digit *= Base;
|
||||
}
|
||||
//
|
||||
// Output digits
|
||||
//
|
||||
do {
|
||||
Div = v / Digit;
|
||||
v -= Div * Digit;
|
||||
_StoreChar(pBufferDesc, _aV2C[Div]);
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
Digit /= Base;
|
||||
} while (Digit);
|
||||
//
|
||||
// Print trailing spaces if necessary
|
||||
//
|
||||
if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) {
|
||||
if (FieldWidth != 0u) {
|
||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||
FieldWidth--;
|
||||
_StoreChar(pBufferDesc, ' ');
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _PrintInt
|
||||
*/
|
||||
static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) {
|
||||
unsigned Width;
|
||||
int Number;
|
||||
|
||||
Number = (v < 0) ? -v : v;
|
||||
|
||||
//
|
||||
// Get actual field width
|
||||
//
|
||||
Width = 1u;
|
||||
while (Number >= (int)Base) {
|
||||
Number = (Number / (int)Base);
|
||||
Width++;
|
||||
}
|
||||
if (NumDigits > Width) {
|
||||
Width = NumDigits;
|
||||
}
|
||||
if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) {
|
||||
FieldWidth--;
|
||||
}
|
||||
|
||||
//
|
||||
// Print leading spaces if necessary
|
||||
//
|
||||
if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) {
|
||||
if (FieldWidth != 0u) {
|
||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||
FieldWidth--;
|
||||
_StoreChar(pBufferDesc, ' ');
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Print sign if necessary
|
||||
//
|
||||
if (pBufferDesc->ReturnValue >= 0) {
|
||||
if (v < 0) {
|
||||
v = -v;
|
||||
_StoreChar(pBufferDesc, '-');
|
||||
} else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) {
|
||||
_StoreChar(pBufferDesc, '+');
|
||||
} else {
|
||||
|
||||
}
|
||||
if (pBufferDesc->ReturnValue >= 0) {
|
||||
//
|
||||
// Print leading zeros if necessary
|
||||
//
|
||||
if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) {
|
||||
if (FieldWidth != 0u) {
|
||||
while ((FieldWidth != 0u) && (Width < FieldWidth)) {
|
||||
FieldWidth--;
|
||||
_StoreChar(pBufferDesc, '0');
|
||||
if (pBufferDesc->ReturnValue < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pBufferDesc->ReturnValue >= 0) {
|
||||
//
|
||||
// Print number without sign
|
||||
//
|
||||
_PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public code
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_vprintf
|
||||
*
|
||||
* Function description
|
||||
* Stores a formatted string in SEGGER RTT control block.
|
||||
* This data is read by the host.
|
||||
*
|
||||
* Parameters
|
||||
* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
|
||||
* sFormat Pointer to format string
|
||||
* pParamList Pointer to the list of arguments for the format string
|
||||
*
|
||||
* Return values
|
||||
* >= 0: Number of bytes which have been stored in the "Up"-buffer.
|
||||
* < 0: Error
|
||||
*/
|
||||
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) {
|
||||
char c;
|
||||
SEGGER_RTT_PRINTF_DESC BufferDesc;
|
||||
int v;
|
||||
unsigned NumDigits;
|
||||
unsigned FormatFlags;
|
||||
unsigned FieldWidth;
|
||||
char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE];
|
||||
|
||||
BufferDesc.pBuffer = acBuffer;
|
||||
BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE;
|
||||
BufferDesc.Cnt = 0u;
|
||||
BufferDesc.RTTBufferIndex = BufferIndex;
|
||||
BufferDesc.ReturnValue = 0;
|
||||
|
||||
do {
|
||||
c = *sFormat;
|
||||
sFormat++;
|
||||
if (c == 0u) {
|
||||
break;
|
||||
}
|
||||
if (c == '%') {
|
||||
//
|
||||
// Filter out flags
|
||||
//
|
||||
FormatFlags = 0u;
|
||||
v = 1;
|
||||
do {
|
||||
c = *sFormat;
|
||||
switch (c) {
|
||||
case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break;
|
||||
case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break;
|
||||
case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break;
|
||||
case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break;
|
||||
default: v = 0; break;
|
||||
}
|
||||
} while (v);
|
||||
//
|
||||
// filter out field with
|
||||
//
|
||||
FieldWidth = 0u;
|
||||
do {
|
||||
c = *sFormat;
|
||||
if ((c < '0') || (c > '9')) {
|
||||
break;
|
||||
}
|
||||
sFormat++;
|
||||
FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0');
|
||||
} while (1);
|
||||
|
||||
//
|
||||
// Filter out precision (number of digits to display)
|
||||
//
|
||||
NumDigits = 0u;
|
||||
c = *sFormat;
|
||||
if (c == '.') {
|
||||
sFormat++;
|
||||
do {
|
||||
c = *sFormat;
|
||||
if ((c < '0') || (c > '9')) {
|
||||
break;
|
||||
}
|
||||
sFormat++;
|
||||
NumDigits = NumDigits * 10u + ((unsigned)c - '0');
|
||||
} while (1);
|
||||
}
|
||||
//
|
||||
// Filter out length modifier
|
||||
//
|
||||
c = *sFormat;
|
||||
do {
|
||||
if ((c == 'l') || (c == 'h')) {
|
||||
sFormat++;
|
||||
c = *sFormat;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
//
|
||||
// Handle specifiers
|
||||
//
|
||||
switch (c) {
|
||||
case 'c': {
|
||||
char c0;
|
||||
v = va_arg(*pParamList, int);
|
||||
c0 = (char)v;
|
||||
_StoreChar(&BufferDesc, c0);
|
||||
break;
|
||||
}
|
||||
case 'd':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags);
|
||||
break;
|
||||
case 'u':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags);
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags);
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
const char * s = va_arg(*pParamList, const char *);
|
||||
do {
|
||||
c = *s;
|
||||
s++;
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
_StoreChar(&BufferDesc, c);
|
||||
} while (BufferDesc.ReturnValue >= 0);
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
v = va_arg(*pParamList, int);
|
||||
_PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u);
|
||||
break;
|
||||
case '%':
|
||||
_StoreChar(&BufferDesc, '%');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sFormat++;
|
||||
} else {
|
||||
_StoreChar(&BufferDesc, c);
|
||||
}
|
||||
} while (BufferDesc.ReturnValue >= 0);
|
||||
|
||||
if (BufferDesc.ReturnValue > 0) {
|
||||
//
|
||||
// Write remaining data, if any
|
||||
//
|
||||
if (BufferDesc.Cnt != 0u) {
|
||||
SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt);
|
||||
}
|
||||
BufferDesc.ReturnValue += (int)BufferDesc.Cnt;
|
||||
}
|
||||
return BufferDesc.ReturnValue;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* SEGGER_RTT_printf
|
||||
*
|
||||
* Function description
|
||||
* Stores a formatted string in SEGGER RTT control block.
|
||||
* This data is read by the host.
|
||||
*
|
||||
* Parameters
|
||||
* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal")
|
||||
* sFormat Pointer to format string, followed by the arguments for conversion
|
||||
*
|
||||
* Return values
|
||||
* >= 0: Number of bytes which have been stored in the "Up"-buffer.
|
||||
* < 0: Error
|
||||
*
|
||||
* Notes
|
||||
* (1) Conversion specifications have following syntax:
|
||||
* %[flags][FieldWidth][.Precision]ConversionSpecifier
|
||||
* (2) Supported flags:
|
||||
* -: Left justify within the field width
|
||||
* +: Always print sign extension for signed conversions
|
||||
* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision
|
||||
* Supported conversion specifiers:
|
||||
* c: Print the argument as one char
|
||||
* d: Print the argument as a signed integer
|
||||
* u: Print the argument as an unsigned integer
|
||||
* x: Print the argument as an hexadecimal integer
|
||||
* s: Print the string pointed to by the argument
|
||||
* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.)
|
||||
*/
|
||||
int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) {
|
||||
int r;
|
||||
va_list ParamList;
|
||||
|
||||
va_start(ParamList, sFormat);
|
||||
r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList);
|
||||
va_end(ParamList);
|
||||
return r;
|
||||
}
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,125 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.82c *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_Syscalls_GCC.c
|
||||
Purpose : Low-level functions for using printf() via RTT in GCC.
|
||||
To use RTT for printf output, include this file in your
|
||||
application.
|
||||
Revision: $Rev: 24316 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#if (defined __GNUC__) && !(defined __SES_ARM) && !(defined __CROSSWORKS_ARM) && !(defined __ARMCC_VERSION) && !(defined __CC_ARM)
|
||||
|
||||
#include <reent.h> // required for _write_r
|
||||
#include "SEGGER_RTT.h"
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Types
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//
|
||||
// If necessary define the _reent struct
|
||||
// to match the one passed by the used standard library.
|
||||
//
|
||||
struct _reent;
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function prototypes
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
_ssize_t _write (int file, const void *ptr, size_t len);
|
||||
_ssize_t _write_r(struct _reent *r, int file, const void *ptr, size_t len);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _write()
|
||||
*
|
||||
* Function description
|
||||
* Low-level write function.
|
||||
* libc subroutines will use this system routine for output to all files,
|
||||
* including stdout.
|
||||
* Write data via RTT.
|
||||
*/
|
||||
_ssize_t _write(int file, const void *ptr, size_t len) {
|
||||
(void) file; /* Not used, avoid warning */
|
||||
SEGGER_RTT_Write(0, ptr, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _write_r()
|
||||
*
|
||||
* Function description
|
||||
* Low-level reentrant write function.
|
||||
* libc subroutines will use this system routine for output to all files,
|
||||
* including stdout.
|
||||
* Write data via RTT.
|
||||
*/
|
||||
_ssize_t _write_r(struct _reent *r, int file, const void *ptr, size_t len) {
|
||||
(void) file; /* Not used, avoid warning */
|
||||
(void) r; /* Not used, avoid warning */
|
||||
SEGGER_RTT_Write(0, ptr, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif
|
||||
/****** End Of File *************************************************/
|
||||
@@ -0,0 +1,120 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.82c *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_Syscalls_IAR.c
|
||||
Purpose : Low-level functions for using printf() via RTT in IAR.
|
||||
To use RTT for printf output, include this file in your
|
||||
application and set the Library Configuration to Normal.
|
||||
Revision: $Rev: 24316 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#ifdef __IAR_SYSTEMS_ICC__
|
||||
|
||||
//
|
||||
// Since IAR EWARM V8 and EWRX V4, yfuns.h is considered as deprecated and LowLevelIOInterface.h
|
||||
// shall be used instead. To not break any compatibility with older compiler versions, we have a
|
||||
// version check in here.
|
||||
//
|
||||
#if ((defined __ICCARM__) && (__VER__ >= 8000000)) || ((defined __ICCRX__) && (__VER__ >= 400))
|
||||
#include <LowLevelIOInterface.h>
|
||||
#else
|
||||
#include <yfuns.h>
|
||||
#endif
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
#pragma module_name = "?__write"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function prototypes
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
size_t __write(int handle, const unsigned char * buffer, size_t size);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* __write()
|
||||
*
|
||||
* Function description
|
||||
* Low-level write function.
|
||||
* Standard library subroutines will use this system routine
|
||||
* for output to all files, including stdout.
|
||||
* Write data via RTT.
|
||||
*/
|
||||
size_t __write(int handle, const unsigned char * buffer, size_t size) {
|
||||
(void) handle; /* Not used, avoid warning */
|
||||
SEGGER_RTT_Write(0, (const char*)buffer, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* __write_buffered()
|
||||
*
|
||||
* Function description
|
||||
* Low-level write function.
|
||||
* Standard library subroutines will use this system routine
|
||||
* for output to all files, including stdout.
|
||||
* Write data via RTT.
|
||||
*/
|
||||
size_t __write_buffered(int handle, const unsigned char * buffer, size_t size) {
|
||||
(void) handle; /* Not used, avoid warning */
|
||||
SEGGER_RTT_Write(0, (const char*)buffer, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
#endif
|
||||
/****** End Of File *************************************************/
|
||||
@@ -0,0 +1,394 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.82c *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : RTT_Syscalls_KEIL.c
|
||||
Purpose : Retargeting module for KEIL MDK-CM3.
|
||||
Low-level functions for using printf() via RTT
|
||||
Revision: $Rev: 24316 $
|
||||
Notes : (1) https://wiki.segger.com/Keil_MDK-ARM#RTT_in_uVision
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#if (defined __CC_ARM) || (defined __ARMCC_VERSION)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <rt_sys.h>
|
||||
#include <rt_misc.h>
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
/*********************************************************************
|
||||
*
|
||||
* #pragmas
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
#if __ARMCC_VERSION < 6000000
|
||||
#pragma import(__use_no_semihosting)
|
||||
#endif
|
||||
|
||||
#ifdef _MICROLIB
|
||||
#pragma import(__use_full_stdio)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines non-configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/* Standard IO device handles - arbitrary, but any real file system handles must be
|
||||
less than 0x8000. */
|
||||
#define STDIN 0x8001 // Standard Input Stream
|
||||
#define STDOUT 0x8002 // Standard Output Stream
|
||||
#define STDERR 0x8003 // Standard Error Stream
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public const
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
#if __ARMCC_VERSION < 5000000
|
||||
//const char __stdin_name[] = "STDIN";
|
||||
const char __stdout_name[] = "STDOUT";
|
||||
const char __stderr_name[] = "STDERR";
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Public code
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _ttywrch
|
||||
*
|
||||
* Function description:
|
||||
* Outputs a character to the console
|
||||
*
|
||||
* Parameters:
|
||||
* c - character to output
|
||||
*
|
||||
*/
|
||||
void _ttywrch(int c) {
|
||||
fputc(c, stdout); // stdout
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_open
|
||||
*
|
||||
* Function description:
|
||||
* Opens the device/file in order to do read/write operations
|
||||
*
|
||||
* Parameters:
|
||||
* sName - sName of the device/file to open
|
||||
* OpenMode - This parameter is currently ignored
|
||||
*
|
||||
* Return value:
|
||||
* != 0 - Handle to the object to open, otherwise
|
||||
* == 0 -"device" is not handled by this module
|
||||
*
|
||||
*/
|
||||
FILEHANDLE _sys_open(const char * sName, int OpenMode) {
|
||||
(void)OpenMode;
|
||||
// Register standard Input Output devices.
|
||||
if (strcmp(sName, __stdout_name) == 0) {
|
||||
return (STDOUT);
|
||||
} else if (strcmp(sName, __stderr_name) == 0) {
|
||||
return (STDERR);
|
||||
} else
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_close
|
||||
*
|
||||
* Function description:
|
||||
* Closes the handle to the open device/file
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
*
|
||||
* Return value:
|
||||
* 0 - device/file closed
|
||||
*
|
||||
*/
|
||||
int _sys_close(FILEHANDLE hFile) {
|
||||
(void)hFile;
|
||||
return 0; // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_write
|
||||
*
|
||||
* Function description:
|
||||
* Writes the data to an open handle.
|
||||
* Currently this function only outputs data to the console
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
* pBuffer - Pointer to the data that shall be written
|
||||
* NumBytes - Number of bytes to write
|
||||
* Mode - The Mode that shall be used
|
||||
*
|
||||
* Return value:
|
||||
* Number of bytes *not* written to the file/device
|
||||
*
|
||||
*/
|
||||
int _sys_write(FILEHANDLE hFile, const unsigned char * pBuffer, unsigned NumBytes, int Mode) {
|
||||
int r = 0;
|
||||
|
||||
(void)Mode;
|
||||
if (hFile == STDOUT) {
|
||||
SEGGER_RTT_Write(0, (const char*)pBuffer, NumBytes);
|
||||
return 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_read
|
||||
*
|
||||
* Function description:
|
||||
* Reads data from an open handle.
|
||||
* Currently this modules does nothing.
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
* pBuffer - Pointer to buffer to store the read data
|
||||
* NumBytes - Number of bytes to read
|
||||
* Mode - The Mode that shall be used
|
||||
*
|
||||
* Return value:
|
||||
* Number of bytes read from the file/device
|
||||
*
|
||||
*/
|
||||
int _sys_read(FILEHANDLE hFile, unsigned char * pBuffer, unsigned NumBytes, int Mode) {
|
||||
(void)hFile;
|
||||
(void)pBuffer;
|
||||
(void)NumBytes;
|
||||
(void)Mode;
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_istty
|
||||
*
|
||||
* Function description:
|
||||
* This function shall return whether the opened file
|
||||
* is a console device or not.
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
*
|
||||
* Return value:
|
||||
* 1 - Device is a console
|
||||
* 0 - Device is not a console
|
||||
*
|
||||
*/
|
||||
int _sys_istty(FILEHANDLE hFile) {
|
||||
if (hFile > 0x8000) {
|
||||
return (1);
|
||||
}
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_seek
|
||||
*
|
||||
* Function description:
|
||||
* Seeks via the file to a specific position
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
* Pos -
|
||||
*
|
||||
* Return value:
|
||||
* int -
|
||||
*
|
||||
*/
|
||||
int _sys_seek(FILEHANDLE hFile, long Pos) {
|
||||
(void)hFile;
|
||||
(void)Pos;
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_ensure
|
||||
*
|
||||
* Function description:
|
||||
*
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
*
|
||||
* Return value:
|
||||
* int -
|
||||
*
|
||||
*/
|
||||
int _sys_ensure(FILEHANDLE hFile) {
|
||||
(void)hFile;
|
||||
return (-1); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_flen
|
||||
*
|
||||
* Function description:
|
||||
* Returns the length of the opened file handle
|
||||
*
|
||||
* Parameters:
|
||||
* hFile - Handle to a file opened via _sys_open
|
||||
*
|
||||
* Return value:
|
||||
* Length of the file
|
||||
*
|
||||
*/
|
||||
long _sys_flen(FILEHANDLE hFile) {
|
||||
(void)hFile;
|
||||
return (0); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_tmpnam
|
||||
*
|
||||
* Function description:
|
||||
* This function converts the file number fileno for a temporary
|
||||
* file to a unique filename, for example, tmp0001.
|
||||
*
|
||||
* Parameters:
|
||||
* pBuffer - Pointer to a buffer to store the name
|
||||
* FileNum - file number to convert
|
||||
* MaxLen - Size of the buffer
|
||||
*
|
||||
* Return value:
|
||||
* 1 - Error
|
||||
* 0 - Success
|
||||
*
|
||||
*/
|
||||
int _sys_tmpnam(char * pBuffer, int FileNum, unsigned MaxLen) {
|
||||
(void)pBuffer;
|
||||
(void)FileNum;
|
||||
(void)MaxLen;
|
||||
return (1); // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_command_string
|
||||
*
|
||||
* Function description:
|
||||
* This function shall execute a system command.
|
||||
*
|
||||
* Parameters:
|
||||
* cmd - Pointer to the command string
|
||||
* len - Length of the string
|
||||
*
|
||||
* Return value:
|
||||
* == NULL - Command was not successfully executed
|
||||
* == sCmd - Command was passed successfully
|
||||
*
|
||||
*/
|
||||
char * _sys_command_string(char * cmd, int len) {
|
||||
(void)len;
|
||||
return cmd; // Not implemented
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _sys_exit
|
||||
*
|
||||
* Function description:
|
||||
* This function is called when the application returns from main
|
||||
*
|
||||
* Parameters:
|
||||
* ReturnCode - Return code from the main function
|
||||
*
|
||||
*
|
||||
*/
|
||||
void _sys_exit(int ReturnCode) {
|
||||
(void)ReturnCode;
|
||||
while (1); // Not implemented
|
||||
}
|
||||
|
||||
#if __ARMCC_VERSION >= 5000000
|
||||
/*********************************************************************
|
||||
*
|
||||
* stdout_putchar
|
||||
*
|
||||
* Function description:
|
||||
* Put a character to the stdout
|
||||
*
|
||||
* Parameters:
|
||||
* ch - Character to output
|
||||
*
|
||||
*
|
||||
*/
|
||||
int stdout_putchar(int ch) {
|
||||
(void)ch;
|
||||
return ch; // Not implemented
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*************************** End of file ****************************/
|
||||
@@ -0,0 +1,252 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
* *
|
||||
* (c) 1995 - 2021 SEGGER Microcontroller GmbH *
|
||||
* *
|
||||
* www.segger.com Support: support@segger.com *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* SEGGER RTT * Real Time Transfer for embedded targets *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* SEGGER strongly recommends to not make any changes *
|
||||
* to or modify the source code of this software in order to stay *
|
||||
* compatible with the RTT protocol and J-Link. *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or *
|
||||
* without modification, are permitted provided that the following *
|
||||
* condition is met: *
|
||||
* *
|
||||
* o Redistributions of source code must retain the above copyright *
|
||||
* notice, this condition and the following disclaimer. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
||||
* DAMAGE. *
|
||||
* *
|
||||
**********************************************************************
|
||||
* *
|
||||
* RTT version: 7.82c *
|
||||
* *
|
||||
**********************************************************************
|
||||
|
||||
---------------------------END-OF-HEADER------------------------------
|
||||
File : SEGGER_RTT_Syscalls_SES.c
|
||||
Purpose : Reimplementation of printf, puts and __getchar using RTT
|
||||
in SEGGER Embedded Studio.
|
||||
To use RTT for printf output, include this file in your
|
||||
application.
|
||||
Revision: $Rev: 24316 $
|
||||
----------------------------------------------------------------------
|
||||
*/
|
||||
#if (defined __SES_ARM) || (defined __SES_RISCV) || (defined __CROSSWORKS_ARM)
|
||||
|
||||
#include "SEGGER_RTT.h"
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "limits.h"
|
||||
#include "__libc.h"
|
||||
#include "__vfprintf.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, configurable
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
//
|
||||
// Select string formatting implementation.
|
||||
//
|
||||
// RTT printf formatting
|
||||
// - Configurable stack usage. (SEGGER_RTT_PRINTF_BUFFER_SIZE in SEGGER_RTT_Conf.h)
|
||||
// - No maximum string length.
|
||||
// - Limited conversion specifiers and flags. (See SEGGER_RTT_printf.c)
|
||||
// Standard library printf formatting
|
||||
// - Configurable formatting capabilities.
|
||||
// - Full conversion specifier and flag support.
|
||||
// - Maximum string length has to be known or (slightly) slower character-wise output.
|
||||
//
|
||||
// #define PRINTF_USE_SEGGER_RTT_FORMATTING 0 // Use standard library formatting
|
||||
// #define PRINTF_USE_SEGGER_RTT_FORMATTING 1 // Use RTT formatting
|
||||
//
|
||||
#ifndef PRINTF_USE_SEGGER_RTT_FORMATTING
|
||||
#define PRINTF_USE_SEGGER_RTT_FORMATTING 0
|
||||
#endif
|
||||
//
|
||||
// If using standard library formatting,
|
||||
// select maximum output string buffer size or character-wise output.
|
||||
//
|
||||
// #define PRINTF_BUFFER_SIZE 0 // Use character-wise output
|
||||
// #define PRINTF_BUFFER_SIZE 128 // Default maximum string length
|
||||
//
|
||||
#ifndef PRINTF_BUFFER_SIZE
|
||||
#define PRINTF_BUFFER_SIZE 128
|
||||
#endif
|
||||
|
||||
#if PRINTF_USE_SEGGER_RTT_FORMATTING // Use SEGGER RTT formatting implementation
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function prototypes
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList);
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions, printf
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* printf()
|
||||
*
|
||||
* Function description
|
||||
* print a formatted string using RTT and SEGGER RTT formatting.
|
||||
*/
|
||||
int printf(const char *fmt,...) {
|
||||
int n;
|
||||
va_list args;
|
||||
|
||||
va_start (args, fmt);
|
||||
n = SEGGER_RTT_vprintf(0, fmt, &args);
|
||||
va_end(args);
|
||||
return n;
|
||||
}
|
||||
|
||||
#elif PRINTF_BUFFER_SIZE == 0 // Use standard library formatting with character-wise output
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Static functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
static int _putchar(int x, __printf_tag_ptr ctx) {
|
||||
(void)ctx;
|
||||
SEGGER_RTT_Write(0, (char *)&x, 1);
|
||||
return x;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions, printf
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* printf()
|
||||
*
|
||||
* Function description
|
||||
* print a formatted string character-wise, using RTT and standard
|
||||
* library formatting.
|
||||
*/
|
||||
int printf(const char *fmt, ...) {
|
||||
int n;
|
||||
va_list args;
|
||||
__printf_t iod;
|
||||
|
||||
va_start(args, fmt);
|
||||
iod.string = 0;
|
||||
iod.maxchars = INT_MAX;
|
||||
iod.output_fn = _putchar;
|
||||
SEGGER_RTT_LOCK();
|
||||
n = __vfprintf(&iod, fmt, args);
|
||||
SEGGER_RTT_UNLOCK();
|
||||
va_end(args);
|
||||
return n;
|
||||
}
|
||||
|
||||
#else // Use standard library formatting with static buffer
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions, printf
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* printf()
|
||||
*
|
||||
* Function description
|
||||
* print a formatted string using RTT and standard library formatting.
|
||||
*/
|
||||
int printf(const char *fmt,...) {
|
||||
int n;
|
||||
char aBuffer[PRINTF_BUFFER_SIZE];
|
||||
va_list args;
|
||||
|
||||
va_start (args, fmt);
|
||||
n = vsnprintf(aBuffer, sizeof(aBuffer), fmt, args);
|
||||
if (n > (int)sizeof(aBuffer)) {
|
||||
SEGGER_RTT_Write(0, aBuffer, sizeof(aBuffer));
|
||||
} else if (n > 0) {
|
||||
SEGGER_RTT_Write(0, aBuffer, n);
|
||||
}
|
||||
va_end(args);
|
||||
return n;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Global functions
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
/*********************************************************************
|
||||
*
|
||||
* puts()
|
||||
*
|
||||
* Function description
|
||||
* print a string using RTT.
|
||||
*/
|
||||
int puts(const char *s) {
|
||||
return SEGGER_RTT_WriteString(0, s);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* __putchar()
|
||||
*
|
||||
* Function description
|
||||
* Write one character via RTT.
|
||||
*/
|
||||
int __putchar(int x, __printf_tag_ptr ctx) {
|
||||
(void)ctx;
|
||||
SEGGER_RTT_Write(0, (char *)&x, 1);
|
||||
return x;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* __getchar()
|
||||
*
|
||||
* Function description
|
||||
* Wait for and get a character via RTT.
|
||||
*/
|
||||
int __getchar() {
|
||||
return SEGGER_RTT_WaitKey();
|
||||
}
|
||||
|
||||
#endif
|
||||
/****** End Of File *************************************************/
|
||||
66
app_cail/mx_log/logRTT/log_rtt.c
Normal file
66
app_cail/mx_log/logRTT/log_rtt.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @file log_rtt.c
|
||||
* @brief Legacy log_rtt compatibility wrapper over mx_log
|
||||
*/
|
||||
|
||||
#include "log_rtt.h"
|
||||
#include "mx_log.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if MX_LOG_BACKEND_RTT
|
||||
#include "SEGGER_RTT.h"
|
||||
#endif
|
||||
|
||||
static mx_log_level_t log_rtt_to_mx_level(log_level_t lvl)
|
||||
{
|
||||
switch (lvl) {
|
||||
case LOG_LVL_ERROR:
|
||||
return MX_LOG_LEVEL_ERROR;
|
||||
case LOG_LVL_WARN:
|
||||
return MX_LOG_LEVEL_WARN;
|
||||
case LOG_LVL_INFO:
|
||||
return MX_LOG_LEVEL_INFO;
|
||||
case LOG_LVL_DEBUG:
|
||||
default:
|
||||
return MX_LOG_LEVEL_DEBUG;
|
||||
}
|
||||
}
|
||||
|
||||
void log_rtt_set_level(log_level_t lvl)
|
||||
{
|
||||
mx_log_set_level(log_rtt_to_mx_level(lvl));
|
||||
}
|
||||
|
||||
void log_rtt_printf(log_level_t lvl, const char *tag, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
mx_log_vprintf(log_rtt_to_mx_level(lvl), tag, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void log_hex_frame(const char *tag, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
mx_log_hex_frame(tag, data, len);
|
||||
}
|
||||
|
||||
void log_rtt_init(void)
|
||||
{
|
||||
mx_log_init();
|
||||
}
|
||||
|
||||
#if MX_LOG_BACKEND_RTT
|
||||
/* Keep legacy printf redirection behavior only when RTT backend is enabled. */
|
||||
int fputc(int ch, FILE *f)
|
||||
{
|
||||
(void)f;
|
||||
{
|
||||
char c = (char)ch;
|
||||
SEGGER_RTT_Write(0, &c, 1);
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
#endif
|
||||
|
||||
20
app_cail/mx_log/logRTT/log_rtt.h
Normal file
20
app_cail/mx_log/logRTT/log_rtt.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
typedef enum {
|
||||
LOG_LVL_ERROR = 0,
|
||||
LOG_LVL_WARN = 1,
|
||||
LOG_LVL_INFO = 2,
|
||||
LOG_LVL_DEBUG = 3,
|
||||
} log_level_t;
|
||||
|
||||
void log_rtt_set_level(log_level_t lvl);
|
||||
void log_rtt_printf(log_level_t lvl, const char* tag, const char* fmt, ...);
|
||||
void log_rtt_init(void);
|
||||
void log_hex_frame(const char * tag , const uint8_t* data, uint16_t len);
|
||||
|
||||
#define LOGE(tag, fmt, ...) log_rtt_printf(LOG_LVL_ERROR, tag, fmt, ##__VA_ARGS__)
|
||||
#define LOGW(tag, fmt, ...) log_rtt_printf(LOG_LVL_WARN, tag, fmt, ##__VA_ARGS__)
|
||||
#define LOGI(tag, fmt, ...) log_rtt_printf(LOG_LVL_INFO, tag, fmt, ##__VA_ARGS__)
|
||||
#define LOGD(tag, fmt, ...) log_rtt_printf(LOG_LVL_DEBUG, tag, fmt, ##__VA_ARGS__)
|
||||
|
||||
192
app_cail/mx_log/mx_log.c
Normal file
192
app_cail/mx_log/mx_log.c
Normal file
@@ -0,0 +1,192 @@
|
||||
#include "mx_log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if MX_LOG_BACKEND_RTT
|
||||
#include "SEGGER_RTT.h"
|
||||
#endif
|
||||
|
||||
#ifndef MX_LOG_LINE_BUF_SIZE
|
||||
#define MX_LOG_LINE_BUF_SIZE 256U
|
||||
#endif
|
||||
|
||||
#ifndef MX_LOG_DEFAULT_LEVEL
|
||||
#define MX_LOG_DEFAULT_LEVEL MX_LOG_LEVEL_DEBUG
|
||||
#endif
|
||||
|
||||
static volatile mx_log_level_t s_log_level = MX_LOG_DEFAULT_LEVEL;
|
||||
static mx_log_writer_t s_log_writer = 0;
|
||||
static uint8_t s_log_inited = 0U;
|
||||
|
||||
static const char *mx_log_level_to_str(mx_log_level_t level)
|
||||
{
|
||||
switch (level) {
|
||||
case MX_LOG_LEVEL_ERROR:
|
||||
return "E";
|
||||
case MX_LOG_LEVEL_WARN:
|
||||
return "W";
|
||||
case MX_LOG_LEVEL_INFO:
|
||||
return "I";
|
||||
case MX_LOG_LEVEL_DEBUG:
|
||||
default:
|
||||
return "D";
|
||||
}
|
||||
}
|
||||
|
||||
static size_t mx_log_strnlen(const char *s, size_t maxlen)
|
||||
{
|
||||
size_t len = 0U;
|
||||
if (s == 0) {
|
||||
return 0U;
|
||||
}
|
||||
while ((len < maxlen) && (s[len] != '\0')) {
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static void mx_log_output_line(const char *line)
|
||||
{
|
||||
if (line == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (s_log_writer != 0) {
|
||||
s_log_writer(line);
|
||||
return;
|
||||
}
|
||||
|
||||
#if MX_LOG_BACKEND_RTT
|
||||
SEGGER_RTT_WriteString(0, line);
|
||||
#elif MX_LOG_BACKEND_STDIO
|
||||
(void)fputs(line, stdout);
|
||||
#else
|
||||
(void)line;
|
||||
#endif
|
||||
}
|
||||
|
||||
void mx_log_init(void)
|
||||
{
|
||||
if (s_log_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if MX_LOG_BACKEND_RTT
|
||||
SEGGER_RTT_Init();
|
||||
SEGGER_RTT_SetTerminal(0);
|
||||
#endif
|
||||
|
||||
s_log_inited = 1U;
|
||||
}
|
||||
|
||||
void mx_log_set_level(mx_log_level_t level)
|
||||
{
|
||||
s_log_level = level;
|
||||
}
|
||||
|
||||
mx_log_level_t mx_log_get_level(void)
|
||||
{
|
||||
return s_log_level;
|
||||
}
|
||||
|
||||
void mx_log_set_writer(mx_log_writer_t writer)
|
||||
{
|
||||
s_log_writer = writer;
|
||||
}
|
||||
|
||||
void mx_log_vprintf(mx_log_level_t level, const char *tag, const char *fmt, va_list ap)
|
||||
{
|
||||
char line[MX_LOG_LINE_BUF_SIZE];
|
||||
int prefix_len;
|
||||
int payload_len;
|
||||
size_t line_len;
|
||||
|
||||
if ((fmt == 0) || (level > s_log_level)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MX_LOG_ENABLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s_log_inited) {
|
||||
mx_log_init();
|
||||
}
|
||||
|
||||
prefix_len = snprintf(line,
|
||||
sizeof(line),
|
||||
"[%s][%s] ",
|
||||
mx_log_level_to_str(level),
|
||||
(tag != 0) ? tag : "");
|
||||
if (prefix_len < 0) {
|
||||
return;
|
||||
}
|
||||
if ((size_t)prefix_len >= sizeof(line)) {
|
||||
line[sizeof(line) - 1U] = '\0';
|
||||
mx_log_output_line(line);
|
||||
return;
|
||||
}
|
||||
|
||||
payload_len = vsnprintf(line + prefix_len, sizeof(line) - (size_t)prefix_len, fmt, ap);
|
||||
(void)payload_len;
|
||||
|
||||
line_len = mx_log_strnlen(line, sizeof(line));
|
||||
if ((line_len + 2U) < sizeof(line)) {
|
||||
line[line_len++] = '\r';
|
||||
line[line_len++] = '\n';
|
||||
line[line_len] = '\0';
|
||||
} else {
|
||||
line[sizeof(line) - 1U] = '\0';
|
||||
}
|
||||
|
||||
mx_log_output_line(line);
|
||||
}
|
||||
|
||||
void mx_log_printf(mx_log_level_t level, const char *tag, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
mx_log_vprintf(level, tag, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void mx_log_hex_frame(const char *tag, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
static const char hex[] = "0123456789ABCDEF";
|
||||
char line[(32U * 3U) + 1U];
|
||||
uint16_t i = 0U;
|
||||
|
||||
if ((data == 0) || (len == 0U)) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (i < len) {
|
||||
uint16_t chunk = (uint16_t)(len - i);
|
||||
uint16_t pos = 0U;
|
||||
uint16_t j;
|
||||
|
||||
if (chunk > 32U) {
|
||||
chunk = 32U;
|
||||
}
|
||||
|
||||
for (j = 0U; j < chunk; j++) {
|
||||
uint8_t v = data[(uint16_t)(i + j)];
|
||||
line[pos++] = hex[(v >> 4) & 0x0FU];
|
||||
line[pos++] = hex[v & 0x0FU];
|
||||
line[pos++] = ' ';
|
||||
}
|
||||
|
||||
if (pos > 0U) {
|
||||
line[pos - 1U] = '\0';
|
||||
} else {
|
||||
line[0] = '\0';
|
||||
}
|
||||
|
||||
MX_LOGD((tag != 0) ? tag : "HEX", "%s", line);
|
||||
i = (uint16_t)(i + chunk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
101
app_cail/mx_log/mx_log.h
Normal file
101
app_cail/mx_log/mx_log.h
Normal file
@@ -0,0 +1,101 @@
|
||||
#ifndef __MX_LOG_H
|
||||
#define __MX_LOG_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef MX_LOG_ENABLE
|
||||
#define MX_LOG_ENABLE 0U
|
||||
#endif
|
||||
|
||||
/* Optional backends (choose at compile time):
|
||||
* - MX_LOG_BACKEND_STDIO: prints via printf/fputs (default: 1)
|
||||
* - MX_LOG_BACKEND_RTT : prints via SEGGER RTT (default: 0)
|
||||
* - MX_LOG_SET_WRITER() : user provided output callback
|
||||
*/
|
||||
#ifndef MX_LOG_BACKEND_STDIO
|
||||
#define MX_LOG_BACKEND_STDIO 0U
|
||||
#endif
|
||||
|
||||
#ifndef MX_LOG_BACKEND_RTT
|
||||
#define MX_LOG_BACKEND_RTT 0U
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
MX_LOG_LEVEL_ERROR = 0,
|
||||
MX_LOG_LEVEL_WARN = 1,
|
||||
MX_LOG_LEVEL_INFO = 2,
|
||||
MX_LOG_LEVEL_DEBUG = 3
|
||||
} mx_log_level_t;
|
||||
|
||||
typedef void (*mx_log_writer_t)(const char *msg);
|
||||
|
||||
void mx_log_init(void);
|
||||
void mx_log_set_level(mx_log_level_t level);
|
||||
mx_log_level_t mx_log_get_level(void);
|
||||
void mx_log_set_writer(mx_log_writer_t writer);
|
||||
void mx_log_printf(mx_log_level_t level, const char *tag, const char *fmt, ...);
|
||||
void mx_log_vprintf(mx_log_level_t level, const char *tag, const char *fmt, va_list ap);
|
||||
void mx_log_hex_frame(const char *tag, const uint8_t *data, uint16_t len);
|
||||
|
||||
#if MX_LOG_ENABLE
|
||||
#define MX_LOGD(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_DEBUG, (tag), (fmt), ##__VA_ARGS__)
|
||||
#define MX_LOGI(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_INFO, (tag), (fmt), ##__VA_ARGS__)
|
||||
#define MX_LOGW(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_WARN, (tag), (fmt), ##__VA_ARGS__)
|
||||
#define MX_LOGE(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_ERROR, (tag), (fmt), ##__VA_ARGS__)
|
||||
#else
|
||||
#define MX_LOGD(tag, fmt, ...) ((void)0)
|
||||
#define MX_LOGI(tag, fmt, ...) ((void)0)
|
||||
#define MX_LOGW(tag, fmt, ...) ((void)0)
|
||||
#define MX_LOGE(tag, fmt, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
#ifndef APP_CALI_LOG_ENABLE
|
||||
#define APP_CALI_LOG_ENABLE MX_LOG_ENABLE
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_PORT_LOG_ENABLE
|
||||
#define FLASH_PORT_LOG_ENABLE MX_LOG_ENABLE
|
||||
#endif
|
||||
|
||||
#ifndef MOZEN_LOG_ENABLE
|
||||
#define MOZEN_LOG_ENABLE MX_LOG_ENABLE
|
||||
#endif
|
||||
|
||||
#if APP_CALI_LOG_ENABLE && MX_LOG_ENABLE
|
||||
#define APP_CALI_LOGD(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_DEBUG, (tag), (fmt), ##__VA_ARGS__)
|
||||
#define APP_CALI_LOGI(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_INFO, (tag), (fmt), ##__VA_ARGS__)
|
||||
#define APP_CALI_LOGW(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_WARN, (tag), (fmt), ##__VA_ARGS__)
|
||||
#define APP_CALI_LOGE(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_ERROR, (tag), (fmt), ##__VA_ARGS__)
|
||||
#else
|
||||
#define APP_CALI_LOGD(tag, fmt, ...) ((void)0)
|
||||
#define APP_CALI_LOGI(tag, fmt, ...) ((void)0)
|
||||
#define APP_CALI_LOGW(tag, fmt, ...) ((void)0)
|
||||
#define APP_CALI_LOGE(tag, fmt, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if FLASH_PORT_LOG_ENABLE && MX_LOG_ENABLE
|
||||
#define FLASH_PORT_LOGD(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_DEBUG, (tag), (fmt), ##__VA_ARGS__)
|
||||
#define FLASH_PORT_LOGI(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_INFO, (tag), (fmt), ##__VA_ARGS__)
|
||||
#define FLASH_PORT_LOGW(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_WARN, (tag), (fmt), ##__VA_ARGS__)
|
||||
#define FLASH_PORT_LOGE(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_ERROR, (tag), (fmt), ##__VA_ARGS__)
|
||||
#else
|
||||
#define FLASH_PORT_LOGD(tag, fmt, ...) ((void)0)
|
||||
#define FLASH_PORT_LOGI(tag, fmt, ...) ((void)0)
|
||||
#define FLASH_PORT_LOGW(tag, fmt, ...) ((void)0)
|
||||
#define FLASH_PORT_LOGE(tag, fmt, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
#if MOZEN_LOG_ENABLE && MX_LOG_ENABLE
|
||||
#define MOZEN_LOGD(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_DEBUG, (tag), (fmt), ##__VA_ARGS__)
|
||||
#define MOZEN_LOGI(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_INFO, (tag), (fmt), ##__VA_ARGS__)
|
||||
#define MOZEN_LOGW(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_WARN, (tag), (fmt), ##__VA_ARGS__)
|
||||
#define MOZEN_LOGE(tag, fmt, ...) mx_log_printf(MX_LOG_LEVEL_ERROR, (tag), (fmt), ##__VA_ARGS__)
|
||||
#else
|
||||
#define MOZEN_LOGD(tag, fmt, ...) ((void)0)
|
||||
#define MOZEN_LOGI(tag, fmt, ...) ((void)0)
|
||||
#define MOZEN_LOGW(tag, fmt, ...) ((void)0)
|
||||
#define MOZEN_LOGE(tag, fmt, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
#endif /* __MX_LOG_H */
|
||||
172
app_cail/port/bsp_fmc_flash.c
Normal file
172
app_cail/port/bsp_fmc_flash.c
Normal file
@@ -0,0 +1,172 @@
|
||||
#include "bsp_fmc_flash.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/* 这个文件默认是根据GD32F303 实现的flash 操作接口函数,所以移植的时候,需要根据项目自行实现芯片平台相关的fmc 外设操作函数,只需要替换实现以下函数的函数体:
|
||||
bsp_flash_read
|
||||
bsp_flash_write
|
||||
bsp_flash_is_erased
|
||||
bsp_flash_erased
|
||||
其他不需要动
|
||||
*/
|
||||
|
||||
#include "at32a423.h" // Device header
|
||||
|
||||
|
||||
#define BSP_FLASH_BANK_FLAGS ((fmc_flag_enum)(FMC_FLAG_PGAERR | FMC_FLAG_WPERR | \
|
||||
FMC_FLAG_END | FMC_FLAG_PGERR ))
|
||||
#define BSP_FLASH_SN_SIZE 16U
|
||||
|
||||
static const bsp_flash_info_t s_bsp_flash_info =
|
||||
{
|
||||
BSP_FLASH_PAGE_SIZE,
|
||||
BSP_FLASH_PROGRAM_UNIT,
|
||||
BSP_FLASH_ERASE_VALUE,
|
||||
};
|
||||
|
||||
static uint32_t bsp_flash_align_down(uint32_t value, uint32_t align)
|
||||
{
|
||||
return value & ~(align - 1U);
|
||||
}
|
||||
|
||||
static uint32_t bsp_flash_align_up(uint32_t value, uint32_t align)
|
||||
{
|
||||
return (value + align - 1U) & ~(align - 1U);
|
||||
}
|
||||
|
||||
static void bsp_flash_clear_flags(void)
|
||||
{
|
||||
fmc_flag_clear(BSP_FLASH_BANK_FLAGS);
|
||||
}
|
||||
|
||||
static uint8_t bsp_flash_pack_word(const uint8_t *src, uint32_t size, uint32_t *word_out)
|
||||
{
|
||||
uint8_t bytes[BSP_FLASH_PROGRAM_UNIT] = { BSP_FLASH_ERASE_VALUE, BSP_FLASH_ERASE_VALUE,
|
||||
BSP_FLASH_ERASE_VALUE, BSP_FLASH_ERASE_VALUE };
|
||||
|
||||
if ((word_out == 0) || ((src == 0) && (size > 0U))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size > BSP_FLASH_PROGRAM_UNIT) {
|
||||
size = BSP_FLASH_PROGRAM_UNIT;
|
||||
}
|
||||
|
||||
if (size > 0U) {
|
||||
memcpy(bytes, src, size);
|
||||
}
|
||||
|
||||
*word_out = ((uint32_t)bytes[0]) |
|
||||
((uint32_t)bytes[1] << 8) |
|
||||
((uint32_t)bytes[2] << 16) |
|
||||
((uint32_t)bytes[3] << 24);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const bsp_flash_info_t *bsp_flash_get_info(void)
|
||||
{
|
||||
return &s_bsp_flash_info;
|
||||
}
|
||||
|
||||
uint8_t bsp_flash_read(uint32_t addr, void *buffer, uint32_t size)
|
||||
{
|
||||
if ((buffer == 0) && (size > 0U)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size > 0U) {
|
||||
memcpy(buffer, (const void *)addr, size);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t bsp_flash_is_erased(uint32_t addr, uint32_t size)
|
||||
{
|
||||
const uint8_t *flash_ptr = (const uint8_t *)addr;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0U; i < size; i++) {
|
||||
if (flash_ptr[i] != BSP_FLASH_ERASE_VALUE) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t bsp_flash_erased(uint32_t addr, uint32_t size)
|
||||
{
|
||||
uint32_t erase_addr;
|
||||
uint32_t erase_end;
|
||||
|
||||
if (size == 0U) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
erase_addr = bsp_flash_align_down(addr, BSP_FLASH_PAGE_SIZE);
|
||||
erase_end = bsp_flash_align_up(addr + size, BSP_FLASH_PAGE_SIZE);
|
||||
|
||||
fmc_unlock();
|
||||
bsp_flash_clear_flags();
|
||||
|
||||
while (erase_addr < erase_end) {
|
||||
if (fmc_page_erase(erase_addr) != FMC_READY) {
|
||||
fmc_lock();
|
||||
return 0;
|
||||
}
|
||||
erase_addr += BSP_FLASH_PAGE_SIZE;
|
||||
bsp_flash_clear_flags();
|
||||
}
|
||||
|
||||
fmc_lock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t bsp_flash_write(uint32_t addr, const void *data, uint32_t size)
|
||||
{
|
||||
const uint8_t *src = (const uint8_t *)data;
|
||||
uint32_t offset = 0U;
|
||||
uint32_t word = 0U;
|
||||
uint32_t chunk_size;
|
||||
|
||||
if ((addr % BSP_FLASH_PROGRAM_UNIT) != 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((data == 0) && (size > 0U)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size == 0U) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
fmc_unlock();
|
||||
bsp_flash_clear_flags();
|
||||
|
||||
while (offset < size)
|
||||
{
|
||||
chunk_size = size - offset;
|
||||
if (chunk_size > BSP_FLASH_PROGRAM_UNIT) {
|
||||
chunk_size = BSP_FLASH_PROGRAM_UNIT;
|
||||
}
|
||||
|
||||
if (!bsp_flash_pack_word(src + offset, chunk_size, &word)) {
|
||||
fmc_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fmc_word_program(addr + offset, word) != FMC_READY) {
|
||||
fmc_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset += BSP_FLASH_PROGRAM_UNIT;
|
||||
bsp_flash_clear_flags();
|
||||
}
|
||||
|
||||
fmc_lock();
|
||||
return 1;
|
||||
}
|
||||
|
||||
28
app_cail/port/bsp_fmc_flash.h
Normal file
28
app_cail/port/bsp_fmc_flash.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef BSP_FMC_FLASH_H
|
||||
#define BSP_FMC_FLASH_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define BSP_FLASH_PAGE_SIZE ((uint32_t)0x400U) // 1KB per page
|
||||
#define BSP_FLASH_PROGRAM_UNIT ((uint32_t)4U) // 4 bytes per program unit (word)
|
||||
#define BSP_FLASH_ERASE_VALUE ((uint8_t)0xFFU) // Value of erased flash bytes
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t page_size;
|
||||
uint32_t program_unit;
|
||||
uint8_t erased_value;
|
||||
} bsp_flash_info_t;
|
||||
|
||||
const bsp_flash_info_t *bsp_flash_get_info(void);
|
||||
uint8_t bsp_flash_read(uint32_t addr, void *buffer, uint32_t size);
|
||||
uint8_t bsp_flash_erased(uint32_t addr, uint32_t size);
|
||||
uint8_t bsp_flash_write(uint32_t addr, const void *data, uint32_t size);
|
||||
uint8_t bsp_flash_is_erased(uint32_t addr, uint32_t size);
|
||||
|
||||
|
||||
|
||||
#endif /* BSP_FMC_FLASH_H */
|
||||
393
app_cail/port/flash_port.c
Normal file
393
app_cail/port/flash_port.c
Normal file
@@ -0,0 +1,393 @@
|
||||
#include "flash_port.h"
|
||||
#include <string.h>
|
||||
#include "mx_log.h"
|
||||
|
||||
#undef MX_LOGD
|
||||
#undef MX_LOGI
|
||||
#undef MX_LOGW
|
||||
#undef MX_LOGE
|
||||
#define MX_LOGD FLASH_PORT_LOGD
|
||||
#define MX_LOGI FLASH_PORT_LOGI
|
||||
#define MX_LOGW FLASH_PORT_LOGW
|
||||
#define MX_LOGE FLASH_PORT_LOGE
|
||||
|
||||
#define FLASH_PORT_TAG FLASH_PORT_LOG_TAG
|
||||
|
||||
#define FLASH_PORT_ERASE_PROBE_BYTES 8U
|
||||
#define FLASH_PORT_VERIFY_CHUNK_BYTES 64U
|
||||
|
||||
static flash_port_ops_t s_flash_ops = {0};
|
||||
|
||||
void flash_port_init(const flash_port_ops_t *ops)
|
||||
{
|
||||
if (ops != NULL) {
|
||||
s_flash_ops = *ops;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t hal_read(uint32_t addr, void *buf, uint32_t len)
|
||||
{
|
||||
if (s_flash_ops.read) {
|
||||
return s_flash_ops.read(addr, buf, len/2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t hal_write(uint32_t addr, const void *buf, uint32_t len)
|
||||
{
|
||||
if (s_flash_ops.write) {
|
||||
return s_flash_ops.write(addr, buf, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t hal_erase(uint32_t addr, uint32_t len)
|
||||
{
|
||||
if (s_flash_ops.erase) {
|
||||
return s_flash_ops.erase(addr, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t hal_is_erased(uint32_t addr, uint32_t len)
|
||||
{
|
||||
if (s_flash_ops.is_erased) {
|
||||
return s_flash_ops.is_erased(addr, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t flash_port_min_u32(uint32_t a, uint32_t b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
static uint8_t flash_port_addr_is_erased(uint32_t addr, uint32_t bytes)
|
||||
{
|
||||
uint32_t probe_bytes = flash_port_min_u32(bytes, FLASH_PORT_ERASE_PROBE_BYTES);
|
||||
|
||||
if (probe_bytes == 0U)
|
||||
{
|
||||
probe_bytes = FLASH_PORT_ERASE_PROBE_BYTES;
|
||||
}
|
||||
|
||||
return hal_is_erased(addr, probe_bytes);
|
||||
}
|
||||
|
||||
static uint8_t flash_port_erase_range(uint32_t start_addr, uint32_t bytes)
|
||||
{
|
||||
if (!hal_erase(start_addr, bytes))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return flash_port_addr_is_erased(start_addr, bytes);
|
||||
}
|
||||
|
||||
static uint8_t flash_port_verify_bytes(uint32_t addr, const void *expect, uint32_t bytes)
|
||||
{
|
||||
uint8_t verify_buf[FLASH_PORT_VERIFY_CHUNK_BYTES];
|
||||
const uint8_t *expect_bytes = (const uint8_t *)expect;
|
||||
uint32_t offset = 0U;
|
||||
|
||||
if ((expect == NULL) && (bytes > 0U))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (offset < bytes)
|
||||
{
|
||||
uint32_t chunk = flash_port_min_u32(bytes - offset, FLASH_PORT_VERIFY_CHUNK_BYTES);
|
||||
|
||||
if (!hal_read(addr + offset, verify_buf, chunk)) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "verify read failed addr=0x%08X offset=%u",
|
||||
(unsigned int)addr, (unsigned int)offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memcmp(verify_buf, expect_bytes + offset, chunk) != 0) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "verify failed addr=0x%08X offset=%u",
|
||||
(unsigned int)addr, (unsigned int)offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset += chunk;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint8_t flash_port_load_cali_raw(app_math_cali_t *params)
|
||||
{
|
||||
if (params == NULL) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "load cali raw null params");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sizeof(app_math_cali_t) > FLASH_PORT_CALI_REGION_SIZE) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "cali region too small: need=%u size=%u",
|
||||
(unsigned int)sizeof(app_math_cali_t), (unsigned int)FLASH_PORT_CALI_REGION_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hal_read(FLASH_PORT_CALI_REGION_ADDR, params, sizeof(app_math_cali_t));
|
||||
}
|
||||
|
||||
static uint8_t flash_port_store_cali_raw(const app_math_cali_t *params)
|
||||
{
|
||||
if (params == NULL)
|
||||
{
|
||||
MX_LOGE(FLASH_PORT_TAG, "store cali raw null params");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sizeof(app_math_cali_t) > FLASH_PORT_CALI_REGION_SIZE) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "cali region too small: need=%u size=%u",
|
||||
(unsigned int)sizeof(app_math_cali_t), (unsigned int)FLASH_PORT_CALI_REGION_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!flash_port_erase_range(FLASH_PORT_CALI_REGION_ADDR, FLASH_PORT_CALI_REGION_SIZE)) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "erase cali region failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hal_write(FLASH_PORT_CALI_REGION_ADDR, params, sizeof(app_math_cali_t))) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "write cali raw failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return flash_port_verify_bytes(FLASH_PORT_CALI_REGION_ADDR, params, sizeof(app_math_cali_t));
|
||||
}
|
||||
|
||||
uint8_t flash_port_math_load(app_math_cali_t *params)
|
||||
{
|
||||
if (!flash_port_load_cali_raw(params))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((params->min_trigger_res_value == 0xFFFFU) &&
|
||||
(params->max_trigger_res_value == 0xFFFFU) &&
|
||||
(params->div_trigger_res_value == 0xFFFFU) &&
|
||||
(params->max_display_value == 0xFFFFU)) {
|
||||
MX_LOGW(FLASH_PORT_TAG, "math area is empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t flash_port_math_save(const app_math_cali_t *params)
|
||||
{
|
||||
app_math_cali_t merged = {0};
|
||||
|
||||
if (params == NULL)
|
||||
{
|
||||
MX_LOGE(FLASH_PORT_TAG, "math save null params");
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void)flash_port_load_cali_raw(&merged);
|
||||
merged.check_cail = params->check_cail;
|
||||
merged.min_trigger_res_value = params->min_trigger_res_value;
|
||||
merged.max_trigger_res_value = params->max_trigger_res_value;
|
||||
merged.div_trigger_res_value = params->div_trigger_res_value;
|
||||
merged.max_display_value = params->max_display_value;
|
||||
merged.sensor_data_type = params->sensor_data_type;
|
||||
return flash_port_store_cali_raw(&merged);
|
||||
}
|
||||
|
||||
uint8_t flash_port_math_clear(void)
|
||||
{
|
||||
if (!flash_port_erase_range(FLASH_PORT_CALI_REGION_ADDR, FLASH_PORT_CALI_REGION_SIZE)) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "math clear erase failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t flash_port_pressure_load(app_math_cali_t *params)
|
||||
{
|
||||
if (!flash_port_load_cali_raw(params)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((params->num_points == 0xFFFFU) || (params->num_points > MAX_PRESSURE_POINTS)) {
|
||||
MX_LOGW(FLASH_PORT_TAG, "invalid pressure points=%u", (unsigned int)params->num_points);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t flash_port_pressure_save(const app_math_cali_t *params)
|
||||
{
|
||||
app_math_cali_t merged = {0};
|
||||
|
||||
if ((params == NULL) || (params->num_points > MAX_PRESSURE_POINTS)) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "pressure save invalid params, num_points=%u",
|
||||
(unsigned int)(params ? params->num_points : 0U));
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void)flash_port_load_cali_raw(&merged);
|
||||
merged.num_points = params->num_points;
|
||||
memcpy(merged.pressure_points, params->pressure_points, sizeof(merged.pressure_points));
|
||||
|
||||
return flash_port_store_cali_raw(&merged);
|
||||
}
|
||||
|
||||
uint8_t flash_port_pressure_clear(void)
|
||||
{
|
||||
app_math_cali_t merged = {0};
|
||||
|
||||
(void)flash_port_load_cali_raw(&merged);
|
||||
merged.num_points = 0U;
|
||||
memset(merged.pressure_points, 0, sizeof(merged.pressure_points));
|
||||
|
||||
return flash_port_store_cali_raw(&merged);
|
||||
}
|
||||
|
||||
uint8_t flash_port_map_load(uint16_t *map_matrix, uint32_t map_words)
|
||||
{
|
||||
uint32_t map_bytes = map_words * sizeof(uint16_t);
|
||||
|
||||
if ((map_matrix == NULL) || (map_words != FLASH_PORT_MAP_WORDS)) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "map load bad arg, words=%u", (unsigned int)map_words);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (map_bytes > FLASH_PORT_MAP_REGION_SIZE) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "map region too small: need=%u size=%u",
|
||||
(unsigned int)map_bytes, (unsigned int)FLASH_PORT_MAP_REGION_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flash_port_addr_is_erased(FLASH_PORT_MAP_REGION_ADDR, map_bytes)) {
|
||||
MX_LOGW(FLASH_PORT_TAG, "map area is empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hal_read(FLASH_PORT_MAP_REGION_ADDR, map_matrix, map_bytes);
|
||||
}
|
||||
|
||||
uint8_t flash_port_map_save(const uint16_t *map_matrix, uint32_t map_words)
|
||||
{
|
||||
uint32_t map_bytes = map_words * sizeof(uint16_t);
|
||||
|
||||
if ((map_matrix == NULL) || (map_words != FLASH_PORT_MAP_WORDS)) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "map save bad arg, words=%u", (unsigned int)map_words);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (map_bytes > FLASH_PORT_MAP_REGION_SIZE) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "map region too small: need=%u size=%u",
|
||||
(unsigned int)map_bytes, (unsigned int)FLASH_PORT_MAP_REGION_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!flash_port_erase_range(FLASH_PORT_MAP_REGION_ADDR, FLASH_PORT_MAP_REGION_SIZE)) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "map erase failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hal_write(FLASH_PORT_MAP_REGION_ADDR, map_matrix, map_bytes)) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "map write failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return flash_port_verify_bytes(FLASH_PORT_MAP_REGION_ADDR, map_matrix, map_bytes);
|
||||
}
|
||||
|
||||
uint8_t flash_port_map_clear(void)
|
||||
{
|
||||
if (!flash_port_erase_range(FLASH_PORT_MAP_REGION_ADDR, FLASH_PORT_MAP_REGION_SIZE)) {
|
||||
MX_LOGE(FLASH_PORT_TAG, "map clear erase failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t flash_port_creep_load(app_creep_params *params)
|
||||
{
|
||||
uint32_t raw_data[2];
|
||||
|
||||
if (params == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hal_read(FLASH_PORT_CREEP_REGION_ADDR, raw_data, sizeof(raw_data))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((raw_data[0] == 0xFFFFFFFFUL) && (raw_data[1] == 0xFFFFFFFFUL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
params->creep_strength = (uint8_t)raw_data[0];
|
||||
params->creep_level = (uint8_t)raw_data[1];
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t flash_port_creep_save(const app_creep_params *params)
|
||||
{
|
||||
uint32_t raw_data[2];
|
||||
|
||||
if (params == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
raw_data[0] = (uint32_t)params->creep_strength;
|
||||
raw_data[1] = (uint32_t)params->creep_level;
|
||||
|
||||
if (!flash_port_erase_range(FLASH_PORT_CREEP_REGION_ADDR, FLASH_PORT_CREEP_REGION_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hal_write(FLASH_PORT_CREEP_REGION_ADDR, raw_data, sizeof(raw_data))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return flash_port_verify_bytes(FLASH_PORT_CREEP_REGION_ADDR, raw_data, sizeof(raw_data));
|
||||
}
|
||||
|
||||
uint8_t flash_port_creep_clear(void)
|
||||
{
|
||||
if (!flash_port_erase_range(FLASH_PORT_CREEP_REGION_ADDR, FLASH_PORT_CREEP_REGION_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t flash_port_device_info_load(app_dev_info *info)
|
||||
{
|
||||
if (info == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flash_port_addr_is_erased(FLASH_PORT_DEVICE_INFO_REGION_ADDR, sizeof(*info))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hal_read(FLASH_PORT_DEVICE_INFO_REGION_ADDR, info, sizeof(*info));
|
||||
}
|
||||
|
||||
uint8_t flash_port_device_info_save(const app_dev_info *info)
|
||||
{
|
||||
if (info == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!flash_port_erase_range(FLASH_PORT_DEVICE_INFO_REGION_ADDR, FLASH_PORT_DEVICE_INFO_REGION_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!hal_write(FLASH_PORT_DEVICE_INFO_REGION_ADDR, info, sizeof(*info))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return flash_port_verify_bytes(FLASH_PORT_DEVICE_INFO_REGION_ADDR, info, sizeof(*info));
|
||||
}
|
||||
82
app_cail/port/flash_port.h
Normal file
82
app_cail/port/flash_port.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#ifndef __FLASH_PORT_H
|
||||
#define __FLASH_PORT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "app_calibration.h"
|
||||
|
||||
#ifndef FLASH_PORT_LOG_TAG
|
||||
#define FLASH_PORT_LOG_TAG "FLASH_PORT"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Flash Region Configuration
|
||||
* Adjust Sector Size and Base Addresses for your specific MCU.
|
||||
*/
|
||||
#ifndef PORT_SECTOR_SIZE
|
||||
#define PORT_SECTOR_SIZE (2048U) // Target MCU Sector Size
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_PORT_CREEP_REGION
|
||||
#define FLASH_PORT_CREEP_REGION_ADDR (0x08000000 + 1024 * 58)
|
||||
#define FLASH_PORT_CREEP_REGION_SIZE PORT_SECTOR_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_PORT_DEVICE_INFO_REGION
|
||||
#define FLASH_PORT_DEVICE_INFO_REGION_ADDR (0x08000000 + 1024 * 60)
|
||||
#define FLASH_PORT_DEVICE_INFO_REGION_SIZE PORT_SECTOR_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_PORT_CALI_REGION
|
||||
#define FLASH_PORT_CALI_REGION_ADDR (0x08000000 + 1024 * 62) // FMC_WRITE_MAP_ADDR in old code
|
||||
#define FLASH_PORT_CALI_REGION_SIZE PORT_SECTOR_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef FLASH_PORT_MAP_REGION
|
||||
#define FLASH_PORT_MAP_REGION_ADDR (FLASH_PORT_CALI_REGION_ADDR + PORT_SECTOR_SIZE)
|
||||
#define FLASH_PORT_MAP_REGION_SIZE APP_MAP_MATRIX_BYTES
|
||||
#define FLASH_PORT_MAP_WORDS APP_MAP_MATRIX_WORDS
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* ============================================================================
|
||||
* HAL Interface (Function pointer injection)
|
||||
* ============================================================================ */
|
||||
typedef struct flash_port_ops_t
|
||||
{
|
||||
uint8_t (*read)(uint32_t addr, void *buf, uint32_t len);
|
||||
uint8_t (*write)(uint32_t addr, const void *buf, uint32_t len);
|
||||
uint8_t (*erase)(uint32_t addr, uint32_t len);
|
||||
uint8_t (*is_erased)(uint32_t addr, uint32_t len);
|
||||
} flash_port_ops_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the flash port layer with hardware specific operations.
|
||||
* @param ops Pointer to hardware operations structure.
|
||||
*/
|
||||
void flash_port_init(const flash_port_ops_t *ops);
|
||||
|
||||
/* ============================================================================
|
||||
* Application APIs
|
||||
* ============================================================================ */
|
||||
uint8_t flash_port_math_load(app_math_cali_t *params);
|
||||
uint8_t flash_port_math_save(const app_math_cali_t *params);
|
||||
uint8_t flash_port_math_clear(void);
|
||||
|
||||
uint8_t flash_port_pressure_load(app_math_cali_t *params);
|
||||
uint8_t flash_port_pressure_save(const app_math_cali_t *params);
|
||||
uint8_t flash_port_pressure_clear(void);
|
||||
|
||||
uint8_t flash_port_map_load(uint16_t *map_matrix, uint32_t map_words);
|
||||
uint8_t flash_port_map_save(const uint16_t *map_matrix, uint32_t map_words);
|
||||
uint8_t flash_port_map_clear(void);
|
||||
|
||||
uint8_t flash_port_creep_load(app_creep_params *params);
|
||||
uint8_t flash_port_creep_save(const app_creep_params *params);
|
||||
uint8_t flash_port_creep_clear(void);
|
||||
|
||||
uint8_t flash_port_device_info_load(app_dev_info *info);
|
||||
uint8_t flash_port_device_info_save(const app_dev_info *info);
|
||||
|
||||
#endif /* __FLASH_PORT_H */
|
||||
Reference in New Issue
Block a user