主要参考文档:rt-thread-master\rt-thread-master\bsp\gd32\docs\GD32系列BSP制作教程.md

GD32F4xx_Firmware_Library_User_Guide_V1.0.pdf

GD32F4xx_yonghushouce_Rev2.6.pdf

GD32F427xx_Datasheet_Rev1.0.pdf

GD32407R_START_Demo_Suites

过程中的关键点:

  1. RT-Thread完整版和nano的区别
  2. 移植的具体哪个型号,要据此修改配置文件
  3. 注意标准库和rt-thread间的匹配,可能版本不一样,前者在兆易创新官网找,后者在rt-thread开源仓库找
  4. 标准库和rt-thread间的过度库移植自gdf103,所以版本一样也可能库不兼容,在下面的坑描述会提到
  5. 主要修改的文件:SConscript、SConstruct、Kconfig,这些分布在各个子文件夹中

注意事项:

  1. 如果把rt-thread-master中的例程移植到别的地方,注意修改bsp/gd32/gd32407v-start/Kconfig中的路径相关内容,比如default “…/…/…” source “…/libraries/Kconfig” source “board/Kconfig”,修改为自己的相对位置

  2. bsp/gd32/gd32407v-start/SConstruct中的路径相关内容要修改比如,RTT_ROOT = os.path.normpath(os.getcwd() + ‘/…/…/…’)

  3. bsp/gd32/gd32407v-start/board/linker_scripts/link.sct中的flash和ram地址要根据手册提供的具体大小进行修改,并且和keil的 Read/Only Memory Areas设置一致

  4. 移植完成后记得复制rtconfig.py文件过来,否则在控制台使用scons的时候会报错

  5. 注意单片机flash分几块,ram分几块区域:仿真调试一直卡在rt_hw_hard_fault_exception,在rt_system_heap_init的时候报错,

    修改board.h里面的GD32_SRAM_SIZE从256改为192 因为两个ram不连续,另外64kb从0x10000000开始

  6. 官方没有提供GD32f425或者427的库的话,可以选择f405或者407,基本可以替代

  7. 每次用rtt的工具设置后都要求添加某个路径,即便之前已经在keil中添加过了;路径要在使用env前在文件对应文件夹下的SConscript中进行添加,比如path = [cwd] path += [cwd + ‘/CubeMX_Config/Core/Inc’]

  8. Error: L6200E: Symbol __rt_init_cpu_usage_init multiply defined (by cpu_usage-v1.0.0_cpu_usage.o and cpu_usage.o). 去掉packages文件夹里面的cpu_usage-latest文件夹,或者其它类似的packages文件夹里有两个不同版本的第三方包问题

  9. 如果把rt_components_board_init和rt_components_init和屏蔽了,INIT_BOARD_EXPORT和其它类似函数是不起作用的

一、在rt-thread环境下移植外设到GD32

  1. 如果在RT-Thread env工具的menuconfig中找不到对应内容,要按照固定格式编辑board中的Kconfig文件

  2. 外设号在stm32的基础上统一减一,从0开始,比如stm32的串口1对应gd32的串口0,stm32的串口2对应gd32的串口1,以此类推;stm32的iic1对应gd32的iic0;stm32的spi1对应gd32的spi0;stm32的pwm1对应gd32的pwm0;stm32的timer1对应gd32的timer0;stm32的adc1对应gd32的adc0;stm32的dac1对应gd32的dac0;其它外设以此类推

  3. 下述一些问题的共同点是rt-thread的过渡函数和gd32的新标准库匹配不上

    一、移植看门狗/RTC到GD32

    1. drv_wdt.c 中 “RCU_IRC40K” is undefined,经查阅手册,没有40k内部时钟,改为RCU_IRC32K

    2. 添加WWDG_IRQn定义,HAL_NVIC_DisableIRQ改为NVIC_DisableIRQ,HAL_NVIC_ClearPendingIRQ改为NVIC_ClearPendingIRQ

      #define  WWDG_IRQn             0     // Window WatchDog Interrupt
      
    3. 在watchdog_init中添加rt_device_init(wdg_dev);

    4. rcu_periph_clock_enable(RCU_BKPI);中的RCU_BKPI找不到定义,经查阅用户手册应为RCU_BKPSRAM

    5. board\board.c(31): error: #20: identifier “RTC_HandleTypeDef” is undefined 去掉其定义,用标准库替代

    6. 修改获取时间戳get_rtc_timestamp的内部实现为rtc_timestamp_subsecond_get();

    7. 添加设置时间戳函数rtc_timestamp_subsecond_set(rtc_counter); 重新实现set_rtc_timestamp

    二、移植ADC/DAC到GD32

    1. adc配置时报错libraries\gd32_drivers\drv_adc.c(61): error: #20: identifier “GPIO_MODE_AIN” is undefined:error所在行的函数和参数都不对,改为 gpio_mode_set(PIN_GDPORT(pin), GPIO_MODE_ANALOG, GPIO_OSPEED_50MHZ, PIN_GDPIN(pin));//bug gpio_init - gpio_mode_set GPIO_MODE_AIN - GPIO_MODE_ANALOG
    2. adc_deinit(adc_periph);显示error: #140: too many arguments in function call 去掉adc_periph可解决
    3. adc_external_trigger_source_config(adc_periph, ADC_REGULAR_CHANNEL, ADC0_1_2_EXTTRIG_REGULAR_NONE);中的ADC0_1_2_EXTTRIG_REGULAR_NONE找不到定义,将其暂时改为ADC_EXTTRIG_REGULAR_T0_CH0,并将上面的规则组外部触发使能改为不使能
    4. adc_regular_channel_config(adc_periph, 0, channel, ADC_SAMPLETIME_239POINT5);中的ADC_SAMPLETIME_239POINT5未定义 将ADC_SAMPLETIME_239POINT5 改为 ADC_SAMPLETIME_480
    5. rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6);找不到定义,改为rcu_apb2_clock_config(RCU_APB2_CKAHB_DIV8);
    6. adc_mode_config(ADC_MODE_FREE);找不到定义,改为adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
    7. gd32未提供drv_dac文件,需手动实现(具体实现文件在工程中搜drv_dac.c),drv_dac比drv_pwm实现简单,实现过程的一些记录
      1. Kconfig及dac相关文件的DAC1\2改为0\1,并开启DAC0
      2. 添加drv_dac.c、drv_dac.h和dac_config.h文件
      3. 添加HAL_DAC_StateTypeDef、DAC_HandleTypeDef及其它dac相关的结构体和宏定义,暂时去掉DMA相关内容
      4. 添加gd32_dac_enabled和gd32_dac_disabled函数
      5. 添加gd32_set_dac_value和gd32_dac_init函数,注意dac的两个引脚对应通道是固定的
      6. 在Kconfig中添加DAC的设备名字和通道选择

    三、移植内部flash操作到GD32

    1. fal_flash_stm32l4_port.c文件需要适配gd32
    2. rt_sfud_flash_probe(SPI_FLASH_CHIP, SPI_FLASH_DEVICE_NAME)中的SPI_FLASH_CHIP找不到定义,将SPI_FLASH_CHIP改为自己外部flash芯片的名字或者规定名字
    3. drv_flash需手动实现(具体实现文件在工程中搜drv_flash.c和fmc_operation.c),用于对片内和片外flash的访问读写等操作,实现过程的一些记录
      1. 添加drv_flash源文件和头文件
      2. 在gd32驱动库脚本中添加drv_flash.c路径,修改SOC_SERIES_STM32L4为SOC_SERIES_GD32F4xx
      3. 在gd32标准库脚本中添加gd32f4xx_fmc.c路径
      4. 添加fmc_operation头文件和源文件及脚本路径
      5. stm32_onchip_flash中的FLASH_PAGE_SIZE改为SIZE_4KB,gd32只有少数芯片支持页擦除即4k擦除,如果是不支持页擦除的芯片不可以用SIZE_4KB,要根据块来定,不同位置的块大小不一样
      6. 添加flash起始和结束地址
      7. 重写fal_flash_read、fal_flash_write函数
      8. 添加fal_flash_erase函数
      9. 将fal_flash_stm32l4_port.c改为fal_flash_gd32f4_port.c,并在脚本中添加路径
      10. 添加get_page和fmc_page_erase函数
      11. 添加FMC_PECFG和FMC_PEKEY寄存器
      12. 添加UNLOCK_PAGE_KEY定义
      13. 在flash读写操作中添加操作状态返回

    四、移植外部flash操作及spi到GD32

    1. spi底层未初始化正确,会卡在rt_assert_handler,assertion failed at function:rt_hw_spi_device_attach, line number:419 ,即注册失败,可能原因是序号错误、引脚定义或复用错误
    2. 报错:“no source”: Error: #219: error while deleting file “.\build\keil\obj\gd32_drivers_drv_spi.d”: Permission denied;原因是每次通过env生成过程的时候会自动加入gd32_drivers_drv_spi.c文件,找了各个构建文件都没有这个文件,但是显示到了keil的project上,没法打开,也不存在这个文件; 解决方法:将gd32_drivers_drv_spi.c去掉或者禁止编译
    3. libraries\gd32_drivers\drv_spi_flash.c(89): error: At end of source: #65: expected a “;” 在INIT_COMPONENT_EXPORT(rt_hw_spi_flash_with_sfud_init)后面加一个;
    4. 缺少stm32_onchip_flash的定义,gd32_drivers没有drv_flash文件夹,暂时将stm32_onchip_flash也改为nor_flash0
    5. 没有板载flash或者flash损坏情况会卡在sfud_device_init(sfud_dev)这里,错误原因是SFUD_ERR_NOT_FOUND,为了后续测试可以先屏蔽此错误(屏蔽rt_sfud_flash_probe(“xxxxx”, xxxxx_SPI_DEVICE_NAME))

    五、移植定时器和时钟配置

    1. GD32标准库没有drv_pwm文件,暂不支持DMA和捕获,手动实现(具体实现文件在工程中搜drv_pwm.c),实现过程的一些记录

      1. 修改gd32_drivers的SConscript文件,添加手动实现的pwm源文件及drv_log头文件
      2. 修改Kconfig以适配不同库对同一外设的不同命名,比如BSP_USING_TIM改为BSP_USING_HWTIMER
      3. 修改标准库的脚本文件添加gd32f4xx_timer.c
      4. 按着标准库提供的文件添加TIM_HandleTypeDef定义,暂时去掉DMA相关的内容
      5. 添加pwm_config头文件,修改其中.tim_handle.Instance为gd32标准库格式并添加定时器0
      6. 修改HAL_TIM_ActiveChannel定义
      7. 使用移位实现__HAL_TIM_GET_CLOCKDIVISION等简单hal函数
      8. 使用gd32库函数重新实现_HAL_TIM_SET_PRESCALER、_HAL_TIM_SET_AUTORELOAD、__HAL_TIM_SET_COUNTER、__HAL_TIM_GET_COMPARE等复杂一些函数
      9. 根据GD32时钟树及hal库逻辑重写drv_pwm_get和drv_pwm_set函数(只适配了f4)
      10. 未找到HAL_TIM_GenerateEvent对应的替代函数,暂时使用timer_disable和timer_enable代替
      11. 替代TIM_OC_InitTypeDef和__HAL_TIM_URS_ENABLE,未找到TIM_MasterConfigTypeDef和TIM_ClockConfigTypeDef的替代
      12. HAL_TIM_Base_Init替换为timer_init,timer_init没有初始化失败返回,未找到HAL_TIM_PWM_Init替代,注意gd32库中基本没有pwm的定义,取而代之的是TIMER channel output的定义
      13. 替代pwm初始化关于时钟源相关的配置
      14. 将timer0添加到CK_APB2判断中(需要查看数据手册的时钟树)
      15. HAL_TIMEx_MasterConfigSynchronization未找到替代,应该是输入捕获相关的,暂不需要实现
      16. 参考hal_msp文件实现pwm输出引脚映射函数GD32_TIM_MspPostInit(TIM_HandleTypeDef* htim),没有cubemx了,这个函数每次更换引脚后要手动更新
      17. 修改pwm_get_channel函数中数据填充内容
      18. 按照hal库的stm32_hw_pwm_init逻辑重新实现gd32_hw_pwm_init
      19. pwm的时间不对,1khz出来4khz,修改分频clockdivision不起作用,将分频prescaler扩大4倍起作用
      20. gd32库未提供pwm单通道开关函数(用的另一种方式实现,但这种方式和rt-thread的调用顺序相违背),只有某定时器开关函数,暂不实现对pwm单通道的开关,默认设置pwm后自动输出

    六、其它

    1. 修改I2C0驱动不兼容的问题,I2C4_BUS_CONFIG修改为I2C0_BUS_CONFIG
    2. GPIO相关的一些重映射
#define GPIO_PIN_RESET       RESET
#define GPIO_PIN_SET         SET#define HAL_GPIO_WritePin(GPIOx, GPIO_Pin, PinState)   gpio_bit_write(GPIOx, GPIO_Pin, PinState)
#define HAL_GPIO_ReadPin(GPIOx, GPIO_Pin)    gpio_input_bit_get(GPIOx, GPIO_Pin)#define __HAL_RCC_GPIOA_CLK_ENABLE() rcu_periph_clock_enable(RCU_GPIOA)
#define __HAL_RCC_GPIOB_CLK_ENABLE() rcu_periph_clock_enable(RCU_GPIOB)#define HAL_GPIO_DeInit(GPIOx, GPIO_Pin)   __NOP  //gpio_deinit(GPIOx)  gd32没有初始化单个引脚,只有port#define HAL_Delay(Delay)   rt_thread_mdelay(Delay)
  1. 一些外设测试函数
//test   OTA extern void rt_fota_init(void);rt_fota_init();//test    adc     extern int16_t get_adc_temperature_value(void);uint16_t vol = get_adc_temperature_value();LOG_I("the controller temperature is :%dmV", vol);//test   dac rt_dac_device_t dac_dev = (rt_dac_device_t)rt_device_find(BSP_USING_RF_PA_VBIAS_DAC_DEVICE_NAME);if (dac_dev == RT_NULL){LOG_E(find_device_Err, BSP_USING_RF_PA_VBIAS_DAC_DEVICE_NAME);}rt_dac_enable(dac_dev, BSP_USING_RF_PA_VBIAS_DAC_DEVICE_CHANNEL);for(uint16_t i=0; i<4095; i++)    {rt_thread_mdelay(10);rt_dac_write(dac_dev, BSP_USING_RF_PA_VBIAS_DAC_DEVICE_CHANNEL, i);}
//test  pwmrt_pwm_set(pwm_device, TIMER_CH_0, LED_STATE_PERIOD, LED_STATE_PERIOD/2);//设置pwm设备的TIMER_CH_0通道  //test  wkuprt_thread_mdelay(2000);LOG_I("enter standbymode");rt_thread_mdelay(2000);Sys_Enter_Standby();LOG_I("out standbymode");//test    gpiort_pin_write(LEDR_PIN, PIN_LOW);rt_thread_mdelay(1000);rt_pin_write(LEDR_PIN, PIN_HIGH);    extern rt_uint8_t key_up_read_pin();uint8_t IO = key_up_read_pin();LOG_I("the io state is :%d", IO);

二、在rt-thread环境下移植HAL库到GD32

  1. GD32也可以使用hal库,但是异常比较多,可以使用标准库,把之前的hal库的函数用类似的标准库函数替代

  2. CubeMX_Config文件夹的内容需要做适配,不用hal也要适配,否则找不到main.h文件(board\CubeMX_Config\Core\Inc\main.h)

  3. stm32l4xx_hal.h文件和gd32f30x.h不一样,gd32f30x.h和stm32l476xx.h一样是地址映射相关的内容

  4. libraries\GD32F30x_Firmware_Library\CMSIS\GD\GD32F30x\Include\gd32f30x.h(115): error: #101: “NonMaskableInt_IRQn” has already been declared in the current scope:出现上述错误是因为重定义了,需要把CubeMX_Config文件中的l4相关的内容去掉

  5. 报错 #error “Please select the target GD32F4xx device in gd32f4xx.h file”,是因为标准库没有定义GD32F42x,需要在keil的宏定义里面点击魔术棒->C/C++/Define,添加GD32F405,或者修改board文件夹下面的SConscript文件中的GD32F425为GD32F405(这是长久生效的方法),F405和407是最接近的

  6. 修改引用头文件stm32l4xx.h为gd32f4xx.h

  7. 直接复制移植HAL_StatusTypeDef定义

  8. libraries\GD32F4xx_Firmware_Library\CMSIS\GD\GD32F4xx\Include\gd32f4xx.h(292): error: #40: expected an identifier

    typedef enum {FALSE = 0, TRUE = !FALSE} bool; 参考解决方法,省流:重复定义了

  9. GPIO_MODE_AF_PP显示未定义 原因:SOC_SERIES_GD32F4xx未定义导致"gd32f4xx_gpio.h"未被添加进来,解决方法:board\Kconfig文件config SOC_SERIES_GD32F425RG改为SOC_SERIES_GD32F4xx

  10. 重新实现SystemClock_Config

    void SystemClock_Config(void)
    {SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);systick_clksource_set(SYSTICK_CLKSOURCE_HCLK);NVIC_SetPriority(SysTick_IRQn, 0xFF);
    }
    
  11. 重新实现进入低功耗函数Sys_Enter_Standby

    int Sys_Enter_Standby(void)
    {   rcu_periph_clock_enable(RCU_PMU);pmu_wakeup_pin_enable();pmu_to_standbymode(WFI_CMD);   //notice:WFI need EXTI interrupt wakeup return 0;
    }
    
  12. 注意stm32l476有5个wkup唤醒源引脚,gd32只有一个PA0引脚做待机唤醒用

  13. gd32没有实现类似HAL_PWREx_DisablePullUpPullDownConfig的函数,即gd32没有进入待机模式后锁定某个引脚状态的功能

  14. 移植获取uid的相关定义

uint32_t UUID = FMC_PID;
```

  1. 将__HAL_PWR_GET_FLAG(PWR_FLAG_SB)替换为pmu_flag_get(PMU_CS_STBF)

  2. 将__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);替换为pmu_flag_reset(PMU_FLAG_RESET_STANDBY);

  3. 将HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN5);改为pmu_wakeup_pin_disable();

  4. HAL_RCC_DeInit改为rcu_deinit

三、在rt-thread环境下移植bootloader/OTA到GD32

  1. rt-thread的bootloader不开源,可参考及移植的开源项目https://toscode.gitee.com/Aladdin-Wang/RT-FOTA-STM32L431和https://gitee.com/spunky_973/rt-fota?_from=gitee_search

  2. 添加或者去掉bootloader时需要修改\board\linker_scripts\link.sct,或者点击keil->options->linker->scatter file->edit,修改LR_IROM1和ER_IROM1的起始地址,比如bootloader占256k,就改为0x08040000

  3. 程序中关于中断偏移的要修改,正常的话就nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0);偏移256k的话就 nvic_vector_table_set(NVIC_VECTTAB_RAM, 0x40000);或者沿用自己的方式

  4. SCB->VTOR在单片机的数据手册找不到,可以取M4内核编程手册上查找

  5. RF-FOTA开源移植过程的一些记录

    1. 打开ymodem配置,为了方便开关ota功能,在kconfig中添加PKG_USING_YMODEM_OTA相关定义,用于开启rf_fota.h中关于ota的宏定义,并修改fm_area为下载分区,df_area为工程文件分区

      #ifdef PKG_USING_YMODEM_OTA#define RT_USING_SPI
      #define RT_USING_SFUD
      #define RT_SFUD_USING_SFDP
      #define RT_SFUD_USING_FLASH_INFO_TABLE
      #define RT_USING_WDT/* FOTA application partition name */
      #ifndef RT_FOTA_APP_PART_NAME
      #define RT_FOTA_APP_PART_NAME   "app"
      #endif/* FOTA download partition name */
      #ifndef DEFAULT_DOWNLOAD_PART_NAME
      #define DEFAULT_DOWNLOAD_PART_NAME    "download"
      #endif/* FOTA default partition name */
      #ifndef DEFAULT_FACTORY_PART_NAME
      #define DEFAULT_FACTORY_PART_NAME    "factory"
      #endif/* AES256 encryption algorithm option */
      #define RT_FOTA_ALGO_AES_IV     "0123456789ABCDEF"
      #define RT_FOTA_ALGO_AES_KEY    "0123456789ABCDEF0123456789ABCDEF"/* RT-FOTA module define */
      #define RT_FOTA_SW_VERSION      "1.0.0"#endif#define FAL_PART_TABLE                                                               \
      {                                                                                    \{FAL_PART_MAGIC_WORD,    "bl",          "onchip_flash",                0*128*1024,    128*1024, 0}, \{FAL_PART_MAGIC_WORD,    "app",         "onchip_flash",                2*128*1024,    256*1024, 0}, \{FAL_PART_MAGIC_WORD,    "download",    "onchip_flash",                4*128*1024,    256*1024, 0}, \{FAL_PART_MAGIC_WORD,    "factory",     "onchip_flash",                6*128*1024,    256*1024, 0}, \
      }

    2. 添加FastLZ库、QuickLZ库、 SignalLed库,这些库在fota上用

    3. 因为用的是片内flash升级,开源是片外的,为了省一些bin的大小,去掉片外相关的内容,比如sfud和nor_flash0

    4. 屏蔽掉fal库中fal_flash_sfud_port.c的内容

    5. 添加WWDG_IRQn定义,定义为0

    6. HAL_RCC_DeInit();改为rcu_deinit();

    7. 重新实现HAL_DeInit(); – 添加复位所有外设的实现,复位之后清除复位标志,未找到复位时钟,例

        rcu_periph_reset_enable(RCU_GPIOARST);rcu_periph_reset_disable(RCU_GPIOARST);·····
      
    8. 原工程未定义按键恢复出厂及按键时间,可以加上

    9. 因为是从原gd32工程复制过来修改成bootloader的,注意修改中断偏移和link.sct、各个线程的顺序和一些重要参数(比如rt_system_scheduler_init、rt_hw_board_init)的一致性,尽量把之前没用的外设关掉,没用的文件输出,保证bootloader的精简

    10. 打开“Options for target…”->“target”勾选“Use MiclroLIB”,否则一仿真就在BEAB BKPT 0xAB

    11. 添加是否进入shell mode的提示,打开FAL_DEBUG

    12. GD32的FMC读取一次最多256字节,OTA搬移的时候一次需要4k,fmc_read_8bit_data的读取长度改为32位

    13. 将fmc_write_8bit_data中的擦除函数去掉,因为在fal_flash_erase中重定义fal_flash_erase了,否则会crc校验错误

    14. 通过Xshell进入控制台后,发送ymdown -p factory可以直接将rbl文件升级到工厂固件区

    15. FOTA未实现hash校验功能,https://gitee.com/spunky_973/rt-fota/issues/I41CTW这里面有实现

    16. 其它一些issues见https://toscode.gitee.com/Aladdin-Wang/RT-FOTA-STM32L431/issues/I1S58N和https://gitee.com/spunky_973/rt-fota/issues

    17. 移植的rbl文件如果打不开,可以添加.bin的后缀,使用STM32 ST-LINK Utility或者BCompare.exe打开

四、移植GD32遇到的和程序无关keil报错

  1. browse information of one or more file is not available:.\xx\xxxx.c,解决方法:注释再取消注释文件 ①全选文件中的代码,按下注释键,编译 ②再全选,按下取消注释,问题就解决了
  2. 插上jlink报错没识别到f427,会自动跳出一个页面选择,这时候选择f407rg可以互相兼容
  3. keil显示encountered an improper argument,后台中止重新启动
  4. 打开“Options for target…”->“target”勾选“Use MiclroLIB”,否则一仿真就在BEAB BKPT 0xAB
  5. 在rtt的配置工具中使用scons --target=mdk5 -s生成工程后会出现一个文件夹中没有的文件,命名格式是它的路径+文件名,比如src文件下的timer.c会变成src_timer.c,这样编译的时候会显示找不到这个文件或者报错误1,原因是还有一个别的路径下也有一个timer.c,重复,系统自动改名字了,解决方法是修改重复文件的名字,重新scons --target=mdk5 -s

五、移植过程中添加的pwm驱动、dac驱动、flash驱动、RTC驱动、OTA例程

本来想给上传到rt-thread的github库,但之前没上传过别人的库,也没有做其它型号芯片的兼容,所以发到博客上吧

GD32 RT-Thread PWM驱动函数

GD32 RT-Thread DAC驱动函数

GD32 RT-Thread flash驱动函数

GD32 RT-Thread RTC驱动函数

GD32 RT-Thread OTA/Bootloader驱动函数

移植完整版RT-Thread到GD32F4XX(详细)相关推荐

  1. python使用kafka原理详解真实完整版_史上最详细Kafka原理总结

    Kafka Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(partition).多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实 ...

  2. 一天一阔阔儿ZYNQ的linux移植完整版(Linux环境搭建以及内核编译)

    虚拟机UBUNTU12.04 64bit 701N 芯片是7020clg400 XILINX的交叉编译器安装 主要就是安装出现的一些问题,方法总结: 主要涉及的问题是,ubuntu12.04 64位系 ...

  3. 开关电源传导篇(完整版)-有图有真相

    开关电源传导篇(完整版) 1.前沿 电源产品在做验证时,经常会遭遇到电磁干扰(EMI)的问题,有时处理起来需花费非常多的时间,许多工程师在对策电磁干扰时也是经验重于理论,知道哪个频段要对策那些组件,但 ...

  4. Qgis3.2编译移植成功文档完整版

    Qgis3.2编译移植成功文档完整版 1.1平台环境 VS2015 + QT5.9.2 + Cmake + OSGEO4W 具体环境搭建,参考博客https://blog.csdn.net/xiong ...

  5. RT-Thread完整版fal及easyflash移植

    最近深圳开始隔离了,居家办公对于我们这种需要做验证仿真的,而家伙都没在手上的打工人太难了.因为最近项目需要用到fal加easyflash软件包,而之前搞过,但是忘记具体的了.还好留有文档,现在也转为文 ...

  6. JavaScript + Audio API自制简易音乐播放器(详细完整版、小白都能看懂)

    JavaScript + Audio API自制简易音乐播放器(详细完整版) ** 音乐播放器的功能清单如下: ** 1.点击暂停按钮,歌曲暂停 2.点击播放按钮,歌曲播放 3.单曲循环与取消单曲循环 ...

  7. ASCII码表 0-255完整版 附详细注释

    信息在计算机上是用二进制表示的,这种表示法让人理解就很困难.因此计算机上都配有输入和输出设备,这些设备的主要目的就是,以一种人类可阅读的形式将信息在这些设备上显示出来供人阅读理解.为保证人类和设备,设 ...

  8. 2018大数据培训学习路线图(详细完整版)

    2018大数据培训学习路线全课程目录+学习线路详解(详细完整版) 第一阶段:大数据基础Java语言基础阶段 1.1:Java开发介绍 1.1.1 Java的发展历史 1.1.2 Java的应用领域 1 ...

  9. 超级详细!!!Spring、SpringMVC、Mybatis知识点完整版更新!IOD、DI依赖注入、Mybatis配置、SQL、MVC拦截器、Web开发、SSM整合案例。

    Spring Spring框架知识点完整版 上篇,SSM三部曲之一 知识点涵盖:Spring简介IOC控制反转DI依赖注入LombokSPEL配置文件低频知识点注解开发Spring常用注解 链接:ht ...

最新文章

  1. 安装完Arch后,要安装的软件
  2. aop对请求后端的参数修改_Spring Boot AOP之对请求的参数入参与返回结果进行拦截处理...
  3. Linux实现最常用的磁盘阵列--RAID5
  4. Sed:以/etc/passwd文件为模板
  5. 用python计算两个二维list依据第二维的前一个数据相加
  6. tortoisegit推送ssh-key需要输入用户信息
  7. java 获取文件的全路径
  8. Atitti 过程导向 vs 结果导向 attilax的策略
  9. AUTOCAD——标注关联
  10. 传智播客黑马程序员_Hanselminutes播客48-适用于极客和程序员的入门棋盘游戏
  11. 实验七matlab数值计算,数学应用软件实验报告---MATLAB的数值计算
  12. [洛谷1849] 拖拉机
  13. 饥荒联机版专属服务器建立和后续mod更新
  14. Android 免root 备份数据,教你安卓手机免Root恢复手机数据的三种方法
  15. (深度神经网络多.py文件)python打包过程遇到的问题记录
  16. 程序逸的Java项目之旅-图书管理系统之环境的搭建
  17. 对称加密——AES算法使用
  18. 两个List数据集合合并成一个List
  19. centos7.4/rehat7.0系统安装
  20. Mongodb 索引 对查询结果的排序

热门文章

  1. 百度在年前会在打击一轮快排!
  2. python中字符串常用方法
  3. 人的好奇心是有多强。
  4. 燕十八老师 JS高级学习笔记 之作用域链
  5. 姜命 扬州格外机器人_机器人抢饭碗 苏州昆山一工厂少用5万工人
  6. 南京邮电大学C语言实验报告4v2(仅供参考)
  7. 常见的XSS攻击方法
  8. app架构升级,该如何高效实用Kotlin?学习路线+知识点梳理
  9. 机器学习基础(完结篇)—初识推荐系统与计算机视觉
  10. 如何设置wordpress多语言站点