console.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * console.c
  3. *
  4. * printf-style interface to USART1.
  5. *
  6. * Written & released by Keir Fraser <keir.xen@gmail.com>
  7. *
  8. * This is free and unencumbered software released into the public domain.
  9. * See the file COPYING for more details, or visit <http://unlicense.org>.
  10. */
  11. #ifndef BAUD
  12. #define BAUD 3000000 /* 3Mbaud */
  13. #endif
  14. #if MCU == STM32F1
  15. #define PCLK SYSCLK
  16. #elif MCU == STM32F7
  17. #define PCLK (APB2_MHZ * 1000000)
  18. #elif MCU == AT32F4
  19. #define PCLK SYSCLK
  20. #endif
  21. #define USART1_IRQ 37
  22. static void ser_putc(uint8_t c)
  23. {
  24. #if MCU == STM32F1 || MCU == AT32F4
  25. while (!(usart1->sr & USART_SR_TXE))
  26. cpu_relax();
  27. usart1->dr = c;
  28. #elif MCU == STM32F7
  29. while (!(usart1->isr & USART_ISR_TXE))
  30. cpu_relax();
  31. usart1->tdr = c;
  32. #endif
  33. }
  34. int vprintk(const char *format, va_list ap)
  35. {
  36. static char str[128];
  37. unsigned int flags;
  38. char *p, c;
  39. int n;
  40. IRQ_global_save(flags);
  41. n = vsnprintf(str, sizeof(str), format, ap);
  42. p = str;
  43. while ((c = *p++) != '\0') {
  44. switch (c) {
  45. case '\r': /* CR: ignore as we generate our own CR/LF */
  46. break;
  47. case '\n': /* LF: convert to CR/LF (usual terminal behaviour) */
  48. ser_putc('\r');
  49. /* fall through */
  50. default:
  51. ser_putc(c);
  52. break;
  53. }
  54. }
  55. IRQ_global_restore(flags);
  56. return n;
  57. }
  58. int printk(const char *format, ...)
  59. {
  60. va_list ap;
  61. int n;
  62. va_start(ap, format);
  63. n = vprintk(format, ap);
  64. va_end(ap);
  65. return n;
  66. }
  67. void console_init(void)
  68. {
  69. /* Turn on the clocks. */
  70. rcc->apb2enr |= RCC_APB2ENR_USART1EN;
  71. peripheral_clock_delay();
  72. /* Enable TX pin (PA9) for USART output, RX pin (PA10) as input. */
  73. #if MCU == STM32F1 || MCU == AT32F4
  74. gpio_configure_pin(gpioa, 9, AFO_pushpull(_10MHz));
  75. gpio_configure_pin(gpioa, 10, GPI_pull_up);
  76. #elif MCU == STM32F7
  77. gpio_set_af(gpioa, 9, 7);
  78. gpio_set_af(gpioa, 10, 7);
  79. gpio_configure_pin(gpioa, 9, AFO_pushpull(IOSPD_MED));
  80. gpio_configure_pin(gpioa, 10, AFI(PUPD_up));
  81. #endif
  82. /* BAUD, 8n1. */
  83. usart1->brr = PCLK / BAUD;
  84. usart1->cr1 = (USART_CR1_UE | USART_CR1_TE | USART_CR1_RE);
  85. }
  86. /* Debug helper: if we get stuck somewhere, calling this beforehand will cause
  87. * any serial input to cause a crash dump of the stuck context. */
  88. void console_crash_on_input(void)
  89. {
  90. #if MCU == STM32F1 || MCU == AT32F4
  91. (void)usart1->dr; /* clear UART_SR_RXNE */
  92. #elif MCU == STM32F7
  93. usart1->rqr = USART_RQR_RXFRQ; /* clear ISR_RXNE */
  94. usart1->icr = USART_ICR_ORECF; /* clear ISR_ORE */
  95. #endif
  96. usart1->cr1 |= USART_CR1_RXNEIE;
  97. IRQx_set_prio(USART1_IRQ, RESET_IRQ_PRI);
  98. IRQx_enable(USART1_IRQ);
  99. }
  100. /*
  101. * Local variables:
  102. * mode: C
  103. * c-file-style: "Linux"
  104. * c-basic-offset: 4
  105. * tab-width: 4
  106. * indent-tabs-mode: nil
  107. * End:
  108. */