立创逻辑派FPGA-G1开发板,搭载国产高云GW2A-LV18,融合GD32F303的M4内核。提供入门资料和近百款模块移植案例、步骤清晰的教程帮助初学者更快地掌握FPGA基础知识。

简介:立创逻辑派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;
           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式程序员小刘

很高兴文章有帮助到你

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值