kservice.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  1. /*
  2. * File : kservice.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2011, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2006-03-16 Bernard the first version
  13. * 2006-05-25 Bernard rewrite vsprintf
  14. * 2006-08-10 Bernard add rt_show_version
  15. * 2010-03-17 Bernard remove rt_strlcpy function
  16. * fix gcc compiling issue.
  17. * 2010-04-15 Bernard remove weak definition on ICCM16C compiler
  18. */
  19. #include <rtthread.h>
  20. #include <rthw.h>
  21. /**
  22. * @addtogroup KernelService
  23. */
  24. /*@{*/
  25. /* global errno in RT-Thread */
  26. static volatile int _errno;
  27. #if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)
  28. static rt_device_t _console_device = RT_NULL;
  29. #endif
  30. /*
  31. * This function will get errno
  32. *
  33. * @return errno
  34. */
  35. rt_err_t rt_get_errno(void)
  36. {
  37. rt_thread_t tid;
  38. if (rt_interrupt_get_nest() != 0)
  39. {
  40. /* it's in interrupt context */
  41. return _errno;
  42. }
  43. tid = rt_thread_self();
  44. if (tid == RT_NULL) return _errno;
  45. return tid->error;
  46. }
  47. /*
  48. * This function will set errno
  49. *
  50. * @param error the errno shall be set
  51. */
  52. void rt_set_errno(rt_err_t error)
  53. {
  54. rt_thread_t tid;
  55. if (rt_interrupt_get_nest() != 0)
  56. {
  57. /* it's in interrupt context */
  58. _errno = error;
  59. return;
  60. }
  61. tid = rt_thread_self();
  62. if (tid == RT_NULL) { _errno = error; return; }
  63. tid->error = error;
  64. }
  65. /**
  66. * This function returns errno.
  67. *
  68. * @return the errno in the system
  69. */
  70. int *_rt_errno(void)
  71. {
  72. rt_thread_t tid;
  73. if (rt_interrupt_get_nest() != 0) return (int *)&_errno;
  74. tid = rt_thread_self();
  75. if (tid != RT_NULL) return (int *)&(tid->error);
  76. return (int *)&_errno;
  77. }
  78. /**
  79. * This function will set the content of memory to specified value
  80. *
  81. * @param s the address of source memory
  82. * @param c the value shall be set in content
  83. * @param count the copied length
  84. *
  85. * @return the address of source memory
  86. *
  87. */
  88. void *rt_memset(void *s, int c, rt_ubase_t count)
  89. {
  90. #ifdef RT_TINY_SIZE
  91. char *xs = (char *)s;
  92. while (count--)
  93. *xs++ = c;
  94. return s;
  95. #else
  96. #define LBLOCKSIZE (sizeof(rt_int32_t))
  97. #define UNALIGNED(X) ((rt_int32_t)X & (LBLOCKSIZE - 1))
  98. #define TOO_SMALL(LEN) ((LEN) < LBLOCKSIZE)
  99. int i;
  100. char *m = (char *)s;
  101. rt_uint32_t buffer;
  102. rt_uint32_t *aligned_addr;
  103. rt_uint32_t d = c & 0xff;
  104. if (!TOO_SMALL(count) && !UNALIGNED(s))
  105. {
  106. /* If we get this far, we know that n is large and m is word-aligned. */
  107. aligned_addr = (rt_uint32_t *)s;
  108. /* Store D into each char sized location in BUFFER so that
  109. * we can set large blocks quickly.
  110. */
  111. if (LBLOCKSIZE == 4)
  112. {
  113. buffer = (d << 8) | d;
  114. buffer |= (buffer << 16);
  115. }
  116. else
  117. {
  118. buffer = 0;
  119. for (i = 0; i < LBLOCKSIZE; i++)
  120. buffer = (buffer << 8) | d;
  121. }
  122. while (count >= LBLOCKSIZE*4)
  123. {
  124. *aligned_addr++ = buffer;
  125. *aligned_addr++ = buffer;
  126. *aligned_addr++ = buffer;
  127. *aligned_addr++ = buffer;
  128. count -= 4*LBLOCKSIZE;
  129. }
  130. while (count >= LBLOCKSIZE)
  131. {
  132. *aligned_addr++ = buffer;
  133. count -= LBLOCKSIZE;
  134. }
  135. /* Pick up the remainder with a bytewise loop. */
  136. m = (char *)aligned_addr;
  137. }
  138. while (count--)
  139. {
  140. *m++ = (char)d;
  141. }
  142. return s;
  143. #undef LBLOCKSIZE
  144. #undef UNALIGNED
  145. #undef TOO_SMALL
  146. #endif
  147. }
  148. /**
  149. * This function will copy memory content from source address to destination
  150. * address.
  151. *
  152. * @param dst the address of destination memory
  153. * @param src the address of source memory
  154. * @param count the copied length
  155. *
  156. * @return the address of destination memory
  157. *
  158. */
  159. void *rt_memcpy(void *dst, const void *src, rt_ubase_t count)
  160. {
  161. #ifdef RT_TINY_SIZE
  162. char *tmp = (char *)dst, *s = (char *)src;
  163. while (count--)
  164. *tmp++ = *s++;
  165. return dst;
  166. #else
  167. #define UNALIGNED(X, Y) \
  168. (((rt_int32_t)X & (sizeof(rt_int32_t) - 1)) | ((rt_int32_t)Y & (sizeof(rt_int32_t) - 1)))
  169. #define BIGBLOCKSIZE (sizeof(rt_int32_t) << 2)
  170. #define LITTLEBLOCKSIZE (sizeof(rt_int32_t))
  171. #define TOO_SMALL(LEN) ((LEN) < BIGBLOCKSIZE)
  172. char *dst_ptr = (char *)dst;
  173. char *src_ptr = (char *)src;
  174. rt_int32_t *aligned_dst;
  175. rt_int32_t *aligned_src;
  176. int len = count;
  177. /* If the size is small, or either SRC or DST is unaligned,
  178. then punt into the byte copy loop. This should be rare. */
  179. if (!TOO_SMALL(len) && !UNALIGNED(src_ptr, dst_ptr))
  180. {
  181. aligned_dst = (rt_int32_t *)dst_ptr;
  182. aligned_src = (rt_int32_t *)src_ptr;
  183. /* Copy 4X long words at a time if possible. */
  184. while (len >= BIGBLOCKSIZE)
  185. {
  186. *aligned_dst++ = *aligned_src++;
  187. *aligned_dst++ = *aligned_src++;
  188. *aligned_dst++ = *aligned_src++;
  189. *aligned_dst++ = *aligned_src++;
  190. len -= BIGBLOCKSIZE;
  191. }
  192. /* Copy one long word at a time if possible. */
  193. while (len >= LITTLEBLOCKSIZE)
  194. {
  195. *aligned_dst++ = *aligned_src++;
  196. len -= LITTLEBLOCKSIZE;
  197. }
  198. /* Pick up any residual with a byte copier. */
  199. dst_ptr = (char *)aligned_dst;
  200. src_ptr = (char *)aligned_src;
  201. }
  202. while (len--)
  203. *dst_ptr++ = *src_ptr++;
  204. return dst;
  205. #undef UNALIGNED
  206. #undef BIGBLOCKSIZE
  207. #undef LITTLEBLOCKSIZE
  208. #undef TOO_SMALL
  209. #endif
  210. }
  211. /**
  212. * This function will move memory content from source address to destination
  213. * address.
  214. *
  215. * @param dest the address of destination memory
  216. * @param src the address of source memory
  217. * @param n the copied length
  218. *
  219. * @return the address of destination memory
  220. *
  221. */
  222. void *rt_memmove(void *dest, const void *src, rt_ubase_t n)
  223. {
  224. char *tmp = (char *)dest, *s = (char *)src;
  225. if (s < tmp && tmp < s + n)
  226. {
  227. tmp += n;
  228. s += n;
  229. while (n--)
  230. *tmp-- = *s--;
  231. }
  232. else
  233. {
  234. while (n--)
  235. *tmp++ = *s++;
  236. }
  237. return dest;
  238. }
  239. /**
  240. * This function will compare two areas of memory
  241. *
  242. * @param cs one area of memory
  243. * @param ct znother area of memory
  244. * @param count the size of the area
  245. *
  246. * @return the result
  247. */
  248. rt_int32_t rt_memcmp(const void *cs, const void *ct, rt_ubase_t count)
  249. {
  250. const unsigned char *su1, *su2;
  251. int res = 0;
  252. for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
  253. if ((res = *su1 - *su2) != 0)
  254. break;
  255. return res;
  256. }
  257. /**
  258. * This function will return the first occurrence of a string.
  259. *
  260. * @param s1 the source string
  261. * @param s2 the find string
  262. *
  263. * @return the first occurrence of a s2 in s1, or RT_NULL if no found.
  264. */
  265. char *rt_strstr(const char *s1, const char *s2)
  266. {
  267. int l1, l2;
  268. l2 = rt_strlen(s2);
  269. if (!l2)
  270. return (char *)s1;
  271. l1 = rt_strlen(s1);
  272. while (l1 >= l2)
  273. {
  274. l1 --;
  275. if (!rt_memcmp(s1, s2, l2))
  276. return (char *)s1;
  277. s1 ++;
  278. }
  279. return RT_NULL;
  280. }
  281. /**
  282. * This function will compare two strings while ignoring differences in case
  283. *
  284. * @param a the string to be compared
  285. * @param b the string to be compared
  286. *
  287. * @return the result
  288. */
  289. rt_uint32_t rt_strcasecmp(const char *a, const char *b)
  290. {
  291. int ca, cb;
  292. do
  293. {
  294. ca = *a++ & 0xff;
  295. cb = *b++ & 0xff;
  296. if (ca >= 'A' && ca <= 'Z')
  297. ca += 'a' - 'A';
  298. if (cb >= 'A' && cb <= 'Z')
  299. cb += 'a' - 'A';
  300. }
  301. while (ca == cb && ca != '\0');
  302. return ca - cb;
  303. }
  304. /**
  305. * This function will copy string no more than n bytes.
  306. *
  307. * @param dst the string to copy
  308. * @param src the string to be copied
  309. * @param n the maximum copied length
  310. *
  311. * @return the result
  312. */
  313. char *rt_strncpy(char *dst, const char *src, rt_ubase_t n)
  314. {
  315. if (n != 0)
  316. {
  317. char *d = dst;
  318. const char *s = src;
  319. do
  320. {
  321. if ((*d++ = *s++) == 0)
  322. {
  323. /* NUL pad the remaining n-1 bytes */
  324. while (--n != 0)
  325. *d++ = 0;
  326. break;
  327. }
  328. } while (--n != 0);
  329. }
  330. return (dst);
  331. }
  332. /**
  333. * This function will compare two strings with specified maximum length
  334. *
  335. * @param cs the string to be compared
  336. * @param ct the string to be compared
  337. * @param count the maximum compare length
  338. *
  339. * @return the result
  340. */
  341. rt_ubase_t rt_strncmp(const char *cs, const char *ct, rt_ubase_t count)
  342. {
  343. register signed char __res = 0;
  344. while (count)
  345. {
  346. if ((__res = *cs - *ct++) != 0 || !*cs++)
  347. break;
  348. count --;
  349. }
  350. return __res;
  351. }
  352. /**
  353. * This function will compare two strings without specified length
  354. *
  355. * @param cs the string to be compared
  356. * @param ct the string to be compared
  357. *
  358. * @return the result
  359. */
  360. rt_ubase_t rt_strcmp(const char *cs, const char *ct)
  361. {
  362. while (*cs && *cs == *ct)
  363. cs++, ct++;
  364. return (*cs - *ct);
  365. }
  366. /**
  367. * This function will return the length of a string, which terminate will
  368. * null character.
  369. *
  370. * @param s the string
  371. *
  372. * @return the length of string
  373. */
  374. rt_ubase_t rt_strlen(const char *s)
  375. {
  376. const char *sc;
  377. for (sc = s; *sc != '\0'; ++sc) /* nothing */
  378. ;
  379. return sc - s;
  380. }
  381. #ifdef RT_USING_HEAP
  382. /**
  383. * This function will duplicate a string.
  384. *
  385. * @param s the string to be duplicated
  386. *
  387. * @return the duplicated string pointer
  388. */
  389. char *rt_strdup(const char *s)
  390. {
  391. rt_size_t len = rt_strlen(s) + 1;
  392. char *tmp = (char *)rt_malloc(len);
  393. if (!tmp) return RT_NULL;
  394. rt_memcpy(tmp, s, len);
  395. return tmp;
  396. }
  397. #endif
  398. /**
  399. * This function will show the version of rt-thread rtos
  400. */
  401. void rt_show_version(void)
  402. {
  403. rt_kprintf("\n \\ | /\n");
  404. rt_kprintf("- RT - Thread Operating System\n");
  405. rt_kprintf(" / | \\ %d.%d.%d build %s\n", RT_VERSION, RT_SUBVERSION, RT_REVISION, __DATE__);
  406. rt_kprintf(" 2006 - 2011 Copyright by rt-thread team\n");
  407. }
  408. /* private function */
  409. #define isdigit(c) ((unsigned)((c) - '0') < 10)
  410. rt_inline rt_int32_t divide(rt_int32_t *n, rt_int32_t base)
  411. {
  412. rt_int32_t res;
  413. /* optimized for processor which does not support divide instructions. */
  414. if (base == 10)
  415. {
  416. res = ((rt_uint32_t)*n) % 10U;
  417. *n = ((rt_uint32_t)*n) / 10U;
  418. }
  419. else
  420. {
  421. res = ((rt_uint32_t)*n) % 16U;
  422. *n = ((rt_uint32_t)*n) / 16U;
  423. }
  424. return res;
  425. }
  426. rt_inline int skip_atoi(const char **s)
  427. {
  428. register int i=0;
  429. while (isdigit(**s)) i = i*10 + *((*s)++) - '0';
  430. return i;
  431. }
  432. #define ZEROPAD (1 << 0) /* pad with zero */
  433. #define SIGN (1 << 1) /* unsigned/signed long */
  434. #define PLUS (1 << 2) /* show plus */
  435. #define SPACE (1 << 3) /* space if plus */
  436. #define LEFT (1 << 4) /* left justified */
  437. #define SPECIAL (1 << 5) /* 0x */
  438. #define LARGE (1 << 6) /* use 'ABCDEF' instead of 'abcdef' */
  439. #ifdef RT_PRINTF_PRECISION
  440. static char *print_number(char *buf, char *end, long num, int base, int s, int precision, int type)
  441. #else
  442. static char *print_number(char *buf, char *end, long num, int base, int s, int type)
  443. #endif
  444. {
  445. char c, sign;
  446. #ifdef RT_PRINTF_LONGLONG
  447. char tmp[32];
  448. #else
  449. char tmp[16];
  450. #endif
  451. const char *digits;
  452. static const char small_digits[] = "0123456789abcdef";
  453. static const char large_digits[] = "0123456789ABCDEF";
  454. register int i;
  455. register int size;
  456. size = s;
  457. digits = (type & LARGE) ? large_digits : small_digits;
  458. if (type & LEFT) type &= ~ZEROPAD;
  459. c = (type & ZEROPAD) ? '0' : ' ';
  460. /* get sign */
  461. sign = 0;
  462. if (type & SIGN)
  463. {
  464. if (num < 0)
  465. {
  466. sign = '-';
  467. num = -num;
  468. }
  469. else if (type & PLUS) sign = '+';
  470. else if (type & SPACE) sign = ' ';
  471. }
  472. #ifdef RT_PRINTF_SPECIAL
  473. if (type & SPECIAL)
  474. {
  475. if (base == 16) size -= 2;
  476. else if (base == 8) size--;
  477. }
  478. #endif
  479. i = 0;
  480. if (num == 0) tmp[i++]='0';
  481. else
  482. {
  483. while (num != 0) tmp[i++] = digits[divide(&num, base)];
  484. }
  485. #ifdef RT_PRINTF_PRECISION
  486. if (i > precision) precision = i;
  487. size -= precision;
  488. #else
  489. size -= i;
  490. #endif
  491. if (!(type&(ZEROPAD | LEFT)))
  492. {
  493. while (size-->0)
  494. {
  495. if (buf <= end) *buf = ' ';
  496. ++ buf;
  497. }
  498. }
  499. if (sign)
  500. {
  501. if (buf <= end)
  502. {
  503. *buf = sign;
  504. -- size;
  505. }
  506. ++ buf;
  507. }
  508. #ifdef RT_PRINTF_SPECIAL
  509. if (type & SPECIAL)
  510. {
  511. if (base==8)
  512. {
  513. if (buf <= end) *buf = '0';
  514. ++ buf;
  515. }
  516. else if (base == 16)
  517. {
  518. if (buf <= end) *buf = '0';
  519. ++ buf;
  520. if (buf <= end)
  521. {
  522. *buf = type & LARGE? 'X' : 'x';
  523. }
  524. ++ buf;
  525. }
  526. }
  527. #endif
  528. /* no align to the left */
  529. if (!(type & LEFT))
  530. {
  531. while (size-- > 0)
  532. {
  533. if (buf <= end) *buf = c;
  534. ++ buf;
  535. }
  536. }
  537. #ifdef RT_PRINTF_PRECISION
  538. while (i < precision--)
  539. {
  540. if (buf <= end) *buf = '0';
  541. ++ buf;
  542. }
  543. #endif
  544. /* put number in the temporary buffer */
  545. while (i-- > 0)
  546. {
  547. if (buf <= end) *buf = tmp[i];
  548. ++ buf;
  549. }
  550. while (size-- > 0)
  551. {
  552. if (buf <= end) *buf = ' ';
  553. ++ buf;
  554. }
  555. return buf;
  556. }
  557. static rt_int32_t vsnprintf(char *buf, rt_size_t size, const char *fmt, va_list args)
  558. {
  559. #ifdef RT_PRINTF_LONGLONG
  560. unsigned long long num;
  561. #else
  562. rt_uint32_t num;
  563. #endif
  564. int i, len;
  565. char *str, *end, c;
  566. const char *s;
  567. rt_uint8_t base; /* the base of number */
  568. rt_uint8_t flags; /* flags to print number */
  569. rt_uint8_t qualifier; /* 'h', 'l', or 'L' for integer fields */
  570. rt_int32_t field_width; /* width of output field */
  571. #ifdef RT_PRINTF_PRECISION
  572. int precision; /* min. # of digits for integers and max for a string */
  573. #endif
  574. str = buf;
  575. end = buf + size - 1;
  576. /* Make sure end is always >= buf */
  577. if (end < buf)
  578. {
  579. end = ((char *)-1);
  580. size = end - buf;
  581. }
  582. for (; *fmt ; ++fmt)
  583. {
  584. if (*fmt != '%')
  585. {
  586. if (str <= end) *str = *fmt;
  587. ++ str;
  588. continue;
  589. }
  590. /* process flags */
  591. flags = 0;
  592. while (1)
  593. {
  594. /* skips the first '%' also */
  595. ++ fmt;
  596. if (*fmt == '-') flags |= LEFT;
  597. else if (*fmt == '+') flags |= PLUS;
  598. else if (*fmt == ' ') flags |= SPACE;
  599. else if (*fmt == '#') flags |= SPECIAL;
  600. else if (*fmt == '0') flags |= ZEROPAD;
  601. else break;
  602. }
  603. /* get field width */
  604. field_width = -1;
  605. if (isdigit(*fmt)) field_width = skip_atoi(&fmt);
  606. else if (*fmt == '*')
  607. {
  608. ++ fmt;
  609. /* it's the next argument */
  610. field_width = va_arg(args, int);
  611. if (field_width < 0)
  612. {
  613. field_width = -field_width;
  614. flags |= LEFT;
  615. }
  616. }
  617. #ifdef RT_PRINTF_PRECISION
  618. /* get the precision */
  619. precision = -1;
  620. if (*fmt == '.')
  621. {
  622. ++ fmt;
  623. if (isdigit(*fmt)) precision = skip_atoi(&fmt);
  624. else if (*fmt == '*')
  625. {
  626. ++ fmt;
  627. /* it's the next argument */
  628. precision = va_arg(args, int);
  629. }
  630. if (precision < 0) precision = 0;
  631. }
  632. #endif
  633. /* get the conversion qualifier */
  634. qualifier = 0;
  635. if (*fmt == 'h' || *fmt == 'l'
  636. #ifdef RT_PRINTF_LONGLONG
  637. || *fmt == 'L'
  638. #endif
  639. )
  640. {
  641. qualifier = *fmt;
  642. ++ fmt;
  643. #ifdef RT_PRINTF_LONGLONG
  644. if (qualifier == 'l' && *fmt == 'l')
  645. {
  646. qualifier = 'L';
  647. ++ fmt;
  648. }
  649. #endif
  650. }
  651. /* the default base */
  652. base = 10;
  653. switch (*fmt)
  654. {
  655. case 'c':
  656. if (!(flags & LEFT))
  657. {
  658. while (--field_width > 0)
  659. {
  660. if (str <= end) *str = ' ';
  661. ++ str;
  662. }
  663. }
  664. /* get character */
  665. c = (rt_uint8_t)va_arg(args, int);
  666. if (str <= end) *str = c;
  667. ++ str;
  668. /* put width */
  669. while (--field_width > 0)
  670. {
  671. if (str <= end) *str = ' ';
  672. ++ str;
  673. }
  674. continue;
  675. case 's':
  676. s = va_arg(args, char *);
  677. if (!s) s = "(NULL)";
  678. len = rt_strlen(s);
  679. #ifdef RT_PRINTF_PRECISION
  680. if (precision > 0 && len > precision) len = precision;
  681. #endif
  682. if (!(flags & LEFT))
  683. {
  684. while (len < field_width--)
  685. {
  686. if (str <= end) *str = ' ';
  687. ++ str;
  688. }
  689. }
  690. for (i = 0; i < len; ++i)
  691. {
  692. if (str <= end) *str = *s;
  693. ++ str;
  694. ++ s;
  695. }
  696. while (len < field_width--)
  697. {
  698. if (str <= end) *str = ' ';
  699. ++ str;
  700. }
  701. continue;
  702. case 'p':
  703. if (field_width == -1)
  704. {
  705. field_width = sizeof(void *) << 1;
  706. flags |= ZEROPAD;
  707. }
  708. #ifdef RT_PRINTF_PRECISION
  709. str = print_number(str, end,
  710. (long)va_arg(args, void *),
  711. 16, field_width, precision, flags);
  712. #else
  713. str = print_number(str, end,
  714. (long)va_arg(args, void *),
  715. 16, field_width, flags);
  716. #endif
  717. continue;
  718. case '%':
  719. if (str <= end) *str = '%';
  720. ++ str;
  721. continue;
  722. /* integer number formats - set up the flags and "break" */
  723. case 'o':
  724. base = 8;
  725. break;
  726. case 'X':
  727. flags |= LARGE;
  728. case 'x':
  729. base = 16;
  730. break;
  731. case 'd':
  732. case 'i':
  733. flags |= SIGN;
  734. case 'u':
  735. break;
  736. default:
  737. if (str <= end) *str = '%';
  738. ++ str;
  739. if (*fmt)
  740. {
  741. if (str <= end) *str = *fmt;
  742. ++ str;
  743. }
  744. else
  745. {
  746. -- fmt;
  747. }
  748. continue;
  749. }
  750. #ifdef RT_PRINTF_LONGLONG
  751. if (qualifier == 'L') num = va_arg(args, long long);
  752. else if (qualifier == 'l')
  753. #else
  754. if (qualifier == 'l')
  755. #endif
  756. {
  757. num = va_arg(args, rt_uint32_t);
  758. if (flags & SIGN) num = (rt_int32_t)num;
  759. }
  760. else if (qualifier == 'h')
  761. {
  762. num = (rt_uint16_t)va_arg(args, rt_int32_t);
  763. if (flags & SIGN) num = (rt_int16_t)num;
  764. }
  765. else
  766. {
  767. num = va_arg(args, rt_uint32_t);
  768. if (flags & SIGN) num = (rt_int32_t)num;
  769. }
  770. #ifdef RT_PRINTF_PRECISION
  771. str = print_number(str, end, num, base, field_width, precision, flags);
  772. #else
  773. str = print_number(str, end, num, base, field_width, flags);
  774. #endif
  775. }
  776. if (str <= end) *str = '\0';
  777. else *end = '\0';
  778. /* the trailing null byte doesn't count towards the total
  779. * ++str;
  780. */
  781. return str-buf;
  782. }
  783. /**
  784. * This function will fill a formatted string to buffer
  785. *
  786. * @param buf the buffer to save formatted string
  787. * @param size the size of buffer
  788. * @param fmt the format
  789. */
  790. rt_int32_t rt_snprintf(char *buf, rt_size_t size, const char *fmt, ...)
  791. {
  792. rt_int32_t n;
  793. va_list args;
  794. va_start(args, fmt);
  795. n = vsnprintf(buf, size, fmt, args);
  796. va_end(args);
  797. return n;
  798. }
  799. /**
  800. * This function will fill a formatted string to buffer
  801. *
  802. * @param buf the buffer to save formatted string
  803. * @param arg_ptr the arg_ptr
  804. * @param format the format
  805. */
  806. rt_int32_t rt_vsprintf(char *buf, const char *format, va_list arg_ptr)
  807. {
  808. return vsnprintf(buf, (rt_size_t) -1, format, arg_ptr);
  809. }
  810. /**
  811. * This function will fill a formatted string to buffer
  812. *
  813. * @param buf the buffer to save formatted string
  814. * @param format the format
  815. */
  816. rt_int32_t rt_sprintf(char *buf, const char *format, ...)
  817. {
  818. rt_int32_t n;
  819. va_list arg_ptr;
  820. va_start(arg_ptr, format);
  821. n = rt_vsprintf(buf ,format, arg_ptr);
  822. va_end(arg_ptr);
  823. return n;
  824. }
  825. #ifdef RT_USING_CONSOLE
  826. #ifdef RT_USING_DEVICE
  827. /**
  828. * This function returns the device using in console.
  829. *
  830. * @return the device using in console or RT_NULL
  831. */
  832. rt_device_t rt_console_get_device(void)
  833. {
  834. return _console_device;
  835. }
  836. /**
  837. * This function will set a device as console device.
  838. * After set a device to console, all output of rt_kprintf will be
  839. * redirected to this new device.
  840. *
  841. * @param name the name of new console device
  842. *
  843. * @return the old console device handler
  844. */
  845. rt_device_t rt_console_set_device(const char *name)
  846. {
  847. rt_device_t new, old;
  848. /* save old device */
  849. old = _console_device;
  850. /* find new console device */
  851. new = rt_device_find(name);
  852. if (new != RT_NULL)
  853. {
  854. if (_console_device != RT_NULL)
  855. {
  856. /* close old console device */
  857. rt_device_close(_console_device);
  858. }
  859. /* set new console device */
  860. _console_device = new;
  861. rt_device_open(_console_device, RT_DEVICE_OFLAG_RDWR);
  862. }
  863. return old;
  864. }
  865. #endif
  866. #if defined(__GNUC__)
  867. void rt_hw_console_output(const char *str) __attribute__((weak));
  868. void rt_hw_console_output(const char *str)
  869. #elif defined(__CC_ARM)
  870. __weak void rt_hw_console_output(const char *str)
  871. #elif defined(__IAR_SYSTEMS_ICC__)
  872. #if __VER__ > 540
  873. __weak
  874. #endif
  875. void rt_hw_console_output(const char *str)
  876. #endif
  877. {
  878. /* empty console output */
  879. }
  880. /**
  881. * This function will print a formatted string on system console
  882. *
  883. * @param fmt the format
  884. */
  885. void rt_kprintf(const char *fmt, ...)
  886. {
  887. va_list args;
  888. rt_size_t length;
  889. static char rt_log_buf[RT_CONSOLEBUF_SIZE];
  890. va_start(args, fmt);
  891. length = vsnprintf(rt_log_buf, sizeof(rt_log_buf), fmt, args);
  892. #ifdef RT_USING_DEVICE
  893. if (_console_device == RT_NULL)
  894. {
  895. rt_hw_console_output(rt_log_buf);
  896. }
  897. else
  898. {
  899. rt_device_write(_console_device, 0, rt_log_buf, length);
  900. }
  901. #else
  902. rt_hw_console_output(rt_log_buf);
  903. #endif
  904. va_end(args);
  905. }
  906. #else
  907. void rt_kprintf(const char *fmt, ...)
  908. {
  909. }
  910. #endif
  911. #ifdef RT_USING_HEAP
  912. /**
  913. * This function allocates a memory block, which address is aligned to the
  914. * specified alignment size.
  915. *
  916. * @param size the allocated memory block size
  917. * @param align the alignment size
  918. *
  919. * @return the allocated memory block on successful, otherwise returns RT_NULL
  920. */
  921. void* rt_malloc_align(rt_size_t size, rt_size_t align)
  922. {
  923. void *align_ptr;
  924. void *ptr;
  925. rt_size_t align_size;
  926. /* align the alignment size to 4 byte */
  927. align = ((align + 0x03) & ~0x03);
  928. /* get total aligned size */
  929. align_size = ((size + 0x03) & ~0x03) + align;
  930. /* allocate memory block from heap */
  931. ptr = rt_malloc(align_size);
  932. if (ptr != RT_NULL)
  933. {
  934. if (((rt_uint32_t)ptr & (align - 1)) == 0) /* the allocated memory block is aligned */
  935. {
  936. align_ptr = (void*) ((rt_uint32_t)ptr + align);
  937. }
  938. else
  939. {
  940. align_ptr = (void*) (((rt_uint32_t)ptr + (align - 1)) & ~(align - 1));
  941. }
  942. /* set the pointer before alignment pointer to the real pointer */
  943. *((rt_uint32_t*)((rt_uint32_t)align_ptr - sizeof(void*))) = (rt_uint32_t)ptr;
  944. ptr = align_ptr;
  945. }
  946. return ptr;
  947. }
  948. /**
  949. * This function release the memory block, which is allocated by rt_malloc_align
  950. * function and address is aligned.
  951. *
  952. * @param ptr the memory block pointer
  953. */
  954. void rt_free_align(void* ptr)
  955. {
  956. void* real_ptr;
  957. real_ptr = (void*)*(rt_uint32_t*)((rt_uint32_t)ptr - sizeof(void*));
  958. rt_free(real_ptr);
  959. }
  960. #endif
  961. #if !defined (RT_USING_NEWLIB) && defined (RT_USING_MINILIBC) && defined (__GNUC__)
  962. #include <sys/types.h>
  963. void *memcpy(void *dest, const void *src, size_t n) __attribute__((weak, alias("rt_memcpy")));
  964. void *memset(void *s, int c, size_t n) __attribute__((weak, alias("rt_memset")));
  965. void *memmove(void *dest, const void *src, size_t n) __attribute__((weak, alias("rt_memmove")));
  966. int memcmp(const void *s1, const void *s2, size_t n) __attribute__((weak, alias("rt_memcmp")));
  967. size_t strlen(const char *s) __attribute__((weak, alias("rt_strlen")));
  968. char *strstr(const char *s1,const char *s2) __attribute__((weak, alias("rt_strstr")));
  969. int strcasecmp(const char *a, const char *b) __attribute__((weak, alias("rt_strcasecmp")));
  970. char *strncpy(char *dest, const char *src, size_t n) __attribute__((weak, alias("rt_strncpy")));
  971. int strncmp(const char *cs, const char *ct, size_t count) __attribute__((weak, alias("rt_strncmp")));
  972. #ifdef RT_USING_HEAP
  973. char *strdup(const char *s) __attribute__((weak, alias("rt_strdup")));
  974. #endif
  975. int sprintf(char *buf, const char *format, ...) __attribute__((weak, alias("rt_sprintf")));
  976. int snprintf(char *buf, rt_size_t size, const char *fmt, ...) __attribute__((weak, alias("rt_snprintf")));
  977. int vsprintf(char *buf, const char *format, va_list arg_ptr) __attribute__((weak, alias("rt_vsprintf")));
  978. #endif
  979. /*@}*/