Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed random pause/hesitation when printing #2827

Merged
merged 3 commits into from
Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion TFT/src/User/API/Printing.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ void loopBreakToCondition(CONDITION_CALLBACK condCallback)
// from that command. Than another "M108" will be sent to unlock a next possible blocking command.
// This way enough "M108" will be sent to unlock all possible blocking command(s) (ongoing or enqueued) but not too much and
// not too fast one after another to overload/overrun the serial communication
TASK_LOOP_WHILE(condCallback(), if (infoHost.rx_ok[SERIAL_PORT] == true) sendEmergencyCmd("M108\n"))
TASK_LOOP_WHILE(condCallback(), if (Serial_Available(SERIAL_PORT) != 0) sendEmergencyCmd("M108\n"));

// remove any enqueued command that could come from a supplementary serial port or TFT media
// (if printing from remote host or TFT media) during the loop above
Expand Down
47 changes: 22 additions & 25 deletions TFT/src/User/API/SerialConnection.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ void Serial_Forward(SERIAL_PORT_INDEX portIndex, const char * msg)
Serial_Put(SERIAL_DEBUG_PORT, msg);
#endif

uint8_t portCount = SERIAL_PORT_COUNT; // by default, select all the serial ports
uint8_t portCount = SERIAL_PORT_COUNT; // by default, select all the serial ports

if (portIndex == ALL_PORTS) // if ALL_PORTS, forward the message to all the enabled serial ports
portIndex = PORT_1;
Expand All @@ -136,55 +136,52 @@ void Serial_Forward(SERIAL_PORT_INDEX portIndex, const char * msg)
}
}

uint16_t Serial_Available(SERIAL_PORT_INDEX portIndex)
{
if (!WITHIN(portIndex, PORT_1, SERIAL_PORT_COUNT - 1))
return 0;

return (dmaL1Data[portIndex].cacheSize + dmaL1Data[portIndex].wIndex - dmaL1Data[portIndex].rIndex) % dmaL1Data[portIndex].cacheSize;
}

uint16_t Serial_Get(SERIAL_PORT_INDEX portIndex, char * buf, uint16_t bufSize)
{
// if port index is out of range or no data to read from L1 cache
if (!WITHIN(portIndex, PORT_1, SERIAL_PORT_COUNT - 1) || !infoHost.rx_ok[portIndex])
if (!WITHIN(portIndex, PORT_1, SERIAL_PORT_COUNT - 1) || dmaL1Data[portIndex].flag == dmaL1Data[portIndex].wIndex)
return 0;

// make access to dinamically changed (by L1 cache's interrupt handler) variables/attributes faster and also reducing the code
DMA_CIRCULAR_BUFFER * dmaL1Data_ptr = &dmaL1Data[portIndex];
uint16_t * wIndex_ptr = &dmaL1Data_ptr->wIndex;

// L1 cache's reading index (not dinamically changed (by L1 cache's interrupt handler) variables/attributes)
// make a static access to dynamically changed (by L1 cache's interrupt handler) variables/attributes
uint16_t wIndex = dmaL1Data_ptr->wIndex;

// L1 cache's reading index (not dynamically changed (by L1 cache's interrupt handler) variables/attributes)
uint16_t rIndex = dmaL1Data_ptr->rIndex;

while (dmaL1Data_ptr->cache[rIndex] == ' ' && rIndex != *wIndex_ptr) // remove leading empty space, if any
while (dmaL1Data_ptr->cache[rIndex] == ' ' && rIndex != wIndex) // remove leading empty space, if any
{
rIndex = (rIndex + 1) % dmaL1Data_ptr->cacheSize;
}

for (uint16_t i = 0; i < (bufSize - 1) && rIndex != *wIndex_ptr; ) // retrieve data until buf is full or L1 cache is empty
for (uint16_t i = 0; i < (bufSize - 1) && rIndex != wIndex; ) // retrieve data until buf is full or L1 cache is empty
{
buf[i] = dmaL1Data_ptr->cache[rIndex];
rIndex = (rIndex + 1) % dmaL1Data_ptr->cacheSize;

if (buf[i++] == '\n') // if data end marker is found
{
buf[i] = '\0'; // end character
dmaL1Data_ptr->rIndex = rIndex; // update queue's index

if (rIndex == dmaL1Data_ptr->wIndex) // if L1 cache is empty, mark the port as containing no more data
infoHost.rx_ok[portIndex] = false;
buf[i] = '\0'; // end character
dmaL1Data_ptr->flag = dmaL1Data_ptr->rIndex = rIndex; // update queue's custom flag and reading index with rIndex

return i; // return the number of bytes stored in buf
}
}

// if here, a partial message is present on the L1 cache (message not terminated by "\n").
// We temporary skip the message until it is fully received
//
// NOTES:
// - this scenario typically happens when the TFT receives a burst of messages (e.g. the output for "M420 V1 T1").
// The first fully received message (terminated by "\n") is enough to trigger the L1 cache as available
// (infoHost.rx_ok[portIndex] set to "true") for reading
// - it is more safe to leave the following code line commented out just to avoid any possibility the
// L1 cache's interrupt handler is receiving (and triggering L1 cache as available) in the meanwhile
// (more safe to perform an active polling on the next invokation of this function than the possibility
// to not be able to read the message (if infoHost.rx_ok[portIndex] is found set to "false") until a
// next message (if any) becomes available)
//
// infoHost.rx_ok[portIndex] = false; // mark the port as containing no more (or partial) data
// We temporary skip the message until it is fully received updating also dmaL1Data_ptr->flag to
// prevent to read again (multiple times) the same partial message on next function invokation

dmaL1Data_ptr->flag = wIndex; // update queue's custom flag with wIndex

return 0; // return the number of bytes stored in buf
}
Expand Down
6 changes: 6 additions & 0 deletions TFT/src/User/API/SerialConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ void Serial_DeInit(SERIAL_PORT_INDEX portIndex);
// - specific port index: specific serial port
void Serial_Forward(SERIAL_PORT_INDEX portIndex, const char * msg);

// retrieve the number of bytes available on the provided serial port:
// - portIndex: index of serial port
//
// - return value: number of bytes available on serial port
uint16_t Serial_Available(SERIAL_PORT_INDEX portIndex);

// retrieve a message from the provided serial port, if any:
// - portIndex: index of serial port where data are read from
// - buf: buffer where data are stored
Expand Down
9 changes: 1 addition & 8 deletions TFT/src/User/Hal/gd32f20x/Serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,13 @@ void Serial_DMA_Config(uint8_t port)

void Serial_ClearData(uint8_t port)
{
dmaL1Data[port].rIndex = dmaL1Data[port].wIndex = dmaL1Data[port].cacheSize = 0;
dmaL1Data[port].wIndex = dmaL1Data[port].rIndex = dmaL1Data[port].flag = dmaL1Data[port].cacheSize = 0;

if (dmaL1Data[port].cache != NULL)
{
free(dmaL1Data[port].cache);
dmaL1Data[port].cache = NULL;
}

infoHost.rx_ok[port] = false;
}

void Serial_Config(uint8_t port, uint16_t cacheSize, uint32_t baudrate)
Expand Down Expand Up @@ -109,11 +107,6 @@ void USART_IRQHandler(uint8_t port)
USART_DATA(Serial[port].uart);

dmaL1Data[port].wIndex = dmaL1Data[port].cacheSize - DMA_CHCNT(Serial[port].dma_stream, Serial[port].dma_channel);
uint16_t wIndex = (dmaL1Data[port].wIndex == 0) ? dmaL1Data[port].cacheSize : dmaL1Data[port].wIndex;
if (dmaL1Data[port].cache[wIndex - 1] == '\n') // Receive completed
{
infoHost.rx_ok[port] = true;
}
}
}

Expand Down
7 changes: 4 additions & 3 deletions TFT/src/User/Hal/gd32f20x/Serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
#include "variants.h" // for uint32_t etc...
#include "uart.h"

typedef struct
typedef volatile struct // precautionally declared as volatile due to access from interrupt handler and main thread
{
char *cache;
uint16_t wIndex;
uint16_t rIndex;
uint16_t wIndex; // writing index
uint16_t rIndex; // reading index
uint16_t flag; // custom flag (for custom usage by the application)
uint16_t cacheSize;
} DMA_CIRCULAR_BUFFER;

Expand Down
9 changes: 1 addition & 8 deletions TFT/src/User/Hal/stm32f10x/Serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,13 @@ void Serial_DMA_Config(uint8_t port)

void Serial_ClearData(uint8_t port)
{
dmaL1Data[port].rIndex = dmaL1Data[port].wIndex = dmaL1Data[port].cacheSize = 0;
dmaL1Data[port].wIndex = dmaL1Data[port].rIndex = dmaL1Data[port].flag = dmaL1Data[port].cacheSize = 0;

if (dmaL1Data[port].cache != NULL)
{
free(dmaL1Data[port].cache);
dmaL1Data[port].cache = NULL;
}

infoHost.rx_ok[port] = false;
}

void Serial_Config(uint8_t port, uint16_t cacheSize, uint32_t baudrate)
Expand Down Expand Up @@ -80,11 +78,6 @@ void USART_IRQHandler(uint8_t port)
Serial[port].uart->DR;

dmaL1Data[port].wIndex = dmaL1Data[port].cacheSize - Serial[port].dma_chanel->CNDTR;
uint16_t wIndex = (dmaL1Data[port].wIndex == 0) ? dmaL1Data[port].cacheSize : dmaL1Data[port].wIndex;
if (dmaL1Data[port].cache[wIndex - 1] == '\n') // Receive completed
{
infoHost.rx_ok[port] = true;
}
}
}

Expand Down
7 changes: 4 additions & 3 deletions TFT/src/User/Hal/stm32f10x/Serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
#include "variants.h" // for uint32_t etc...
#include "uart.h"

typedef struct
typedef volatile struct // precautionally declared as volatile due to access from interrupt handler and main thread
{
char *cache;
uint16_t wIndex;
uint16_t rIndex;
uint16_t wIndex; // writing index
uint16_t rIndex; // reading index
uint16_t flag; // custom flag (for custom usage by the application)
uint16_t cacheSize;
} DMA_CIRCULAR_BUFFER;

Expand Down
9 changes: 1 addition & 8 deletions TFT/src/User/Hal/stm32f2_f4xx/Serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,13 @@ void Serial_DMA_Config(uint8_t port)

void Serial_ClearData(uint8_t port)
{
dmaL1Data[port].rIndex = dmaL1Data[port].wIndex = dmaL1Data[port].cacheSize = 0;
dmaL1Data[port].wIndex = dmaL1Data[port].rIndex = dmaL1Data[port].flag = dmaL1Data[port].cacheSize = 0;

if (dmaL1Data[port].cache != NULL)
{
free(dmaL1Data[port].cache);
dmaL1Data[port].cache = NULL;
}

infoHost.rx_ok[port] = false;
}

void Serial_Config(uint8_t port, uint16_t cacheSize, uint32_t baudrate)
Expand Down Expand Up @@ -110,11 +108,6 @@ void USART_IRQHandler(uint8_t port)
Serial[port].uart->DR;

dmaL1Data[port].wIndex = dmaL1Data[port].cacheSize - Serial[port].dma_stream->NDTR;
uint16_t wIndex = (dmaL1Data[port].wIndex == 0) ? dmaL1Data[port].cacheSize : dmaL1Data[port].wIndex;
if (dmaL1Data[port].cache[wIndex - 1] == '\n') // Receive completed
{
infoHost.rx_ok[port] = true;
}
}
}

Expand Down
7 changes: 4 additions & 3 deletions TFT/src/User/Hal/stm32f2_f4xx/Serial.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
#include "variants.h" // for uint32_t etc...
#include "uart.h"

typedef struct
typedef volatile struct // precautionally declared as volatile due to access from interrupt handler and main thread
{
char *cache;
uint16_t wIndex;
uint16_t rIndex;
uint16_t wIndex; // writing index
uint16_t rIndex; // reading index
uint16_t flag; // custom flag (for custom usage by the application)
uint16_t cacheSize;
} DMA_CIRCULAR_BUFFER;

Expand Down
14 changes: 7 additions & 7 deletions TFT/src/User/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ extern "C" {
#include "variants.h" // for RCC_ClocksTypeDef
#include "uart.h" // for _UART_CNT

#define MAX_MENU_DEPTH 10 // Max sub menu depth
#define MAX_MENU_DEPTH 10 // max sub menu depth

typedef void (* FP_MENU)(void);

typedef struct
{
FP_MENU menu[MAX_MENU_DEPTH]; // Menu function buffer
uint8_t cur; // Current menu index in buffer
FP_MENU menu[MAX_MENU_DEPTH]; // menu function buffer
uint8_t cur; // current menu index in buffer
} MENU;

typedef enum
Expand All @@ -30,10 +31,9 @@ typedef enum

typedef struct
{
bool wait; // Whether wait for Marlin's response
bool rx_ok[_UART_CNT]; // Whether receive Marlin's response or get gcode by other UART (ESP3D/OctoPrint)
bool connected; // Whether have connected to Marlin
HOST_STATUS status; // Whether the host is busy in printing execution. (USB serial printing and gcode print from onboard)
bool wait; // whether wait for Marlin's response
bool connected; // whether have connected to Marlin
HOST_STATUS status; // whether the host is busy in printing execution. (USB serial printing and gcode print from onboard)
} HOST;

typedef struct
Expand Down