Duet 2 disconnects after running a custom M command
-
I wrote a custom M command to insert a drive movement in the move queue. The firmware complies and flashes fine but whenever I run the M command, the blue light flashes once and the board disconnects from YAT. I tried using the stackanalyzer tool but unfortunately it did not give me any results whatsoever. How else can I figure out where the fault is occurring?
Here is the M Code :
case 840: // insert move { for (size_t axis = 0; axis < numVisibleAxes; ++axis) { if (gb.Seen(axisLetters[axis])) { const uint32_t ipval = gb.GetUIValue(); //reply.catf("input given is : %.3f \n",(double)ipval); //reprap.GetMove().insertmymove(simulationMode,firstUnpreparedMove,(int)ipval); reprap.GetMove().insertmymove(simulationMode, ipval, axis); } } } break;
where the function is defined in DDA.cpp as
void DDA::MoveInsert(uint8_t simMode, uint32_t input,size_t axis) noexcept { debugPrintf("Sim mode : %d \n" , simMode); debugPrintf("Input : %" PRIu32 "\n" , input); Platform& platform = reprap.GetPlatform(); PrepParams params; AxesBitmap additionalAxisMotorsToEnable, axisMotorsEnabled; int32_t delta = input*80 - prev->endPoint[axis]; if (delta != 0) { platform.EnableDrivers(axis); if (platform.GetDriversBitmap(axis) != 0) { DriveMovement* const pdm = DriveMovement::Allocate(axis, DMState::accel0); pdm->totalSteps = labs(delta); pdm->direction = (delta >= 0); if (pdm->PrepareCartesianAxis(*this, params)) { pdm->directionChanged = false; if (reprap.Debug(moduleDda) && pdm->totalSteps > 1000000) { DebugPrintAll("pr"); } InsertDM(pdm); } else { pdm->state = DMState::idle; pdm->nextDM = completedDMs; completedDMs = pdm; } } axisMotorsEnabled.SetBit(axis); additionalAxisMotorsToEnable |= reprap.GetMove().GetKinematics().GetConnectedAxes(axis); } const DDAState st = prev->state; afterPrepare.moveStartTime = (st == DDAState::executing || st == DDAState::frozen) ? prev->afterPrepare.moveStartTime + prev->clocksNeeded : StepTimer::GetTimerTicks() + AbsoluteMinimumPreparedTime; if (flags.checkEndstops) { platform.EnableAllSteppingDrivers(); CheckEndstops(platform); } if (reprap.Debug(moduleDda) && reprap.Debug(moduleMove)) { DebugPrintAll("pr"); } if (state != completed) { state = frozen; } }
Edit
Upon running M122 I obtain the following log :
=== Diagnostics ===<LF>RepRapFirmware for Duet 2 WiFi/Ethernet version 3.3+ (2021-10-12 17:16:29) running on Duet WiFi 1.02 or later<LF> Board ID: 08DJM-9178L-L2MSD-6JKDG-3SS6M-18GAQ<LF>Used output buffers: 1 of 24 (1 max)<LF>=== RTOS ===<LF>Static ram: 23884<LF>Dynamic ram: 750 40 of which 0 recycled<LF>Never used RAM 14484, free system stack 193 words<LF>Tasks: NETWORK(ready,6.7%,369) HEAT(delaying,0.0%,342) Mo ve(notifyWait,0.1%,364) MAIN(running,93.2%,463) IDLE(ready,0.0%,29), total 100.0%<LF>Owned mutexes: USB(MAIN)<LF>=== Platform ===<LF>Last r eset 00:50:31 ago, cause: software<LF>Last software reset time unknown, reason: HardFault bfarValid precise, GCodes spinning, availab le RAM 14484, slot 0<LF>Software reset code 0x0063 HFSR 0x40000000 CFSR 0x00008200 ICSR 0x00400803 BFAR 0xa5a5a5a9 SP 0x200023f0 Task MAIN Freestk 811 ok<LF>Stack: a5a5a5a5 00000000 00000002 00000000 00000038 004422db 00424db4 210f0000 00000000 0042c4b1 200024c4 200 00e68 00000000 00000058 00000000 00000005 20000e68 2000a2b8 20008b70 2000a324 20008b70 0043811d 00000000 2000a2b8 20008b70 0043ff4 3 00000000<LF>Error status: 0x00<LF>Step timer max interval 0<LF>MCU temperature: min 37.3, current 38.9, max 39.3<LF>Supply voltage: min 1.6, current 1.7, max 1.8, under voltage events: 0, over voltage events: 0, power good: no<LF>Heap OK, handles allocated/used 0/0, heap m emory allocated/used/recyclable 0/0/0, gc cycles 0<LF>Driver 0: position 0, ok, SG min/max not available<LF>Driver 1: position 0, ok, SG min/max not available<LF>Driver 2: position 0, ok, SG min/max not available<LF>Driver 3: position 0, ok, SG min/max not available<LF>Drive r 4: position 0, ok, SG min/max not available<LF>Driver 5: position 0<LF>Driver 6: position 0<LF>Driver 7: position 0<LF>Driver 8: position 0<LF> Driver 9: position 0<LF>Driver 10: position 0<LF>Driver 11: position 0<LF>Date/time: 1970-01-01 00:00:00<LF>Cache data hit count 4294967295<LF>Sl owest loop: 5.88ms; fastest: 0.13ms<LF>I2C nak errors 0, send timeouts 0, receive timeouts 0, finishTimeouts 0, resets 0<LF>=== Storage ===<LF>Free file entries: 10<LF>SD card 0 detected, interface speed: 20.0MBytes/sec<LF>SD card longest read time 3.3ms, write time 0.0ms, m ax retries 0<LF>=== Move ===<LF>DMs created 83, maxWait 0ms, bed compensation in use: none, comp offset 0.000<LF>=== MainDDARing ===<LF>Schedu led moves 0, completed moves 0, hiccups 0, stepErrors 0, LaErrors 0, Underruns [0, 0, 0], CDDA state -1<LF>=== AuxDDARing ===<LF>Schedul ed moves 0, completed moves 0, hiccups 0, stepErrors 0, LaErrors 0, Underruns [0, 0, 0], CDDA state -1<LF>=== Heat ===<LF>Bed heaters = 0 -1 -1 -1, chamberHeaters = -1 -1 -1 -1<LF>=== GCodes ===<LF>Segments left: 0<LF>Movement lock held by null<LF>HTTP is idle in state(s) 0<LF>Tel net is idle in state(s) 0<LF>File is idle in state(s) 0<LF>USB is ready with "M122" in state(s) 0<LF>Aux is idle in state(s) 0<LF>Trigger is i dle in state(s) 0<LF>Queue is idle in state(s) 0<LF>LCD is idle in state(s) 0<LF>Daemon is idle in state(s) 0<LF>Autopause is idle in state(s) 0<LF>Code queue is empty.<LF>=== Network ===<LF>Slowest loop: 1.26ms; fastest: 0.00ms<LF>Responder states: HTTP(0) HTTP(0) HTTP(0) HTTP(0) FT P(0) Telnet(0), 0 sessions<LF>HTTP sessions: 0 of 8<LF>- WiFi -<LF>Network state is changingMode<LF>WiFi module is idle<LF>Failed messages: pendi ng 0, notready 0, noresp 0<LF>Failed to get WiFi status<LF>Socket states: 0 0 0 0 0 0 0 0<LF>ok<LF>Error retrieving WiFi status message: SPI t imeout<LF>WiFi module is idle<LF>Failed to change WiFi mode: SPI timeout<LF>
I can see that there is a software reset and the reason seems to be
HardFault bfarValid precise
which I believe is the register hold the address where fault occurred. However, I have no idea how pinpoint the section of code which results in an error. Any help would be greatly appreciated.
-
@jazbaatbadalgaye you haven't shown the code you added in the Move and DDARing classes to establish a DDA to call InsertMyMove on. Perhaps the DDA is invalid.
You can use the stack analyser to identify the function that the fault occurred in and the offset within that function. Then you can use the assembly file for that module to identify the exact instruction that caused the fault. After that it's a matter of relating the assembly code to the C++ source code.,
-
@dc42 So i am copying the output given to me by the M122 command and saving it as
logM122.txt
. I copied both files (mymapfile.map
file + m122 output) into../../stackanalyzer/win
and run the follwing commandstackanalyzer -m122 logM122.txt -mapFile mymapfile.map
But I don't see any output on the terminal. Is there a separate file or something that is created by stackanalyzer?
-
//in move.cpp void Move::insertmymove(uint8_t simMode, uint32_t input, size_t axis) //insert my move { mainDDARing.prepmoves(simulationMode, input, axis); //prepmoves }
//in DDARing void DDARing:prepmoves(uint8_t simMode, uint32_t input,size_t axis) noexcept { addPointer2->MoveInsert(simMode, input,axis); }
This is what I have in DDARing and Move.cpp.
// in DDA.cpp void DDA::MoveInsert(uint8_t simMode, uint32_t input,size_t axis) noexcept { debugPrintf("Sim mode : %d \n" , simMode); debugPrintf("Input : %" PRIu32 "\n" , input); Platform& platform = reprap.GetPlatform(); PrepParams params; AxesBitmap additionalAxisMotorsToEnable, axisMotorsEnabled; int32_t delta = input*80 - prev->endPoint[axis]; if (delta != 0) { platform.EnableDrivers(axis); if (platform.GetDriversBitmap(axis) != 0) { DriveMovement* const pdm = DriveMovement::Allocate(axis, DMState::accel0); pdm->totalSteps = labs(delta); pdm->direction = (delta >= 0); if (pdm->PrepareCartesianAxis(*this, params)) { pdm->directionChanged = false; if (reprap.Debug(moduleDda) && pdm->totalSteps > 1000000) { DebugPrintAll("pr"); } InsertDM(pdm); } else { pdm->state = DMState::idle; pdm->nextDM = completedDMs; completedDMs = pdm; } } axisMotorsEnabled.SetBit(axis); additionalAxisMotorsToEnable |= reprap.GetMove().GetKinematics().GetConnectedAxes(axis); } const DDAState st = prev->state; afterPrepare.moveStartTime = (st == DDAState::executing || st == DDAState::frozen) ? prev->afterPrepare.moveStartTime + prev->clocksNeeded : StepTimer::GetTimerTicks() + AbsoluteMinimumPreparedTime; if (flags.checkEndstops) { platform.EnableAllSteppingDrivers(); CheckEndstops(platform); } if (reprap.Debug(moduleDda) && reprap.Debug(moduleMove)) { DebugPrintAll("pr"); } if (state != completed) { state = frozen; } }
This is what I have in DDA.cpp
case 840: // insert move { for (size_t axis = 0; axis < numVisibleAxes; ++axis) { if (gb.Seen(axisLetters[axis])) { const uint32_t ipval = gb.GetUIValue(); //reply.catf("input given is : %.3f \n",(double)ipval); reprap.GetMove().insertmymove(simulationMode, ipval, axis); } } } break;
And this what I have in GCodes2.cpp
-
@jazbaatbadalgaye the map file needs to be the .map file that was created alongside the firmware binary. Also you need to configure YAT to recognise LF only as a line terminator so that the output is in the correct format. See the Getting Connected page.
-
@dc42 Yes, I am using the same mapfile named
Duet2combinedfirmware.map
. I just renamed it after copying. I will try giving it the absolute path -
@dc42 okay changing it to LF did the trick! Thanks a bunch.
Faulted at: .text._ZN3DDA11StepDriversER8Platformm 0x00425e74 0x148 ./src/Movement/DDA.o 0x00425e74 DDA::MoveInsert(unsigned char, unsigned long, unsigned int) Error is at offset: 0x4
So I can see that the the MoveInsert is giving me an error as suspected.
How to interpret the
Error is at offset: 0x4
I have the DDA.s which I believe is the assembly file (?). So I look for the 5th byte in the assembly file?
-
@jazbaatbadalgaye said in Duet 2 disconnects after running a custom M command:
I have the DDA.s which I believe is the assembly file (?). So I look for the 5th byte in the assembly file?
Look in the assembly file for the instruction that is at offset 4 within function DDA::MoveInsert.