debugVarTool/debug_tools.c
Razvalyaev ae2c90160e +библиотека .c/.h переписана под универсальные дефайны intX_t uintX_t
+сделано задание размера короткого имени
+ добавлена бета поддержка stm:+
   - парс переменных из файла преокта Keil или makefile CubeIDE
   - запись в utf-8 для STM, вместо cp1251 для TMS
   - другой размер int (32 бита, вместо 16 бит) для STM
2025-07-17 09:18:03 +03:00

309 lines
10 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "debug_tools.h"
#if !defined(GLOBAL_Q)
#define GLOBAL_Q 16
#endif
DebugLowLevel_t debug_ll = DEBUG_LOWLEVEL_INIT; ///< Ñòðóêòóðà îòëàäêè íèæíåãî óðîâíÿ (èíèöèàëèçàöèÿ)
static int getDebugVar(DebugVar_t *var, int32_t *int_var, float *float_var);
static int convertDebugVarToIQx(DebugVar_t *var, int32_t *ret_var);
///////////////////////////----EXAPLE-----//////////////////////////////
int var_numb = 1; ///< Ïðèìåð ïåðåìåííîé äëÿ îòëàäêè
DebugVarName_t var_name; ///< Èìÿ ïåðåìåííîé
int32_t return_var; ///< Ïåðåìåííàÿ äëÿ âîçâðàòà ðåçóëüòàòà
int32_t return_ll_var; ///< Âîçâðàùàåìîå çíà÷åíèå ñ íèæíåãî óðîâíÿ
int result; ///< Ïåðåìåííàÿ ðåçóëüòàòà
DateTime_t ext_date = {2025, 11, 07, 16, 50}; ///< Ïðèìåð âíåøíåé äàòû ñáîðêè
/**
* @brief Ïðèìåð èñïîëüçîâàíèÿ ôóíêöèé îòëàäêè.
* @details Äåìîíñòðàöèîííàÿ ôóíêöèÿ äëÿ ðàáîòû ñ ïåðåìåííûìè îòëàäêè.
*/
void Debug_Test_Example(void)
{
result = Debug_ReadVar(var_numb, &return_var);
result = Debug_ReadVarName(var_numb, var_name);
if(Debug_LowLevel_Initialize(&ext_date) == 0)
result = Debug_LowLevel_ReadVar(&return_ll_var);
}
///////////////////////////----PUBLIC-----//////////////////////////////
/**
* @brief ×èòàåò ïåðåìåííóþ ïî èíäåêñó.
* @param var_ind èíäåêñ ïåðåìåííîé.
* @param return_32b óêàçàòåëü äëÿ âîçâðàòà ðåçóëüòàòà.
* @return int 0: óñïåõ, 1: îøèáêà.
* @details Èñïîëüçóåòñÿ äëÿ ÷òåíèÿ çíà÷åíèé ïåðåìåííûõ ïî èõ èíäåêñó.
*/
int Debug_ReadVar(int var_ind, int32_t *return_32b)
{
if(return_32b == NULL)
return 1;
int32_t tmp_var;
if (var_ind >= DebugVar_Qnt)
return 1;
if((dbg_vars[var_ind].ptr_type == pt_struct) || (dbg_vars[var_ind].ptr_type == pt_union) ||
(dbg_vars[var_ind].ptr_type == pt_unknown))
return 1;
return convertDebugVarToIQx(&dbg_vars[var_ind], return_32b);
}
/**
* @brief ×èòàåò èìÿ ïåðåìåííîé ïî èíäåêñó.
* @param var_ind èíäåêñ ïåðåìåííîé.
* @param name_ptr óêàçàòåëü íà áóôåð èìåíè (DebugVarName_t).
* @return int 0: óñïåõ, 1: îøèáêà.
* @details Êîïèðóåò èìÿ ïåðåìåííîé â ïðåäîñòàâëåííûé áóôåð.
*/
int Debug_ReadVarName(int var_ind, DebugVarName_t name_ptr)
{
if(name_ptr == NULL)
return 1;
if (var_ind >= DebugVar_Qnt)
return 1;
int i;
// Êîïèðîâàíèå ñ çàùèòîé îò ïåðåïîëíåíèÿ è ÿâíîé îñòàíîâêîé ïî '\0'
for (i = 0; i < sizeof(dbg_vars[var_ind].name); i++)
{
name_ptr[i] = dbg_vars[var_ind].name[i];
if (dbg_vars[var_ind].name[i] == '\0')
break;
}
// Ãàðàíòèðîâàííîå çàâåðøåíèå ñòðîêè (íà ñëó÷àé, åñëè â var->name íå áûëî '\0')
name_ptr[sizeof(dbg_vars[var_ind].name) - 1] = '\0';
return 0;
}
/**
* @brief ×èòàåò çíà÷åíèå ïåðåìåííîé îòëàäêè ñ íèæíåãî óðîâíÿ.
* @param return_32b óêàçàòåëü íà ïåðåìåííóþ, êóäà çàïèñûâàåòñÿ ðåçóëüòàò.
* @return int 0: óñïåõ, 1: îøèáêà, 2: íåäîïóñòèìûé àäðåñ.
* @details Èñïîëüçóåò àäðåññ, ïåðåäàâàåìûé ñ òåðìèíàëêè äëÿ ïîëó÷åíèÿ çíà÷åíèÿ.
*/
int Debug_LowLevel_ReadVar(int32_t *return_32b)
{
if (return_32b == NULL)
return 1;
if (debug_ll.isVerified == 0)
return 1;
uint8_t *addr = debug_ll.dbg_var.Ptr;
uint32_t addr_val = (uint32_t)addr;
// Ðàçðåø¸ííûå äèàïàçîíû ïàìÿòè (èç .cmd ôàéëà)
if (!(
(addr_val <= 0x0007FF) || // RAMM0 + RAMM1
(addr_val >= 0x008120 && addr_val <= 0x009FFC) || // L0 + L1 SARAM
(addr_val >= 0x3F8000 && addr_val <= 0x3F9FFF) || // PRAMH0 + DRAMH0
(addr_val >= 0x3FF000 && addr_val <= 0x3FFFFF) || // BOOTROM + RESET
(addr_val >= 0x080002 && addr_val <= 0x09FFFF) || // RAMEX1
(addr_val >= 0x0F0000 && addr_val <= 0x0FFEFF) || // RAMEX4
(addr_val >= 0x100002 && addr_val <= 0x103FFF) || // RAMEX0 + RAMEX2 + RAMEX01
(addr_val >= 0x102000 && addr_val <= 0x103FFF) // RAMEX2
)) {
return 2; // Çàïðåù¸ííûé àäðåñ — íåëüçÿ ÷èòàòü
}
return convertDebugVarToIQx(&debug_ll.dbg_var, return_32b);
}
/**
* @brief Èíèöèàëèçàöèÿ îòëàäêè íà íèæíåì óðîâíå ïî äàòå ñáîðêè.
* @param external_date ñòðóêòóðà ñ äàòîé DateTime_t
* @return int 0: ñîâïàäàåò, 1: íå ñîâïàäàåò, -1: îøèáêà.
* @details Ñðàâíèâàåò äàòó êîìïèëÿöèè ñ çàïðàøèâàåìîé è èíèöèàëèçèðóåò îòëàäî÷íóþ ïåðåìåííóþ.
*/
int Debug_LowLevel_Initialize(DateTime_t* external_date)
{
if (external_date == NULL) {
return -1;
}
// Ñðàâíåíèå âñåõ ïîëåé
if (external_date->year == debug_ll.build_date.year &&
external_date->month == debug_ll.build_date.month &&
external_date->day == debug_ll.build_date.day &&
external_date->hour == debug_ll.build_date.hour &&
external_date->minute == debug_ll.build_date.minute)
{
debug_ll.isVerified = 1;
return 0; // Ñîâïàëî
}
debug_ll.isVerified = 0;
return 1; // Íå ñîâïàëî
}
/////////////////////----INTERNAL FUNCTIONS-----////////////////////////
/**
* @brief Ïðåîáðàçóåò òèï IQ ïåðåìåííîé â ÷èñëî áèòîâ äëÿ ñäâèãà(Q-ôàêòîð).
* @param t òèï IQ (ïåðå÷èñëåíèå DebugVarIQType_t).
* @return int Q-ôàêòîð (íàïðèìåð, 24), 0: åñëè t_iq_none, -1: îøèáêà.
* @details Ñîïîñòàâëÿåò òèï IQ ïåðåìåííîé ñ ñîîòâåòñòâóþùèì Q-çíà÷åíèåì.
*/
static int iqTypeToQ(DebugVarIQType_t t)
{
if (t == t_iq_none)
return 0; // áåç IQ, float, int
else if (t == t_iq)
return GLOBAL_Q; // îáùèé IQ, íàïðèìåð 24
else if (t >= t_iq1 && t <= t_iq30)
return (int)t - (int)t_iq1 + 1; // íàïðèìåð t_iq1 -> 1, t_iq2 -> 2 è ò.ä.
else
return -1; // îøèáêà
}
/**
* @brief Ïðåîáðàçóåò ïåðåìåííóþ îòëàäêè â IQ ôîðìàò.
* @param var óêàçàòåëü íà ïåðåìåííóþ îòëàäêè.
* @param ret_var óêàçàòåëü äëÿ âîçâðàòà çíà÷åíèÿ â ôîðìàòå 32 áèòà.
* @return int 0: óñïåõ, 1: îøèáêà ÷òåíèÿ, 2: íåïðàâèëüíûé ôîðìàò, 3: ïåðåïîëíåíèå.
* @details Îïðåäåëÿåò ôîðìàò IQ ïåðåìåííîé, êîíâåðòèðóåò å¸ â 32b ñ ó÷¸òîì ìàñøòàáà.
*/
static int convertDebugVarToIQx(DebugVar_t *var, int32_t *ret_var)
{
int32_t iq_numb, iq_united, iq_final;
float float_numb;
if(getDebugVar(var, &iq_numb, &float_numb) != 0)
return 1;
int src_q = iqTypeToQ(var->iq_type);
int dst_q = iqTypeToQ(var->return_type);
if (src_q < 0 || dst_q < 0)
return 2; // íåïðàâèëüíûé ôîðìàò
int64_t iq_united64 = 0;
int64_t iq_final64 = 0;
// Êîíâåðòàöèÿ ê GLOBAL_Q (64-áèò)
if (var->iq_type == t_iq_none) {
if (var->ptr_type == pt_float) {
// float_numb óìíîæàåì íà 2^GLOBAL_Q (2^24=16777216)
// Ðåçóëüòàò ïðèâîäèì ê 64 áèòà
iq_united64 = (int64_t)(float_numb * 16777216.0f);
} else {
iq_united64 = ((int64_t)iq_numb) << GLOBAL_Q;
}
} else {
int shift = GLOBAL_Q - src_q;
if (shift >= 0)
iq_united64 = ((int64_t)iq_numb) << shift;
else
iq_united64 = ((int64_t)iq_numb) >> (-shift);
}
// Êîíâåðòàöèÿ èç GLOBAL_Q â öåëåâîé IQ (64-áèò)
if (var->return_type == t_iq_none) {
// Âîçâðàùàåì öåëîå, îòáðîñèâ äðîáíóþ ÷àñòü
*ret_var = (uint32_t)(iq_united64 >> GLOBAL_Q);
} else {
int shift = dst_q - GLOBAL_Q;
if (shift >= 0)
iq_final64 = iq_united64 << shift;
else
iq_final64 = iq_united64 >> (-shift);
// Ïðîâåðÿåì ïåðåïîëíåíèå int32_t
if (iq_final64 > 2147483647 || iq_final64 < -2147483648)
return 3; // ïåðåïîëíåíèå
*ret_var = (uint32_t)iq_final64;
}
return 0;
}
/**
* @brief Ïðî÷èòàòü çíà÷åíèå ïåðåìåííîé îòëàäêè.
* @param var óêàçàòåëü íà ñòðóêòóðó DebugVar.
* @param int_var óêàçàòåëü íà ïåðåìåííóþ òèïà 32 áèòà äëÿ âîçâðàòà öåëî÷èñëåííîãî çíà÷åíèÿ.
* @param float_var óêàçàòåëü íà ïåðåìåííóþ òèïà float äëÿ âîçâðàòà çíà÷åíèÿ ñ ïëàâàþùåé òî÷êîé.
* @return int 0: óñïåõ, 1: îøèáêà óêàçàòåëåé èëè íåïîääåðæèâàåìûé òèï, 3/4: îøèáêà âûðàâíèâàíèÿ.
* @details  çàâèñèìîñòè îò òèïà ïåðåìåííîé ñ÷èòûâàåò å¸ çíà÷åíèå è ñîõðàíÿåò â ñîîòâåòñòâóþùåì óêàçàòåëå.
*/
static int getDebugVar(DebugVar_t *var, int32_t *int_var, float *float_var)
{
if (!var || !int_var || !float_var || !var->Ptr)
return 1; // îøèáêà: null óêàçàòåëü
uint8_t *addr = var->Ptr;
uint32_t addr_val = (uint32_t)addr;
switch (var->ptr_type)
{
case pt_int8: // 8 áèò
if ((addr_val & ALIGN_8BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 1; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile int8_t *)addr);
case pt_uint8:
if ((addr_val & ALIGN_8BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 1; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile uint8_t *)addr);
break;
case pt_int16: // 16 áèò (int)
if ((addr_val & ALIGN_16BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 2; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile int16_t *)addr);
case pt_uint16:
if ((addr_val & ALIGN_16BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 2; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile uint16_t *)addr);
break;
case pt_int32: // 32 áèò
if ((addr_val & ALIGN_32BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 3; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile int32_t *)addr);
case pt_uint32:
if ((addr_val & ALIGN_32BIT) != 0) // ïðîâåðÿåì âûðàâíèâàíèå
return 3; // îøèáêà âûðàâíèâàíèÿ
*int_var = *((volatile uint32_t *)addr);
break;
case pt_float: // float (4 áàéòà)
if ((addr_val & ALIGN_FLOAT) != 0) // ïðîâåðêà âûðàâíèâàíèÿ
return 4; // îøèáêà âûðàâíèâàíèÿ
*float_var = *((volatile float *)addr);
break;
default:
return 1; // íåïîääåðæèâàåìûé òèï
// äëÿ óêàçàòåëåé è ìàññèâîâ íå ïîääåðæèâàåòñÿ ÷òåíèå
// case pt_ptr_int8:
// case pt_ptr_int16:
// case pt_ptr_int32:
// case pt_ptr_uint8:
// case pt_ptr_uint16:
// case pt_ptr_uint32:
// case pt_arr_int8:
// case pt_arr_int16:
// case pt_arr_int32:
// case pt_arr_uint8:
// case pt_arr_uint16:
// case pt_arr_uint32:
}
return 0; // óñïåõ
}