打印
[应用相关]

H750移植rt_thread操作系统完整工程分享

[复制链接]
846|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
磨砂|  楼主 | 2021-7-1 18:40 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、移植注意事项
1、在运行外部FLASH存储的代码之前首先要初始化QSPI进入内存映射模式,参考代码:

//QSPI进入内存映射模式(执行QSPI代码必备前提,为了减少引入的文件,
//除了GPIO驱动外,其他的外设驱动均采用寄存器形式)
void QSPI_Enable_Memmapmode(void)
{
        unsigned int tempreg=0;
        volatile unsigned int *data_reg=&QUADSPI->DR;
        GPIO_InitTypeDef qspi_gpio;
       
        RCC->AHB4ENR|=1<<1;                                                    //使能PORTB时钟          
        RCC->AHB4ENR|=1<<5;                                                    //使能PORTF时钟          
        RCC->AHB3ENR|=1<<14;                                                   //QSPI时钟使能

        qspi_gpio.Pin=GPIO_PIN_6;                                        //PB6 AF10       
        qspi_gpio.Mode=GPIO_MODE_AF_PP;
        qspi_gpio.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
        qspi_gpio.Pull=GPIO_NOPULL;
        qspi_gpio.Alternate=GPIO_AF10_QUADSPI;
        HAL_GPIO_Init(GPIOB,&qspi_gpio);
       
        qspi_gpio.Pin=GPIO_PIN_2;                                        //PB2 AF9       
        qspi_gpio.Alternate=GPIO_AF9_QUADSPI;
        HAL_GPIO_Init(GPIOB,&qspi_gpio);
       
        qspi_gpio.Pin=GPIO_PIN_6|GPIO_PIN_7;                //PF6,7 AF9       
        qspi_gpio.Alternate=GPIO_AF9_QUADSPI;
        HAL_GPIO_Init(GPIOF,&qspi_gpio);
       
        qspi_gpio.Pin=GPIO_PIN_8|GPIO_PIN_9;                //PF8,9 AF10               
        qspi_gpio.Alternate=GPIO_AF10_QUADSPI;
        HAL_GPIO_Init(GPIOF,&qspi_gpio);
       
        //QSPI设置,参考QSPI实验的QSPI_Init函数
        RCC->AHB3RSTR|=1<<14;                        //复位QSPI
        RCC->AHB3RSTR&=~(1<<14);                //停止复位QSPI
        while(QUADSPI->SR&(1<<5));                //等待BUSY位清零
        QUADSPI->CR=0X01000310;                        //设置CR寄存器,这些值怎么来的,请参考QSPI实验/看H750参考手册寄存器描述分析
        QUADSPI->DCR=0X00160401;                //设置DCR寄存器
        QUADSPI->CR|=1<<0;                                //使能QSPI

        //注意:QSPI QE位的使能,在QSPI烧写算法里面,就已经设置了
        //所以,这里可以不用设置QE位,否则需要加入对QE位置1的代码
        //不过,代码必须通过仿真器下载,直接烧录到外部QSPI FLASH,是不可用的
        //如果想直接烧录到外部QSPI FLASH也可以用,则需要在这里添加QE位置1的代码
       
        //W25QXX进入QPI模式(0X38指令)
        while(QUADSPI->SR&(1<<5));                //等待BUSY位清零
        QUADSPI->CCR=0X00000138;                //发送0X38指令,W25QXX进入QPI模式
        while((QUADSPI->SR&(1<<1))==0);        //等待指令发送完成
        QUADSPI->FCR|=1<<1;                                //清除发送完成标志位        

        //W25QXX写使能(0X06指令)
        while(QUADSPI->SR&(1<<5));                //等待BUSY位清零
        QUADSPI->CCR=0X00000106;                //发送0X06指令,W25QXX写使能
        while((QUADSPI->SR&(1<<1))==0);        //等待指令发送完成
        QUADSPI->FCR|=1<<1;                                //清除发送完成标志位
       
        //W25QXX设置QPI相关读参数(0XC0)
        while(QUADSPI->SR&(1<<5));                //等待BUSY位清零
        QUADSPI->CCR=0X030003C0;                //发送0XC0指令,W25QXX读参数设置
        QUADSPI->DLR=0;
        while((QUADSPI->SR&(1<<2))==0);        //等待FTF
        *(unsigned char *)data_reg=3<<4;                        //设置P4&P5=11,8个dummy clocks,104M
        QUADSPI->CR|=1<<2;                                //终止传输
        while((QUADSPI->SR&(1<<1))==0);        //等待数据发送完成
        QUADSPI->FCR|=1<<1;                                //清除发送完成标志位  
        while(QUADSPI->SR&(1<<5));                //等待BUSY位清零          

        //MemroyMap 模式设置
        while(QUADSPI->SR&(1<<5));                //等待BUSY位清零
        QUADSPI->ABR=0;                                        //交替字节设置为0,实际上就是W25Q 0XEB指令的,M0~M7=0
        tempreg=0XEB;                                        //INSTRUCTION[7:0]=0XEB,发送0XEB指令(Fast Read QUAD I/O)
        tempreg|=3<<8;                                        //IMODE[1:0]=3,四线传输指令
        tempreg|=3<<10;                                        //ADDRESS[1:0]=3,四线传输地址
        tempreg|=2<<12;                                        //ADSIZE[1:0]=2,24位地址长度
        tempreg|=3<<14;                                        //ABMODE[1:0]=3,四线传输交替字节
        tempreg|=0<<16;                                        //ABSIZE[1:0]=0,8位交替字节(M0~M7)
        tempreg|=6<<18;                                        //DCYC[4:0]=6,6个dummy周期
        tempreg|=3<<24;                                        //DMODE[1:0]=3,四线传输数据
        tempreg|=3<<26;                                        //FMODE[1:0]=3,内存映射模式
        QUADSPI->CCR=tempreg;                        //设置CCR寄存器
       
        //设置QSPI FLASH空间的MPU保护
        SCB->SHCSR&=~(1<<16);                        //禁止MemManage
        MPU->CTRL&=~(1<<0);                                //禁止MPU
        MPU->RNR=0;                                                //设置保护区域编号为0(1~7可以给其他内存用)
        MPU->RBAR=0X90000000;                        //基地址为0X9000 000,即QSPI的起始地址
        MPU->RASR=0X0303002D;                        //设置相关保护参数(禁止共用,允许cache,允许缓冲),详见MPU实验的解析
        MPU->CTRL=(1<<2)|(1<<0);                //使能PRIVDEFENA,使能MPU
        SCB->SHCSR|=1<<16;                                //使能MemManage
}


使用特权

评论回复
沙发
磨砂|  楼主 | 2021-7-1 18:40 | 只看该作者
2、分散加载文件中,需要将没有开启QSPI内存映射之前的代码要放在内部FLASH。否则上电就会进入硬件中断。
分散加载文件参考如下:

#! armcc -E


#define m_stmflash_start                                0X08000000                //m_stmflash(STM32内部FLASH)域起始地址
#define m_stmflash_size                                        0X20000                        //m_stmflash(STM32内部FLASH)大小,H750是128KB

#define m_qspiflash_start                                0X90000000                //m_qspiflash(外扩QSPI FLASH)域起始地址
#define m_qspiflash_size                                0X800000                //m_qspiflash(外扩QSPI FLASH)大小,W25Q64是8MB

#define m_stmsram_start                                        0X24000000                //m_stmsram(STM32内部RAM)域起始地址,定义在D1,AXI SRAM
#define m_stmsram_size                                        0X80000                        //m_stmsram(STM32内部RAM)大小,AXI SRAM共512KB



LR_m_stmflash m_stmflash_start m_stmflash_size {                //LR_m_stmflash加载域
  ER_m_stmflash m_stmflash_start m_stmflash_size {                //ER_m_stmfalsh运行域,起始地址为:m_stmflash_start,大小为:m_stmflash_size
    *.o (RESET, +First)                                                                        //优先(+FIRST)将RESET(中断向量表)段放这个域,实际上就是把中断向量表拷贝到m_stmflash_start
                                                                                                                //RESET是一个段名,表示中断向量表(在.s文件定义);+FIRST表示时第一个要加载的.
        * (InRoot$$Sections)                                                                //将所有的库段(C/C++标准库)放在root region.如__main.o,__scatter*.o等
        * (Veneer$$Code)
        board.o
        clock.o
        context_rvds.o
        drv_common.o
        stm32h7xx_hal_gpio.o
        stm32h7xx_hal_rcc.o
        stm32h7xx_hal_rcc_ex.o
    startup_stm32h750xx.o
    system_stm32h7xx.o


  }
  RW_m_stmsram m_stmsram_start m_stmsram_size {                        //RW_m_stmsram运行域,起始地址为:m_stmsram_start,大小为:m_stmsram_size.
   .ANY (+RW +ZI)                                                                                //将所有用到的RAM都放在这个区域
  }
}

LR_m_qspiflash m_qspiflash_start m_qspiflash_size {                //LR_m_qspiflash加载域
   ER_m_qspiflash m_qspiflash_start m_qspiflash_size {        //ER_m_qspiflash加载域,起始地址为:m_qspiflash_start,大小为:m_qspiflash_size
    .ANY (+RO)                                                                                         //将只读数据(+RO)放这个域,任意分配.相当于程序就是存放在这个域的.
        * (FSymTab)
  }                                                                                                                         
}


使用特权

评论回复
板凳
磨砂|  楼主 | 2021-7-1 18:41 | 只看该作者
3、系统初始化后就要配置时钟,并且配置QSPI进入内存映射模式,参考代码如下:

void SystemInit (void)
{
#if defined (DATA_IN_D2_SRAM)
__IO uint32_t tmpreg;
#endif /* DATA_IN_D2_SRAM */

  /* FPU settings ------------------------------------------------------------*/
  #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
    SCB->CPACR |= ((3UL << (10*2))|(3UL << (11*2)));  /* set CP10 and CP11 Full Access */
  #endif
  /* Reset the RCC clock configuration to the default reset state ------------*/
  /* Set HSION bit */
  RCC->CR |= RCC_CR_HSION;

  /* Reset CFGR register */
  RCC->CFGR = 0x00000000;

  /* Reset HSEON, CSSON , CSION,RC48ON, CSIKERON PLL1ON, PLL2ON and PLL3ON bits */
  RCC->CR &= 0xEAF6ED7FU;

  /* Reset D1CFGR register */
  RCC->D1CFGR = 0x00000000;

  /* Reset D2CFGR register */
  RCC->D2CFGR = 0x00000000;

  /* Reset D3CFGR register */
  RCC->D3CFGR = 0x00000000;

  /* Reset PLLCKSELR register */
  RCC->PLLCKSELR = 0x00000000;

  /* Reset PLLCFGR register */
  RCC->PLLCFGR = 0x00000000;
  /* Reset PLL1DIVR register */
  RCC->PLL1DIVR = 0x00000000;
  /* Reset PLL1FRACR register */
  RCC->PLL1FRACR = 0x00000000;

  /* Reset PLL2DIVR register */
  RCC->PLL2DIVR = 0x00000000;

  /* Reset PLL2FRACR register */

  RCC->PLL2FRACR = 0x00000000;
  /* Reset PLL3DIVR register */
  RCC->PLL3DIVR = 0x00000000;

  /* Reset PLL3FRACR register */
  RCC->PLL3FRACR = 0x00000000;

  /* Reset HSEBYP bit */
  RCC->CR &= 0xFFFBFFFFU;

  /* Disable all interrupts */
  RCC->CIER = 0x00000000;

#if defined (DATA_IN_D2_SRAM)
  /* in case of initialized data in D2 SRAM (AHB SRAM) , enable the D2 SRAM clock ((AHB SRAM clock) */
#if defined(RCC_AHB2ENR_D2SRAM1EN)
  RCC->AHB2ENR |= (RCC_AHB2ENR_D2SRAM1EN | RCC_AHB2ENR_D2SRAM2EN | RCC_AHB2ENR_D2SRAM3EN);
#else
  RCC->AHB2ENR |= (RCC_AHB2ENR_AHBSRAM1EN | RCC_AHB2ENR_AHBSRAM2EN);
#endif /* RCC_AHB2ENR_D2SRAM1EN */

  tmpreg = RCC->AHB2ENR;
  (void) tmpreg;
#endif /* DATA_IN_D2_SRAM */

#if defined(DUAL_CORE) && defined(CORE_CM4)
  /* Configure the Vector Table location add offset address for cortex-M4 ------------------*/
#ifdef VECT_TAB_SRAM
  SCB->VTOR = D2_AHBSRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
  SCB->VTOR = FLASH_BANK2_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif /* VECT_TAB_SRAM */

#else
  /* dual core CM7 or single core line */
  if((DBGMCU->IDCODE & 0xFFFF0000U) < 0x20000000U)
  {
    /* if stm32h7 revY*/
    /* Change  the switch matrix read issuing capability to 1 for the AXI SRAM target (Target 7) */
    *((__IO uint32_t*)0x51008108) = 0x000000001U;
  }

  /* Configure the Vector Table location add offset address for cortex-M7 ------------------*/
#ifdef VECT_TAB_SRAM
  SCB->VTOR = D1_AXISRAM_BASE  | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D1 AXI-RAM */
#else
  SCB->VTOR = FLASH_BANK1_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif

#endif /*DUAL_CORE && CORE_CM4*/
        extern void SystemClock_Config(void);
        SystemClock_Config();
}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

94

主题

4126

帖子

2

粉丝