Primary Bootloader (before u-boot) in sysmoBTSv2
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

262 lines
5.6 KiB

  1. /*
  2. * uart.c - UART Rx and Tx functions
  3. *
  4. * Copyright (C) 2008 Hugo Villeneuve <hugo@hugovil.com>
  5. *
  6. * Based on TI DaVinci Flash and Boot Utilities, original copyright follows:
  7. * Copyright 2008 Texas Instruments, Inc. <www.ti.com>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation; either version 2 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
  22. */
  23. #include "common.h"
  24. #include "davinci.h"
  25. #include "uart.h"
  26. #include "util.h"
  27. #include "crc.h"
  28. /* Symbol from linker script */
  29. extern uint32_t __DDR_FREE; /* Start of free DDR memory region. */
  30. /* Receive data from UART */
  31. static int
  32. uart_recv_bytes(size_t count, uint8_t *dest)
  33. {
  34. uint32_t i, status = 0;
  35. uint32_t timerStatus = 1;
  36. for (i = 0; i < count; i++) {
  37. /* Enable timer one time */
  38. timer0_start(SYSTEM_CLK_HZ * 5);
  39. do {
  40. status = (UART0->LSR)&(0x01);
  41. timerStatus = timer0_status();
  42. } while (!status && timerStatus);
  43. if (timerStatus == 0) {
  44. host_msg("UART_TIMEOUT");
  45. return E_TIMEOUT;
  46. }
  47. /* Receive byte */
  48. dest[i] = (UART0->RBR) & 0xFF;
  49. /* Check status for errors */
  50. if ((UART0->LSR & 0x1C) != 0) {
  51. host_msg("UART_RXERR");
  52. return E_FAIL;
  53. }
  54. }
  55. return E_PASS;
  56. }
  57. /* Send bytes with optional null terminating character. */
  58. static void
  59. uart_send_bytes(char *string)
  60. {
  61. uint32_t status = 0;
  62. int32_t i, count;
  63. uint32_t timerStatus = 1;
  64. count = strlen(string);
  65. for (i = 0; i < count; i++) {
  66. /* Enable Timer one time */
  67. timer0_start(SYSTEM_CLK_HZ * 5);
  68. do {
  69. status = (UART0->LSR)&(0x20);
  70. timerStatus = timer0_status();
  71. } while (!status && timerStatus);
  72. if (timerStatus == 0)
  73. return; /* E_TIMEOUT */
  74. /* Send byte */
  75. (UART0->THR) = string[i];
  76. }
  77. }
  78. /* Check if the given string is received via UART */
  79. static int
  80. uart_check_string(char *string, int include_null)
  81. {
  82. int i, count;
  83. count = strlen(string);
  84. if (include_null != false)
  85. count++;
  86. for (i = 0; i < count; i++) {
  87. uint8_t recv;
  88. /* Get one byte */
  89. if (uart_recv_bytes(1, &recv) != E_PASS)
  90. return E_FAIL;
  91. if (recv != string[i])
  92. return E_FAIL;
  93. }
  94. return E_PASS;
  95. }
  96. /* Receive a uint32 value in HEX form (8 bytes) */
  97. static int
  98. uart_recv_hex_uint32(uint32_t *data)
  99. {
  100. int k;
  101. uint8_t recv[8];
  102. uint32_t temp;
  103. int shift;
  104. const int num_ascii_char = 8;
  105. /* Get 8 bytes from UART */
  106. if (uart_recv_bytes(num_ascii_char, recv) != E_PASS)
  107. return E_FAIL;
  108. *data = 0;
  109. /* Converting ascii to Hex */
  110. for (k = 0, shift = 28; k < num_ascii_char; k++, shift -= 4) {
  111. temp = recv[k] - 48;
  112. if (temp > 22) /* Lower case a,b,c,d,e,f */
  113. temp -= 39;
  114. else if (temp > 9) /* Upper case A,B,C,D,E,F */
  115. temp -= 7;
  116. *data |= temp << shift;
  117. }
  118. return E_PASS;
  119. }
  120. /* Send line feed (\n) to UART. */
  121. void
  122. uart_send_lf(void)
  123. {
  124. uart_send_bytes("\r\n");
  125. }
  126. /* Send a string to UART, without line feed. */
  127. void
  128. uart_send_str(char *string)
  129. {
  130. uart_send_bytes(string);
  131. }
  132. /* Send a string to UART, with line feed. */
  133. void
  134. uart_send_str_lf(char *string)
  135. {
  136. uart_send_bytes(string);
  137. uart_send_lf();
  138. }
  139. void
  140. uart_send_hexnum(uint32_t value, int digits)
  141. {
  142. char seq[9];
  143. uint32_t i, shift;
  144. uint8_t temp;
  145. for (i = 0; i < digits; i++) {
  146. shift = ((digits - 1) - i) * 4;
  147. temp = (value >> shift) & 0x0F;
  148. if (temp > 9)
  149. temp += 7;
  150. seq[i] = temp + 48;
  151. }
  152. seq[digits] = 0;
  153. uart_send_str("0x");
  154. uart_send_bytes(seq);
  155. }
  156. int
  157. uart_get_cmd(uint32_t *boot_cmd)
  158. {
  159. if (uart_check_string(" CMD", true) != E_PASS)
  160. return E_FAIL;
  161. if (uart_recv_hex_uint32(boot_cmd) != E_PASS)
  162. return E_FAIL;
  163. return E_PASS;
  164. }
  165. uint32_t
  166. uart_get_prog(struct uart_ack_header_t *uart_ack_header)
  167. {
  168. uint32_t error;
  169. uint32_t recv_crc, computed_crc;
  170. uint8_t *ddr_free = (uint8_t *) &__DDR_FREE;
  171. uart_ack_header->recv_buffer = ddr_free;
  172. /* Send ACK command */
  173. error = uart_check_string(" ACK", true);
  174. if (error != E_PASS)
  175. return E_FAIL;
  176. /* Get the ACK header elements */
  177. error = uart_recv_hex_uint32(&uart_ack_header->magic);
  178. error |= uart_recv_hex_uint32(&recv_crc);
  179. error |= uart_recv_hex_uint32(&uart_ack_header->size);
  180. error |= uart_recv_hex_uint32(&uart_ack_header->entry_point);
  181. error |= uart_check_string("0000", false);
  182. if (error != E_PASS)
  183. return E_FAIL;
  184. uart_send_str("Magic = ");
  185. uart_send_hexnum(uart_ack_header->magic, 8);
  186. uart_send_str(", CRC = ");
  187. uart_send_hexnum(recv_crc, 8);
  188. uart_send_str(", Entry = ");
  189. uart_send_hexnum(uart_ack_header->entry_point, 8);
  190. uart_send_str(", Size = ");
  191. uart_send_hexnum(uart_ack_header->size, 8);
  192. uart_send_lf();
  193. /* Verify that the file size is appropriate */
  194. if ((uart_ack_header->size == 0) ||
  195. (uart_ack_header->size > MAX_IMAGE_SIZE)) {
  196. host_msg("BADCNT");
  197. return E_FAIL;
  198. }
  199. /* Send BEGIN command */
  200. host_msg("BEGIN");
  201. /* Receive the data over UART */
  202. if (uart_recv_bytes(uart_ack_header->size,
  203. uart_ack_header->recv_buffer)
  204. != E_PASS) {
  205. return E_FAIL;
  206. }
  207. /* Return first DONE when all data arrives */
  208. host_msg("DONE");
  209. computed_crc = crc32_dv_compute(uart_ack_header->recv_buffer,
  210. uart_ack_header->size);
  211. if (computed_crc != recv_crc) {
  212. host_msg("BADCRC");
  213. return E_FAIL;
  214. }
  215. /* Return DONE when all data is validated */
  216. host_msg("DONE");
  217. return E_PASS;
  218. }