system_ab32vgx.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. /*
  2. * Copyright (c) 2020-2020, BLUETRUM Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include "ab32vgx.h"
  7. #ifndef ALIGN
  8. #define ALIGN(n) __attribute__((aligned(n)))
  9. #endif // ALIGN
  10. typedef struct _sys_t {
  11. uint8_t cnt_1us; //delay 1us cnt
  12. uint8_t main_start; //Main是否已启动
  13. uint8_t clk_sel; //system clock select
  14. uint8_t sys_clk;
  15. // uint8_t aupll_type; //区分AUPLL的频率
  16. uint16_t rand_seed;
  17. uint32_t uart0baud; //UART0BAUD
  18. } sys_t;
  19. const uint8_t sysclk_sel_tbl[] = {
  20. OSCDIV_2M, //SYS_2M
  21. PLL0DIV_12M, //SYS_12M
  22. OSCDIV_13M, //SYS_13M
  23. PLL0DIV_24M, //SYS_24M
  24. OSCDIV_26M, //SYS_26M
  25. PLL0DIV_30M, //SYS_30M
  26. PLL0DIV_48M, //SYS_48M
  27. PLL0DIV_60M, //SYS_60M
  28. PLL0DIV_80M, //SYS_80M
  29. PLL0DIV_120M, //SYS_120M
  30. };
  31. const uint8_t sysclk_index[] = {
  32. 2,
  33. 12,
  34. 13,
  35. 24,
  36. 26,
  37. 30,
  38. 48,
  39. 60,
  40. 80,
  41. 120,
  42. };
  43. sys_t sys = {0};
  44. void my_printf(const char *format, ...);
  45. static void delay_us(uint16_t nus)
  46. {
  47. int i;
  48. for (i = 0; i < nus*10; i++) {
  49. asm("nop");
  50. }
  51. }
  52. uint8_t get_clksel_val(uint8_t val)
  53. {
  54. return sysclk_sel_tbl[val];
  55. }
  56. uint8_t get_cur_sysclk(void)
  57. {
  58. return sys.sys_clk;
  59. }
  60. uint32_t get_sysclk_nhz(void)
  61. {
  62. return sysclk_index[sys.sys_clk] * 1000000;
  63. }
  64. ////AT(.com_text.set_flash_safety)
  65. //static ALWAYS_INLINE void set_flash_safety(uint32_t sys_clk)
  66. //{
  67. // SPI0CON |= BIT(10);
  68. // if (sys_clk > SYS_48M) {
  69. // SPI0CON |= BIT(3); //2bit mode
  70. // spiflash_init(0x3b, 1); //dummy = 1
  71. // } else {
  72. // SPI0CON &= ~BIT(3); //2bit mode
  73. // spiflash_init(0x0b, 1); //dummy = 0
  74. // }
  75. //}
  76. uint8_t get_sd_rate(void)
  77. {
  78. return 0; //unit: M
  79. }
  80. uint8_t set_sd_baud(uint8_t sd_rate)
  81. {
  82. uint8_t sd0baud=0;
  83. uint8_t sys_clk=0;
  84. if(sd_rate > 14){//不支持超过14M
  85. return 0;
  86. }
  87. if (sys.sys_clk <= SYSCLK_26M) {
  88. sys_clk=26;
  89. }else if (sys.sys_clk == SYSCLK_48M) {
  90. sys_clk=48;
  91. } else if (sys.sys_clk <= SYSCLK_60M) {
  92. sys_clk=52;
  93. } else if (sys.sys_clk == SYSCLK_80M) {
  94. sys_clk=80;
  95. } else if (sys.sys_clk <= SYSCLK_120M) {
  96. sys_clk=120;
  97. }
  98. sd0baud = sys_clk/sd_rate-1;
  99. if(sys_clk%sd_rate*2/sd_rate) {
  100. sd0baud=sd0baud+1;
  101. }
  102. return sd0baud;
  103. }
  104. void update_sd0baud(void)
  105. {
  106. if (!(SD0CON & BIT(0))) {
  107. return;
  108. }
  109. uint8_t sd_rate=get_sd_rate();
  110. if(sd_rate){
  111. uint8_t sd0baud=set_sd_baud(sd_rate);
  112. if(sd0baud){
  113. SD0BAUD=sd0baud;
  114. return ;
  115. }
  116. }
  117. if (sys.sys_clk <= SYSCLK_30M) {
  118. SD0BAUD = 1;
  119. } else if (sys.sys_clk <= SYSCLK_60M) {
  120. SD0BAUD = 3;
  121. } else if (sys.sys_clk == SYSCLK_80M) {
  122. SD0BAUD = 5;
  123. } else if (sys.sys_clk <= SYSCLK_120M) {
  124. SD0BAUD = 9;
  125. }
  126. }
  127. uint8_t sysclk_update_baud(uint8_t baud)
  128. {
  129. uint8_t sd_rate=get_sd_rate();
  130. if(baud>20||!sd_rate) {
  131. if (sys.sys_clk == SYSCLK_120M) {
  132. return ((uint16_t)(baud + 1) * 25 / 10 - 1);
  133. } else if (sys.sys_clk >= SYSCLK_80M) {
  134. return ((baud + 1) * 2 - 1);
  135. } else if (sys.sys_clk <= SYSCLK_30M) {
  136. return (((baud + 1) >> 1) - 1);
  137. }
  138. } else if (sd_rate){
  139. return set_sd_baud(sd_rate);
  140. }
  141. return baud;
  142. }
  143. //客户可能用到UART0(使用26M时钟源)做通信,这里可选设置系统时钟时不改波特率
  144. WEAK void update_uart0baud_in_sysclk(uint32_t uart_baud)
  145. {
  146. if(UART0CON & BIT(0)) {
  147. while (!(UART0CON & BIT(8)));
  148. }
  149. UART0BAUD = (uart_baud << 16) | uart_baud;
  150. }
  151. void set_sys_uart0baud(uint32_t baud)
  152. {
  153. sys.uart0baud = baud;
  154. }
  155. //切系统时钟前,先设置模块时钟分频较大值,保证模块不会超频的情况
  156. void set_peripherals_clkdiv_safety(void)
  157. {
  158. uint32_t clkcon3 = CLKCON3;
  159. uint32_t clkcon2 = CLKCON2;
  160. //src clkdiv
  161. clkcon3 &= ~0xf0; //reset src clkdiv
  162. clkcon3 |= (1 << 4); //src clk = sys_clk / (n+1)
  163. //sbcenc硬件要小于48M
  164. clkcon3 &= ~(0x0f << 12); //reset sbcenc clkdiv
  165. clkcon3 |= (2 << 12); //src clk = sys_clk / (n+1)
  166. //aec ram硬件要小于50M
  167. clkcon3 &= ~0x0f; //reset aec clkdiv
  168. clkcon3 &= ~(0x0f << 19); //reset plc clkdiv
  169. clkcon3 &= ~(0x0f << 23); //reset cvsd clkdiv
  170. clkcon3 |= 0x02; //aec clk = sys_clk / (n+1)
  171. clkcon3 |= (2 << 19); //plc clk = sys_clk / (n+1)
  172. clkcon3 |= (2 << 23); //cvsd clk = sys_clk / (n+1)
  173. //audec硬件要小于48M
  174. clkcon2 &= ~(0x0f << 13); //reset audec clkdiv
  175. clkcon2 |= (2 << 13); //audec clk = sys_clk / (n+1)
  176. CLKCON3 = clkcon3;
  177. CLKCON2 = clkcon2;
  178. }
  179. //根据实际系统时钟,设置合适的模块时钟分频
  180. void set_peripherals_clkdiv(void)
  181. {
  182. uint32_t clkcon3 = CLKCON3;
  183. uint32_t clkcon2 = CLKCON2;
  184. uint32_t clkdiv;
  185. uint8_t sys_clk = sys.sys_clk;
  186. //src clkdiv
  187. clkcon3 &= ~0xf0; //reset src clkdiv
  188. if (sys_clk > SYSCLK_80M) {
  189. clkcon3 |= (1 << 4); //src clk = sys_clk / (n+1)
  190. }
  191. //sbcec硬件要小于48M
  192. clkcon3 &= ~(0x0f << 12);
  193. if (sys_clk > SYSCLK_80M) {
  194. clkcon3 |= (2 << 12);
  195. } else if (sys_clk >= SYSCLK_60M) {
  196. clkcon3 |= (1 << 12);
  197. }
  198. //aec ram硬件要小于50M
  199. clkcon3 &= ~0x0f; //reset aec clkdiv
  200. clkcon3 &= ~(0x0f << 19); //reset plc clkdiv
  201. clkcon3 &= ~(0x0f << 23); //reset cvsd clkdiv
  202. if (sys_clk > SYSCLK_80M) {
  203. clkdiv = 2;
  204. } else if (sys_clk >= SYSCLK_60M) {
  205. clkdiv = 1;
  206. } else {
  207. clkdiv = 0;
  208. }
  209. clkcon3 |= clkdiv; //aec clk = sys_clk / (n+1)
  210. clkcon3 |= (clkdiv << 19); //plc clk = sys_clk / (n+1)
  211. clkcon3 |= (clkdiv << 23); //cvsd clk = sys_clk / (n+1)
  212. //audec硬件要小于48M
  213. clkcon2 &= ~(0x0f << 13); //reset audec clkdiv
  214. if (sys_clk > SYSCLK_80M) {
  215. clkdiv = 2;
  216. } else if (sys_clk >= SYSCLK_60M) {
  217. clkdiv = 1;
  218. } else {
  219. clkdiv = 0;
  220. }
  221. clkcon2 |= (clkdiv << 13); //audec clk = sys_clk / (n+1)
  222. CLKCON3 = clkcon3;
  223. CLKCON2 = clkcon2;
  224. // if (sys_clk <= SYS_48M) {
  225. // PWRCON0 = (PWRCON0 & ~0xf) | (sys_trim.vddcore); //VDDCORE减一档
  226. // }
  227. // vddcore_other_offset();
  228. }
  229. ALIGN(512) //注意:超过512byte时,要用lock cache
  230. static void set_sysclk_do(uint32_t sys_clk, uint32_t clk_sel, uint32_t spll_div, uint32_t spi_baud, uint32_t spi1baud)
  231. {
  232. uint32_t cpu_ie;
  233. cpu_ie = PICCON & BIT(0);
  234. PICCONCLR = BIT(0); //关中断,切换系统时钟
  235. set_peripherals_clkdiv_safety();
  236. CLKCON0 &= ~(BIT(2) | BIT(3)); //sysclk sel rc2m
  237. CLKCON2 &= ~(0x1f << 8); //reset spll div
  238. if(clk_sel <= PLL0DIV_120M) {
  239. //sys_clk来源PLL0的分频配置
  240. CLKCON0 &= ~(BIT(4) | BIT(5) | BIT(6)); //sys_pll select pll0out
  241. if (PLL0DIV != (240 * 65536 / 26)) {
  242. PLL0DIV = 240 * 65536 / 26; //pll: 240M, XOSC: 26M
  243. PLL0CON &= ~(BIT(3) | BIT(4) | BIT(5));
  244. PLL0CON |= BIT(3); //Select PLL/VCO frequency band (PLL大于206M vcos = 0x01, 否则为0)
  245. PLL0CON |= BIT(20); //update pll0div to pll0_clk
  246. CLKCON3 &= ~(7 << 16);
  247. CLKCON3 |= (4 << 16); //USB CLK 48M
  248. }
  249. } else if (clk_sel <= OSCDIV_26M) {
  250. //sys_clk来源于XOSC26M时钟分频, 无USB时关闭PLL0
  251. // if (!is_usb_support()) {
  252. // PLL0CON &= ~BIT(18);
  253. // PLL0CON &= ~(BIT(12) | BIT(6)); //close pll0
  254. // }
  255. CLKCON0 &= ~(BIT(4) | BIT(5) | BIT(6));
  256. CLKCON0 |= BIT(6); //spll select xosc26m_clk
  257. }
  258. CLKCON2 |= (spll_div << 8);
  259. CLKCON0 |= BIT(3); //sysclk sel spll
  260. SPI0BAUD = spi_baud;
  261. if (CLKGAT1 & BIT(12)) {
  262. SPI1BAUD = spi1baud;
  263. }
  264. // if (spiflash_speed_up_en()) {
  265. // set_flash_safety(sys_clk);
  266. // }
  267. PICCON |= cpu_ie;
  268. }
  269. void set_sysclk(uint32_t sys_clk)
  270. {
  271. uint32_t uart_baud, spll_div = 0, spi_baud = 0, spi1baud;
  272. uint8_t cnt_1us, clk_sel;
  273. clk_sel = get_clksel_val(sys_clk);
  274. if(sys.clk_sel == clk_sel) {
  275. return;
  276. }
  277. // if (sys_clk > SYSCLK_48M) {
  278. // PWRCON0 = (PWRCON0 & ~0xf) | (sys_trim.vddcore + 1); //VDDCORE加一档
  279. // }
  280. // vddcore_other_offset();
  281. // printf("%s: %d, %d\n", __func__, sys_clk, clk_sel);
  282. switch (sys_clk) {
  283. case SYSCLK_12M:
  284. spll_div = 19; //pll0 240M
  285. cnt_1us = 1;
  286. spi_baud = 0;
  287. spi1baud = 0;
  288. break;
  289. case SYSCLK_24M:
  290. spll_div = 9; //pll0 240M
  291. cnt_1us = 2;
  292. spi_baud = 0;
  293. spi1baud = 1;
  294. break;
  295. case SYSCLK_30M:
  296. spll_div = 7; //pll0 240M
  297. cnt_1us = 3;
  298. spi_baud = 1; //Baud Rate =Fsys clock / (SPI_BAUD+1)
  299. spi1baud = 1;
  300. break;
  301. case SYSCLK_48M:
  302. spll_div = 4; //pll0 240M
  303. cnt_1us = 4;
  304. spi_baud = 1; //Baud Rate =Fsys clock / (SPI_BAUD+1)
  305. spi1baud = 3;
  306. break;
  307. case SYSCLK_60M:
  308. spll_div = 3; //pll0 240M
  309. cnt_1us = 5;
  310. spi_baud = 2; //Baud Rate =Fsys clock / (SPI_BAUD+1)
  311. spi1baud = 3;
  312. break;
  313. case SYSCLK_80M:
  314. spll_div = 2; //pll0 240M
  315. cnt_1us = 7;
  316. spi_baud = 3; //Baud Rate =Fsys clock / (SPI_BAUD+1)
  317. spi1baud = 4;
  318. break;
  319. case SYSCLK_120M:
  320. spll_div = 1; //pll0 240M
  321. cnt_1us = 10;
  322. spi_baud = 4; //Baud Rate =Fsys clock / (SPI_BAUD+1) //spiclk 120/5 = 24M
  323. spi1baud = 9;
  324. break;
  325. case SYSCLK_26M:
  326. spll_div = 0;
  327. cnt_1us = 3;
  328. spi_baud = 1;
  329. spi1baud = 1;
  330. break;
  331. case SYSCLK_13M:
  332. spll_div = 1;
  333. cnt_1us = 1;
  334. spi_baud = 0;
  335. spi1baud = 0;
  336. break;
  337. case SYSCLK_2M:
  338. spll_div = 1;
  339. cnt_1us = 1;
  340. spi_baud = 0;
  341. spi1baud = 0;
  342. break;
  343. default:
  344. return;
  345. }
  346. //先判断PLL0是否打开
  347. if(clk_sel <= PLL0DIV_120M) {
  348. if (!(PLL0CON & BIT(12))) {
  349. PLL0CON &= ~(BIT(3) | BIT(4) | BIT(5));
  350. PLL0CON |= BIT(3); //Select PLL/VCO frequency band (PLL大于206M vcos = 0x01, 否则为0)
  351. PLL0CON |= BIT(12); //enable pll0 ldo
  352. delay_us(100); //delay 100us
  353. PLL0DIV = 240 * 65536 / 26; //pll0: 240M, XOSC: 26M
  354. PLL0CON |= BIT(20); //update pll0div to pll0_clk
  355. PLL0CON |= BIT(6); //enable analog pll0
  356. PLL0CON |= BIT(18); //pll0 sdm enable
  357. delay_us(1000); //wait pll0 stable
  358. }
  359. }
  360. sys.cnt_1us = cnt_1us;
  361. sys.sys_clk = sys_clk;
  362. sys.clk_sel = clk_sel;
  363. uart_baud = (((get_sysclk_nhz() + (sys.uart0baud / 2)) / sys.uart0baud) - 1);
  364. set_sysclk_do(sys_clk, clk_sel,spll_div, spi_baud, spi1baud);
  365. set_peripherals_clkdiv();
  366. update_sd0baud(); //更新下SD0BAUD
  367. update_uart0baud_in_sysclk(uart_baud);
  368. }