@@ -108,6 +108,23 @@ enum GaugeInternalCommand {
108108bool vid6608Present = false ;
109109float vid6608StepsFloat = VID6608_DEFAULT_MAX_STEPS;
110110vid6608 *vid6608Drives[VID6608_MAX_DRIVES];
111+ #ifdef VID6608_RTOS
112+ /* *
113+ * @brief Mutex for RTOS precision timing
114+ *
115+ * We have to use "real" trheads under FreeRTOS, as precision timing is required
116+ * for stepper motor driving. This mutex protects data access from multiple
117+ * threads simultaniously. Else it will lead to stepper motor glitches and random move.
118+ *
119+ */
120+ SemaphoreHandle_t vid6608Mutex;
121+ // Macro for mutexs take/give
122+ #define VID6608_MUTEX_TAKE xSemaphoreTake (vid6608Mutex, portMAX_DELAY);
123+ #define VID6608_MUTEX_GIVE xSemaphoreGive (vid6608Mutex);
124+ #else
125+ #define VID6608_MUTEX_TAKE
126+ #define VID6608_MUTEX_GIVE
127+ #endif
111128
112129/* *
113130 * @brief Command Gauge
@@ -148,6 +165,7 @@ void CmndGaugeZero(void) {
148165 * @param payload command argument
149166 */
150167void CmndGaugeCommand (int32_t command, uint32_t index, int32_t payload) {
168+ VID6608_MUTEX_TAKE
151169 Response_P (PSTR (" {\" " D_PRFX_GAUGE " \" :{" ));
152170 bool isFirstItem = true ;
153171 for (uint8_t x = 0 ; x < VID6608_MAX_DRIVES; x++) {
@@ -179,6 +197,7 @@ void CmndGaugeCommand(int32_t command, uint32_t index, int32_t payload) {
179197 }
180198 }
181199 ResponseAppend_P (PSTR (" }}" ));
200+ VID6608_MUTEX_GIVE
182201}
183202
184203/* *
@@ -188,6 +207,7 @@ void CmndGaugeCommand(int32_t command, uint32_t index, int32_t payload) {
188207void VID6608StatusJson () {
189208 ResponseAppend_P (PSTR (" \" " D_PRFX_GAUGE " \" :{" ));
190209 bool isFirstItem = true ;
210+ VID6608_MUTEX_TAKE
191211 for (uint8_t x = 0 ; x < VID6608_MAX_DRIVES; x++) {
192212 vid6608 *driver = vid6608Drives[x];
193213 if (driver) {
@@ -198,6 +218,7 @@ void VID6608StatusJson() {
198218 isFirstItem = false ;
199219 }
200220 }
221+ VID6608_MUTEX_GIVE
201222 ResponseJsonEnd ();
202223}
203224
@@ -208,12 +229,14 @@ void VID6608StatusJson() {
208229 */
209230void VID6608StatusWeb () {
210231 WSContentSend_PD (HTTP_TABLE100);
232+ VID6608_MUTEX_TAKE
211233 for (uint8_t x = 0 ; x < VID6608_MAX_DRIVES; x++) {
212234 vid6608 *driver = vid6608Drives[x];
213235 if (driver) {
214236 WSContentSend_PD (PSTR (" <tr><th>Gauge %d</th><td>%d</td></tr>" ), (int32_t )(x+1 ), (int32_t )driver->getPosition ());
215237 }
216238 }
239+ VID6608_MUTEX_GIVE
217240 WSContentSend_PD (PSTR (" </table>" ));
218241}
219242#endif
@@ -227,6 +250,7 @@ void VID6608StatusWeb() {
227250void VID6608XvTask (void *) {
228251 while (true ) {
229252 bool needToMove = false ;
253+ VID6608_MUTEX_TAKE
230254 for (uint8_t x = 0 ; x < VID6608_MAX_DRIVES; x++) {
231255 vid6608 *driver = vid6608Drives[x];
232256 if (driver) {
@@ -236,6 +260,7 @@ void VID6608XvTask(void *) {
236260 }
237261 }
238262 }
263+ VID6608_MUTEX_GIVE
239264 /*
240265 If we dont need to move any -> go sleep.
241266 This will delay next move begin up to 500ms, but freeds up CPU a lot.
@@ -274,6 +299,8 @@ void VID6608Init() {
274299 return ;
275300 }
276301#ifdef VID6608_RTOS
302+ // Create mutex for RTOS thread safety
303+ vid6608Mutex = xSemaphoreCreateMutex ();
277304 // Start background RTOS thread -> required for precision timing
278305 xTaskCreate (
279306 VID6608XvTask, /* Function to implement the task */
0 commit comments