From bef6b94b7e340075096b4a6ca81adb736f9569ce Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sat, 30 Jun 2018 20:04:04 -0500 Subject: [PATCH] Max7219 RTOS changes --- Marlin/src/Marlin.cpp | 55 +++++++++++++++++- Marlin/src/feature/Max7219_Debug_LEDs.cpp | 68 +++++++++++++++++++++++ Marlin/src/feature/Max7219_Debug_LEDs.h | 28 ++++++++++ Marlin/src/gcode/feature/leds/M102.cpp | 37 ++++++++++++ Marlin/src/gcode/gcode.cpp | 4 ++ Marlin/src/gcode/gcode.h | 5 ++ 6 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 Marlin/src/gcode/feature/leds/M102.cpp diff --git a/Marlin/src/Marlin.cpp b/Marlin/src/Marlin.cpp index f067bce082..6188d7f954 100644 --- a/Marlin/src/Marlin.cpp +++ b/Marlin/src/Marlin.cpp @@ -531,6 +531,14 @@ void manage_inactivity(const bool ignore_stepper_queue/*=false*/) { } } +#if ENABLED(MAX7219_DEBUG) + QueueHandle_t Max7219_Queue = NULL; + unsigned long int zz = 0, // Temporary - will go away soon - used by loop() + zzz = 0, // Temporary - will go away soon - used by Marlin_idle() + zzzz = 0, // Temporary - will go away soon - used by Marlin_main_loop() + zzzzz = 0; // Temporary - will go away soon - used by idle() +#endif + /** * Standard idle routine keeps the machine alive */ @@ -540,7 +548,8 @@ void idle( #endif ) { #if ENABLED(MAX7219_DEBUG) - max7219.idle_tasks(); + zzzzz++; + Max7219_Do_Cmd(LED_SET_ROW, 0, 5, uint8_t(zzzzz >> 5)); #endif lcd_update(); @@ -683,6 +692,18 @@ void setup() { #if ENABLED(MAX7219_DEBUG) max7219.init(); + + Max7219_Queue = xQueueCreate(3 /* # of queue items */, sizeof(LED_Msg)); + if (Max7219_Queue == NULL) { + Max7219_Set_Row(0, 0xe5); + for (;;); + } + + // Create the Max7219 debug task. It is very low priority in an attempt to not affect the + // normal timing of Marlin. But if too many messages are sent too quickly to the task, + // the command queue will fill up and the sender will block until a message has been drained + // to make room for the next message. + xTaskCreate((TaskFunction_t)Max7219_Cmd_Processor, "Max7219_LEDs", 200 /* Stack size */, NULL, 2 /* priority */, NULL); #endif ptr = (char *) malloc(75); // reserve some memory for the RTOS to use later. It will be given @@ -965,8 +986,17 @@ TaskFunction_t Marlin_main_loop() { // In the mean time... settings.load() is run at the start of the Marlin_main_loop() // task. This approach seems to work around what ever the problem is. + Max7219_Do_Cmd(LED_CLEAR_MATRIX, 0, 0, 0); + for (;;) { + #if ENABLED(MAX7219_DEBUG) + zzzz++; + Max7219_Do_Cmd(LED_SET_ROW, 0, 7, uint8_t(zzzz >> 4)); + if ((zzzz & 0x20) == 0x20) + Max7219_Do_Cmd(LED_TOGGLE, 5, 1, 0); + #endif + #if ENABLED(SDSUPPORT) card.checkautostart(); #endif @@ -1000,3 +1030,26 @@ TaskFunction_t Marlin_main_loop() { vTaskDelay(1); } } + +TaskFunction_t Marlin_idle() { + for (;;) { + Max7219_Do_Cmd(LED_SET_ROW, 0, 6, (uint8_t) (zzz++>>3)); + vTaskDelay(3); + } +} + +/** + * Very low priority, non-blocking logic can be called from loop() This represents + * a small shift from the past. FreeRTOS expects a setup() routine and loop() routine + * within an Arduino environment. loop() is called from the RTOS idle task and is of a + * very low priority. The FreeRTOS idle routine can not be any priority except zero. + * + * A loop() function must be available for FreeRTOS to call. But the main Marlin loop + * logic needs to be at a very high priority. That is the reason for the name shifts. + */ + +void loop() { + #if ENABLED(MAX7219_DEBUG) + Max7219_LED_Toggle(7, 0); // Max7219_Do_Cmd(LED_TOGGLE, 7, 0, 0); can not be used because loop() is not allowed to block! + #endif +} diff --git a/Marlin/src/feature/Max7219_Debug_LEDs.cpp b/Marlin/src/feature/Max7219_Debug_LEDs.cpp index 0588c836b5..cf522739cd 100644 --- a/Marlin/src/feature/Max7219_Debug_LEDs.cpp +++ b/Marlin/src/feature/Max7219_Debug_LEDs.cpp @@ -48,6 +48,9 @@ #include "../Marlin.h" #include "../HAL/shared/Delay.h" +#include +#include + Max7219 max7219; uint8_t Max7219::led_line[MAX7219_LINES]; // = { 0 }; @@ -101,6 +104,68 @@ void Max7219::error(const char * const func, const int32_t v1, const int32_t v2/ #endif } +extern QueueHandle_t Max7219_Queue; +struct LED_Msg incoming_led_msg; +#define MSG incoming_led_msg + +void Max7219_Do_Cmd(uint8_t msg, uint8_t col, uint8_t row, uint32_t val ) { + struct LED_Msg out_going_led_msg; + + out_going_led_msg.operation = msg; + out_going_led_msg.col = col; + out_going_led_msg.row = row; + out_going_led_msg.val = val; + + while (pdPASS != xQueueSendToBack(Max7219_Queue, &out_going_led_msg, 100)) { /* nada */ } +} + +TaskFunction_t Max7219_Cmd_Processor(void *ptr) { + + while (Max7219_Queue == NULL) // wait until the message queue is set up to look for stuff to process + vTaskDelay(50); + + for (;;) { + + while (pdPASS != xQueueReceive( Max7219_Queue, &incoming_led_msg, 2000)) { /* nada */ } + + switch (MSG.operation) { + case LED_NOP: break; + case LED_INIT: Max7219_init(); + break; + case LED_LOAD_REGS: Max7219_register_setup(); + break; + case LED_ON: Max7219_LED_On(MSG.col, MSG.row); + break; + case LED_OFF: Max7219_LED_Off(MSG.col, MSG.row); + break; + case LED_TOGGLE: Max7219_LED_Toggle(MSG.col, MSG.row); + break; + case LED_CLEAR_MATRIX: Max7219_Clear(); + break; + case LED_CLEAR_ROW: Max7219_Clear_Row(MSG.row); + break; + case LED_CLEAR_COLUMN: Max7219_Clear_Column(MSG.col); + break; + case LED_SET_ROW: Max7219_Set_Row(MSG.row, (uint8_t) MSG.val); + break; + case LED_SET_2_ROWS: Max7219_Set_2_Rows(MSG.row, (uint16_t) MSG.val); + break; + case LED_SET_4_ROWS: Max7219_Set_4_Rows(MSG.row, MSG.val); + break; + case LED_SET_COLUMN: Max7219_Set_Column(MSG.col, (uint8_t) MSG.val); + break; + case LED_IDLE_TASK: Max7219_idle_tasks(); + break; + } + } +} + +void Max7219_PutByte(uint8_t data) { + #ifndef CPU_32_BIT + CRITICAL_SECTION_START; + #endif +} + /** * Flip the lowest n_bytes of the supplied bits: * flipped(x, 1) flips the low 8 bits of x. @@ -510,6 +575,9 @@ void Max7219::quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv) { } void Max7219::idle_tasks() { + + return; // Temporary!!! + #define MAX7219_USE_HEAD (defined(MAX7219_DEBUG_PLANNER_HEAD) || defined(MAX7219_DEBUG_PLANNER_QUEUE)) #define MAX7219_USE_TAIL (defined(MAX7219_DEBUG_PLANNER_TAIL) || defined(MAX7219_DEBUG_PLANNER_QUEUE)) #if MAX7219_USE_HEAD || MAX7219_USE_TAIL diff --git a/Marlin/src/feature/Max7219_Debug_LEDs.h b/Marlin/src/feature/Max7219_Debug_LEDs.h index 8b3d19e18c..08ed7ccfe9 100644 --- a/Marlin/src/feature/Max7219_Debug_LEDs.h +++ b/Marlin/src/feature/Max7219_Debug_LEDs.h @@ -155,3 +155,31 @@ private: }; extern Max7219 max7219; + +// RTOS hooks +void Max7219_Do_Cmd(uint8_t msg, uint8_t row, uint8_t col, uint32_t val); +TaskFunction_t Max7219_Cmd_Processor(void*); + +#define LED_NOP 0x00 +#define LED_LOAD_REGS 0x01 +#define LED_INIT 0x02 +#define LED_ON 0x03 +#define LED_OFF 0x04 +#define LED_TOGGLE 0x05 +#define LED_CLEAR_MATRIX 0x06 +#define LED_CLEAR_ROW 0x07 +#define LED_CLEAR_COLUMN 0x08 +#define LED_SET_ROW 0x09 +#define LED_SET_2_ROWS 0x0a +#define LED_SET_4_ROWS 0x0b +#define LED_SET_COLUMN 0x0c +#define LED_IDLE_TASK 0x0d + +struct LED_Msg { + uint8_t operation; + uint8_t row; + uint8_t col; + uint32_t val; +}; + +#endif // __MAX7219_DEBUG_LEDS_H__ diff --git a/Marlin/src/gcode/feature/leds/M102.cpp b/Marlin/src/gcode/feature/leds/M102.cpp new file mode 100644 index 0000000000..e84affb726 --- /dev/null +++ b/Marlin/src/gcode/feature/leds/M102.cpp @@ -0,0 +1,37 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "../../../inc/MarlinConfig.h" + +#if ENABLED(MAX7219_DEBUG) + +#include "../../gcode.h" +#include "../../../feature/Max7219_Debug_LEDs.h" + +/** + * M102: Directly re-initialize Max7219 debug LEDs + */ +void GcodeSuite::M102() { + Max7219_register_setup(); +} + +#endif // MAX7219_DEBUG diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp index 864a933674..7755a84b5f 100644 --- a/Marlin/src/gcode/gcode.cpp +++ b/Marlin/src/gcode/gcode.cpp @@ -355,6 +355,10 @@ void GcodeSuite::process_parsed_command( #endif case 101: M101(); break; // M101: RTOS Task Free Memory Report + #if ENABLED(MAX7219_DEBUG) + case 102: M102(); break; // M102: Max7219 register re-initialization (for debugging) + #endif + case 104: M104(); break; // M104: Set hot end temperature case 109: M109(); break; // M109: Wait for hotend temperature to reach target case 110: M110(); break; // M110: Set Current Line Number diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index 76cf38a5f5..382e20b206 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -115,6 +115,7 @@ * M92 - Set planner.axis_steps_per_mm for one or more axes. * M100 - Watch Free Memory (for debugging) (Requires M100_FREE_MEMORY_WATCHER) * M101 - RTOS Task Free Memory report (for debugging) + * M102 - Max7219 re-initialization of setup registers (for debugging) * M104 - Set extruder target temp. * M105 - Report current temperatures. * M106 - Set print fan speed. @@ -515,6 +516,10 @@ private: #endif static void M101(); + #if ENABLED(MAX7219_DEBUG) + static void M102(); + #endif + static void M104(); static void M105(); static void M106();