kservice.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2006-03-16 Bernard the first version
  9. * 2006-05-25 Bernard rewrite vsprintf
  10. * 2006-08-10 Bernard add rt_show_version
  11. * 2010-03-17 Bernard remove rt_strlcpy function
  12. * fix gcc compiling issue.
  13. * 2010-04-15 Bernard remove weak definition on ICCM16C compiler
  14. * 2012-07-18 Arda add the alignment display for signed integer
  15. * 2012-11-23 Bernard fix IAR compiler error.
  16. * 2012-12-22 Bernard fix rt_kprintf issue, which found by Grissiom.
  17. * 2013-06-24 Bernard remove rt_kprintf if RT_USING_CONSOLE is not defined.
  18. * 2013-09-24 aozima make sure the device is in STREAM mode when used by rt_kprintf.
  19. * 2015-07-06 Bernard Add rt_assert_handler routine.
  20. * 2021-02-28 Meco Man add RT_KSERVICE_USING_STDLIB
  21. */
  22. #include <rtthread.h>
  23. #include <rthw.h>
  24. #ifdef RT_USING_MODULE
  25. #include <dlmodule.h>
  26. #endif
  27. /* use precision */
  28. #define RT_PRINTF_PRECISION
  29. #ifdef ARCH_CPU_64BIT
  30. #define RT_PRINTF_LONGLONG
  31. #endif
  32. /**
  33. * @addtogroup KernelService
  34. */
  35. /**@{*/
  36. /* global errno in RT-Thread */
  37. static volatile int __rt_errno;
  38. #if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)
  39. static rt_device_t _console_device = RT_NULL;
  40. #endif
  41. /*
  42. * This function will get errno
  43. *
  44. * @return errno
  45. */
  46. rt_err_t rt_get_errno(void)
  47. {
  48. rt_thread_t tid;
  49. if (rt_interrupt_get_nest() != 0)
  50. {
  51. /* it's in interrupt context */
  52. return __rt_errno;
  53. }
  54. tid = rt_thread_self();
  55. if (tid == RT_NULL)
  56. return __rt_errno;
  57. return tid->error;
  58. }
  59. RTM_EXPORT(rt_get_errno);
  60. /*
  61. * This function will set errno
  62. *
  63. * @param error the errno shall be set
  64. */
  65. void rt_set_errno(rt_err_t error)
  66. {
  67. rt_thread_t tid;
  68. if (rt_interrupt_get_nest() != 0)
  69. {
  70. /* it's in interrupt context */
  71. __rt_errno = error;
  72. return;
  73. }
  74. tid = rt_thread_self();
  75. if (tid == RT_NULL)
  76. {
  77. __rt_errno = error;
  78. return;
  79. }
  80. tid->error = error;
  81. }
  82. RTM_EXPORT(rt_set_errno);
  83. /**
  84. * This function returns errno.
  85. *
  86. * @return the errno in the system
  87. */
  88. int *_rt_errno(void)
  89. {
  90. rt_thread_t tid;
  91. if (rt_interrupt_get_nest() != 0)
  92. return (int *)&__rt_errno;
  93. tid = rt_thread_self();
  94. if (tid != RT_NULL)
  95. return (int *) & (tid->error);
  96. return (int *)&__rt_errno;
  97. }
  98. RTM_EXPORT(_rt_errno);
  99. /**
  100. * This function will set the content of memory to specified value
  101. *
  102. * @param s the address of source memory
  103. * @param c the value shall be set in content
  104. * @param count the copied length
  105. *
  106. * @return the address of source memory
  107. */
  108. RT_WEAK void *rt_memset(void *s, int c, rt_ubase_t count)
  109. {
  110. #ifdef RT_KSERVICE_USING_TINY_SIZE
  111. char *xs = (char *)s;
  112. while (count--)
  113. *xs++ = c;
  114. return s;
  115. #else
  116. #define LBLOCKSIZE (sizeof(long))
  117. #define UNALIGNED(X) ((long)X & (LBLOCKSIZE - 1))
  118. #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
  119. unsigned int i;
  120. char *m = (char *)s;
  121. unsigned long buffer;
  122. unsigned long *aligned_addr;
  123. unsigned int d = c & 0xff; /* To avoid sign extension, copy C to an
  124. unsigned variable. */
  125. if (!TOO_SMALL(count) && !UNALIGNED(s))
  126. {
  127. /* If we get this far, we know that count is large and s is word-aligned. */
  128. aligned_addr = (unsigned long *)s;
  129. /* Store d into each char sized location in buffer so that
  130. * we can set large blocks quickly.
  131. */
  132. if (LBLOCKSIZE == 4)
  133. {
  134. buffer = (d << 8) | d;
  135. buffer |= (buffer << 16);
  136. }
  137. else
  138. {
  139. buffer = 0;
  140. for (i = 0; i < LBLOCKSIZE; i ++)
  141. buffer = (buffer << 8) | d;
  142. }
  143. while (count >= LBLOCKSIZE * 4)
  144. {
  145. *aligned_addr++ = buffer;
  146. *aligned_addr++ = buffer;
  147. *aligned_addr++ = buffer;
  148. *aligned_addr++ = buffer;
  149. count -= 4 * LBLOCKSIZE;
  150. }
  151. while (count >= LBLOCKSIZE)
  152. {
  153. *aligned_addr++ = buffer;
  154. count -= LBLOCKSIZE;
  155. }
  156. /* Pick up the remainder with a bytewise loop. */
  157. m = (char *)aligned_addr;
  158. }
  159. while (count--)
  160. {
  161. *m++ = (char)d;
  162. }
  163. return s;
  164. #undef LBLOCKSIZE
  165. #undef UNALIGNED
  166. #undef TOO_SMALL
  167. #endif
  168. }
  169. RTM_EXPORT(rt_memset);
  170. /**
  171. * This function will copy memory content from source address to destination
  172. * address.
  173. *
  174. * @param dst the address of destination memory
  175. * @param src the address of source memory
  176. * @param count the copied length
  177. *
  178. * @return the address of destination memory
  179. */
  180. RT_WEAK void *rt_memcpy(void *dst, const void *src, rt_ubase_t count)
  181. {
  182. #ifdef RT_KSERVICE_USING_TINY_SIZE
  183. char *tmp = (char *)dst, *s = (char *)src;
  184. rt_ubase_t len;
  185. if (tmp <= s || tmp > (s + count))
  186. {
  187. while (count--)
  188. *tmp ++ = *s ++;
  189. }
  190. else
  191. {
  192. for (len = count; len > 0; len --)
  193. tmp[len - 1] = s[len - 1];
  194. }
  195. return dst;
  196. #else
  197. #define UNALIGNED(X, Y) \
  198. (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
  199. #define BIGBLOCKSIZE (sizeof (long) << 2)
  200. #define LITTLEBLOCKSIZE (sizeof (long))
  201. #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE)
  202. char *dst_ptr = (char *)dst;
  203. char *src_ptr = (char *)src;
  204. long *aligned_dst;
  205. long *aligned_src;
  206. int len = count;
  207. /* If the size is small, or either SRC or DST is unaligned,
  208. then punt into the byte copy loop. This should be rare. */
  209. if (!TOO_SMALL(len) && !UNALIGNED(src_ptr, dst_ptr))
  210. {
  211. aligned_dst = (long *)dst_ptr;
  212. aligned_src = (long *)src_ptr;
  213. /* Copy 4X long words at a time if possible. */
  214. while (len >= BIGBLOCKSIZE)
  215. {
  216. *aligned_dst++ = *aligned_src++;
  217. *aligned_dst++ = *aligned_src++;
  218. *aligned_dst++ = *aligned_src++;
  219. *aligned_dst++ = *aligned_src++;
  220. len -= BIGBLOCKSIZE;
  221. }
  222. /* Copy one long word at a time if possible. */
  223. while (len >= LITTLEBLOCKSIZE)
  224. {
  225. *aligned_dst++ = *aligned_src++;
  226. len -= LITTLEBLOCKSIZE;
  227. }
  228. /* Pick up any residual with a byte copier. */
  229. dst_ptr = (char *)aligned_dst;
  230. src_ptr = (char *)aligned_src;
  231. }
  232. while (len--)
  233. *dst_ptr++ = *src_ptr++;
  234. return dst;
  235. #undef UNALIGNED
  236. #undef BIGBLOCKSIZE
  237. #undef LITTLEBLOCKSIZE
  238. #undef TOO_SMALL
  239. #endif
  240. }
  241. RTM_EXPORT(rt_memcpy);
  242. #ifndef RT_KSERVICE_USING_STDLIB
  243. /**
  244. * This function will move memory content from source address to destination
  245. * address.
  246. *
  247. * @param dest the address of destination memory
  248. * @param src the address of source memory
  249. * @param n the copied length
  250. *
  251. * @return the address of destination memory
  252. */
  253. void *rt_memmove(void *dest, const void *src, rt_ubase_t n)
  254. {
  255. char *tmp = (char *)dest, *s = (char *)src;
  256. if (s < tmp && tmp < s + n)
  257. {
  258. tmp += n;
  259. s += n;
  260. while (n--)
  261. *(--tmp) = *(--s);
  262. }
  263. else
  264. {
  265. while (n--)
  266. *tmp++ = *s++;
  267. }
  268. return dest;
  269. }
  270. RTM_EXPORT(rt_memmove);
  271. /**
  272. * This function will compare two areas of memory
  273. *
  274. * @param cs one area of memory
  275. * @param ct another area of memory
  276. * @param count the size of the area
  277. *
  278. * @return the result
  279. */
  280. RT_WEAK rt_int32_t rt_memcmp(const void *cs, const void *ct, rt_ubase_t count)
  281. {
  282. const unsigned char *su1, *su2;
  283. int res = 0;
  284. for (su1 = (const unsigned char *)cs, su2 = (const unsigned char *)ct; 0 < count; ++su1, ++su2, count--)
  285. if ((res = *su1 - *su2) != 0)
  286. break;
  287. return res;
  288. }
  289. RTM_EXPORT(rt_memcmp);
  290. /**
  291. * This function will return the first occurrence of a string.
  292. *
  293. * @param s1 the source string
  294. * @param s2 the find string
  295. *
  296. * @return the first occurrence of a s2 in s1, or RT_NULL if no found.
  297. */
  298. char *rt_strstr(const char *s1, const char *s2)
  299. {
  300. int l1, l2;
  301. l2 = rt_strlen(s2);
  302. if (!l2)
  303. return (char *)s1;
  304. l1 = rt_strlen(s1);
  305. while (l1 >= l2)
  306. {
  307. l1 --;
  308. if (!rt_memcmp(s1, s2, l2))
  309. return (char *)s1;
  310. s1 ++;
  311. }
  312. return RT_NULL;
  313. }
  314. RTM_EXPORT(rt_strstr);
  315. /**
  316. * This function will compare two strings while ignoring differences in case
  317. *
  318. * @param a the string to be compared
  319. * @param b the string to be compared
  320. *
  321. * @return the result
  322. */
  323. rt_int32_t rt_strcasecmp(const char *a, const char *b)
  324. {
  325. int ca, cb;
  326. do
  327. {
  328. ca = *a++ & 0xff;
  329. cb = *b++ & 0xff;
  330. if (ca >= 'A' && ca <= 'Z')
  331. ca += 'a' - 'A';
  332. if (cb >= 'A' && cb <= 'Z')
  333. cb += 'a' - 'A';
  334. }
  335. while (ca == cb && ca != '\0');
  336. return ca - cb;
  337. }
  338. RTM_EXPORT(rt_strcasecmp);
  339. /**
  340. * This function will copy string no more than n bytes.
  341. *
  342. * @param dst the string to copy
  343. * @param src the string to be copied
  344. * @param n the maximum copied length
  345. *
  346. * @return the result
  347. */
  348. char *rt_strncpy(char *dst, const char *src, rt_ubase_t n)
  349. {
  350. if (n != 0)
  351. {
  352. char *d = dst;
  353. const char *s = src;
  354. do
  355. {
  356. if ((*d++ = *s++) == 0)
  357. {
  358. /* NUL pad the remaining n-1 bytes */
  359. while (--n != 0)
  360. *d++ = 0;
  361. break;
  362. }
  363. } while (--n != 0);
  364. }
  365. return (dst);
  366. }
  367. RTM_EXPORT(rt_strncpy);
  368. /**
  369. * This function will compare two strings with specified maximum length
  370. *
  371. * @param cs the string to be compared
  372. * @param ct the string to be compared
  373. * @param count the maximum compare length
  374. *
  375. * @return the result
  376. */
  377. rt_int32_t rt_strncmp(const char *cs, const char *ct, rt_ubase_t count)
  378. {
  379. register signed char __res = 0;
  380. while (count)
  381. {
  382. if ((__res = *cs - *ct++) != 0 || !*cs++)
  383. break;
  384. count --;
  385. }
  386. return __res;
  387. }
  388. RTM_EXPORT(rt_strncmp);
  389. /**
  390. * This function will compare two strings without specified length
  391. *
  392. * @param cs the string to be compared
  393. * @param ct the string to be compared
  394. *
  395. * @return the result
  396. */
  397. rt_int32_t rt_strcmp(const char *cs, const char *ct)
  398. {
  399. while (*cs && *cs == *ct)
  400. {
  401. cs++;
  402. ct++;
  403. }
  404. return (*cs - *ct);
  405. }
  406. RTM_EXPORT(rt_strcmp);
  407. /**
  408. * The strnlen() function returns the number of characters in the
  409. * string pointed to by s, excluding the terminating null byte ('\0'),
  410. * but at most maxlen. In doing this, strnlen() looks only at the
  411. * first maxlen characters in the string pointed to by s and never
  412. * beyond s+maxlen.
  413. *
  414. * @param s the string
  415. * @param maxlen the max size
  416. * @return the length of string
  417. */
  418. rt_size_t rt_strnlen(const char *s, rt_ubase_t maxlen)
  419. {
  420. const char *sc;
  421. for (sc = s; *sc != '\0' && (rt_ubase_t)(sc - s) < maxlen; ++sc) /* nothing */
  422. ;
  423. return sc - s;
  424. }
  425. RTM_EXPORT(rt_strnlen);
  426. /**
  427. * This function will return the length of a string, which terminate will
  428. * null character.
  429. *
  430. * @param s the string
  431. *
  432. * @return the length of string
  433. */
  434. rt_size_t rt_strlen(const char *s)
  435. {
  436. const char *sc;
  437. for (sc = s; *sc != '\0'; ++sc) /* nothing */
  438. ;
  439. return sc - s;
  440. }
  441. RTM_EXPORT(rt_strlen);
  442. #endif /*RT_KSERVICE_USING_STDLIB*/
  443. #ifdef RT_USING_HEAP
  444. /**
  445. * This function will duplicate a string.
  446. *
  447. * @param s the string to be duplicated
  448. *
  449. * @return the duplicated string pointer
  450. */
  451. char *rt_strdup(const char *s)
  452. {
  453. rt_size_t len = rt_strlen(s) + 1;
  454. char *tmp = (char *)rt_malloc(len);
  455. if (!tmp)
  456. return RT_NULL;
  457. rt_memcpy(tmp, s, len);
  458. return tmp;
  459. }
  460. RTM_EXPORT(rt_strdup);
  461. #if defined(__CC_ARM) || defined(__CLANG_ARM)
  462. char *strdup(const char *s) __attribute__((alias("rt_strdup")));
  463. #endif
  464. #endif
  465. /**
  466. * This function will show the version of rt-thread rtos
  467. */
  468. void rt_show_version(void)
  469. {
  470. rt_kprintf("\n \\ | /\n");
  471. rt_kprintf("- RT - Thread Operating System\n");
  472. rt_kprintf(" / | \\ %d.%d.%d build %s\n",
  473. RT_VERSION, RT_SUBVERSION, RT_REVISION, __DATE__);
  474. rt_kprintf(" 2006 - 2021 Copyright by rt-thread team\n");
  475. }
  476. RTM_EXPORT(rt_show_version);
  477. /* private function */
  478. #define _ISDIGIT(c) ((unsigned)((c) - '0') < 10)
  479. #ifdef RT_PRINTF_LONGLONG
  480. rt_inline int divide(long long *n, int base)
  481. {
  482. int res;
  483. /* optimized for processor which does not support divide instructions. */
  484. if (base == 10)
  485. {
  486. res = (int)(((unsigned long long)*n) % 10U);
  487. *n = (long long)(((unsigned long long)*n) / 10U);
  488. }
  489. else
  490. {
  491. res = (int)(((unsigned long long)*n) % 16U);
  492. *n = (long long)(((unsigned long long)*n) / 16U);
  493. }
  494. return res;
  495. }
  496. #else
  497. rt_inline int divide(long *n, int base)
  498. {
  499. int res;
  500. /* optimized for processor which does not support divide instructions. */
  501. if (base == 10)
  502. {
  503. res = (int)(((unsigned long)*n) % 10U);
  504. *n = (long)(((unsigned long)*n) / 10U);
  505. }
  506. else
  507. {
  508. res = (int)(((unsigned long)*n) % 16U);
  509. *n = (long)(((unsigned long)*n) / 16U);
  510. }
  511. return res;
  512. }
  513. #endif
  514. rt_inline int skip_atoi(const char **s)
  515. {
  516. register int i = 0;
  517. while (_ISDIGIT(**s))
  518. i = i * 10 + *((*s)++) - '0';
  519. return i;
  520. }
  521. #define ZEROPAD (1 << 0) /* pad with zero */
  522. #define SIGN (1 << 1) /* unsigned/signed long */
  523. #define PLUS (1 << 2) /* show plus */
  524. #define SPACE (1 << 3) /* space if plus */
  525. #define LEFT (1 << 4) /* left justified */
  526. #define SPECIAL (1 << 5) /* 0x */
  527. #define LARGE (1 << 6) /* use 'ABCDEF' instead of 'abcdef' */
  528. #ifdef RT_PRINTF_PRECISION
  529. static char *print_number(char *buf,
  530. char *end,
  531. #ifdef RT_PRINTF_LONGLONG
  532. long long num,
  533. #else
  534. long num,
  535. #endif
  536. int base,
  537. int s,
  538. int precision,
  539. int type)
  540. #else
  541. static char *print_number(char *buf,
  542. char *end,
  543. #ifdef RT_PRINTF_LONGLONG
  544. long long num,
  545. #else
  546. long num,
  547. #endif
  548. int base,
  549. int s,
  550. int type)
  551. #endif
  552. {
  553. char c, sign;
  554. #ifdef RT_PRINTF_LONGLONG
  555. char tmp[32];
  556. #else
  557. char tmp[16];
  558. #endif
  559. int precision_bak = precision;
  560. const char *digits;
  561. static const char small_digits[] = "0123456789abcdef";
  562. static const char large_digits[] = "0123456789ABCDEF";
  563. register int i;
  564. register int size;
  565. size = s;
  566. digits = (type & LARGE) ? large_digits : small_digits;
  567. if (type & LEFT)
  568. type &= ~ZEROPAD;
  569. c = (type & ZEROPAD) ? '0' : ' ';
  570. /* get sign */
  571. sign = 0;
  572. if (type & SIGN)
  573. {
  574. if (num < 0)
  575. {
  576. sign = '-';
  577. num = -num;
  578. }
  579. else if (type & PLUS)
  580. sign = '+';
  581. else if (type & SPACE)
  582. sign = ' ';
  583. }
  584. #ifdef RT_PRINTF_SPECIAL
  585. if (type & SPECIAL)
  586. {
  587. if (base == 16)
  588. size -= 2;
  589. else if (base == 8)
  590. size--;
  591. }
  592. #endif
  593. i = 0;
  594. if (num == 0)
  595. tmp[i++] = '0';
  596. else
  597. {
  598. while (num != 0)
  599. tmp[i++] = digits[divide(&num, base)];
  600. }
  601. #ifdef RT_PRINTF_PRECISION
  602. if (i > precision)
  603. precision = i;
  604. size -= precision;
  605. #else
  606. size -= i;
  607. #endif
  608. if (!(type & (ZEROPAD | LEFT)))
  609. {
  610. if ((sign) && (size > 0))
  611. size--;
  612. while (size-- > 0)
  613. {
  614. if (buf < end)
  615. *buf = ' ';
  616. ++ buf;
  617. }
  618. }
  619. if (sign)
  620. {
  621. if (buf < end)
  622. {
  623. *buf = sign;
  624. }
  625. -- size;
  626. ++ buf;
  627. }
  628. #ifdef RT_PRINTF_SPECIAL
  629. if (type & SPECIAL)
  630. {
  631. if (base == 8)
  632. {
  633. if (buf < end)
  634. *buf = '0';
  635. ++ buf;
  636. }
  637. else if (base == 16)
  638. {
  639. if (buf < end)
  640. *buf = '0';
  641. ++ buf;
  642. if (buf < end)
  643. {
  644. *buf = type & LARGE ? 'X' : 'x';
  645. }
  646. ++ buf;
  647. }
  648. }
  649. #endif
  650. /* no align to the left */
  651. if (!(type & LEFT))
  652. {
  653. while (size-- > 0)
  654. {
  655. if (buf < end)
  656. *buf = c;
  657. ++ buf;
  658. }
  659. }
  660. #ifdef RT_PRINTF_PRECISION
  661. while (i < precision--)
  662. {
  663. if (buf < end)
  664. *buf = '0';
  665. ++ buf;
  666. }
  667. #endif
  668. /* put number in the temporary buffer */
  669. while (i-- > 0 && (precision_bak != 0))
  670. {
  671. if (buf < end)
  672. *buf = tmp[i];
  673. ++ buf;
  674. }
  675. while (size-- > 0)
  676. {
  677. if (buf < end)
  678. *buf = ' ';
  679. ++ buf;
  680. }
  681. return buf;
  682. }
  683. rt_int32_t rt_vsnprintf(char *buf,
  684. rt_size_t size,
  685. const char *fmt,
  686. va_list args)
  687. {
  688. #ifdef RT_PRINTF_LONGLONG
  689. unsigned long long num;
  690. #else
  691. rt_uint32_t num;
  692. #endif
  693. int i, len;
  694. char *str, *end, c;
  695. const char *s;
  696. rt_uint8_t base; /* the base of number */
  697. rt_uint8_t flags; /* flags to print number */
  698. rt_uint8_t qualifier; /* 'h', 'l', or 'L' for integer fields */
  699. rt_int32_t field_width; /* width of output field */
  700. #ifdef RT_PRINTF_PRECISION
  701. int precision; /* min. # of digits for integers and max for a string */
  702. #endif
  703. str = buf;
  704. end = buf + size;
  705. /* Make sure end is always >= buf */
  706. if (end < buf)
  707. {
  708. end = ((char *) - 1);
  709. size = end - buf;
  710. }
  711. for (; *fmt ; ++fmt)
  712. {
  713. if (*fmt != '%')
  714. {
  715. if (str < end)
  716. *str = *fmt;
  717. ++ str;
  718. continue;
  719. }
  720. /* process flags */
  721. flags = 0;
  722. while (1)
  723. {
  724. /* skips the first '%' also */
  725. ++ fmt;
  726. if (*fmt == '-') flags |= LEFT;
  727. else if (*fmt == '+') flags |= PLUS;
  728. else if (*fmt == ' ') flags |= SPACE;
  729. else if (*fmt == '#') flags |= SPECIAL;
  730. else if (*fmt == '0') flags |= ZEROPAD;
  731. else break;
  732. }
  733. /* get field width */
  734. field_width = -1;
  735. if (_ISDIGIT(*fmt)) field_width = skip_atoi(&fmt);
  736. else if (*fmt == '*')
  737. {
  738. ++ fmt;
  739. /* it's the next argument */
  740. field_width = va_arg(args, int);
  741. if (field_width < 0)
  742. {
  743. field_width = -field_width;
  744. flags |= LEFT;
  745. }
  746. }
  747. #ifdef RT_PRINTF_PRECISION
  748. /* get the precision */
  749. precision = -1;
  750. if (*fmt == '.')
  751. {
  752. ++ fmt;
  753. if (_ISDIGIT(*fmt)) precision = skip_atoi(&fmt);
  754. else if (*fmt == '*')
  755. {
  756. ++ fmt;
  757. /* it's the next argument */
  758. precision = va_arg(args, int);
  759. }
  760. if (precision < 0) precision = 0;
  761. }
  762. #endif
  763. /* get the conversion qualifier */
  764. qualifier = 0;
  765. #ifdef RT_PRINTF_LONGLONG
  766. if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L')
  767. #else
  768. if (*fmt == 'h' || *fmt == 'l')
  769. #endif
  770. {
  771. qualifier = *fmt;
  772. ++ fmt;
  773. #ifdef RT_PRINTF_LONGLONG
  774. if (qualifier == 'l' && *fmt == 'l')
  775. {
  776. qualifier = 'L';
  777. ++ fmt;
  778. }
  779. #endif
  780. }
  781. /* the default base */
  782. base = 10;
  783. switch (*fmt)
  784. {
  785. case 'c':
  786. if (!(flags & LEFT))
  787. {
  788. while (--field_width > 0)
  789. {
  790. if (str < end) *str = ' ';
  791. ++ str;
  792. }
  793. }
  794. /* get character */
  795. c = (rt_uint8_t)va_arg(args, int);
  796. if (str < end) *str = c;
  797. ++ str;
  798. /* put width */
  799. while (--field_width > 0)
  800. {
  801. if (str < end) *str = ' ';
  802. ++ str;
  803. }
  804. continue;
  805. case 's':
  806. s = va_arg(args, char *);
  807. if (!s) s = "(NULL)";
  808. len = rt_strlen(s);
  809. #ifdef RT_PRINTF_PRECISION
  810. if (precision > 0 && len > precision) len = precision;
  811. #endif
  812. if (!(flags & LEFT))
  813. {
  814. while (len < field_width--)
  815. {
  816. if (str < end) *str = ' ';
  817. ++ str;
  818. }
  819. }
  820. for (i = 0; i < len; ++i)
  821. {
  822. if (str < end) *str = *s;
  823. ++ str;
  824. ++ s;
  825. }
  826. while (len < field_width--)
  827. {
  828. if (str < end) *str = ' ';
  829. ++ str;
  830. }
  831. continue;
  832. case 'p':
  833. if (field_width == -1)
  834. {
  835. field_width = sizeof(void *) << 1;
  836. flags |= ZEROPAD;
  837. }
  838. #ifdef RT_PRINTF_PRECISION
  839. str = print_number(str, end,
  840. (long)va_arg(args, void *),
  841. 16, field_width, precision, flags);
  842. #else
  843. str = print_number(str, end,
  844. (long)va_arg(args, void *),
  845. 16, field_width, flags);
  846. #endif
  847. continue;
  848. case '%':
  849. if (str < end) *str = '%';
  850. ++ str;
  851. continue;
  852. /* integer number formats - set up the flags and "break" */
  853. case 'o':
  854. base = 8;
  855. break;
  856. case 'X':
  857. flags |= LARGE;
  858. case 'x':
  859. base = 16;
  860. break;
  861. case 'd':
  862. case 'i':
  863. flags |= SIGN;
  864. case 'u':
  865. break;
  866. default:
  867. if (str < end) *str = '%';
  868. ++ str;
  869. if (*fmt)
  870. {
  871. if (str < end) *str = *fmt;
  872. ++ str;
  873. }
  874. else
  875. {
  876. -- fmt;
  877. }
  878. continue;
  879. }
  880. #ifdef RT_PRINTF_LONGLONG
  881. if (qualifier == 'L') num = va_arg(args, long long);
  882. else if (qualifier == 'l')
  883. #else
  884. if (qualifier == 'l')
  885. #endif
  886. {
  887. num = va_arg(args, rt_uint32_t);
  888. if (flags & SIGN) num = (rt_int32_t)num;
  889. }
  890. else if (qualifier == 'h')
  891. {
  892. num = (rt_uint16_t)va_arg(args, rt_int32_t);
  893. if (flags & SIGN) num = (rt_int16_t)num;
  894. }
  895. else
  896. {
  897. num = va_arg(args, rt_uint32_t);
  898. if (flags & SIGN) num = (rt_int32_t)num;
  899. }
  900. #ifdef RT_PRINTF_PRECISION
  901. str = print_number(str, end, num, base, field_width, precision, flags);
  902. #else
  903. str = print_number(str, end, num, base, field_width, flags);
  904. #endif
  905. }
  906. if (size > 0)
  907. {
  908. if (str < end) *str = '\0';
  909. else
  910. {
  911. end[-1] = '\0';
  912. }
  913. }
  914. /* the trailing null byte doesn't count towards the total
  915. * ++str;
  916. */
  917. return str - buf;
  918. }
  919. RTM_EXPORT(rt_vsnprintf);
  920. /**
  921. * This function will fill a formatted string to buffer
  922. *
  923. * @param buf the buffer to save formatted string
  924. * @param size the size of buffer
  925. * @param fmt the format
  926. */
  927. rt_int32_t rt_snprintf(char *buf, rt_size_t size, const char *fmt, ...)
  928. {
  929. rt_int32_t n;
  930. va_list args;
  931. va_start(args, fmt);
  932. n = rt_vsnprintf(buf, size, fmt, args);
  933. va_end(args);
  934. return n;
  935. }
  936. RTM_EXPORT(rt_snprintf);
  937. /**
  938. * This function will fill a formatted string to buffer
  939. *
  940. * @param buf the buffer to save formatted string
  941. * @param arg_ptr the arg_ptr
  942. * @param format the format
  943. */
  944. rt_int32_t rt_vsprintf(char *buf, const char *format, va_list arg_ptr)
  945. {
  946. return rt_vsnprintf(buf, (rt_size_t) - 1, format, arg_ptr);
  947. }
  948. RTM_EXPORT(rt_vsprintf);
  949. /**
  950. * This function will fill a formatted string to buffer
  951. *
  952. * @param buf the buffer to save formatted string
  953. * @param format the format
  954. */
  955. rt_int32_t rt_sprintf(char *buf, const char *format, ...)
  956. {
  957. rt_int32_t n;
  958. va_list arg_ptr;
  959. va_start(arg_ptr, format);
  960. n = rt_vsprintf(buf, format, arg_ptr);
  961. va_end(arg_ptr);
  962. return n;
  963. }
  964. RTM_EXPORT(rt_sprintf);
  965. #ifdef RT_USING_CONSOLE
  966. #ifdef RT_USING_DEVICE
  967. /**
  968. * This function returns the device using in console.
  969. *
  970. * @return the device using in console or RT_NULL
  971. */
  972. rt_device_t rt_console_get_device(void)
  973. {
  974. return _console_device;
  975. }
  976. RTM_EXPORT(rt_console_get_device);
  977. /**
  978. * This function will set a device as console device.
  979. * After set a device to console, all output of rt_kprintf will be
  980. * redirected to this new device.
  981. *
  982. * @param name the name of new console device
  983. *
  984. * @return the old console device handler on successful, or RT_NULL on failure.
  985. */
  986. rt_device_t rt_console_set_device(const char *name)
  987. {
  988. rt_device_t new_device, old_device;
  989. /* save old device */
  990. old_device = _console_device;
  991. /* find new console device */
  992. new_device = rt_device_find(name);
  993. /* check whether it's a same device */
  994. if (new_device == old_device) return RT_NULL;
  995. if (new_device != RT_NULL)
  996. {
  997. if (_console_device != RT_NULL)
  998. {
  999. /* close old console device */
  1000. rt_device_close(_console_device);
  1001. }
  1002. /* set new console device */
  1003. rt_device_open(new_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
  1004. _console_device = new_device;
  1005. }
  1006. return old_device;
  1007. }
  1008. RTM_EXPORT(rt_console_set_device);
  1009. #endif
  1010. RT_WEAK void rt_hw_console_output(const char *str)
  1011. {
  1012. /* empty console output */
  1013. }
  1014. RTM_EXPORT(rt_hw_console_output);
  1015. /**
  1016. * This function will put string to the console.
  1017. *
  1018. * @param str the string output to the console.
  1019. */
  1020. void rt_kputs(const char *str)
  1021. {
  1022. if (!str) return;
  1023. #ifdef RT_USING_DEVICE
  1024. if (_console_device == RT_NULL)
  1025. {
  1026. rt_hw_console_output(str);
  1027. }
  1028. else
  1029. {
  1030. rt_uint16_t old_flag = _console_device->open_flag;
  1031. _console_device->open_flag |= RT_DEVICE_FLAG_STREAM;
  1032. rt_device_write(_console_device, 0, str, rt_strlen(str));
  1033. _console_device->open_flag = old_flag;
  1034. }
  1035. #else
  1036. rt_hw_console_output(str);
  1037. #endif
  1038. }
  1039. /**
  1040. * This function will print a formatted string on system console
  1041. *
  1042. * @param fmt the format
  1043. */
  1044. RT_WEAK void rt_kprintf(const char *fmt, ...)
  1045. {
  1046. va_list args;
  1047. rt_size_t length;
  1048. static char rt_log_buf[RT_CONSOLEBUF_SIZE];
  1049. va_start(args, fmt);
  1050. /* the return value of vsnprintf is the number of bytes that would be
  1051. * written to buffer had if the size of the buffer been sufficiently
  1052. * large excluding the terminating null byte. If the output string
  1053. * would be larger than the rt_log_buf, we have to adjust the output
  1054. * length. */
  1055. length = rt_vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
  1056. if (length > RT_CONSOLEBUF_SIZE - 1)
  1057. length = RT_CONSOLEBUF_SIZE - 1;
  1058. #ifdef RT_USING_DEVICE
  1059. if (_console_device == RT_NULL)
  1060. {
  1061. rt_hw_console_output(rt_log_buf);
  1062. }
  1063. else
  1064. {
  1065. rt_uint16_t old_flag = _console_device->open_flag;
  1066. _console_device->open_flag |= RT_DEVICE_FLAG_STREAM;
  1067. rt_device_write(_console_device, 0, rt_log_buf, length);
  1068. _console_device->open_flag = old_flag;
  1069. }
  1070. #else
  1071. rt_hw_console_output(rt_log_buf);
  1072. #endif
  1073. va_end(args);
  1074. }
  1075. RTM_EXPORT(rt_kprintf);
  1076. #endif
  1077. #ifdef RT_USING_HEAP
  1078. /**
  1079. * This function allocates a memory block, which address is aligned to the
  1080. * specified alignment size.
  1081. *
  1082. * @param size the allocated memory block size
  1083. * @param align the alignment size
  1084. *
  1085. * @return the allocated memory block on successful, otherwise returns RT_NULL
  1086. */
  1087. void *rt_malloc_align(rt_size_t size, rt_size_t align)
  1088. {
  1089. void *ptr;
  1090. void *align_ptr;
  1091. int uintptr_size;
  1092. rt_size_t align_size;
  1093. /* sizeof pointer */
  1094. uintptr_size = sizeof(void*);
  1095. uintptr_size -= 1;
  1096. /* align the alignment size to uintptr size byte */
  1097. align = ((align + uintptr_size) & ~uintptr_size);
  1098. /* get total aligned size */
  1099. align_size = ((size + uintptr_size) & ~uintptr_size) + align;
  1100. /* allocate memory block from heap */
  1101. ptr = rt_malloc(align_size);
  1102. if (ptr != RT_NULL)
  1103. {
  1104. /* the allocated memory block is aligned */
  1105. if (((rt_ubase_t)ptr & (align - 1)) == 0)
  1106. {
  1107. align_ptr = (void *)((rt_ubase_t)ptr + align);
  1108. }
  1109. else
  1110. {
  1111. align_ptr = (void *)(((rt_ubase_t)ptr + (align - 1)) & ~(align - 1));
  1112. }
  1113. /* set the pointer before alignment pointer to the real pointer */
  1114. *((rt_ubase_t *)((rt_ubase_t)align_ptr - sizeof(void *))) = (rt_ubase_t)ptr;
  1115. ptr = align_ptr;
  1116. }
  1117. return ptr;
  1118. }
  1119. RTM_EXPORT(rt_malloc_align);
  1120. /**
  1121. * This function release the memory block, which is allocated by
  1122. * rt_malloc_align function and address is aligned.
  1123. *
  1124. * @param ptr the memory block pointer
  1125. */
  1126. void rt_free_align(void *ptr)
  1127. {
  1128. void *real_ptr;
  1129. real_ptr = (void *) * (rt_ubase_t *)((rt_ubase_t)ptr - sizeof(void *));
  1130. rt_free(real_ptr);
  1131. }
  1132. RTM_EXPORT(rt_free_align);
  1133. #endif
  1134. #ifndef RT_USING_CPU_FFS
  1135. const rt_uint8_t __lowest_bit_bitmap[] =
  1136. {
  1137. /* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1138. /* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1139. /* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1140. /* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1141. /* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1142. /* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1143. /* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1144. /* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1145. /* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1146. /* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1147. /* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1148. /* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1149. /* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1150. /* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1151. /* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
  1152. /* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
  1153. };
  1154. /**
  1155. * This function finds the first bit set (beginning with the least significant bit)
  1156. * in value and return the index of that bit.
  1157. *
  1158. * Bits are numbered starting at 1 (the least significant bit). A return value of
  1159. * zero from any of these functions means that the argument was zero.
  1160. *
  1161. * @return return the index of the first bit set. If value is 0, then this function
  1162. * shall return 0.
  1163. */
  1164. int __rt_ffs(int value)
  1165. {
  1166. if (value == 0) return 0;
  1167. if (value & 0xff)
  1168. return __lowest_bit_bitmap[value & 0xff] + 1;
  1169. if (value & 0xff00)
  1170. return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9;
  1171. if (value & 0xff0000)
  1172. return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17;
  1173. return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;
  1174. }
  1175. #endif
  1176. #ifdef RT_DEBUG
  1177. /* RT_ASSERT(EX)'s hook */
  1178. void (*rt_assert_hook)(const char *ex, const char *func, rt_size_t line);
  1179. /**
  1180. * This function will set a hook function to RT_ASSERT(EX). It will run when the expression is false.
  1181. *
  1182. * @param hook the hook function
  1183. */
  1184. void rt_assert_set_hook(void (*hook)(const char *ex, const char *func, rt_size_t line))
  1185. {
  1186. rt_assert_hook = hook;
  1187. }
  1188. /**
  1189. * The RT_ASSERT function.
  1190. *
  1191. * @param ex the assertion condition string
  1192. * @param func the function name when assertion.
  1193. * @param line the file line number when assertion.
  1194. */
  1195. void rt_assert_handler(const char *ex_string, const char *func, rt_size_t line)
  1196. {
  1197. volatile char dummy = 0;
  1198. if (rt_assert_hook == RT_NULL)
  1199. {
  1200. #ifdef RT_USING_MODULE
  1201. if (dlmodule_self())
  1202. {
  1203. /* close assertion module */
  1204. dlmodule_exit(-1);
  1205. }
  1206. else
  1207. #endif
  1208. {
  1209. rt_kprintf("(%s) assertion failed at function:%s, line number:%d \n", ex_string, func, line);
  1210. while (dummy == 0);
  1211. }
  1212. }
  1213. else
  1214. {
  1215. rt_assert_hook(ex_string, func, line);
  1216. }
  1217. }
  1218. RTM_EXPORT(rt_assert_handler);
  1219. #endif /* RT_DEBUG */
  1220. /**@}*/