#include "nim_config.h" #include "uart.h" /* * uart_util.c * * Created on: 2025年7月30日 * Author: wulianwei */ //static char txArray[] = "Nim DSP Application\r\n"; /* A mapping from an integer between 0 and 15 to its ASCII character * equivalent. */ static const char *const g_pcHex = "0123456789abcdef"; static uart_recv_t console_recv = { 0 }; //串口接收缓存 static void uart_recv_clear(uart_recv_t* uart_recv); static void uart_recv_wait(uart_recv_t* uart_recv,int timeout); /****************************************************************************/ /* */ /* 串口控制台初始化 */ /* */ /****************************************************************************/ void ConsoleDeviceInit(void) { if(UART_CONSOLE_BASE == SOC_UART_1_REGS) { UART1Init(); } else if(UART_CONSOLE_BASE == SOC_UART_2_REGS) { UART2Init(); } } /****************************************************************************/ /* */ /* 输出一个字符 */ /* */ /****************************************************************************/ void UARTConsolePutc(unsigned char data) { UARTCharPut(UART_CONSOLE_BASE, data); } /****************************************************************************/ /* */ /* 取得一个字符 */ /* */ /****************************************************************************/ unsigned char UARTConsoleGetc(void) { return ((unsigned char) UARTCharGet(UART_CONSOLE_BASE)); } void ConsolePutsHexStr(unsigned char *source, unsigned int numBytesToWrite) { unsigned char highByte, lowByte; short i = 0; for (i = 0; i < numBytesToWrite; i++) { highByte = ((source[i] >> 4)&0x0f) + 0x30; lowByte = (source[i] & 0x0f) + 0x30; highByte = highByte>0x39? highByte+0x07 : highByte; lowByte = lowByte>0x39? lowByte+0x07 : lowByte; UARTConsolePutc(highByte); UARTConsolePutc(lowByte); } } /** * \brief This function writes data from a specified buffer onto the * transmitter FIFO of UART. * * \param pTxBuffer Pointer to a buffer in the transmitter. * \param numBytesToWrite Number of bytes to be transmitted to the * transmitter FIFO. The user has the freedom to not * specify any valid value for this if he wants to * print until the occurence of a NULL character. * In this case, he has to pass a negative value as * this parameter. * * \return Number of bytes written to the transmitter FIFO. * * \note 1> Whenever a null character(\0) is encountered in the * data to be transmitted, the transmission is stopped. \n * 2> Whenever the transmitter data has a new line character(\n), * it is interpreted as a new line(\n) + carraige return(\r) * characters. This is because the serial console interprets a * new line character as it is and does not introduce a carraige * return. \n * * Some example function calls of this function are: \n * * UARTPuts(txArray, -2): This shall print the contents of txArray[] * until the occurence of a NULL character. \n * * UARTPuts("Hello World", 8): This shall print the first 8 characters * of the string shown. \n * * UARTPuts("Hello World", 20): This shall print the string shown until * the occurence of the NULL character. Here, the NULL character is * encountered earlier than the length of 20 bytes.\n * */ unsigned int ConsolePuts(char *pTxBuffer, int numBytesToWrite) { unsigned int count = 0; unsigned int flag = 0; if (numBytesToWrite < 0) { flag = 1; } while ('\0' != *pTxBuffer) { /* Checks if data is a newline character. */ if ('\n' == *pTxBuffer) { /* Ensuring applicability to serial console.*/ UARTConsolePutc('\r'); UARTConsolePutc('\n'); } else { UARTConsolePutc((unsigned char) *pTxBuffer); } pTxBuffer++; count++; if ((0 == flag) && (count == numBytesToWrite)) { break; } } /* Returns the number of bytes written onto the transmitter FIFO. */ return count; } void ConsolePrintf(char *fmt, ...) { //return ; unsigned char UsartPrintfBuf[512]; va_list ap; unsigned char *pStr = UsartPrintfBuf; va_start(ap, fmt); vsnprintf((char*) UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap); va_end(ap); while (*pStr != 0) { UARTConsolePutc(*pStr++); } } unsigned int UARTwrite(const char *pcBuf, unsigned int len) { unsigned int uIdx; /* Send the characters */ for(uIdx = 0; uIdx < len; uIdx++) { /* If the character to the UART is \n, then add a \r before it so that * \n is translated to \n\r in the output. */ if(pcBuf[uIdx] == '\n') { UARTConsolePutc('\r'); } /* Send the character to the UART output. */ UARTConsolePutc(pcBuf[uIdx]); } /* Return the number of characters written. */ return(uIdx); } /** * A simple UART based printf function supporting \%c, \%d, \%p, \%s, \%u, * \%x, and \%X. * * \param pcString is the format string. * \param ... are the optional arguments, which depend on the contents of the * format string. * * This function is very similar to the C library fprintf() function. * All of its output will be sent to the UART. Only the following formatting * characters are supported: * * - \%c to print a character * - \%d to print a decimal value * - \%s to print a string * - \%u to print an unsigned decimal value * - \%x to print a hexadecimal value using lower case letters * - \%X to print a hexadecimal value using lower case letters (not upper case * letters as would typically be used) * - \%p to print a pointer as a hexadecimal value * - \%\% to print out a \% character * * For \%s, \%d, \%u, \%p, \%x, and \%X, an optional number may reside * between the \% and the format character, which specifies the minimum number * of characters to use for that value; if preceded by a 0 then the extra * characters will be filled with zeros instead of spaces. For example, * ``\%8d'' will use eight characters to print the decimal value with spaces * added to reach eight; ``\%08d'' will use eight characters as well but will * add zeroes instead of spaces. * * The type of the arguments after \e pcString must match the requirements of * the format string. For example, if an integer was passed where a string * was expected, an error of some kind will most likely occur. * * \return None. */ void LogPrintf(const char *pcString, ...) { unsigned int idx, pos, count, base, neg; char *pcStr, pcBuf[16], cFill; va_list vaArgP; int value; /* Start the varargs processing. */ va_start(vaArgP, pcString); /* Loop while there are more characters in the string. */ while (*pcString) { /* Find the first non-% character, or the end of the string. */ for (idx = 0; (pcString[idx] != '%') && (pcString[idx] != '\0'); idx++) { } /* Write this portion of the string. */ UARTwrite(pcString, idx); /* Skip the portion of the string that was written. */ pcString += idx; /* See if the next character is a %. */ if (*pcString == '%') { /* Skip the %. */ pcString++; /* Set the digit count to zero, and the fill character to space * (i.e. to the defaults). */ count = 0; cFill = ' '; /* It may be necessary to get back here to process more characters. * Goto's aren't pretty, but effective. I feel extremely dirty for * using not one but two of the beasts. */ again: /* Determine how to handle the next character. */ switch (*pcString++) { /* Handle the digit characters. */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { /* If this is a zero, and it is the first digit, then the * fill character is a zero instead of a space. */ if ((pcString[-1] == '0') && (count == 0)) { cFill = '0'; } /* Update the digit count. */ count *= 10; count += pcString[-1] - '0'; /* Get the next character. */ goto again; } /* Handle the %c command. */ case 'c': { /* Get the value from the varargs. */ value = va_arg(vaArgP, unsigned int); /* Print out the character. */ UARTwrite((char*) &value, 1); /* This command has been handled. */ break; } /* Handle the %d command. */ case 'd': { /* Get the value from the varargs. */ value = va_arg(vaArgP, unsigned int); /* Reset the buffer position. */ pos = 0; /* If the value is negative, make it positive and indicate * that a minus sign is needed. */ if ((int) value < 0) { /* Make the value positive. */ value = -(int) value; /* Indicate that the value is negative. */ neg = 1; } else { /* Indicate that the value is positive so that a minus * sign isn't inserted. */ neg = 0; } /* Set the base to 10. */ base = 10; /* Convert the value to ASCII. */ goto convert; } /* Handle the %s command. */ case 's': { /* Get the string pointer from the varargs. */ pcStr = va_arg(vaArgP, char *); /* Determine the length of the string. */ for (idx = 0; pcStr[idx] != '\0'; idx++) { } /* Write the string. */ UARTwrite(pcStr, idx); /* Write any required padding spaces */ if (count > idx) { count -= idx; while (count--) { UARTwrite((const char*) " ", 1); } } /* This command has been handled. */ break; } /* Handle the %u command. */ case 'u': { /* Get the value from the varargs. */ value = va_arg(vaArgP, unsigned int); /* Reset the buffer position. */ pos = 0; /* Set the base to 10. */ base = 10; /* Indicate that the value is positive so that a minus sign * isn't inserted. */ neg = 0; /* Convert the value to ASCII. */ goto convert; } /* Handle the %x and %X commands. Note that they are treated * identically; i.e. %X will use lower case letters for a-f * instead of the upper case letters is should use. We also * alias %p to %x. */ case 'x': case 'X': case 'p': { /* Get the value from the varargs. */ value = va_arg(vaArgP, unsigned int); /* Reset the buffer position. */ pos = 0; /* Set the base to 16. */ base = 16; /* Indicate that the value is positive so that a minus sign * isn't inserted. */ neg = 0; /* Determine the number of digits in the string version of * the value. */ convert: for (idx = 1; (((idx * base) <= value) && (((idx * base) / base) == idx)); idx *= base, count--) { } /* If the value is negative, reduce the count of padding * characters needed. */ if (neg) { count--; } /* If the value is negative and the value is padded with * zeros, then place the minus sign before the padding. */ if (neg && (cFill == '0')) { /* Place the minus sign in the output buffer. */ pcBuf[pos++] = '-'; /* The minus sign has been placed, so turn off the * negative flag. */ neg = 0; } /* Provide additional padding at the beginning of the * string conversion if needed. */ if ((count > 1) && (count < 16)) { for (count--; count; count--) { pcBuf[pos++] = cFill; } } /* If the value is negative, then place the minus sign * before the number. */ if (neg) { /* Place the minus sign in the output buffer. */ pcBuf[pos++] = '-'; } /* Convert the value into a string. */ for (; idx; idx /= base) { pcBuf[pos++] = g_pcHex[(value / idx) % base]; } /* Write the string. */ UARTwrite(pcBuf, pos); /* This command has been handled. */ break; } /* Handle the %% command. */ case '%': { /* Simply write a single %. */ UARTwrite(pcString - 1, 1); /* This command has been handled. */ break; } /* Handle all other commands. */ default: { /* Indicate an error. */ UARTwrite((const char*) "ERROR", 5); /* This command has been handled. */ break; } } } } /* End the varargs processing. */ va_end(vaArgP); } /** *接收控制台数据 */ void ConsoleRecvFill(unsigned char data) { if (console_recv.len >= sizeof(console_recv.buf) - 1) console_recv.len = 0; console_recv.buf[console_recv.len++] = data; } /** * 清空接收的控制台数据 */ void ConsoleRecvClear() { uart_recv_clear(&console_recv); } /** * @Title 等待接收控制台数据 * @Param timeout, 最长等待时间,单位毫秒 */ void ConsoleRecvWait(int timeout) { uart_recv_wait(&console_recv,timeout); } /** * 串口接收状态 */ unsigned char* ConsoleRecvData() { return console_recv.buf; } /** * 串口接收长度 */ int ConsoleRecvLen() { return console_recv.len; } /** * 串口接收状态 */ recv_status_e ConsoleRecvFlag() { return console_recv.recv_flag; } /** *@Title 清空串口接收缓存 */ static void uart_recv_clear(uart_recv_t* uart_recv) { memset(uart_recv->buf,0,sizeof(uart_recv->buf)); uart_recv->len = 0; uart_recv->recv_flag = REV_WAIT; } /** *@Title 等待串口接收数据 *@Param 最长等待时间 */ static void uart_recv_wait(uart_recv_t* uart_recv,int timeout) { int per = 5; // int prelen = 0; if(timeout<=0) return; timeout=timeout/per+(timeout%per==0? 0 : 1); while(timeout--) { if(uart_recv->len) { if(uart_recv->len == prelen) { uart_recv->recv_flag = REV_OK; // break; } else { prelen = uart_recv->len; } } delay_ms(per); } }