console.c 16 KB

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