console.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. #include "nim_config.h"
  2. #include "uart.h"
  3. /*
  4. * uart_util.c
  5. *
  6. * Created on: 2025年7月30日
  7. * Author: wulianwei
  8. */
  9. //static char txArray[] = "Nim DSP Application\r\n";
  10. /* A mapping from an integer between 0 and 15 to its ASCII character
  11. * equivalent. */
  12. static const char *const g_pcHex = "0123456789abcdef";
  13. static uart_recv_t console_recv = { 0 }; //串口接收缓存
  14. static void uart_recv_clear(uart_recv_t* uart_recv);
  15. static void uart_recv_wait(uart_recv_t* uart_recv,int timeout);
  16. /****************************************************************************/
  17. /* */
  18. /* 串口控制台初始化 */
  19. /* */
  20. /****************************************************************************/
  21. void ConsoleDeviceInit(void)
  22. {
  23. if(UART_CONSOLE_BASE == SOC_UART_1_REGS)
  24. {
  25. UART1Init();
  26. }
  27. else if(UART_CONSOLE_BASE == SOC_UART_2_REGS)
  28. {
  29. UART2Init();
  30. }
  31. }
  32. /****************************************************************************/
  33. /* */
  34. /* 输出一个字符 */
  35. /* */
  36. /****************************************************************************/
  37. void UARTConsolePutc(unsigned char data)
  38. {
  39. UARTCharPut(UART_CONSOLE_BASE, data);
  40. }
  41. /****************************************************************************/
  42. /* */
  43. /* 取得一个字符 */
  44. /* */
  45. /****************************************************************************/
  46. unsigned char UARTConsoleGetc(void)
  47. {
  48. return ((unsigned char) UARTCharGet(UART_CONSOLE_BASE));
  49. }
  50. /**
  51. * \brief This function writes data from a specified buffer onto the
  52. * transmitter FIFO of UART.
  53. *
  54. * \param pTxBuffer Pointer to a buffer in the transmitter.
  55. * \param numBytesToWrite Number of bytes to be transmitted to the
  56. * transmitter FIFO. The user has the freedom to not
  57. * specify any valid value for this if he wants to
  58. * print until the occurence of a NULL character.
  59. * In this case, he has to pass a negative value as
  60. * this parameter.
  61. *
  62. * \return Number of bytes written to the transmitter FIFO.
  63. *
  64. * \note 1> Whenever a null character(\0) is encountered in the
  65. * data to be transmitted, the transmission is stopped. \n
  66. * 2> Whenever the transmitter data has a new line character(\n),
  67. * it is interpreted as a new line(\n) + carraige return(\r)
  68. * characters. This is because the serial console interprets a
  69. * new line character as it is and does not introduce a carraige
  70. * return. \n
  71. *
  72. * Some example function calls of this function are: \n
  73. *
  74. * UARTPuts(txArray, -2): This shall print the contents of txArray[]
  75. * until the occurence of a NULL character. \n
  76. *
  77. * UARTPuts("Hello World", 8): This shall print the first 8 characters
  78. * of the string shown. \n
  79. *
  80. * UARTPuts("Hello World", 20): This shall print the string shown until
  81. * the occurence of the NULL character. Here, the NULL character is
  82. * encountered earlier than the length of 20 bytes.\n
  83. *
  84. */
  85. unsigned int ConsolePuts(char *pTxBuffer, int numBytesToWrite)
  86. {
  87. unsigned int count = 0;
  88. unsigned int flag = 0;
  89. if (numBytesToWrite < 0)
  90. {
  91. flag = 1;
  92. }
  93. while ('\0' != *pTxBuffer)
  94. {
  95. /* Checks if data is a newline character. */
  96. if ('\n' == *pTxBuffer)
  97. {
  98. /* Ensuring applicability to serial console.*/
  99. UARTConsolePutc('\r');
  100. UARTConsolePutc('\n');
  101. }
  102. else
  103. {
  104. UARTConsolePutc((unsigned char) *pTxBuffer);
  105. }
  106. pTxBuffer++;
  107. count++;
  108. if ((0 == flag) && (count == numBytesToWrite))
  109. {
  110. break;
  111. }
  112. }
  113. /* Returns the number of bytes written onto the transmitter FIFO. */
  114. return count;
  115. }
  116. void ConsolePrintf(char *fmt, ...)
  117. {
  118. //return ;
  119. unsigned char UsartPrintfBuf[512];
  120. va_list ap;
  121. unsigned char *pStr = UsartPrintfBuf;
  122. va_start(ap, fmt);
  123. vsnprintf((char*) UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);
  124. va_end(ap);
  125. while (*pStr != 0)
  126. {
  127. UARTConsolePutc(*pStr++);
  128. }
  129. }
  130. static unsigned int UARTwrite(const char *pcBuf, unsigned int len)
  131. {
  132. unsigned int uIdx;
  133. /* Send the characters */
  134. for(uIdx = 0; uIdx < len; uIdx++)
  135. {
  136. /* If the character to the UART is \n, then add a \r before it so that
  137. * \n is translated to \n\r in the output. */
  138. if(pcBuf[uIdx] == '\n')
  139. {
  140. UARTConsolePutc('\r');
  141. }
  142. /* Send the character to the UART output. */
  143. UARTConsolePutc(pcBuf[uIdx]);
  144. }
  145. /* Return the number of characters written. */
  146. return(uIdx);
  147. }
  148. /**
  149. * A simple UART based printf function supporting \%c, \%d, \%p, \%s, \%u,
  150. * \%x, and \%X.
  151. *
  152. * \param pcString is the format string.
  153. * \param ... are the optional arguments, which depend on the contents of the
  154. * format string.
  155. *
  156. * This function is very similar to the C library <tt>fprintf()</tt> function.
  157. * All of its output will be sent to the UART. Only the following formatting
  158. * characters are supported:
  159. *
  160. * - \%c to print a character
  161. * - \%d to print a decimal value
  162. * - \%s to print a string
  163. * - \%u to print an unsigned decimal value
  164. * - \%x to print a hexadecimal value using lower case letters
  165. * - \%X to print a hexadecimal value using lower case letters (not upper case
  166. * letters as would typically be used)
  167. * - \%p to print a pointer as a hexadecimal value
  168. * - \%\% to print out a \% character
  169. *
  170. * For \%s, \%d, \%u, \%p, \%x, and \%X, an optional number may reside
  171. * between the \% and the format character, which specifies the minimum number
  172. * of characters to use for that value; if preceded by a 0 then the extra
  173. * characters will be filled with zeros instead of spaces. For example,
  174. * ``\%8d'' will use eight characters to print the decimal value with spaces
  175. * added to reach eight; ``\%08d'' will use eight characters as well but will
  176. * add zeroes instead of spaces.
  177. *
  178. * The type of the arguments after \e pcString must match the requirements of
  179. * the format string. For example, if an integer was passed where a string
  180. * was expected, an error of some kind will most likely occur.
  181. *
  182. * \return None.
  183. */
  184. void LogPrintf(const char *pcString, ...)
  185. {
  186. unsigned int idx, pos, count, base, neg;
  187. char *pcStr, pcBuf[16], cFill;
  188. va_list vaArgP;
  189. int value;
  190. /* Start the varargs processing. */
  191. va_start(vaArgP, pcString);
  192. /* Loop while there are more characters in the string. */
  193. while (*pcString)
  194. {
  195. /* Find the first non-% character, or the end of the string. */
  196. for (idx = 0; (pcString[idx] != '%') && (pcString[idx] != '\0'); idx++)
  197. {
  198. }
  199. /* Write this portion of the string. */
  200. UARTwrite(pcString, idx);
  201. /* Skip the portion of the string that was written. */
  202. pcString += idx;
  203. /* See if the next character is a %. */
  204. if (*pcString == '%')
  205. {
  206. /* Skip the %. */
  207. pcString++;
  208. /* Set the digit count to zero, and the fill character to space
  209. * (i.e. to the defaults). */
  210. count = 0;
  211. cFill = ' ';
  212. /* It may be necessary to get back here to process more characters.
  213. * Goto's aren't pretty, but effective. I feel extremely dirty for
  214. * using not one but two of the beasts. */
  215. again:
  216. /* Determine how to handle the next character. */
  217. switch (*pcString++)
  218. {
  219. /* Handle the digit characters. */
  220. case '0':
  221. case '1':
  222. case '2':
  223. case '3':
  224. case '4':
  225. case '5':
  226. case '6':
  227. case '7':
  228. case '8':
  229. case '9':
  230. {
  231. /* If this is a zero, and it is the first digit, then the
  232. * fill character is a zero instead of a space. */
  233. if ((pcString[-1] == '0') && (count == 0))
  234. {
  235. cFill = '0';
  236. }
  237. /* Update the digit count. */
  238. count *= 10;
  239. count += pcString[-1] - '0';
  240. /* Get the next character. */
  241. goto again;
  242. }
  243. /* Handle the %c command. */
  244. case 'c':
  245. {
  246. /* Get the value from the varargs. */
  247. value = va_arg(vaArgP, unsigned int);
  248. /* Print out the character. */
  249. UARTwrite((char*) &value, 1);
  250. /* This command has been handled. */
  251. break;
  252. }
  253. /* Handle the %d command. */
  254. case 'd':
  255. {
  256. /* Get the value from the varargs. */
  257. value = va_arg(vaArgP, unsigned int);
  258. /* Reset the buffer position. */
  259. pos = 0;
  260. /* If the value is negative, make it positive and indicate
  261. * that a minus sign is needed. */
  262. if ((int) value < 0)
  263. {
  264. /* Make the value positive. */
  265. value = -(int) value;
  266. /* Indicate that the value is negative. */
  267. neg = 1;
  268. }
  269. else
  270. {
  271. /* Indicate that the value is positive so that a minus
  272. * sign isn't inserted. */
  273. neg = 0;
  274. }
  275. /* Set the base to 10. */
  276. base = 10;
  277. /* Convert the value to ASCII. */
  278. goto convert;
  279. }
  280. /* Handle the %s command. */
  281. case 's':
  282. {
  283. /* Get the string pointer from the varargs. */
  284. pcStr = va_arg(vaArgP, char *);
  285. /* Determine the length of the string. */
  286. for (idx = 0; pcStr[idx] != '\0'; idx++)
  287. {
  288. }
  289. /* Write the string. */
  290. UARTwrite(pcStr, idx);
  291. /* Write any required padding spaces */
  292. if (count > idx)
  293. {
  294. count -= idx;
  295. while (count--)
  296. {
  297. UARTwrite((const char*) " ", 1);
  298. }
  299. }
  300. /* This command has been handled. */
  301. break;
  302. }
  303. /* Handle the %u command. */
  304. case 'u':
  305. {
  306. /* Get the value from the varargs. */
  307. value = va_arg(vaArgP, unsigned int);
  308. /* Reset the buffer position. */
  309. pos = 0;
  310. /* Set the base to 10. */
  311. base = 10;
  312. /* Indicate that the value is positive so that a minus sign
  313. * isn't inserted. */
  314. neg = 0;
  315. /* Convert the value to ASCII. */
  316. goto convert;
  317. }
  318. /* Handle the %x and %X commands. Note that they are treated
  319. * identically; i.e. %X will use lower case letters for a-f
  320. * instead of the upper case letters is should use. We also
  321. * alias %p to %x. */
  322. case 'x':
  323. case 'X':
  324. case 'p':
  325. {
  326. /* Get the value from the varargs. */
  327. value = va_arg(vaArgP, unsigned int);
  328. /* Reset the buffer position. */
  329. pos = 0;
  330. /* Set the base to 16. */
  331. base = 16;
  332. /* Indicate that the value is positive so that a minus sign
  333. * isn't inserted. */
  334. neg = 0;
  335. /* Determine the number of digits in the string version of
  336. * the value. */
  337. convert: for (idx = 1;
  338. (((idx * base) <= value)
  339. && (((idx * base) / base) == idx));
  340. idx *= base, count--)
  341. {
  342. }
  343. /* If the value is negative, reduce the count of padding
  344. * characters needed. */
  345. if (neg)
  346. {
  347. count--;
  348. }
  349. /* If the value is negative and the value is padded with
  350. * zeros, then place the minus sign before the padding. */
  351. if (neg && (cFill == '0'))
  352. {
  353. /* Place the minus sign in the output buffer. */
  354. pcBuf[pos++] = '-';
  355. /* The minus sign has been placed, so turn off the
  356. * negative flag. */
  357. neg = 0;
  358. }
  359. /* Provide additional padding at the beginning of the
  360. * string conversion if needed. */
  361. if ((count > 1) && (count < 16))
  362. {
  363. for (count--; count; count--)
  364. {
  365. pcBuf[pos++] = cFill;
  366. }
  367. }
  368. /* If the value is negative, then place the minus sign
  369. * before the number. */
  370. if (neg)
  371. {
  372. /* Place the minus sign in the output buffer. */
  373. pcBuf[pos++] = '-';
  374. }
  375. /* Convert the value into a string. */
  376. for (; idx; idx /= base)
  377. {
  378. pcBuf[pos++] = g_pcHex[(value / idx) % base];
  379. }
  380. /* Write the string. */
  381. UARTwrite(pcBuf, pos);
  382. /* This command has been handled. */
  383. break;
  384. }
  385. /* Handle the %% command. */
  386. case '%':
  387. {
  388. /* Simply write a single %. */
  389. UARTwrite(pcString - 1, 1);
  390. /* This command has been handled. */
  391. break;
  392. }
  393. /* Handle all other commands. */
  394. default:
  395. {
  396. /* Indicate an error. */
  397. UARTwrite((const char*) "ERROR", 5);
  398. /* This command has been handled. */
  399. break;
  400. }
  401. }
  402. }
  403. }
  404. /* End the varargs processing. */
  405. va_end(vaArgP);
  406. }
  407. /**
  408. *接收控制台数据
  409. */
  410. void ConsoleRecvFill(unsigned char data)
  411. {
  412. if (console_recv.len >= sizeof(console_recv.buf) - 1) console_recv.len = 0;
  413. console_recv.buf[console_recv.len++] = data;
  414. }
  415. /**
  416. * 清空接收的控制台数据
  417. */
  418. void ConsoleRecvClear()
  419. {
  420. uart_recv_clear(&console_recv);
  421. }
  422. /**
  423. * @Title 等待接收控制台数据
  424. * @Param timeout, 最长等待时间,单位毫秒
  425. */
  426. void ConsoleRecvWait(int timeout)
  427. {
  428. uart_recv_wait(&console_recv,timeout);
  429. }
  430. /**
  431. * 串口接收状态
  432. */
  433. unsigned char* ConsoleRecvData()
  434. {
  435. return console_recv.buf;
  436. }
  437. /**
  438. * 串口接收长度
  439. */
  440. int ConsoleRecvLen()
  441. {
  442. return console_recv.len;
  443. }
  444. /**
  445. * 串口接收状态
  446. */
  447. recv_status_e ConsoleRecvFlag()
  448. {
  449. return console_recv.recv_flag;
  450. }
  451. /**
  452. *@Title 清空串口接收缓存
  453. */
  454. static void uart_recv_clear(uart_recv_t* uart_recv)
  455. {
  456. memset(uart_recv->buf,0,sizeof(uart_recv->buf));
  457. uart_recv->len = 0;
  458. uart_recv->recv_flag = REV_WAIT;
  459. }
  460. /**
  461. *@Title 等待串口接收数据
  462. *@Param 最长等待时间
  463. */
  464. static void uart_recv_wait(uart_recv_t* uart_recv,int timeout)
  465. {
  466. int per = 5; //
  467. int prelen = 0;
  468. if(timeout<=0) return;
  469. timeout=timeout/per+(timeout%per==0? 0 : 1);
  470. while(timeout--)
  471. {
  472. if(uart_recv->len)
  473. {
  474. if(uart_recv->len == prelen)
  475. {
  476. uart_recv->recv_flag = REV_OK; //
  477. break;
  478. }
  479. else
  480. {
  481. prelen = uart_recv->len;
  482. }
  483. }
  484. delay_ms(per);
  485. }
  486. }