简介:立创逻辑派FPGA-G1开发板,搭载国产高云GW2A-LV18,融合GD32F303的M4内核。提供入门资料和近百款模块移植案例、步骤清晰的教程帮助初学者更快地掌握FPGA基础知识。我将针对立创逻辑派FPGA-G1开发板,结合其国产高云GW2A-LV18 FPGA和GD32F303 M4内核的特性,详细阐述一个可靠、高效、可扩展的嵌入式系统开发流程,并给出相应的代码架构和C语言实现。
系统概述
立创逻辑派FPGA-G1开发板是一个强大的混合架构平台,它结合了FPGA的并行处理能力和微控制器的灵活性。这种架构非常适合于需要高性能计算和实时控制的应用场景。我们的系统设计目标是充分利用这两种资源的优势,构建一个模块化、可重用、易于维护和升级的嵌入式系统。
1. 需求分析
在开始代码编写之前,我们需要明确系统的需求。基于FPGA和M4内核的特性,我们假设以下应用场景:
- 高速数据采集与处理: 通过FPGA采集高速传感器数据(如ADC),并在FPGA内部进行预处理(如滤波、FFT),然后将处理结果传输给M4内核。
- 实时控制: M4内核负责系统的整体控制,如控制电机、LED显示、与上位机通信等。
- 用户交互: 通过按键、数码管等进行简单的用户交互。
- 扩展性: 系统架构应支持未来添加新的模块和功能。
2. 系统架构设计
为了实现上述需求,我将采用分层架构,将系统划分为以下几个层次:
- 硬件抽象层 (HAL): 提供对硬件资源的抽象接口,如GPIO、ADC、UART、SPI、I2C等。
- FPGA加速层 (FAL): 提供在FPGA内部实现的加速模块的接口,如高速数据采集和预处理。
- 服务层 (Services): 提供各种服务,如数据处理、传感器驱动、控制算法、通信协议等。
- 应用层 (Application): 系统的具体应用逻辑,如数据采集、处理和展示、控制等。
2.1 代码结构
Project_G1/
├── inc/ # 头文件目录
│ ├── hal/ # 硬件抽象层头文件
│ │ ├── gpio.h
│ │ ├── adc.h
│ │ ├── uart.h
│ │ ├── spi.h
│ │ ├── i2c.h
│ │ ├── timer.h
│ │ └── ...
│ ├── fal/ # FPGA加速层头文件
│ │ ├── data_acq.h
│ │ ├── processing.h
│ │ └── ...
│ ├── services/ # 服务层头文件
│ │ ├── sensor.h
│ │ ├── control.h
│ │ ├── comm.h
│ │ ├── utils.h
│ │ └── ...
│ └── app/ # 应用层头文件
│ ├── main.h
│ └── ...
├── src/ # 源文件目录
│ ├── hal/ # 硬件抽象层源文件
│ │ ├── gpio.c
│ │ ├── adc.c
│ │ ├── uart.c
│ │ ├── spi.c
│ │ ├── i2c.c
│ │ ├── timer.c
│ │ └── ...
│ ├── fal/ # FPGA加速层源文件
│ │ ├── data_acq.c
│ │ ├── processing.c
│ │ └── ...
│ ├── services/ # 服务层源文件
│ │ ├── sensor.c
│ │ ├── control.c
│ │ ├── comm.c
│ │ ├── utils.c
│ │ └── ...
│ └── app/ # 应用层源文件
│ ├── main.c
│ └── ...
├── lib/ # 第三方库
│ └── ...
├── bsp/ # 板级支持包(BSP),包含GD32的头文件和启动代码
│ ├── gd32f30x/
│ │ ├── inc/
│ │ └── src/
│ ├── startup/
│ │ └── startup_gd32f30x.s
│ └── system_gd32f30x.c
├── doc/ # 文档
│ └── ...
├── tools/ # 工具脚本和配置文件
│ └── ...
├── CMakeLists.txt # CMake 构建文件
└── .gitignore
3. 技术选型
- 编程语言: C (为主)
- 开发工具: GCC,GDB,OpenOCD(GD32),Vivado/Gowin EDA(FPGA)
- 构建系统: CMake
- 版本控制: Git
4. 代码实现 ©
以下代码将展示上述架构的实现,包括HAL层、FAL层、服务层和应用层的一些关键模块。
4.1 HAL层 (Hardware Abstraction Layer)
hal/gpio.h
#ifndef __GPIO_H__
#define __GPIO_H__
#include <stdint.h>
#include "gd32f30x.h" // 包含GD32的寄存器定义
typedef enum {
GPIO_MODE_INPUT,
GPIO_MODE_OUTPUT,
GPIO_MODE_AF
} gpio_mode_t;
typedef enum {
GPIO_SPEED_50MHZ,
GPIO_SPEED_2MHZ,
GPIO_SPEED_10MHZ
} gpio_speed_t;
typedef enum {
GPIO_PUPD_NONE,
GPIO_PUPD_UP,
GPIO_PUPD_DOWN
} gpio_pupd_t;
typedef enum {
GPIO_OUTPUT_PP, //推挽输出
GPIO_OUTPUT_OD //开漏输出
} gpio_output_t;
typedef struct {
uint32_t pin; // GPIO引脚
gpio_mode_t mode; // GPIO模式
gpio_speed_t speed; // GPIO速度
gpio_pupd_t pupd; // 上下拉模式
gpio_output_t outType; // 输出类型
} gpio_config_t;
void gpio_init(gpio_config_t *config, uint32_t port);
void gpio_write(uint32_t port, uint32_t pin, uint8_t value);
uint8_t gpio_read(uint32_t port, uint32_t pin);
void gpio_toggle(uint32_t port,uint32_t pin);
#endif
hal/gpio.c
#include "hal/gpio.h"
// 定义端口和引脚对应的GPIO寄存器地址 (基于GD32F303)
#define GPIOA_ADDR 0x40010800
#define GPIOB_ADDR 0x40010C00
#define GPIOC_ADDR 0x40011000
#define GPIOD_ADDR 0x40011400
#define GPIOE_ADDR 0x40011800
#define GPIOF_ADDR 0x40011C00
#define GPIOG_ADDR 0x40012000
#define GPIO_CRL_OFFSET 0x00
#define GPIO_CRH_OFFSET 0x04
#define GPIO_IDR_OFFSET 0x08
#define GPIO_ODR_OFFSET 0x0C
#define GPIO_BSRR_OFFSET 0x10
#define GPIO_BRR_OFFSET 0x14
#define GPIO_LCKR_OFFSET 0x18
static void RCC_EnableGPIO(uint32_t port)
{
if(port == GPIOA_ADDR) {
RCC_APB2ENR |= RCC_APB2ENR_IOPAEN; }
else if(port == GPIOB_ADDR) {
RCC_APB2ENR |= RCC_APB2ENR_IOPBEN; }
else if(port == GPIOC_ADDR) {
RCC_APB2ENR |= RCC_APB2ENR_IOPCEN; }
else if(port == GPIOD_ADDR) {
RCC_APB2ENR |= RCC_APB2ENR_IOPDEN; }
else if(port == GPIOE_ADDR) {
RCC_APB2ENR |= RCC_APB2ENR_IOPEEN; }
else if(port == GPIOF_ADDR) {
RCC_APB2ENR |= RCC_APB2ENR_IOPFEN; }
else if(port == GPIOG_ADDR) {
RCC_APB2ENR |= RCC_APB2ENR_IOPGEN; }
}
static void GPIO_SetMode(uint32_t port, uint32_t pin, gpio_config_t *config)
{
volatile uint32_t *CR = (pin < 8) ? (volatile uint32_t*)(port + GPIO_CRL_OFFSET) : (volatile uint32_t*)(port + GPIO_CRH_OFFSET);
uint32_t offset = (pin < 8) ? (pin * 4) : ((pin - 8) * 4);
uint32_t mode = 0;
if (config->mode == GPIO_MODE_INPUT)
{
mode = (config->pupd == GPIO_PUPD_UP) ? 0x08 : (config->pupd == GPIO_PUPD_DOWN ? 0x04 : 0x00);
*CR &= ~(0x0f << offset); //清空原来的设置
*CR |= mode << offset; //配置输入模式
}
else if (config->mode == GPIO_MODE_OUTPUT)
{
if(config->outType == GPIO_OUTPUT_PP) {
mode = 0x01;
}
else{
mode = 0x05;
}
mode |= (config->speed == GPIO_SPEED_50MHZ ? 0x03 << 2 : config->speed == GPIO_SPEED_2MHZ ? 0x01 << 2 : 0x02 << 2) ;
*CR &= ~(0x0f << offset);
*CR |= mode << offset;
}
else if(config->mode == GPIO_MODE_AF)
{
if(config->outType == GPIO_OUTPUT_PP) {
mode = 0x0a;


1819

被折叠的 条评论
为什么被折叠?



