summaryrefslogtreecommitdiff
path: root/bsp/bluetrum/libraries/hal_libraries/bmsis/source
diff options
context:
space:
mode:
authorgreedyhao <[email protected]>2020-12-10 11:02:26 +0800
committergreedyhao <[email protected]>2020-12-10 11:02:26 +0800
commit40ef8229792dedc7c224cddf01472ea86ecd7f9c (patch)
tree4048333666ce7bd9c9b97332b49ea5d6d1bdd675 /bsp/bluetrum/libraries/hal_libraries/bmsis/source
parent86756c0d4cc73f2ec863c0db16c3b4265fcc3ad6 (diff)
[bsp][bluetrum] add a new board support
Diffstat (limited to 'bsp/bluetrum/libraries/hal_libraries/bmsis/source')
-rw-r--r--bsp/bluetrum/libraries/hal_libraries/bmsis/source/startup.S92
-rw-r--r--bsp/bluetrum/libraries/hal_libraries/bmsis/source/system_ab32vgx.c430
2 files changed, 522 insertions, 0 deletions
diff --git a/bsp/bluetrum/libraries/hal_libraries/bmsis/source/startup.S b/bsp/bluetrum/libraries/hal_libraries/bmsis/source/startup.S
new file mode 100644
index 0000000000..d68b31b306
--- /dev/null
+++ b/bsp/bluetrum/libraries/hal_libraries/bmsis/source/startup.S
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2020-2020, BLUETRUM Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "ab32vg1.h"
+
+.global _start
+.section .reset, "ax"
+_start:
+ //load comm
+ la a0, __comm_vma
+ la a1, __comm_lma
+ la a2, __comm_size
+
+ /* memcpy start */
+ //先按32 BYTE一个循环来copy
+ mv t0, a0 //备份dst
+ srli t1, a2, 5 //长度除32的商
+
+ slli t1, t1, 5
+ add t1, a0, t1 //t1存放对齐的结束地址
+
+ _memcpy_loop1: //8 WORDS every cycle
+ lw a2, 0(a1)
+ lw a3, 4(a1)
+ lw a4, 8(a1)
+ lw a5, 12(a1)
+ sw a2, 0(a0)
+ sw a3, 4(a0)
+ sw a4, 8(a0)
+ sw a5, 12(a0)
+
+ lw a2, 16(a1)
+ lw a3, 20(a1)
+ lw a4, 24(a1)
+ lw a5, 28(a1)
+ sw a2, 16(a0)
+ sw a3, 20(a0)
+ sw a4, 24(a0)
+ sw a5, 28(a0)
+
+ addi a0, a0, 32
+ addi a1, a1, 32
+ blt a0, t1, _memcpy_loop1
+
+ mv a0, t0 //返回dst
+ /* memcpy end */
+
+ la a0, __irq_stack_start //Stack清成0x23
+ li a1, 0x23
+ la a2, __irq_stack_size
+ call memset
+ la ra, __irq_stack
+ lui a5, 0x1
+ sw zero, -1920(a5)
+ sw zero, -1916(a5)
+
+ //clear bss
+ la a0, __bss_start
+ li a1, 0
+ la a2, __bss_size
+ call memset
+
+ la a0, __comm_vma
+ sw a0, PICADR(zero)
+
+ call entry
+// la ra, __exception
+// jr ra
+
+.section .vector, "ax"
+// .org 0x10
+//__exception:
+// li sp, 0x10600 //出错后,不破坏错误点的堆栈数据
+// jal exception_isr
+// 1: j 1b
+// mret
+
+ .org 0x40
+ jal x0, low_prio_irq
+ mret
+
+ .global cpu_irq_comm
+ .section .com_text.irq
+cpu_irq_comm:
+ la a5, __irq_stack
+ mv sp, a5
+ j cpu_irq_comm_do
+
+ ret
diff --git a/bsp/bluetrum/libraries/hal_libraries/bmsis/source/system_ab32vgx.c b/bsp/bluetrum/libraries/hal_libraries/bmsis/source/system_ab32vgx.c
new file mode 100644
index 0000000000..9848c785d6
--- /dev/null
+++ b/bsp/bluetrum/libraries/hal_libraries/bmsis/source/system_ab32vgx.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 2020-2020, BLUETRUM Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "ab32vgx.h"
+
+#ifndef ALIGN
+#define ALIGN(n) __attribute__((aligned(n)))
+#endif // ALIGN
+
+typedef struct _sys_t {
+ uint8_t cnt_1us; //delay 1us cnt
+ uint8_t main_start; //Main是否已启动
+ uint8_t clk_sel; //system clock select
+ uint8_t sys_clk;
+// uint8_t aupll_type; //区分AUPLL的频率
+ uint16_t rand_seed;
+ uint32_t uart0baud; //UART0BAUD
+} sys_t;
+
+AT(.text.sys_clk.table)
+const uint8_t sysclk_sel_tbl[] = {
+ OSCDIV_2M, //SYS_2M
+ PLL0DIV_12M, //SYS_12M
+ OSCDIV_13M, //SYS_13M
+ PLL0DIV_24M, //SYS_24M
+ OSCDIV_26M, //SYS_26M
+ PLL0DIV_30M, //SYS_30M
+ PLL0DIV_48M, //SYS_48M
+ PLL0DIV_60M, //SYS_60M
+ PLL0DIV_80M, //SYS_80M
+ PLL0DIV_120M, //SYS_120M
+};
+
+AT(.text.sys_clk.table)
+const uint8_t sysclk_index[] = {
+ 2,
+ 12,
+ 13,
+ 24,
+ 26,
+ 30,
+ 48,
+ 60,
+ 80,
+ 120,
+};
+
+sys_t sys = {0};
+void my_printf(const char *format, ...);
+
+AT(.com_text.delay)
+static void delay_us(uint16_t nus)
+{
+ int i;
+ for (i = 0; i < nus*10; i++) {
+ asm("nop");
+ }
+}
+
+AT(.text.sys_clk)
+uint8_t get_clksel_val(uint8_t val)
+{
+ return sysclk_sel_tbl[val];
+}
+
+AT(.text.sys_clk)
+uint8_t get_cur_sysclk(void)
+{
+ return sys.sys_clk;
+}
+
+uint32_t get_sysclk_nhz(void)
+{
+ return sysclk_index[sys.sys_clk] * 1000000;
+}
+
+////AT(.com_text.set_flash_safety)
+//static ALWAYS_INLINE void set_flash_safety(uint32_t sys_clk)
+//{
+// SPI0CON |= BIT(10);
+// if (sys_clk > SYS_48M) {
+// SPI0CON |= BIT(3); //2bit mode
+// spiflash_init(0x3b, 1); //dummy = 1
+// } else {
+// SPI0CON &= ~BIT(3); //2bit mode
+// spiflash_init(0x0b, 1); //dummy = 0
+// }
+//}
+
+AT(.text.sys_clk)
+uint8_t get_sd_rate(void)
+{
+ return 0; //unit: M
+}
+
+AT(.text.sys_clk)
+uint8_t set_sd_baud(uint8_t sd_rate)
+{
+ uint8_t sd0baud=0;
+ uint8_t sys_clk=0;
+ if(sd_rate > 14){//不支持超过14M
+ return 0;
+ }
+ if (sys.sys_clk <= SYSCLK_26M) {
+ sys_clk=26;
+ }else if (sys.sys_clk == SYSCLK_48M) {
+ sys_clk=48;
+ } else if (sys.sys_clk <= SYSCLK_60M) {
+ sys_clk=52;
+ } else if (sys.sys_clk == SYSCLK_80M) {
+ sys_clk=80;
+ } else if (sys.sys_clk <= SYSCLK_120M) {
+ sys_clk=120;
+ }
+ sd0baud = sys_clk/sd_rate-1;
+ if(sys_clk%sd_rate*2/sd_rate) {
+ sd0baud=sd0baud+1;
+ }
+ return sd0baud;
+}
+
+void update_sd0baud(void)
+{
+ if (!(SD0CON & BIT(0))) {
+ return;
+ }
+
+ uint8_t sd_rate=get_sd_rate();
+ if(sd_rate){
+ uint8_t sd0baud=set_sd_baud(sd_rate);
+ if(sd0baud){
+ SD0BAUD=sd0baud;
+ return ;
+ }
+ }
+
+ if (sys.sys_clk <= SYSCLK_30M) {
+ SD0BAUD = 1;
+ } else if (sys.sys_clk <= SYSCLK_60M) {
+ SD0BAUD = 3;
+ } else if (sys.sys_clk == SYSCLK_80M) {
+ SD0BAUD = 5;
+ } else if (sys.sys_clk <= SYSCLK_120M) {
+ SD0BAUD = 9;
+ }
+}
+
+AT(.text.sys_clk)
+uint8_t sysclk_update_baud(uint8_t baud)
+{
+ uint8_t sd_rate=get_sd_rate();
+ if(baud>20||!sd_rate) {
+ if (sys.sys_clk == SYSCLK_120M) {
+ return ((uint16_t)(baud + 1) * 25 / 10 - 1);
+ } else if (sys.sys_clk >= SYSCLK_80M) {
+ return ((baud + 1) * 2 - 1);
+ } else if (sys.sys_clk <= SYSCLK_30M) {
+ return (((baud + 1) >> 1) - 1);
+ }
+ } else if (sd_rate){
+ return set_sd_baud(sd_rate);
+ }
+ return baud;
+}
+
+//客户可能用到UART0(使用26M时钟源)做通信,这里可选设置系统时钟时不改波特率
+WEAK void update_uart0baud_in_sysclk(uint32_t uart_baud)
+{
+ if(UART0CON & BIT(0)) {
+ while (!(UART0CON & BIT(8)));
+ }
+ UART0BAUD = (uart_baud << 16) | uart_baud;
+}
+
+void set_sys_uart0baud(uint32_t baud)
+{
+ sys.uart0baud = baud;
+}
+
+//切系统时钟前,先设置模块时钟分频较大值,保证模块不会超频的情况
+AT(.com_text.sys)
+void set_peripherals_clkdiv_safety(void)
+{
+ uint32_t clkcon3 = CLKCON3;
+ uint32_t clkcon2 = CLKCON2;
+
+ //src clkdiv
+ clkcon3 &= ~0xf0; //reset src clkdiv
+ clkcon3 |= (1 << 4); //src clk = sys_clk / (n+1)
+
+ //sbcenc硬件要小于48M
+ clkcon3 &= ~(0x0f << 12); //reset sbcenc clkdiv
+ clkcon3 |= (2 << 12); //src clk = sys_clk / (n+1)
+
+ //aec ram硬件要小于50M
+ clkcon3 &= ~0x0f; //reset aec clkdiv
+ clkcon3 &= ~(0x0f << 19); //reset plc clkdiv
+ clkcon3 &= ~(0x0f << 23); //reset cvsd clkdiv
+ clkcon3 |= 0x02; //aec clk = sys_clk / (n+1)
+ clkcon3 |= (2 << 19); //plc clk = sys_clk / (n+1)
+ clkcon3 |= (2 << 23); //cvsd clk = sys_clk / (n+1)
+
+ //audec硬件要小于48M
+ clkcon2 &= ~(0x0f << 13); //reset audec clkdiv
+ clkcon2 |= (2 << 13); //audec clk = sys_clk / (n+1)
+
+ CLKCON3 = clkcon3;
+ CLKCON2 = clkcon2;
+}
+
+//根据实际系统时钟,设置合适的模块时钟分频
+void set_peripherals_clkdiv(void)
+{
+ uint32_t clkcon3 = CLKCON3;
+ uint32_t clkcon2 = CLKCON2;
+ uint32_t clkdiv;
+ uint8_t sys_clk = sys.sys_clk;
+
+ //src clkdiv
+ clkcon3 &= ~0xf0; //reset src clkdiv
+ if (sys_clk > SYSCLK_80M) {
+ clkcon3 |= (1 << 4); //src clk = sys_clk / (n+1)
+ }
+
+ //sbcec硬件要小于48M
+ clkcon3 &= ~(0x0f << 12);
+ if (sys_clk > SYSCLK_80M) {
+ clkcon3 |= (2 << 12);
+ } else if (sys_clk >= SYSCLK_60M) {
+ clkcon3 |= (1 << 12);
+ }
+
+ //aec ram硬件要小于50M
+ clkcon3 &= ~0x0f; //reset aec clkdiv
+ clkcon3 &= ~(0x0f << 19); //reset plc clkdiv
+ clkcon3 &= ~(0x0f << 23); //reset cvsd clkdiv
+ if (sys_clk > SYSCLK_80M) {
+ clkdiv = 2;
+ } else if (sys_clk >= SYSCLK_60M) {
+ clkdiv = 1;
+ } else {
+ clkdiv = 0;
+ }
+ clkcon3 |= clkdiv; //aec clk = sys_clk / (n+1)
+ clkcon3 |= (clkdiv << 19); //plc clk = sys_clk / (n+1)
+ clkcon3 |= (clkdiv << 23); //cvsd clk = sys_clk / (n+1)
+
+ //audec硬件要小于48M
+ clkcon2 &= ~(0x0f << 13); //reset audec clkdiv
+ if (sys_clk > SYSCLK_80M) {
+ clkdiv = 2;
+ } else if (sys_clk >= SYSCLK_60M) {
+ clkdiv = 1;
+ } else {
+ clkdiv = 0;
+ }
+ clkcon2 |= (clkdiv << 13); //audec clk = sys_clk / (n+1)
+
+ CLKCON3 = clkcon3;
+ CLKCON2 = clkcon2;
+
+// if (sys_clk <= SYS_48M) {
+// PWRCON0 = (PWRCON0 & ~0xf) | (sys_trim.vddcore); //VDDCORE减一档
+// }
+// vddcore_other_offset();
+}
+
+ALIGN(512) //注意:超过512byte时,要用lock cache
+static void set_sysclk_do(uint32_t sys_clk, uint32_t clk_sel, uint32_t spll_div, uint32_t spi_baud, uint32_t spi1baud)
+{
+ uint32_t cpu_ie;
+ cpu_ie = PICCON & BIT(0);
+ PICCONCLR = BIT(0); //关中断,切换系统时钟
+ set_peripherals_clkdiv_safety();
+
+ CLKCON0 &= ~(BIT(2) | BIT(3)); //sysclk sel rc2m
+ CLKCON2 &= ~(0x1f << 8); //reset spll div
+
+ if(clk_sel <= PLL0DIV_120M) {
+ //sys_clk来源PLL0的分频配置
+ CLKCON0 &= ~(BIT(4) | BIT(5) | BIT(6)); //sys_pll select pll0out
+ if (PLL0DIV != (240 * 65536 / 26)) {
+ PLL0DIV = 240 * 65536 / 26; //pll: 240M, XOSC: 26M
+ PLL0CON &= ~(BIT(3) | BIT(4) | BIT(5));
+ PLL0CON |= BIT(3); //Select PLL/VCO frequency band (PLL大于206M vcos = 0x01, 否则为0)
+ PLL0CON |= BIT(20); //update pll0div to pll0_clk
+ CLKCON3 &= ~(7 << 16);
+ CLKCON3 |= (4 << 16); //USB CLK 48M
+ }
+ } else if (clk_sel <= OSCDIV_26M) {
+ //sys_clk来源于XOSC26M时钟分频, 无USB时关闭PLL0
+// if (!is_usb_support()) {
+// PLL0CON &= ~BIT(18);
+// PLL0CON &= ~(BIT(12) | BIT(6)); //close pll0
+// }
+
+ CLKCON0 &= ~(BIT(4) | BIT(5) | BIT(6));
+ CLKCON0 |= BIT(6); //spll select xosc26m_clk
+ }
+
+ CLKCON2 |= (spll_div << 8);
+ CLKCON0 |= BIT(3); //sysclk sel spll
+ SPI0BAUD = spi_baud;
+ if (CLKGAT1 & BIT(12)) {
+ SPI1BAUD = spi1baud;
+ }
+// if (spiflash_speed_up_en()) {
+// set_flash_safety(sys_clk);
+// }
+ PICCON |= cpu_ie;
+}
+
+void set_sysclk(uint32_t sys_clk)
+{
+ uint32_t uart_baud, spll_div = 0, spi_baud = 0, spi1baud;
+ uint8_t cnt_1us, clk_sel;
+
+ clk_sel = get_clksel_val(sys_clk);
+ if(sys.clk_sel == clk_sel) {
+ return;
+ }
+// if (sys_clk > SYSCLK_48M) {
+// PWRCON0 = (PWRCON0 & ~0xf) | (sys_trim.vddcore + 1); //VDDCORE加一档
+// }
+// vddcore_other_offset();
+
+// printf("%s: %d, %d\n", __func__, sys_clk, clk_sel);
+ switch (sys_clk) {
+ case SYSCLK_12M:
+ spll_div = 19; //pll0 240M
+ cnt_1us = 1;
+ spi_baud = 0;
+ spi1baud = 0;
+ break;
+
+ case SYSCLK_24M:
+ spll_div = 9; //pll0 240M
+ cnt_1us = 2;
+ spi_baud = 0;
+ spi1baud = 1;
+ break;
+
+ case SYSCLK_30M:
+ spll_div = 7; //pll0 240M
+ cnt_1us = 3;
+ spi_baud = 1; //Baud Rate =Fsys clock / (SPI_BAUD+1)
+ spi1baud = 1;
+ break;
+
+ case SYSCLK_48M:
+ spll_div = 4; //pll0 240M
+ cnt_1us = 4;
+ spi_baud = 1; //Baud Rate =Fsys clock / (SPI_BAUD+1)
+ spi1baud = 3;
+ break;
+
+ case SYSCLK_60M:
+ spll_div = 3; //pll0 240M
+ cnt_1us = 5;
+ spi_baud = 2; //Baud Rate =Fsys clock / (SPI_BAUD+1)
+ spi1baud = 3;
+ break;
+
+ case SYSCLK_80M:
+ spll_div = 2; //pll0 240M
+ cnt_1us = 7;
+ spi_baud = 3; //Baud Rate =Fsys clock / (SPI_BAUD+1)
+ spi1baud = 4;
+ break;
+
+ case SYSCLK_120M:
+ spll_div = 1; //pll0 240M
+ cnt_1us = 10;
+ spi_baud = 4; //Baud Rate =Fsys clock / (SPI_BAUD+1) //spiclk 120/5 = 24M
+ spi1baud = 9;
+ break;
+
+ case SYSCLK_26M:
+ spll_div = 0;
+ cnt_1us = 3;
+ spi_baud = 1;
+ spi1baud = 1;
+ break;
+
+ case SYSCLK_13M:
+ spll_div = 1;
+ cnt_1us = 1;
+ spi_baud = 0;
+ spi1baud = 0;
+ break;
+
+ case SYSCLK_2M:
+ spll_div = 1;
+ cnt_1us = 1;
+ spi_baud = 0;
+ spi1baud = 0;
+ break;
+
+ default:
+ return;
+ }
+
+ //先判断PLL0是否打开
+ if(clk_sel <= PLL0DIV_120M) {
+ if (!(PLL0CON & BIT(12))) {
+ PLL0CON &= ~(BIT(3) | BIT(4) | BIT(5));
+ PLL0CON |= BIT(3); //Select PLL/VCO frequency band (PLL大于206M vcos = 0x01, 否则为0)
+ PLL0CON |= BIT(12); //enable pll0 ldo
+ delay_us(100); //delay 100us
+ PLL0DIV = 240 * 65536 / 26; //pll0: 240M, XOSC: 26M
+ PLL0CON |= BIT(20); //update pll0div to pll0_clk
+ PLL0CON |= BIT(6); //enable analog pll0
+ PLL0CON |= BIT(18); //pll0 sdm enable
+ delay_us(1000); //wait pll0 stable
+ }
+ }
+
+ sys.cnt_1us = cnt_1us;
+ sys.sys_clk = sys_clk;
+ sys.clk_sel = clk_sel;
+ uart_baud = (((get_sysclk_nhz() + (sys.uart0baud / 2)) / sys.uart0baud) - 1);
+
+ set_sysclk_do(sys_clk, clk_sel,spll_div, spi_baud, spi1baud);
+ set_peripherals_clkdiv();
+ update_sd0baud(); //更新下SD0BAUD
+ update_uart0baud_in_sysclk(uart_baud);
+}