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

Added TX Interrupt/DMA based serial writing #2840

Merged
merged 21 commits into from
Oct 31, 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/Notification.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ void addNotification(DIALOG_TYPE style, char *title, char *text, bool ShowDialog
}

// store message
msglist[nextMsgIndex].style = style;
msglist[nextMsgIndex].style = style;
strncpy_no_pad(msglist[nextMsgIndex].text, text, MAX_MSG_LENGTH);
strncpy_no_pad(msglist[nextMsgIndex].title, title, MAX_MSG_TITLE_LENGTH);

Expand Down
7 changes: 5 additions & 2 deletions TFT/src/User/API/Printing.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ void loopBreakToCondition(CONDITION_CALLBACK condCallback)
uint16_t rIndex;

TASK_LOOP_WHILE(condCallback(),
if ((rIndex = Serial_GetReadingIndex(SERIAL_PORT)) != rIndex_old)
if ((rIndex = Serial_GetReadingIndexRX(SERIAL_PORT)) != rIndex_old)
{
sendEmergencyCmd("M108\n");
rIndex_old = rIndex;
Expand Down Expand Up @@ -310,7 +310,7 @@ void initPrintSummary(void)
infoPrintSummary = (PRINT_SUMMARY){.name[0] = '\0', 0, 0, 0, 0, false};

// save print filename (short or long filename)
sprintf(infoPrintSummary.name, "%." STRINGIFY(SUMMARY_NAME_LEN) "s", getPrintFilename());
strncpy_no_pad(infoPrintSummary.name, getPrintFilename(), SUMMARY_NAME_LEN);
}

void preparePrintSummary(void)
Expand Down Expand Up @@ -903,6 +903,9 @@ void loopPrintFromTFT(void)
}
}
}

if (comment_parsing) // parse comment from gcode file
parseComment();
}

if (gcode_count == 0)
Expand Down
64 changes: 15 additions & 49 deletions TFT/src/User/API/RRFSendCmd.c
Original file line number Diff line number Diff line change
@@ -1,58 +1,24 @@
#include "RRFSendCmd.h"
#include "Serial.h"
#include <stdio.h>
#include "includes.h"

static uint8_t n_sent = 0;
static uint32_t line_number = 0;
static uint8_t checksum = 0;

void sendCharAndChecksum(const char c)
void rrfSendCmd(const char * cmd_ptr)
{
checksum ^= c;
Serial_PutChar(SERIAL_PORT, c);
n_sent++;
}
char rrfCmd[CMD_MAX_SIZE];
char * rrfCmd_ptr = rrfCmd;
uint8_t checksum = 0;

void sendChar(const char c)
{
if (c == '\n')
{
if (n_sent != 0)
{
Serial_PutChar(SERIAL_PORT, '*');
char digit0 = checksum % 10 + '0';
checksum /= 10;
char digit1 = checksum % 10 + '0';
checksum /= 10;
if (checksum != 0)
{
Serial_PutChar(SERIAL_PORT, checksum + '0');
}
Serial_PutChar(SERIAL_PORT, digit1);
Serial_PutChar(SERIAL_PORT, digit0);
}
Serial_PutChar(SERIAL_PORT, c);
n_sent = 0;
}
else
{
if (n_sent == 0)
{
char number[11];
checksum = 0;
sendCharAndChecksum('N');
snprintf(number, 11, "%lu", line_number++);
rrfSendCmd(number);
sendCharAndChecksum(' ');
}
sendCharAndChecksum(c);
}
}
sprintf(rrfCmd, "N%lu %s", line_number++, cmd_ptr);

void rrfSendCmd(const char* cmd_ptr)
{
while (*cmd_ptr != 0)
// calculate checksum
while (*rrfCmd_ptr != '\n')
{
sendChar(*cmd_ptr++);
checksum ^= *rrfCmd_ptr++;
}

// add checksum and finalize formatting the RRF command
sprintf(rrfCmd_ptr, "*%u\n", checksum);

// send the command to the serial port
Serial_Put(SERIAL_PORT, rrfCmd);
}
126 changes: 84 additions & 42 deletions TFT/src/User/API/SerialConnection.c
Original file line number Diff line number Diff line change
@@ -1,32 +1,39 @@
#include "SerialConnection.h"
#include "includes.h"

#define SERIAL_PORT_QUEUE_SIZE NOBEYOND(512, RAM_SIZE * 64, 4096)
#define SERIAL_PORT_2_QUEUE_SIZE 512
#define SERIAL_PORT_3_QUEUE_SIZE 512
#define SERIAL_PORT_4_QUEUE_SIZE 512
#define SERIAL_PORT_RX_QUEUE_SIZE NOBEYOND(256, RAM_SIZE * 64, 4096) // ACK messages reading queue from mainboard
#define SERIAL_PORT_2_RX_QUEUE_SIZE 512
#define SERIAL_PORT_3_RX_QUEUE_SIZE 512
#define SERIAL_PORT_4_RX_QUEUE_SIZE 512

#define SERIAL_PORT_TX_QUEUE_SIZE 256 // gcodes writing queue to mainboard
#define SERIAL_PORT_2_TX_QUEUE_SIZE 256
#define SERIAL_PORT_3_TX_QUEUE_SIZE 256
#define SERIAL_PORT_4_TX_QUEUE_SIZE 256

const SERIAL_PORT_INFO serialPort[SERIAL_PORT_COUNT] = {
{SERIAL_PORT, SERIAL_PORT_QUEUE_SIZE, "", "1 - Printer"},
{SERIAL_PORT , SERIAL_PORT_RX_QUEUE_SIZE , SERIAL_PORT_TX_QUEUE_SIZE , "" , "1 - Printer"},
#ifdef SERIAL_PORT_2
{SERIAL_PORT_2, SERIAL_PORT_2_QUEUE_SIZE, "2", "2 - WIFI"},
{SERIAL_PORT_2, SERIAL_PORT_2_RX_QUEUE_SIZE, SERIAL_PORT_2_TX_QUEUE_SIZE, "2", "2 - WiFi"},
#endif
#ifdef SERIAL_PORT_3
{SERIAL_PORT_3, SERIAL_PORT_3_QUEUE_SIZE, "3", "3 - UART3"},
{SERIAL_PORT_3, SERIAL_PORT_3_RX_QUEUE_SIZE, SERIAL_PORT_3_TX_QUEUE_SIZE, "3", "3 - UART3"},
#endif
#ifdef SERIAL_PORT_4
{SERIAL_PORT_4, SERIAL_PORT_4_QUEUE_SIZE, "4", "4 - UART4"}
{SERIAL_PORT_4, SERIAL_PORT_4_RX_QUEUE_SIZE, SERIAL_PORT_4_TX_QUEUE_SIZE, "4", "4 - UART4"}
#endif
};

const uint32_t baudrateValues[BAUDRATE_COUNT] = { 0, 2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000};
const char * const baudrateNames[BAUDRATE_COUNT] = {"OFF", "2400", "9600", "19200", "38400", "57600", "115200", "250000", "500000", "1000000"};
const uint32_t baudrateValues[BAUDRATE_COUNT] = {
0, 2400, 9600, 19200, 38400, 57600, 115200, 230400, 250000, 500000, 921600, 1000000};
const char * const baudrateNames[BAUDRATE_COUNT] = {
"OFF", "2400", "9600", "19200", "38400", "57600", "115200", "230400", "250000", "500000", "921600", "1000000"};

static inline void Serial_InitPrimary(void)
{
InfoHost_Init(false); // initialize infoHost when disconnected

Serial_Config(serialPort[PORT_1].port, serialPort[PORT_1].cacheSize, baudrateValues[infoSettings.serial_port[PORT_1]]);
Serial_Config(serialPort[PORT_1].port, serialPort[PORT_1].cacheSizeRX, serialPort[PORT_1].cacheSizeTX, baudrateValues[infoSettings.serial_port[PORT_1]]);
}

static inline void Serial_DeInitPrimary(void)
Expand All @@ -53,7 +60,7 @@ void Serial_Init(SERIAL_PORT_INDEX portIndex)
// Disable the serial port when it is not in use and/or not connected to a device (floating) to
// avoid to receive and process wrong data due to possible electromagnetic interference (EMI).
if (infoSettings.serial_port[portIndex] > 0) // if serial port is enabled
Serial_Config(serialPort[portIndex].port, serialPort[portIndex].cacheSize,
Serial_Config(serialPort[portIndex].port, serialPort[portIndex].cacheSizeRX, serialPort[portIndex].cacheSizeTX,
baudrateValues[infoSettings.serial_port[portIndex]]);
}
}
Expand All @@ -64,7 +71,7 @@ void Serial_Init(SERIAL_PORT_INDEX portIndex)
{
if (infoSettings.serial_port[portIndex] > 0) // if serial port is enabled
{
Serial_Config(serialPort[portIndex].port, serialPort[portIndex].cacheSize,
Serial_Config(serialPort[portIndex].port, serialPort[portIndex].cacheSizeRX, serialPort[portIndex].cacheSizeTX,
baudrateValues[infoSettings.serial_port[portIndex]]);
}
}
Expand Down Expand Up @@ -133,54 +140,89 @@ void Serial_Forward(SERIAL_PORT_INDEX portIndex, const char * msg)
}
}

uint16_t Serial_GetReadingIndex(SERIAL_PORT_INDEX portIndex)
bool Serial_NewDataAvailable(uint8_t port)
{
if (!WITHIN(portIndex, PORT_1, SERIAL_PORT_COUNT - 1))
// NOTE: used 32 bit variables for performance reasons

// wIndex: update L1 cache's writing index (dynamically changed (by L1 cache's interrupt handler) variables/attributes)
// and make a static access (32 bit) to it to speedup performance on this function
//
uint32_t wIndex = dmaL1DataRX[port].wIndex = Serial_GetWritingIndexRX(port); // get the latest wIndex
uint32_t flag = dmaL1DataRX[port].flag; // get the current flag position

if (flag == wIndex) // if no data to read from L1 cache, nothing to do
return 0;

return dmaL1Data[portIndex].rIndex;
uint32_t cacheSize = dmaL1DataRX[port].cacheSize;

while (dmaL1DataRX[port].cache[flag] != '\n' && flag != wIndex) // check presence of "\n" in available data
{
flag = (flag + 1) % cacheSize;
}

dmaL1DataRX[port].flag = flag; // update queue's custom flag with flag

// return "true" if "\n" was found (message complete), "False" otherwise
return (flag != wIndex);
}

uint16_t Serial_Get(SERIAL_PORT_INDEX portIndex, char * buf, uint16_t bufSize)
uint16_t Serial_Get(uint8_t port, 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) || dmaL1Data[portIndex].flag == dmaL1Data[portIndex].wIndex)
return 0;
// NOTE: used 32 bit variables for performance reasons (in particular for data copy)

// rIndex: L1 cache's reading index (not dynamically changed (by L1 cache's interrupt handler) variables/attributes)
//
DMA_CIRCULAR_BUFFER * dmaL1Data_ptr = &dmaL1DataRX[port];
char * cache = dmaL1Data_ptr->cache;
uint32_t cacheSize = dmaL1Data_ptr->cacheSize;
uint32_t rIndex = dmaL1Data_ptr->rIndex;
uint32_t flag = dmaL1Data_ptr->flag;

DMA_CIRCULAR_BUFFER * dmaL1Data_ptr = &dmaL1Data[portIndex];
while (cache[rIndex] == ' ' && rIndex != flag) // remove leading empty space, if any
{
rIndex = (rIndex + 1) % cacheSize;
}

// make a static access to dynamically changed (by L1 cache's interrupt handler) variables/attributes
uint16_t wIndex = dmaL1Data_ptr->wIndex;
// msgSize: message size (after updating rIndex removing leading empty spaces). Terminating null character '\0' not included
uint32_t msgSize = (cacheSize + flag - rIndex) % cacheSize + 1;

// L1 cache's reading index (not dynamically changed (by L1 cache's interrupt handler) variables/attributes)
uint16_t rIndex = dmaL1Data_ptr->rIndex;
// if buf size is not enough to store the data plus the terminating null character "\0", skip the data copy
//
// NOTE: the following check should never be matched if buf has a proper size and there is no reading error.
// If so, the check could be commented out just to improve performance. Just keep it to make the code more robust
//
if (bufSize < (msgSize + 1)) // +1 is for the terminating null character '\0'
return 0;

while (dmaL1Data_ptr->cache[rIndex] == ' ' && rIndex != wIndex) // remove leading empty space, if any
// if data is one chunk only, retrieve data from upper part of circular cache
if (rIndex <= flag)
{
rIndex = (rIndex + 1) % dmaL1Data_ptr->cacheSize;
while (rIndex <= flag)
{
*(buf++) = cache[rIndex++];
}
}

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

if (buf[i++] == '\n') // if data end marker is found
while (rIndex < cacheSize)
{
buf[i] = '\0'; // end character
dmaL1Data_ptr->flag = dmaL1Data_ptr->rIndex = rIndex; // update queue's custom flag and reading index with rIndex
*(buf++) = cache[rIndex++];
}

return i; // return the number of bytes stored in buf
rIndex = 0;

while (rIndex <= flag)
{
*(buf++) = cache[rIndex++];
}
}

// 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 updating also dmaL1Data_ptr->flag to
// prevent to read again (multiple times) the same partial message on next function invokation
*buf = '\0'; // end character

dmaL1Data_ptr->flag = wIndex; // update queue's custom flag with wIndex
// update queue's custom flag and reading index with next index
dmaL1Data_ptr->flag = dmaL1Data_ptr->rIndex = (flag + 1) % cacheSize;

return 0; // return the number of bytes stored in buf
return msgSize; // return the number of bytes stored in buf
}

#ifdef SERIAL_PORT_2
Expand All @@ -199,7 +241,7 @@ void Serial_GetFromUART(void)
#endif
)
{
while (Serial_Get(serialPort[portIndex].port, cmd, CMD_MAX_SIZE) != 0) // if some data have been retrieved
while (Serial_NewDataAvailable(serialPort[portIndex].port) && Serial_Get(serialPort[portIndex].port, cmd, CMD_MAX_SIZE) != 0)
{
handleCmd(cmd, portIndex);
}
Expand Down
24 changes: 13 additions & 11 deletions TFT/src/User/API/SerialConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ extern "C" {
#include "variants.h" // for SERIAL_PORT_2 etc.
#include "uart.h" // for _UART_CNT etc.

#define BAUDRATE_COUNT 10
#define BAUDRATE_COUNT 12

typedef enum
{
Expand All @@ -27,12 +27,13 @@ typedef enum
PORT_4,
#endif
SERIAL_PORT_COUNT
} SERIAL_PORT_INDEX; // serial port index for all enabled serial ports (This is not actual physical port number)
} SERIAL_PORT_INDEX; // serial port index for all enabled serial ports (this is not the actual physical serial port number)

typedef struct
{
uint8_t port; // physical port (e.g. _USART1) related to serial port (e.g. 0 for SERIAL_PORT, 1 for SERIAL_PORT_2 etc...)
uint16_t cacheSize; // queue size for sending/receiving data to/from the port
uint16_t cacheSizeRX; // buffer size for receiving data from the serial port
uint16_t cacheSizeTX; // buffer size for sending data to the serial port
const char * const id; // serial port ID (e.g. "" for SERIAL_PORT, "2" for SERIAL_PORT_2 etc...)
const char * const desc; // serial port description (e.g. "1 - Printer" for SERIAL_PORT, "2 - WIFI" for SERIAL_PORT_2 etc...)
} SERIAL_PORT_INFO; // serial port info
Expand All @@ -55,26 +56,27 @@ void Serial_Init(SERIAL_PORT_INDEX portIndex);
// - specific port index: specific serial port
void Serial_DeInit(SERIAL_PORT_INDEX portIndex);

// forward a message to the provided serial port/s, if enabled:
// forward a zero terminated message to the provided serial port/s, if enabled:
// - portIndex:
// - ALL_PORTS: all serial ports (primary and supplementary)
// - SUP_PORTS: all supplementary serial ports
// - specific port index: specific serial port
// - msg: message to send
void Serial_Forward(SERIAL_PORT_INDEX portIndex, const char * msg);

// retrieve the next reading index in the message queue of the provided serial port:
// - portIndex: index of serial port
// test if a new message is available in the message queue of the provided physical serial port:
// - port: physical serial port where data availability is tested
//
// - return value: next reading index
uint16_t Serial_GetReadingIndex(SERIAL_PORT_INDEX portIndex);
// - return value: "true" if a new message is available. "false" otherwise
bool Serial_NewDataAvailable(uint8_t port);

// retrieve a message from the provided serial port, if any:
// - portIndex: index of serial port where data are read from
// retrieve a message from the provided physical serial port:
// - port: physical serial port where data are read from
// - buf: buffer where data are stored
// - bufSize: size of buffer (max number of bytes that can be stored in buf)
//
// - return value: number of bytes stored in buf
uint16_t Serial_Get(SERIAL_PORT_INDEX portIndex, char * buf, uint16_t bufSize);
uint16_t Serial_Get(uint8_t port, char * buf, uint16_t bufSize);

#ifdef SERIAL_PORT_2
// retrieve messages from all the enabled supplementary ports storing them
Expand Down
4 changes: 2 additions & 2 deletions TFT/src/User/API/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ extern "C" {
// Config version support (format YYYYMMDD)
// change if new elements/keywords are added/removed/changed in the Configuration.h
// this number should match CONFIG_VERSION in Configuration.h
#define CONFIG_SUPPPORT 20230821
#define CONFIG_SUPPPORT 20230929

#define FONT_FLASH_SIGN 20230821 // (YYYYMMDD) change if fonts require updating
#define CONFIG_FLASH_SIGN 20230821 // (YYYYMMDD) change if any keyword(s) in config.ini is added or removed
#define CONFIG_FLASH_SIGN 20230929 // (YYYYMMDD) change if any keyword(s) in config.ini is added or removed
#define LANGUAGE_FLASH_SIGN 20230821 // (YYYYMMDD) change if any keyword(s) in language pack is added or removed
#define ICON_FLASH_SIGN 20230821 // (YYYYMMDD) change if any icon(s) is added or removed

Expand Down
2 changes: 2 additions & 0 deletions TFT/src/User/API/interfaceCmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ bool sendCmd(bool purge, bool avoidTerminal)

if (!purge) // if command is not purged, send it to printer
{
UPD_TX_KPIS(cmd_len); // debug monitoring KPI

if (infoMachineSettings.firmwareType != FW_REPRAPFW)
Serial_Put(SERIAL_PORT, cmd_ptr);
else
Expand Down
Loading
Loading