util.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /*
  2. * Utility functions
  3. *
  4. * Copyright (C) 2009-2011 Michael Buesch <m@bues.ch>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * version 2 as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. */
  15. #include "util.h"
  16. #include "main.h"
  17. #include "debug.h"
  18. #include "lcd.h"
  19. #include "uart.h"
  20. #include <avr/io.h>
  21. #include <avr/wdt.h>
  22. void long_delay_ms(uint16_t ms)
  23. {
  24. while (ms) {
  25. _delay_ms(50);
  26. wdt_reset();
  27. ms = (ms >= 50) ? ms - 50 : 0;
  28. }
  29. }
  30. char hexdigit_to_ascii(uint8_t digit)
  31. {
  32. /* Convert a hexadecimal digit (0-F) to an ASCII character */
  33. if (digit >= 0xAu)
  34. digit = (uint8_t)(digit + 0x41u - 0xAu);
  35. else
  36. digit = (uint8_t)(digit + 0x30u);
  37. return (char)digit;
  38. }
  39. #ifndef BOOTLOADER
  40. void do_panic(const char PROGPTR *msg)
  41. {
  42. irq_disable();
  43. debug_printf("*** PANIC :( ***\n");
  44. _debug_printf(msg);
  45. debug_printf("\n");
  46. lcd_clear_buffer();
  47. lcd_printf("*** PANIC :( ***\n");
  48. lcd_commit();
  49. long_delay_ms(10000);
  50. reboot();
  51. }
  52. void reboot(void)
  53. {
  54. irq_disable();
  55. debug_printf("*** REBOOTING ***\n");
  56. wdt_enable(WDTO_15MS);
  57. while (1);
  58. }
  59. uint8_t ffs16(uint16_t value)
  60. {
  61. uint16_t mask;
  62. uint8_t count;
  63. for (mask = 1, count = 1; mask; mask <<= 1, count++) {
  64. if (value & mask)
  65. return count;
  66. }
  67. return 0;
  68. }
  69. #endif /* BOOTLOADER */
  70. #ifdef STACKCHECK
  71. /* Stack usage threshold, in percent of SRAM */
  72. #define STACKTHRES 25
  73. #define RAMSIZE (RAMEND - RAMSTART)
  74. #define STACKLIM (RAMEND - ((uint32_t)RAMSIZE * STACKTHRES / 100))
  75. static noinstrument void stack_check(void *this_fn,
  76. void *call_site)
  77. {
  78. static bool had_overflow = 0;
  79. uint16_t sp = SP;
  80. if (sp >= STACKLIM)
  81. return;
  82. if (had_overflow)
  83. return;
  84. had_overflow = 1;
  85. mb();
  86. uart_putstr("WARNING: Stack size limit reached in 0x");
  87. uart_puthex((uint16_t)this_fn >> 8);
  88. uart_puthex((uint16_t)this_fn);
  89. uart_putstr(" (called from 0x");
  90. uart_puthex((uint16_t)call_site >> 8);
  91. uart_puthex((uint16_t)call_site);
  92. uart_putstr(")\n");
  93. }
  94. noinstrument noinline void __cyg_profile_func_enter(void *this_fn,
  95. void *call_site)
  96. {
  97. stack_check(this_fn, call_site);
  98. }
  99. noinstrument noinline void __cyg_profile_func_exit(void *this_fn,
  100. void *call_site)
  101. {
  102. }
  103. #endif /* STACKCHECK */