好的,作为一名高级嵌入式软件开发工程师,我将针对立创逻辑派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 代码结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| 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. 代码实现 (C)
以下代码将展示上述架构的实现,包括HAL层、FAL层、服务层和应用层的一些关键模块。
4.1 HAL层 (Hardware Abstraction Layer)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #ifndef __GPIO_H__ #define __GPIO_H__
#include <stdint.h> #include "gd32f30x.h"
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_mode_t mode; gpio_speed_t speed; 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
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| #include "hal/gpio.h"
#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; } else{ mode = 0x0b; } mode |= (config->speed == GPIO_SPEED_50MHZ ? 0x03 << 2 : config->speed == GPIO_SPEED_2MHZ ? 0x01 << 2 : 0x02 << 2) ; *CR &= ~(0x0f << offset); *CR |= mode << offset; } }
void gpio_init(gpio_config_t *config, uint32_t port) { RCC_EnableGPIO(port); GPIO_SetMode(port,config->pin,config); }
void gpio_write(uint32_t port, uint32_t pin, uint8_t value) { volatile uint32_t *ODR = (volatile uint32_t*)(port + GPIO_ODR_OFFSET);
if (value) { *ODR |= (1 << pin); } else { *ODR &= ~(1 << pin); } }
uint8_t gpio_read(uint32_t port, uint32_t pin) { volatile uint32_t *IDR = (volatile uint32_t*)(port + GPIO_IDR_OFFSET); return (*IDR >> pin) & 0x1; } void gpio_toggle(uint32_t port,uint32_t pin){
volatile uint32_t *ODR = (volatile uint32_t*)(port + GPIO_ODR_OFFSET);
*ODR ^= (1<<pin); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| #ifndef __ADC_H__ #define __ADC_H__
#include <stdint.h> #include "gd32f30x.h"
typedef enum { ADC_RESOLUTION_12BIT, ADC_RESOLUTION_10BIT, ADC_RESOLUTION_8BIT, ADC_RESOLUTION_6BIT, } adc_resolution_t;
typedef struct { uint32_t channel; adc_resolution_t resolution; uint8_t sample_time; } adc_config_t;
void adc_init(adc_config_t *config); uint16_t adc_read(uint8_t channel);
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| #include "hal/adc.h"
#define ADC1_ADDR 0x40012400 #define ADC_CTL0_OFFSET 0x00 #define ADC_CTL1_OFFSET 0x04 #define ADC_SAMPT0_OFFSET 0x08 #define ADC_SAMPT1_OFFSET 0x0C #define ADC_OSTR_OFFSET 0x10 #define ADC_RDATA_OFFSET 0x14 #define ADC_WDATA_OFFSET 0x18 #define ADC_LST0_OFFSET 0x28 #define ADC_LST1_OFFSET 0x2C #define ADC_LST2_OFFSET 0x30 #define ADC_LST3_OFFSET 0x34
static void RCC_EnableADC() { RCC_APB2ENR |= RCC_APB2ENR_ADC1EN; } static void ADC_SetResolution(adc_resolution_t resolution) {
volatile uint32_t *CTL0 = (volatile uint32_t *)(ADC1_ADDR + ADC_CTL0_OFFSET); *CTL0 &= ~(ADC_CTL0_ADCRES_MASK); if (resolution == ADC_RESOLUTION_12BIT) { *CTL0 |= ADC_CTL0_ADCRES_12BIT; } else if (resolution == ADC_RESOLUTION_10BIT) { *CTL0 |= ADC_CTL0_ADCRES_10BIT; } else if (resolution == ADC_RESOLUTION_8BIT) { *CTL0 |= ADC_CTL0_ADCRES_8BIT; } else if (resolution == ADC_RESOLUTION_6BIT) { *CTL0 |= ADC_CTL0_ADCRES_6BIT; } } static void ADC_ConfigChannel(uint8_t channel, uint8_t sample_time) { volatile uint32_t *SAMPT0 = (volatile uint32_t *)(ADC1_ADDR + ADC_SAMPT0_OFFSET); volatile uint32_t *SAMPT1 = (volatile uint32_t *)(ADC1_ADDR + ADC_SAMPT1_OFFSET); volatile uint32_t *LST0 = (volatile uint32_t *)(ADC1_ADDR + ADC_LST0_OFFSET);
if (channel <= 9) { *SAMPT0 &= ~(0x07 << (channel * 3)); *SAMPT0 |= (sample_time << (channel * 3)); } else if(channel <= 17){ *SAMPT1 &= ~(0x07 << ((channel-10) * 3)); *SAMPT1 |= (sample_time << ((channel-10) * 3)); }
*LST0 &= ~(0x1F << (0 * 5)); *LST0 |= (channel << (0 * 5));
} void adc_init(adc_config_t *config) { RCC_EnableADC(); ADC_SetResolution(config->resolution); ADC_ConfigChannel(config->channel,config->sample_time);
volatile uint32_t *CTL0 = (volatile uint32_t *)(ADC1_ADDR + ADC_CTL0_OFFSET); *CTL0 |= ADC_CTL0_ADCON;
} uint16_t adc_read(uint8_t channel) {
volatile uint32_t *CTL1 = (volatile uint32_t *)(ADC1_ADDR + ADC_CTL1_OFFSET); volatile uint32_t *CTL0 = (volatile uint32_t *)(ADC1_ADDR + ADC_CTL0_OFFSET); volatile uint32_t *RDATA = (volatile uint32_t *)(ADC1_ADDR + ADC_RDATA_OFFSET);
*CTL1 |= ADC_CTL1_SWRCST; while (!(*CTL0 & ADC_CTL0_EOC));
return (uint16_t)*RDATA; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #ifndef __UART_H__ #define __UART_H__
#include <stdint.h> #include "gd32f30x.h"
typedef struct { uint32_t baudrate; uint8_t parity; uint8_t stopbits; uint8_t databits; } uart_config_t;
void uart_init(uart_config_t *config,uint32_t uart); void uart_send_byte(uint32_t uart, uint8_t data); void uart_send_string(uint32_t uart, char *str); uint8_t uart_receive_byte(uint32_t uart); void uart_receive_string(uint32_t uart, char *buffer, uint16_t len);
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| #include "hal/uart.h"
#define UART0_ADDR 0x40004400 #define UART1_ADDR 0x40004800 #define UART2_ADDR 0x40004C00
#define UART_CTL0_OFFSET 0x00 #define UART_CTL1_OFFSET 0x04 #define UART_CTL2_OFFSET 0x08 #define UART_BAUD_OFFSET 0x0C #define UART_STAT_OFFSET 0x10 #define UART_DATA_OFFSET 0x14 #define UART_GP_OFFSET 0x18
#define APB1_CLOCK 72000000 #define APB2_CLOCK 72000000 #define UART_DIV(baudrate,clk) ((uint32_t)((float)(clk) / (16.0 * (float)baudrate) + 0.5))
static void RCC_EnableUART(uint32_t uart) { if(uart == UART0_ADDR) { RCC_APB2ENR |= RCC_APB2ENR_AFIOEN | RCC_APB2ENR_UART0EN;} else if (uart == UART1_ADDR) {RCC_APB1ENR |= RCC_APB1ENR_UART1EN; } else if (uart == UART2_ADDR){RCC_APB1ENR |= RCC_APB1ENR_UART2EN;}
} static void GPIO_ConfigUART(uint32_t uart) { gpio_config_t gpio_config; if(uart == UART0_ADDR) { gpio_config.mode = GPIO_MODE_AF; gpio_config.speed = GPIO_SPEED_50MHZ; gpio_config.outType = GPIO_OUTPUT_PP; gpio_config.pin = GPIO_PIN_9; gpio_init(&gpio_config,GPIOA_ADDR);
gpio_config.pin = GPIO_PIN_10; gpio_config.mode = GPIO_MODE_INPUT; gpio_config.pupd = GPIO_PUPD_UP; gpio_init(&gpio_config,GPIOA_ADDR); } else if (uart == UART1_ADDR) { gpio_config.mode = GPIO_MODE_AF; gpio_config.speed = GPIO_SPEED_50MHZ; gpio_config.outType = GPIO_OUTPUT_PP; gpio_config.pin = GPIO_PIN_9; gpio_init(&gpio_config,GPIOB_ADDR);
gpio_config.pin = GPIO_PIN_10; gpio_config.mode = GPIO_MODE_INPUT; gpio_config.pupd = GPIO_PUPD_UP; gpio_init(&gpio_config,GPIOB_ADDR); } else if(uart == UART2_ADDR){ gpio_config.mode = GPIO_MODE_AF; gpio_config.speed = GPIO_SPEED_50MHZ; gpio_config.outType = GPIO_OUTPUT_PP; gpio_config.pin = GPIO_PIN_2; gpio_init(&gpio_config,GPIOA_ADDR);
gpio_config.pin = GPIO_PIN_3; gpio_config.mode = GPIO_MODE_INPUT; gpio_config.pupd = GPIO_PUPD_UP; gpio_init(&gpio_config,GPIOA_ADDR); }
}
void uart_init(uart_config_t *config,uint32_t uart) { RCC_EnableUART(uart); GPIO_ConfigUART(uart);
volatile uint32_t *CTL0 = (volatile uint32_t*)(uart + UART_CTL0_OFFSET); volatile uint32_t *CTL1 = (volatile uint32_t*)(uart + UART_CTL1_OFFSET); volatile uint32_t *BAUD = (volatile uint32_t*)(uart + UART_BAUD_OFFSET);
*CTL0 &= ~(UART_CTL0_WL | UART_CTL0_PCEN | UART_CTL0_STB); if (config->databits == 9) { *CTL0 |= UART_CTL0_WL_9BIT; } if(config->parity == 1) {*CTL0 |= UART_CTL0_PCEN | UART_CTL0_PCE;} else if(config->parity == 2) { *CTL0 |= UART_CTL0_PCEN;} if (config->stopbits == 2) { *CTL0 |= UART_CTL0_STB; } *BAUD = UART_DIV(config->baudrate,(uart==UART0_ADDR)? APB2_CLOCK:APB1_CLOCK);
*CTL1 |= UART_CTL1_UEN | UART_CTL1_TEN | UART_CTL1_REN;
}
void uart_send_byte(uint32_t uart, uint8_t data) { volatile uint32_t *STAT = (volatile uint32_t*)(uart + UART_STAT_OFFSET); volatile uint32_t *DATA = (volatile uint32_t*)(uart + UART_DATA_OFFSET); while (!(*STAT & UART_STAT_TBE)); *DATA = data;
}
void uart_send_string(uint32_t uart, char *str) { while (*str) { uart_send_byte(uart, *str++); } } uint8_t uart_receive_byte(uint32_t uart) { volatile uint32_t *STAT = (volatile uint32_t*)(uart + UART_STAT_OFFSET); volatile uint32_t *DATA = (volatile uint32_t*)(uart + UART_DATA_OFFSET); while (!(*STAT & UART_STAT_RBNE)); return (uint8_t)*DATA; } void uart_receive_string(uint32_t uart, char *buffer, uint16_t len) { for (uint16_t i = 0; i < len; i++) { buffer[i] = uart_receive_byte(uart); if (buffer[i] == '\0') { break; } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #ifndef __TIMER_H__ #define __TIMER_H__
#include <stdint.h> #include "gd32f30x.h"
typedef enum { TIMER_MODE_ONE_SHOT, TIMER_MODE_CONTINUOUS } timer_mode_t;
typedef struct { uint32_t prescaler; uint32_t period; timer_mode_t mode; } timer_config_t; void timer_init(timer_config_t *config,uint32_t timer); void timer_start(uint32_t timer); void timer_stop(uint32_t timer); void timer_enable_interrupt(uint32_t timer); void timer_disable_interrupt(uint32_t timer); void timer_clear_flag(uint32_t timer); #endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| #include "hal/timer.h" #define TIMER0_ADDR 0x40012C00 #define TIMER1_ADDR 0x40012800 #define TIMER2_ADDR 0x40000000 #define TIMER3_ADDR 0x40000400
#define TIMER_CTL0_OFFSET 0x00 #define TIMER_CTL1_OFFSET 0x04 #define TIMER_SMCFG_OFFSET 0x08 #define TIMER_DMAINTEN_OFFSET 0x0C #define TIMER_INTF_OFFSET 0x10 #define TIMER_SWINT_OFFSET 0x14 #define TIMER_PSC_OFFSET 0x28 #define TIMER_CAR_OFFSET 0x2C #define TIMER_CNT_OFFSET 0x30 #define TIMER_CH0CV_OFFSET 0x34 #define TIMER_CH1CV_OFFSET 0x38 #define TIMER_CH2CV_OFFSET 0x3C #define TIMER_CH3CV_OFFSET 0x40
static void RCC_EnableTimer(uint32_t timer) { if(timer == TIMER0_ADDR) { RCC_APB2ENR |= RCC_APB2ENR_TIMER0EN; } else if (timer == TIMER1_ADDR) {RCC_APB2ENR |= RCC_APB2ENR_TIMER1EN;} else if (timer == TIMER2_ADDR) {RCC_APB1ENR |= RCC_APB1ENR_TIMER2EN;} else if (timer == TIMER3_ADDR) {RCC_APB1ENR |= RCC_APB1ENR_TIMER3EN;} }
void timer_init(timer_config_t *config,uint32_t timer){ RCC_EnableTimer(timer); volatile uint32_t *CTL0 = (volatile uint32_t *)(timer + TIMER_CTL0_OFFSET); volatile uint32_t *PSC = (volatile uint32_t *)(timer + TIMER_PSC_OFFSET); volatile uint32_t *CAR = (volatile uint32_t *)(timer + TIMER_CAR_OFFSET);
*PSC = config->prescaler; *CAR = config->period;
*CTL0 &= ~(TIMER_CTL0_OPM); if (config->mode == TIMER_MODE_ONE_SHOT) { *CTL0 |= TIMER_CTL0_OPM; } }
void timer_start(uint32_t timer) { volatile uint32_t *CTL0 = (volatile uint32_t *)(timer + TIMER_CTL0_OFFSET); *CTL0 |= TIMER_CTL0_CEN; } void timer_stop(uint32_t timer) { volatile uint32_t *CTL0 = (volatile uint32_t *)(timer + TIMER_CTL0_OFFSET); *CTL0 &= ~TIMER_CTL0_CEN; } void timer_enable_interrupt(uint32_t timer){ volatile uint32_t *DMAINTEN = (volatile uint32_t *)(timer + TIMER_DMAINTEN_OFFSET); *DMAINTEN |= TIMER_DMAINTEN_UPIE; if (timer == TIMER0_ADDR) { NVIC_EnableIRQ(TIMER0_IRQn); }else if(timer == TIMER1_ADDR) { NVIC_EnableIRQ(TIMER1_IRQn); }else if (timer == TIMER2_ADDR) { NVIC_EnableIRQ(TIMER2_IRQn); } else if (timer == TIMER3_ADDR) { NVIC_EnableIRQ(TIMER3_IRQn); } } void timer_disable_interrupt(uint32_t timer){ volatile uint32_t *DMAINTEN = (volatile uint32_t *)(timer + TIMER_DMAINTEN_OFFSET); *DMAINTEN &= ~TIMER_DMAINTEN_UPIE; if (timer == TIMER0_ADDR) { NVIC_DisableIRQ(TIMER0_IRQn); }else if(timer == TIMER1_ADDR) { NVIC_DisableIRQ(TIMER1_IRQn); }else if (timer == TIMER2_ADDR) { NVIC_DisableIRQ(TIMER2_IRQn); } else if (timer == TIMER3_ADDR) { NVIC_DisableIRQ(TIMER3_IRQn); } } void timer_clear_flag(uint32_t timer){ volatile uint32_t *INTF = (volatile uint32_t *)(timer + TIMER_INTF_OFFSET); *INTF &= ~(TIMER_INTF_UPIF); }
|
4.2 FAL层 (FPGA Acceleration Layer)
由于FPGA代码需要使用硬件描述语言(Verilog/VHDL)进行编写,这里只展示对应的头文件和C接口函数,FPGA的实际实现需要使用对应的FPGA开发工具进行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #ifndef __DATA_ACQ_H__ #define __DATA_ACQ_H__
#include <stdint.h>
#define DATA_BUFFER_SIZE 1024
typedef struct { uint16_t buffer[DATA_BUFFER_SIZE]; uint32_t count; uint8_t full; } data_buffer_t;
extern data_buffer_t data_acq_buffer; void data_acq_init(void); void data_acq_start(void); void data_acq_stop(void); uint16_t data_acq_read_sample(void);
#endif
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| #include "fal/data_acq.h"
data_buffer_t data_acq_buffer = {0};
void data_acq_init(void) { }
void data_acq_start(void) { }
void data_acq_stop(void) { } uint16_t data_acq_read_sample(void){ if(data_acq_buffer.full) { data_acq_buffer.count = 0; data_acq_buffer.full = 0;
} if(data_acq_buffer.count >= DATA_BUFFER_SIZE){ data_acq_buffer.full = 1; return 0; } return data_acq_buffer.buffer[data_acq_buffer.count++]; }
|
fal/processing.h
1 2 3 4 5 6 7 8 9
| #ifndef __PROCESSING_H__ #define __PROCESSING_H__ #include <stdint.h> #include "fal/data_acq.h"
void processing_init(void); void processing_execute(data_buffer_t * input_buffer, uint32_t dataSize, uint16_t *output_buffer);
#endif
|
fal/processing.c
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include "fal/processing.h"
void processing_init(void) { }
void processing_execute(data_buffer_t * input_buffer, uint32_t dataSize, uint16_t *output_buffer) { }
|
4.3 Services层 (服务层)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #ifndef __SENSOR_H__ #define __SENSOR_H__
#include <stdint.h> #include "hal/adc.h" typedef struct { uint16_t value; float scaled_value; } sensor_data_t; typedef struct { adc_config_t config; }sensor_config_t; void sensor_init(sensor_config_t *config); sensor_data_t sensor_read_data(void);
#endif
|