Open FFBoard
Open source force feedback firmware
Loading...
Searching...
No Matches
SystemCommands.cpp
Go to the documentation of this file.
1/*
2 * SystemCommands.cpp
3 *
4 * Created on: 30.11.2021
5 * Author: Yannick
6 */
7
8#include "SystemCommands.h"
9#include "PersistentStorage.h"
10#include "FFBoardMain.h"
11#include "voltagesense.h"
12#include <malloc.h>
13#include "constants.h"
14#include "task.h"
15#include "FreeRTOSConfig.h"
18//extern static const uint8_t SW_VERSION_INT[3];
19
20
21bool SystemCommands::debugMode = false;
24
26 .name = "System Commands" ,
27 .id = CLSID_SYSTEM,
28 .visibility = ClassVisibility::hidden
29 };
30
34
35SystemCommands::SystemCommands() : CommandHandler(CMDCLSTR_SYS, CMDCLSID_SYS) {
37 //CommandHandler::registerCommands();
39
40}
41
45
46
48 CommandHandler::registerCommand("help", FFBoardMain_commands::help, "Print system help",CMDFLAG_STR_ONLY);
49 CommandHandler::registerCommand("save", FFBoardMain_commands::save, "Write all settings to flash",CMDFLAG_GET);
50 CommandHandler::registerCommand("reboot", FFBoardMain_commands::reboot, "Reset chip",CMDFLAG_GET);
51 CommandHandler::registerCommand("dfu", FFBoardMain_commands::dfu, "reboot into DFU bootloader",CMDFLAG_GET);
52 CommandHandler::registerCommand("lsmain", FFBoardMain_commands::lsmain, "List available mainclasses",CMDFLAG_GET);
53 CommandHandler::registerCommand("lsactive", FFBoardMain_commands::lsactive, "List active classes (Fullname:clsname:inst:clsid:idx)",CMDFLAG_GET);
54 CommandHandler::registerCommand("vint", FFBoardMain_commands::vint, "Internal voltage(mV)",CMDFLAG_GET);
55 CommandHandler::registerCommand("vext", FFBoardMain_commands::vext, "External voltage(mV)",CMDFLAG_GET);
56 CommandHandler::registerCommand("main", FFBoardMain_commands::main, "Query or change mainclass",CMDFLAG_GET | CMDFLAG_SET);
57 CommandHandler::registerCommand("swver", FFBoardMain_commands::swver, "Firmware version",CMDFLAG_GET);
58 CommandHandler::registerCommand("hwtype", FFBoardMain_commands::hwtype, "Hardware type",CMDFLAG_GET);
59 CommandHandler::registerCommand("flashraw", FFBoardMain_commands::flashraw, "Write value to flash address",CMDFLAG_SETADR | CMDFLAG_GETADR);
60 CommandHandler::registerCommand("flashdump", FFBoardMain_commands::flashdump, "Read all flash variables (val:adr)",CMDFLAG_GET);
61 CommandHandler::registerCommand("errors", FFBoardMain_commands::errors, "Read error states",CMDFLAG_GET);
62 CommandHandler::registerCommand("errorsclr", FFBoardMain_commands::errorsclr, "Reset errors",CMDFLAG_GET);
63 CommandHandler::registerCommand("heapfree", FFBoardMain_commands::heapfree, "Memory info",CMDFLAG_GET);
64#if configUSE_STATS_FORMATTING_FUNCTIONS> 0
65 CommandHandler::registerCommand("taskstats", FFBoardMain_commands::taskstats, "Task stats",CMDFLAG_GET);
66#endif
67 CommandHandler::registerCommand("format", FFBoardMain_commands::format, "set format=1 to erase all stored values",CMDFLAG_SET);
68 CommandHandler::registerCommand("debug", FFBoardMain_commands::debug, "Enable or disable debug commands",CMDFLAG_SET | CMDFLAG_GET);
69 CommandHandler::registerCommand("devid", FFBoardMain_commands::devid, "Get chip dev id and rev id",CMDFLAG_GET);
70 CommandHandler::registerCommand("name", CommandHandlerCommands::name, "name of class",CMDFLAG_GET|CMDFLAG_STR_ONLY);
71 CommandHandler::registerCommand("cmdinfo", CommandHandlerCommands::cmdinfo, "Flags of a command id (adr). -1 if cmd id invalid",CMDFLAG_GETADR);
72 CommandHandler::registerCommand("uid", FFBoardMain_commands::uid, "Get 96b chip uid. Adr0-2 sel blk",CMDFLAG_GET | CMDFLAG_GETADR | CMDFLAG_INFOSTRING);
73 CommandHandler::registerCommand("temp", FFBoardMain_commands::temp, "Chip temperature in C",CMDFLAG_GET);
74#if defined(OTPMEMORY)
75 CommandHandler::registerCommand("otp", FFBoardMain_commands::otp, "Access OTP memory",CMDFLAG_GETADR | CMDFLAG_SETADR | CMDFLAG_DEBUG);
76#endif
77#if defined(SIGNATURE)
78 CommandHandler::registerCommand("signature", FFBoardMain_commands::signature, "Chip signature in OTP. setadr to write data. set=1 to lock",CMDFLAG_GETADR | CMDFLAG_SETADR | CMDFLAG_GET | CMDFLAG_INFOSTRING);
79#endif
80}
81
82// Choose lower optimize level because the compiler likes to blow up this function
83__attribute__((optimize("-O1")))
84CommandStatus SystemCommands::internalCommand(const ParsedCommand& cmd,std::vector<CommandReply>& replies){
86
87 if(flag != CommandStatus::NOT_FOUND){
88 return flag;
89 }else{
90 flag = CommandStatus::OK;
91 }
92
93 switch(static_cast<FFBoardMain_commands>(cmd.cmdId))
94 {
96 {// help
97 if(cmd.type == CMDtype::info){
98 replies.emplace_back(this->getCsvHelpstring());
99 }else{
100 std::string itfHelp = "";
101 if(cmd.originalInterface){
102 itfHelp = cmd.originalInterface->getHelpstring() + "\n";
103 }
104 std::string reply = itfHelp + "Available classes (use cls.0.help for more info):\n";
105 //std::string reply = "";
107 CmdHandlerInfo* info = handler->getCommandHandlerInfo();
108 reply += std::string(info->clsname) + "." + std::to_string(info->instance)+"\n";
109 }
110 reply += "\n"+this->getCommandsHelpstring();
111 replies.emplace_back(reply);
112 }
113
114 break;
115 }
116
119 handler->saveFlash();
120 }
121 break;
122
124 NVIC_SystemReset();
125 break;
126
128 RebootDFU();
129 break;
131 mainchooser.replyAvailableClasses(replies,mainclass->getSelectionID());
132 break;
133
135 {
136 replies.emplace_back(getIntV());
137 break;
138 }
139
141 return handleGetSet(cmd, replies, SystemCommands::debugMode);
142
144 {
145 replies.emplace_back(getExtV());
146 break;
147 }
148
150 {
151 if(cmd.type == CMDtype::get){
152 uint16_t buf=mainclass->getInfo().id;
153 Flash_Read(ADR_CURRENT_CONFIG, &buf);
154 replies.emplace_back(buf);
155 }else if(cmd.type == CMDtype::set){
156 if(mainchooser.isValidClassId(cmd.val)){
157 Flash_Write(ADR_CURRENT_CONFIG, (uint16_t)cmd.val);
158 if(cmd.val != mainclass->getInfo().id){
159 NVIC_SystemReset(); // Reboot
160 }
161 }
162 }
163 break;
164 }
166 {
167 replyErrors(replies);
168 break;
169 }
171 replyFlashDump(replies);
172 break;
173
175 {
176 if(cmd.type == CMDtype::setat){
177 Flash_Write(cmd.adr, cmd.val);
178
179 }else if(cmd.type == CMDtype::getat){
180 CommandReply reply;
182 uint16_t val;
183 if(Flash_Read(cmd.adr,&val)){
184 reply.val=val;
185 }
186 replies.push_back(reply);
187 }
188 break;
189 }
190
193 break;
194
196 {
197 CommandReply reply;
199
200 extern const uint8_t SW_VERSION_INT[3];
201 reply.reply += std::to_string(SW_VERSION_INT[0]) + "." + std::to_string(SW_VERSION_INT[1]) + "." + std::to_string(SW_VERSION_INT[2]);
202
203 reply.val = (SW_VERSION_INT[0]<<16) | (SW_VERSION_INT[1] << 8) | (SW_VERSION_INT[2]);
204 replies.push_back(reply);
205 break;
206 }
207
209 {
210 replies.emplace_back(HW_TYPE,HW_TYPE_INT);
211 //replies.emplace_back(HAL_GetDEVID());
212 break;
213 }
215 {
216 replies.emplace_back(HAL_GetDEVID(),HAL_GetREVID());
217 break;
218 }
219
220
221 case FFBoardMain_commands::mallinfo: // UNUSED since freertos
222 {
223 CommandReply reply;
224 struct mallinfo info = mallinfo();
225 reply.adr = info.uordblks;
226 reply.val = info.uordblks;
227 reply.reply +="Usage: ";
228 reply.reply += std::to_string(info.uordblks);
229 reply.reply +=" Size: ";
230 reply.reply +=std::to_string(info.arena);
232 replies.push_back(reply);
233 break;
234 }
235
237 {
238 replies.emplace_back(xPortGetFreeHeapSize(),xPortGetMinimumEverFreeHeapSize());
239 break;
240 }
241#if configUSE_STATS_FORMATTING_FUNCTIONS>0
243 {
244 char repl[800];
245 vTaskGetRunTimeStats(repl);
246 replies.emplace_back("\n"+std::string(repl));
247 break;
248 }
249#endif
251 {
253
254 ClassIdentifier i = handler->getInfo();
255 CmdHandlerInfo* hi = handler->getCommandHandlerInfo();
256 CommandReply reply;
258 reply.adr = hi->instance;
259 reply.val = hi->clsTypeid;
260 reply.reply += std::string(i.name)+ ":" + hi->clsname + ":" + std::to_string(hi->instance) + ":" + std::to_string(i.id) + ":" + std::to_string(hi->commandHandlerID);
261 replies.push_back(reply);
262
263 }
264 break;
265 }
267 if(cmd.type == CMDtype::set && cmd.val==1){
268
269 if(Flash_Format()){
270 flag = CommandStatus::OK;
271 }else{
272 flag = CommandStatus::ERR;
273 }
274
275 }
276 break;
278 if(cmd.type == CMDtype::get){
279 replies.emplace_back((uint64_t)HAL_GetUIDw0() | (uint64_t)HAL_GetUIDw1() << 32,HAL_GetUIDw2());
280 }else if(cmd.type == CMDtype::getat){
281 if(cmd.adr == 0){
282 replies.emplace_back(HAL_GetUIDw0());
283 }else if(cmd.adr == 1){
284 replies.emplace_back(HAL_GetUIDw1());
285 }else if(cmd.adr == 2){
286 replies.emplace_back(HAL_GetUIDw2());
287 }
288 }else if(cmd.type == CMDtype::info){
289 char buf[32];
290 std::snprintf(buf,32,"0x%08lx%08lx%08lx",HAL_GetUIDw2(),HAL_GetUIDw1(),HAL_GetUIDw0()); // Print as hex string
291 replies.emplace_back(std::string(buf));
292 }
293 break;
295 {
296 replies.emplace_back(getChipTemp());
297 break;
298 }
299#if defined(OTPMEMORY)
301 if(cmd.type == CMDtype::setat){
302 bool success = OTP_Write(cmd.adr, cmd.val);
303 if(!success){
304 flag = CommandStatus::ERR;
305 }
306 }else if(cmd.type == CMDtype::getat){
307 CommandReply reply;
309 uint64_t val;
310 if(OTP_Read(cmd.adr,&val)){
311 reply.val=val;
312 }else{
313 flag = CommandStatus::ERR;
314 }
315 replies.push_back(reply);
316 }
317 break;
318#endif
319#if defined(SIGNATURE)
321#if defined(SIGNATURELEN) && defined(SIGBNATUREBASEADR)
322 if(cmd.type == CMDtype::info){
323 char buf[(SIGNATURELEN * 16) + 1];
324 uint64_t dat;
325 for(uint8_t i = 0;i<SIGNATURELEN;i++){
326 OTP_Read(SIGBNATUREBASEADR+i, &dat);
327 std::snprintf(buf+i*16,17,"%016llx",dat); // Print as hex string
328 }
329 replies.emplace_back(std::string(buf));
330 }else if(cmd.type == CMDtype::get){
331 for(uint8_t i = 0;i<SIGNATURELEN;i++){
332 uint64_t dat;
333 OTP_Read(SIGBNATUREBASEADR+i, &dat);
334 replies.emplace_back(dat,i);
335 }
336 }else if(cmd.type == CMDtype::getat){
337 if(cmd.adr >= SIGNATURELEN || cmd.adr < 0){
338 flag = CommandStatus::ERR;
339 }else{
340 uint64_t dat;
341 OTP_Read(SIGBNATUREBASEADR+cmd.adr, &dat);
342 replies.emplace_back(dat,cmd.adr);
343 }
344 }else if(cmd.type == CMDtype::setat){
345 bool success = OTP_Write(cmd.adr+SIGBNATUREBASEADR, cmd.val);
346 if(!success){
347 flag = CommandStatus::ERR;
348 }
349 }else{
350 flag = CommandStatus::ERR;
351 }
352#else
353 if(cmd.type == CMDtype::info){
354 replies.emplace_back("0");
355 }else if(cmd.type == CMDtype::get || cmd.type == CMDtype::getat){
356 replies.emplace_back(0);
357 }else{
358 flag = CommandStatus::ERR;
359 }
360#endif
361#endif
362 break;
363
364
365 default:
367 break;
368 }
369 return flag;
370}
371
372/*
373 * Prints a formatted flash dump to the reply string
374 */
375void SystemCommands::replyFlashDump(std::vector<CommandReply>& replies){
376 std::vector<std::tuple<uint16_t,uint16_t>> result;
377 Flash_Dump(&result,false);
378
379 for(auto entry : result){
380 CommandReply reply;
381 uint16_t adr;
382 uint16_t val;
383 std::tie(adr,val) = entry;
384 //reply.reply += std::to_string(adr) + ":" + std::to_string(val) + "\n";
385 reply.adr = adr;
386 reply.val = val;
388 replies.push_back(reply);
389 }
390}
391
392/*
393 * Prints a formatted list of error conditions
394 */
395void SystemCommands::replyErrors(std::vector<CommandReply>& replies){
396 std::span<Error> errors = ErrorHandler::getErrors();
397 if(errors.size() == 0){
398 CommandReply reply;
399 reply.reply += "None";
401 replies.push_back(reply);
402 return;
403 }
404
405 for(Error error : errors){
406 CommandReply reply;
407 reply.reply += error.toString() + "\n";
408 reply.val = (uint32_t)error.code;
410 replies.push_back(reply);
411 }
412
414}
CommandStatus
uint8_t adr
__attribute__((optimize("-O1"))) CommandStatus SystemCommands
FFBoardMain_commands
void registerCommand(const char *cmd, const ID cmdid, const char *help=nullptr, uint32_t flags=0)
virtual CommandStatus internalCommand(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
CommandHandler(const char *clsname, uint16_t clsid, uint8_t instance=0)
static std::vector< CommandHandler * > & getCommandHandlers()
std::string reply
CommandReplyType type
static std::span< Error > getErrors()
static void clearTemp()
static void clearAll()
static std::vector< PersistentStorage * > & getFlashHandlers()
static SystemCommands * systemCommandsInstance
static ClassIdentifier info
virtual ~SystemCommands()
static bool errorPrintingEnabled
static bool debugMode
static void replyErrors(std::vector< CommandReply > &replies)
static void replyFlashDump(std::vector< CommandReply > &replies)
const ClassIdentifier getInfo()
Command handlers always have class infos. Works well with ChoosableClass.
static const uint8_t SW_VERSION_INT[3]
Definition constants.h:11
ClassChooser< FFBoardMain > mainchooser(class_registry)
bool Flash_Format()
void Flash_Dump(std::vector< std::tuple< uint16_t, uint16_t > > *result, bool includeAll=false)
bool Flash_Write(uint16_t adr, uint16_t dat)
bool OTP_Read(uint16_t adroffset, uint64_t *dat)
bool Flash_Read(uint16_t adr, uint16_t *buf, bool checkempty=true)
bool OTP_Write(uint16_t adroffset, uint64_t dat)
FFBoardMain * mainclass
const char * name
const char * clsname
uint16_t commandHandlerID
const uint16_t clsTypeid
int32_t getChipTemp()
int32_t getIntV()
int32_t getExtV()