一、开发板平台简介:
1、开发板资源简介
(1)开发板主芯片型号:GD32F303RCT6
(2)开发板主芯片封装:LQFP-64_10x10x05P
(3)开发板主芯片内核:ARM® Cortex®-M4
(4)开发板主芯片主频:120MHz
(5)开发板主芯片Flash大小:256KB
(6)开发板主芯片RAM大小:48KB
2、Debug调试串口简介
串口全称为串行通讯接口,即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平,串口需要RXD、TXD、GND三根线进行通信。
(1)我们选用的GD32F303RCT6开发板串口0已通过USB转TLL串口芯片CH340G引出,使用时,只需要用公对公USB线连接电脑即可(注意也得安装CH340G驱动)。
(2)开发板上的其他串口已通过排针引出,为TTL电平,通信的时候需要注意选择对应的电平模块,如USB转TTL串口模块等。
二、快速上手RT-Thread
1、选择合适的BSP
(1)我们这里选择GD32303E-EVAL BSP驱动进行移植。可通过如下参考链接下载bsp:
GD32303E-EVALhttps://github.com/RT-Thread/rt-thread/tree/master/bsp/gd32303e-eval
(2)下载上述bsp后就可以在开发板上进行移植尝试了。
2、移植BSP
已下载的GD32303E-EVEL BSP工程文件,是使用 GD32F303ZET6 作为主控制器的,想要移植到我们的GD32F303RCT6开发板上,需要进行简单的修改,如下:
(1)找到gd32f303-bsp文件,并打开项目。
(2)选择options for target-->选择GD32F303RC芯片。
(3)选择对应的下载器,我这里使用的是jlink ,并选择SWD下载模式。
(4) 设置Flash Download下载模式。
(5)那么接下来重点来了,直接下载的代码在GD32F303RCT6是无法运行的,因为GD32F303ZET6的RAM大小为64K,但是GD32F303RCT6的RAM大小为48K。此处需要在board.h头文件中把RAM大小(GD32_SRAM_SIZE)修改为48,如下所示:
(6)修改后,重新编译下载,即可通过Debug串口看到打印的log信息。
三、添加w25q SPI线程
1、新建线程并启动
在components.c文件中,找到rt_application_init(void)函数,并添加新建rtc时钟线程的声明。
rt_thread_t zyxc_w25q_thread;
zyxc_w25q_thread=rt_thread_create("w25q", zyxc_w25q_thread_entry, RT_NULL,1024, 28, 20); //创建SPI线程
if(zyxc_w25q_thread!= RT_NULL)
{
rt_thread_startup(zyxc_w25q_thread);
}
2、添加w25q SPI驱动函数
(1)新建zyxc_w25q.c并添加所需的头文件。
#include "zyxc_w25q.h"
#include "gd32f30x.h"
#include <string.h>
#include <rtthread.h>
(2)打开zyxc_rtc.c文件,并在其中编写w25q函数执行语句,如下所示:
/********************************************
*函数名称:void zyxc_w25q_thread_entry(void *parameter)
*函数功能:空闲线程
*备注:用于看门狗、指示灯等空闲操作
********************************************/
void zyxc_w25q_thread_entry(void *parameter)
{
uint32_t flash_id = 0;
uint16_t i = 0;
uint8_t tx_buffer[TX_BUFFER_SIZE];
uint8_t rx_buffer[TX_BUFFER_SIZE];
uint8_t is_successful = 0;
uint8_t count=0;
/* configure SPI0 GPIO and parameter */
spi_flash_init();
/* GD32303E-EVAL-V1.0 Start up */
rt_kprintf("\n\r###############################################################################\n\r");
rt_kprintf("\n\rGD32303E-EVAL-V1.0 System is Starting up...\n\r");
rt_kprintf("\n\rGD32303E-EVAL-V1.0 Flash:%dK\n\r",*(__IO uint16_t*)(0x1FFFF7E0));
/* get chip serial number */
get_chip_serial_num();
/* printf CPU unique device id */
rt_kprintf("\n\rGD32303E-EVAL-V1.0 The CPU Unique Device ID:[%X-%X-%X]\n\r",int_device_serial[2],int_device_serial[1],int_device_serial[0]);
rt_kprintf("\n\rGD32303E-EVAL-V1.0 SPI Flash:GD25Q16 configured...\n\r");
/* get flash id */
flash_id = spi_flash_read_id();
rt_kprintf("\n\rThe Flash_ID:0x%X\n\r",flash_id);
/* flash id is correct */
if(flash_id!=0xFFFFFFFF) {
rt_kprintf("\n\r\n\rWrite to tx_buffer:\n\r\n\r");
/* printf tx_buffer value */
for(i = 0; i < BUFFER_SIZE; i ++) {
tx_buffer[i] = i;
rt_kprintf("0x%02X ",tx_buffer[i]);
if(15 == i%16)
rt_kprintf("\n\r");
}
rt_kprintf("\n\r\n\rRead from rx_buffer:\n\r");
/* erases the specified flash sector */
spi_flash_sector_erase(FLASH_WRITE_ADDRESS);
/* write tx_buffer data to the flash */
spi_flash_buffer_write(tx_buffer,FLASH_WRITE_ADDRESS,TX_BUFFER_SIZE);
rt_thread_delay(10);
/* read a block of data from the flash to rx_buffer */
spi_flash_buffer_read(rx_buffer,FLASH_READ_ADDRESS,RX_BUFFER_SIZE);
/* printf rx_buffer value */
for(i = 0; i <= 255; i ++) {
rt_kprintf("0x%02X ", rx_buffer[i]);
if(15 == i%16)
rt_kprintf("\n\r");
}
if(ERROR == memory_compare(tx_buffer,rx_buffer,256)) {
rt_kprintf("Err:Data Read and Write aren't Matching.\n\r");
is_successful = 1;
}
/* spi flash test passed */
if(0 == is_successful) {
rt_kprintf("\n\rSPI-GD25Q16 Test Passed!\n\r");
}
} else {
/* spi flash read id fail */
rt_kprintf("\n\rSPI Flash: Read ID Fail!\n\r");
}
while(1)
{
rt_thread_delay(5);
}
}
(3)新建zyxc_w25q.h头文件并声明调用函数。
/*!
\file gd25qxx.h
\brief the header file of SPI flash gd25qxx driver
\version 2021-03-23, V2.0.0, demo for GD32F30x
*/
/*
Copyright (c) 2021, GigaDevice Semiconductor Inc.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE.
*/
#ifndef GD25QXX_H
#define GD25QXX_H
#include "gd32f30x.h"
#define SPI_FLASH_PAGE_SIZE 0x100
#define SPI_FLASH_CS_LOW() gpio_bit_reset(GPIOB, GPIO_PIN_12)
#define SPI_FLASH_CS_HIGH() gpio_bit_set(GPIOB, GPIO_PIN_12)
#define BUFFER_SIZE 256
#define TX_BUFFER_SIZE BUFFER_SIZE
#define RX_BUFFER_SIZE BUFFER_SIZE
#define VERSION_ID "1.0.0"
#define FLASH_WRITE_ADDRESS 0x000000
#define FLASH_READ_ADDRESS FLASH_WRITE_ADDRESS
/* initialize SPI0 GPIO and parameter */
void spi_flash_init(void);
/* erase the specified flash sector */
void spi_flash_sector_erase(uint32_t sector_addr);
/* erase the entire flash */
void spi_flash_bulk_erase(void);
/* write more than one byte to the flash */
void spi_flash_page_write(uint8_t* pbuffer,uint32_t write_addr,uint16_t num_byte_to_write);
/* write block of data to the flash */
void spi_flash_buffer_write(uint8_t* pbuffer,uint32_t write_addr,uint16_t num_byte_to_write);
/* read a block of data from the flash */
void spi_flash_buffer_read(uint8_t* pbuffer,uint32_t read_addr,uint16_t num_byte_to_read);
/* read flash identification */
uint32_t spi_flash_read_id(void);
/* initiate a read data byte (read) sequence from the flash */
void spi_flash_start_read_sequence(uint32_t read_addr);
/* read a byte from the SPI flash */
uint8_t spi_flash_read_byte(void);
/* send a byte through the SPI interface and return the byte received from the SPI bus */
uint8_t spi_flash_send_byte(uint8_t byte);
/* send a half word through the SPI interface and return the half word received from the SPI bus */
uint16_t spi_flash_send_halfword(uint16_t half_word);
/* enable the write access to the flash */
void spi_flash_write_enable(void);
/* poll the status of the write in progress (wip) flag in the flash's status register */
void spi_flash_wait_for_write_end(void);
void get_chip_serial_num(void);
ErrStatus memory_compare(uint8_t* src, uint8_t* dst, uint16_t length);
void zyxc_w25q_thread_entry(void *parameter);
#endif /* GD25QXX_H */
(4)在components.c文件中包含头文件#include "zyxc_w25q.h"。
四、配置KEIL软件下载选项
(1)点击“options for target”——Debug——Jlink/J-TRACE cortex(小编这里用到下载器是
GD32 Jlink OB下载器)——settings——选择SW看到右侧有Device Name即下载器找到了对应的GD32F303RCT6芯片。
(2)选择Flash Download下载模式,这里端子了擦除整片芯片,以及下载程序后自动复位(Reset and run)。
(3)下载完成后,打开串口助手,即可看到w25q flash芯片读写OK。
如下所示:
备注:看到GD32F303RCT6开发板上LED1、LED2、LED3、LED4每隔1S闪烁一次,此功能为额外添加的idle空闲功能,用于提示开发板系统正常工作。