board.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. * 2011-01-13 weety first version
  9. */
  10. #include <rtthread.h>
  11. #include <rthw.h>
  12. #include "board.h"
  13. #include <mmu.h>
  14. /**
  15. * @addtogroup at91sam9g45
  16. */
  17. /*@{*/
  18. #if defined(__CC_ARM)
  19. extern int Image$$ER_ZI$$ZI$$Limit;
  20. #define HEAP_BEGIN (&Image$$ER_ZI$$ZI$$Limit)
  21. #elif (defined (__GNUC__))
  22. extern unsigned char __bss_end;
  23. #define HEAP_BEGIN (&__bss_end)
  24. #elif (defined (__ICCARM__))
  25. #pragma section=".noinit"
  26. #define HEAP_BEGIN (__section_end(".noinit"))
  27. #endif
  28. #define HEAP_END (((rt_uint32_t)HEAP_BEGIN & 0xF0000000) + 0x04000000)
  29. extern void rt_hw_interrupt_init(void);
  30. extern void rt_hw_clock_init(void);
  31. extern void rt_hw_get_clock(void);
  32. extern void rt_hw_set_dividor(rt_uint8_t hdivn, rt_uint8_t pdivn);
  33. extern void rt_hw_set_clock(rt_uint8_t sdiv, rt_uint8_t pdiv, rt_uint8_t mdiv);
  34. extern void rt_dbgu_isr(void);
  35. #define SAM9G45_BLOCK_SIZE 0x10000000 // 256M
  36. #define MMU_SECTION_SIZE 0x100000 // 1M
  37. #define PERIPHERALS_ADDR // 1M
  38. #define SECTION_END(sa) ((sa) + MMU_SECTION_SIZE - 1) // sa: start address
  39. #define BLOCK_END(ba) ((ba) + SAM9G45_BLOCK_SIZE - 1) // ba: block address
  40. static struct mem_desc at91_mem_desc[] = { /* FIXME, hornby, to confirm MMU and memory */
  41. { 0x00000000, 0xFFFFFFFF , 0x00000000, RW_NCNB }, /* None cached for 4G memory */
  42. //{ 0x00000000, SECTION_END(0x00000000), 0x00000000, RW_CNB }, /* TLB for ITCM, ITCM map to address zero, 32KB */
  43. //{ 0x00200000, SECTION_END(0x00200000), 0x00200000, RW_CNB }, /* TLB for DTCM, 32KB */
  44. //{ 0x00300000, SECTION_END(0x00300000), 0x00300000, RW_CNB }, /* TLB for internal RAM, 64KB, we use it as global variable area */
  45. //{ 0x00600000, SECTION_END(0x00600000), 0x00600000, RW_NCNB }, /* TLB for UDPHS(DMA) */
  46. //{ 0x00700000, SECTION_END(0x00700000), 0x00700000, RW_NCNB }, /* TLB for UHP OHCI */
  47. //{ 0x00800000, SECTION_END(0x00800000), 0x00800000, RW_NCNB }, /* TLB for UHP EHCI */
  48. //{ 0x30000000, 0x30000000+0x00100000-1, 0x30000000, RW_CB }, /* 1M external SRAM for program code and stack */
  49. //{ 0x40000000, BLOCK_END(0x40000000), 0x40000000, RW_NCNB }, /* 256M for nand-flash controller */
  50. //{ 0x60000000, BLOCK_END(0x60000000), 0x60000000, RW_NCNB }, /* 256M for FPGA */
  51. //{ 0x70000000, 0x70000000+0x08000000-1, 0x70000000, RW_NCNB }, /* 128M for main DDR-SDRAM for print data */
  52. { 0x00000000, SECTION_END(0x00000000), 0x70000000, RW_CB }, /* isr */
  53. { 0x70000000, 0x70000000+0x08000000-1, 0x70000000, RW_CB }, /* 128M for main DDR-SDRAM for print data */
  54. //{ 0xFFF00000, SECTION_END(0xFFF00000), 0xFFF00000, RW_NCNB }, /* Internal Peripherals, 1MB */
  55. };
  56. #define PIT_CPIV(x) ((x) & AT91C_PITC_CPIV)
  57. #define PIT_PICNT(x) (((x) & AT91C_PITC_PICNT) >> 20)
  58. static rt_uint32_t pit_cycle; /* write-once */
  59. static rt_uint32_t pit_cnt; /* access only w/system irq blocked */
  60. /**
  61. * This function will handle rtos timer
  62. */
  63. void rt_timer_handler(int vector, void *param)
  64. {
  65. #ifdef RT_USING_DBGU
  66. if (readl(AT91C_DBGU_CSR) & AT91C_US_RXRDY)
  67. {
  68. rt_dbgu_isr();
  69. }
  70. #endif
  71. if (readl(AT91C_PITC_PISR) & AT91C_PITC_PITS)
  72. {
  73. unsigned nr_ticks;
  74. /* Get number of ticks performed before irq, and ack it */
  75. nr_ticks = PIT_PICNT(readl(AT91C_PITC_PIVR));
  76. while (nr_ticks--)
  77. rt_tick_increase();
  78. }
  79. }
  80. static void at91sam9g45_pit_reset(void)
  81. {
  82. /* Disable timer and irqs */
  83. AT91C_BASE_PITC->PITC_PIMR = 0;
  84. /* Clear any pending interrupts, wait for PIT to stop counting */
  85. while (PIT_CPIV(readl(AT91C_PITC_PIVR)) != 0)
  86. ;
  87. /* Start PIT but don't enable IRQ */
  88. //AT91C_BASE_PITC->PITC_PIMR = (pit_cycle - 1) | AT91C_PITC_PITEN;
  89. pit_cnt += pit_cycle * PIT_PICNT(readl(AT91C_PITC_PIVR));
  90. AT91C_BASE_PITC->PITC_PIMR =
  91. (pit_cycle - 1) | AT91C_PITC_PITEN | AT91C_PITC_PITIEN;
  92. rt_kprintf("PIT_MR=0x%08x\n", readl(AT91C_PITC_PIMR));
  93. }
  94. /*
  95. * Set up both clocksource and clockevent support.
  96. */
  97. static void at91sam9g45_pit_init(void)
  98. {
  99. rt_uint32_t pit_rate;
  100. //rt_uint32_t bits;
  101. /*
  102. * Use our actual MCK to figure out how many MCK/16 ticks per
  103. * 1/HZ period (instead of a compile-time constant LATCH).
  104. */
  105. pit_rate = clk_get_rate(clk_get("mck")) / 16;
  106. rt_kprintf("pit_rate=%dHZ\n", pit_rate);
  107. pit_cycle = (pit_rate + RT_TICK_PER_SECOND/2) / RT_TICK_PER_SECOND;
  108. /* Initialize and enable the timer */
  109. at91sam9g45_pit_reset();
  110. }
  111. /**
  112. * This function will init pit for system ticks
  113. */
  114. void rt_hw_timer_init()
  115. {
  116. at91sam9g45_pit_init();
  117. /* install interrupt handler */
  118. rt_hw_interrupt_install(AT91C_ID_SYS, rt_timer_handler,
  119. RT_NULL, "system");
  120. rt_hw_interrupt_umask(AT91C_ID_SYS);
  121. }
  122. void at91_tc1_init()
  123. {
  124. AT91C_BASE_PMC->PMC_PCER = 1<<AT91C_ID_TC;
  125. writel(AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_NONE | AT91C_TCB_TC2XC2S_NONE, AT91C_TCB0_BMR);
  126. writel(AT91C_TC_CLKDIS, AT91C_TC0_CCR);
  127. writel(AT91C_TC_CLKS_TIMER_DIV4_CLOCK, AT91C_TC0_CMR);
  128. writel(0xffff, AT91C_TC0_CV);
  129. }
  130. #define BPS 115200 /* serial console port baudrate */
  131. static void at91_usart_putc(char c)
  132. {
  133. while (!(AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXRDY))
  134. ;
  135. AT91C_BASE_DBGU->DBGU_THR = c;
  136. }
  137. /**
  138. * This function is used to display a string on console, normally, it's
  139. * invoked by rt_kprintf
  140. *
  141. * @param str the displayed string
  142. */
  143. void rt_hw_console_output(const char* str)
  144. {
  145. while (*str)
  146. {
  147. if (*str=='\n')
  148. {
  149. at91_usart_putc('\r');
  150. }
  151. at91_usart_putc(*str++);
  152. }
  153. }
  154. static void rt_hw_console_init(void)
  155. {
  156. int div;
  157. int mode = 0;
  158. AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RSTTX | AT91C_US_RSTRX |
  159. AT91C_US_RXDIS | AT91C_US_TXDIS;
  160. mode |= AT91C_US_USMODE_NORMAL | AT91C_US_CLKS_CLOCK |
  161. AT91C_US_CHMODE_NORMAL;
  162. mode |= AT91C_US_CHRL_8_BITS;
  163. mode |= AT91C_US_NBSTOP_1_BIT;
  164. mode |= AT91C_US_PAR_NONE;
  165. AT91C_BASE_DBGU->DBGU_MR = mode;
  166. div = (clk_get_rate(clk_get("mck")) / 16 + BPS/2) / BPS;
  167. AT91C_BASE_DBGU->DBGU_BRGR = div;
  168. AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RXEN | AT91C_US_TXEN;
  169. }
  170. /**
  171. * This function will init at91sam9g45 board
  172. */
  173. void rt_hw_board_init()
  174. {
  175. /* initialize the system clock */
  176. rt_hw_clock_init();
  177. /* initialize console */
  178. rt_hw_console_init();
  179. /* initialize mmu */
  180. rt_hw_mmu_init(at91_mem_desc, sizeof(at91_mem_desc)/sizeof(at91_mem_desc[0]));
  181. /* initialize hardware interrupt */
  182. rt_hw_interrupt_init();
  183. /* initialize early device */
  184. #ifdef RT_USING_COMPONENTS_INIT
  185. rt_components_board_init();
  186. #endif
  187. #if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
  188. rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
  189. #endif
  190. /* initialize timer0 */
  191. rt_hw_timer_init();
  192. /* initialize board */
  193. #ifdef RT_USING_HEAP
  194. rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
  195. #endif
  196. }
  197. /*@}*/