| 1221 | } |
| 1222 | |
| 1223 | void RepRap::Tick() noexcept |
| 1224 | { |
| 1225 | // Kicking the watchdog before it has been initialised may trigger it! |
| 1226 | if (active) |
| 1227 | { |
| 1228 | WatchdogReset(); // kick the watchdog |
| 1229 | |
| 1230 | #if SAM4E || SAME70 |
| 1231 | WatchdogResetSecondary(); // kick the secondary watchdog |
| 1232 | #endif |
| 1233 | |
| 1234 | #if SUPPORT_DIRECT_LCD |
| 1235 | display->Tick(); |
| 1236 | #endif |
| 1237 | if (!stopped) |
| 1238 | { |
| 1239 | platform->Tick(); |
| 1240 | ++ticksInSpinState; |
| 1241 | ++heatTaskIdleTicks; |
| 1242 | const bool heatTaskStuck = (heatTaskIdleTicks >= MaxHeatTaskTicksInSpinState); |
| 1243 | if (heatTaskStuck || ticksInSpinState >= MaxMainTaskTicksInSpinState) // if we stall for 20 seconds, save diagnostic data and reset |
| 1244 | { |
| 1245 | stopped = true; |
| 1246 | heat->SwitchOffAllLocalFromISR(); // can't call SwitchOffAll because remote heaters can't be turned off from inside a ISR |
| 1247 | move->EmergencyDisableDrivers(); |
| 1248 | |
| 1249 | // Save the stack of the stuck task when we get stuck in a spin loop |
| 1250 | const uint32_t *_ecv_array relevantStackPtr; |
| 1251 | |
| 1252 | // When a task gets stuck, sometimes we want the stack of that task and sometimes we want the stack of the running task instead |
| 1253 | #if 1 |
| 1254 | // Record the stack of the running task |
| 1255 | const TaskHandle relevantTask = RTOSIface::GetCurrentTask(); |
| 1256 | #else |
| 1257 | // Record the stack of the stuck task |
| 1258 | const TaskHandle relevantTask = (heatTaskStuck) ? Heat::GetHeatTask() : Tasks::GetMainTask(); |
| 1259 | #endif |
| 1260 | if (relevantTask == RTOSIface::GetCurrentTask()) |
| 1261 | { |
| 1262 | #ifdef __ECV__ |
| 1263 | // eCv doesn't understand the gcc "register const... asm" line |
| 1264 | const uint32_t *_ecv_array stackPtr = _ecv_undefined(const uint32_t *_ecv_array); |
| 1265 | #else |
| 1266 | __asm volatile("mrs r2, psp"); |
| 1267 | register const uint32_t *_ecv_array stackPtr asm ("r2"); // we want the PSP not the MSP |
| 1268 | #endif |
| 1269 | relevantStackPtr = stackPtr + 5; // discard uninteresting registers, keep LR PC PSR |
| 1270 | } |
| 1271 | else |
| 1272 | { |
| 1273 | relevantStackPtr = const_cast<const uint32_t *_ecv_array>(pxTaskGetLastStackTop(relevantTask->GetFreeRTOSHandle())); |
| 1274 | // All registers were saved on the stack, so to get useful return addresses we need to skip most of them. |
| 1275 | // See the port.c files in FreeRTOS for the stack layouts |
| 1276 | #if SAME70 || SAM4E || SAME5x |
| 1277 | // ARM Cortex M7 with double precision floating point, or ARM Cortex M4F |
| 1278 | if ((relevantStackPtr[8] & 0x10) == 0) // test EXC_RETURN FP bit |
| 1279 | { |
| 1280 | relevantStackPtr += 9 + 16; // skip r4-r11 and r14 and s16-s31 |
no test coverage detected