console.c 17 KB

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