函数指针正在改变自己的地址

The function pointer is changing its own address

我是第一次使用函数指针,运行遇到了一个奇怪的问题。我正在为 STM32G4xx 编写代码。主要思路是通过LPUART进行t运行发送和接收数据。我已经实现了简单的 FSM 来处理 TX 和 RX。 LPUART 配置为 DMA 中断模式。我对函数指针进行了 typedef 并在 main.h 文件中声明了三个函数指针变量(ISR 句柄)如下:

#ifndef __MAIN_H
#define __MAIN_H

#ifdef __cplusplus
extern "C" {
#endif
/* USER CODE BEGIN ET */
typedef void (*_func_clbck)(void);
/* USER CODE END ET */
 _func_clbck lpuart_tx_tc_isr_clback;
//_func_clbck lpuart_rx_rne_isr_clback;
 _func_clbck lpuart_dma_tx_tc_isr_clback;
 _func_clbck lpuart_dma_rx_tc_isr_clback;

/* USER CODE END Private defines */

#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H */

函数指针的定义在main.c文件中的函数MX_LPUART1_UART_Init()中。

#include "main.h"
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);

  NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

  /* System interrupt init*/
  /* SysTick_IRQn interrupt configuration */
  NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),1, 0));

  /** Configure the internal voltage reference buffer voltage scale
  */
  LL_VREFBUF_SetVoltageScaling(LL_VREFBUF_VOLTAGE_SCALE1);
  /** Enable the Internal Voltage Reference buffer
  */
  LL_VREFBUF_Enable();
  /** Configure the internal voltage reference buffer high impedance mode
  */
  LL_VREFBUF_DisableHIZ();
  /** Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral
  */
  LL_PWR_DisableUCPDDeadBattery();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_LPUART1_UART_Init();
  MX_RTC_Init();
  /* USER CODE BEGIN 2 */
#ifdef LPUART_TEST
  lpuart_init_test();
#endif
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    LL_GPIO_ResetOutputPin(GPIOC,LL_GPIO_PIN_6);
    //LL_GPIO_SetOutputPin(GPIOC,LL_GPIO_PIN_6);
    LL_mDelay(1);
    uint8_t buf[9] ={'a','d','v',' ','l','o','w','\r','\n'};
    //uint8_t buf[9] ={1,2,3,4,5,6,7,8,9};

#ifdef LPUART_TEST
    uint16_t len_test[19] = {0,16,17,65535, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
    for(uint16_t i = 0 ; i<19 ; i++){
        set_len_rx_dma_buff(len_test[i]);
        lpuart_rx_test();
    }
#endif
static uint8_t once = 1;
    while (1)
    {
        lpuart_task();
        //delay_ms_DWT(1);
        /*if(once){
            once = 0;
            lpuart_start_tx(buf, 9);
            LL_mDelay(100);
        }*/

        if(1){
            //lpuart_start_tx(buf, 9);
            if(!lpuart_isTxBusy()){
                lpuart_start_tx(buf, 9);
                delay_ms_DWT(1);
                if(!lpuart_isRxBusy()){
                    rxOldIndex += rxIndex;
                    if(rxOldIndex > 255){
                        rxOldIndex = 0;
                        rxIndex = 0;
                    }
                    rxIndex = RingBuffer_available(&lpuart_RX_ring_buff);
                    for(i = rxOldIndex ; i < (rxIndex+rxOldIndex) ; i++ ){
                        rxBuff[i] = RingBuffer_readMeas(&lpuart_RX_ring_buff);
                    }
                }
            }
        }
    //}
    }
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

  /* USER CODE END 3 */
}
static void MX_LPUART1_UART_Init(void)
{

  /* USER CODE BEGIN LPUART1_Init 0 */

  /* USER CODE END LPUART1_Init 0 */

  LL_LPUART_InitTypeDef LPUART_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);

  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
  /**LPUART1 GPIO Configuration
  PB10   ------> LPUART1_RX
  PB11   ------> LPUART1_TX
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_8;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = LL_GPIO_PIN_11;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_8;
  LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* LPUART1 DMA Init */

  /* LPUART1_TX Init */
  LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_1, LL_DMAMUX_REQ_LPUART1_TX);

  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);

  LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PRIORITY_HIGH);

  LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MODE_NORMAL);

  LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PERIPH_NOINCREMENT);

  LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MEMORY_INCREMENT);

  LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_PDATAALIGN_BYTE);

  LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_1, LL_DMA_MDATAALIGN_BYTE);

  /* LPUART1_RX Init */
  LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_2, LL_DMAMUX_REQ_LPUART1_RX);

  LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_2, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

  LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PRIORITY_HIGH);

  LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MODE_CIRCULAR);

  LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PERIPH_NOINCREMENT);

  LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MEMORY_INCREMENT);

  LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PDATAALIGN_BYTE);

  LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MDATAALIGN_BYTE);

  /* LPUART1 interrupt Init */
  NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(LPUART1_IRQn);

  /* USER CODE BEGIN LPUART1_Init 1 */

  /* USER CODE END LPUART1_Init 1 */
  LPUART_InitStruct.PrescalerValue = LL_LPUART_PRESCALER_DIV1;
  LPUART_InitStruct.BaudRate = 9600;
  LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;
  LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;
  LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;
  LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
  LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
  LL_LPUART_Init(LPUART1, &LPUART_InitStruct);
  LL_LPUART_SetTXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
  LL_LPUART_SetRXFIFOThreshold(LPUART1, LL_LPUART_FIFOTHRESHOLD_1_8);
  LL_LPUART_DisableFIFO(LPUART1);
  LL_LPUART_SetTXRXSwap(LPUART1, LL_LPUART_TXRX_SWAPPED);
//  LL_LPUART_EnableOverrunDetect(LPUART1);
 // LL_LPUART_EnableDMADeactOnRxErr(LPUART1);

  /* USER CODE BEGIN WKUPType LPUART1 */

  /* USER CODE END WKUPType LPUART1 */

  LL_LPUART_Enable(LPUART1);

  /* Polling LPUART1 initialisation */
  while((!(LL_LPUART_IsActiveFlag_TEACK(LPUART1))) || (!(LL_LPUART_IsActiveFlag_REACK(LPUART1))))
  {
  }
  /* USER CODE BEGIN LPUART1_Init 2 */

    //LL_LPUART_EnableIT_TXE_TXFNF(LPUART1);
    /* Enable TC interrupts for RX */


    /* Enable HT & TC interrupts for TX */
    // LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);

    lpuart_tx_tc_isr_clback = LPUART_TX_TC_ISR_CALLBACK;
    //lpuart_rx_rne_isr_clback = &LPUART_RX_RXNE_ISR_CALLBACK;
    lpuart_dma_tx_tc_isr_clback = LPUART_DMA_TX_TC_CALLBACK;
    lpuart_dma_rx_tc_isr_clback = LPUART_DMA_RX_TC_CALLBACK;

    //LL_LPUART_EnableDirectionRx(LPUART1);
    LL_LPUART_EnableDirectionTx(LPUART1);
    //LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);

  /* USER CODE END LPUART1_Init 2 */

}

在 main 函数中,在 while 循环中,我在 if(!lpuart_isTxBusy()) 语句 之后 调用 lpuart_start_tx(buf, 9); 函数。这会导致函数指针的地址发生变化 lpuart_dma_rx_tc_isr_clback 但其他两个函数指针不会改变其地址并且可以正常工作。当在接收数据时引发中断时,它会尝试执行 lpuart_dma_rx_tc_isr_clback,这会导致硬故障,因为它的地址已被修改。请注意,如果我在 lpuart_start_tx(buf, 9); 之前调用 if(!lpuart_isTxBusy()),那么一切正常。我不明白这可能是什么问题。

我检查了 CFSR 寄存器,每次都出现了不同的标志。我注意到在 IBUSERRIACCVOILINVSTATE 三个标志中,其中一个被举起。我没有包含完整的 main.c 文件。

LPUART FSM实现如下: lpuart.h 文件

#ifndef INC_LPUART_H_
#define INC_LPUART_H_

#include "ring_buffer.h"

#ifdef  USE_FULL_ASSERT
#include "stm32_assert.h"
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */

uint8_t lpuart_start_tx(uint8_t* buff, uint16_t len );
uint8_t LPUART_isTxFinished(void);
void LPUART_clear_tx_finishedFlag();
uint8_t lpuart_isRxBusy(void);
uint8_t lpuart_isTxBusy(void);
void lpuart_task();

void LPUART_TX_TC_ISR_CALLBACK(void);
void LPUART_DMA_TX_TC_CALLBACK(void);
void LPUART_DMA_RX_TC_CALLBACK(void);

#endif /* INC_LPUART_H_ */

lpuart.c

#include "lpuart.h"
#include "string.h"
#include "stm32g4xx_ll_lpuart.h"
#include "stm32g4xx_ll_dma.h"

#define SIZE_TX_BUFF 256
#define SIZE_RX_BUFF 256
#define SIZE_DMA_RX_BUFF 64


static uint8_t rxBuf[SIZE_RX_BUFF];
static uint8_t rxDMA_Buf[SIZE_DMA_RX_BUFF];
static uint8_t txBuf[SIZE_TX_BUFF];
RingBuffer lpuart_RX_ring_buff;
static uint8_t* tempTxBuf;
static uint16_t txLen = 0;


static void setTxDataLengthDMA(uint16_t len);
static void lpuart_transmit();
static void lpuart_finished_tx();
static void no_action();
static void lpuart_rx();
static void check_rx_dma_buff();

static uint8_t ev_no_event(void);
static uint8_t ev_txtc(void);
static uint8_t ev_start_tx(void);
static uint8_t ev_dmatxtc(void);
static uint8_t ev_rx_read(void);
static uint8_t ev_buff_full(void);


typedef  uint8_t (*t_event_func)(void);
typedef  void(*t_action_func)(void);
typedef struct{
    uint16_t txtc:1;
    uint16_t tx_busy:1;
    uint16_t dmatxtc:1;
    uint16_t dmarxtc:1;
    uint16_t start_tx:1;
    uint16_t rx_read:1;
    uint16_t buff_full:1;
    uint16_t is_fsm_table_init:1;
    uint16_t ext_rxBusyFlag:1;

}t_event;

typedef enum {INIT, READY, BUSY, COMPLETE, LPUART_ERROR}t_state;

typedef struct{
    t_state present_state;
    t_event_func event1;
    t_event_func event2;
    t_action_func action1;
    t_action_func action2;
    t_state next_state;

}t_fsm_row;

typedef struct{
    t_state current_state;
    t_state previous_state;
    t_fsm_row stt_row[7];
    uint16_t number_of_rows;
}t_fsm_table;


t_event lpuart_event;

uint8_t lpuart_isTxBusy(void){
    return lpuart_event.tx_busy;
}

uint8_t lpuart_isRxBusy(){
    return lpuart_event.ext_rxBusyFlag;
}
uint8_t ev_no_event(void){
    return 1;
}

uint8_t ev_txtc(void){
    return lpuart_event.txtc;
}

uint8_t ev_start_tx(void){
    return lpuart_event.start_tx;
}

uint8_t ev_dmatxtc(void){
    return lpuart_event.dmatxtc;
}


uint8_t ev_rx_read(void){
    return lpuart_event.rx_read || lpuart_event.dmarxtc;
}

uint8_t ev_buff_full(void){
    return lpuart_event.buff_full;
}

void no_action(){
    return;
}

void lpuart_init(void){
    memset(rxBuf, 0, (size_t)SIZE_RX_BUFF );
    memset(rxDMA_Buf, 0, (size_t)SIZE_DMA_RX_BUFF );
    memset(txBuf, 0, (size_t)SIZE_TX_BUFF );
    RingBuffer_init(&lpuart_RX_ring_buff,rxBuf , (uint16_t)SIZE_RX_BUFF);

    LL_LPUART_DisableIT_TC(LPUART1);
    LL_LPUART_DisableIT_RXNE_RXFNE(LPUART1);
    LL_LPUART_DisableDirectionRx(LPUART1);

    LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_1); //tx
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1); //tx
    LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_2); //rx
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2); //rx

    /*TX buffer address attached to DMA channel1  */
    LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_1,
            (uint32_t)txBuf,
            LL_LPUART_DMA_GetRegAddr(LPUART1, LL_LPUART_DMA_REG_DATA_TRANSMIT),
            LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1));
    LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, SIZE_TX_BUFF);

    /*RX buffer address attached to DMA channel2  */
    LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_2,
                LL_LPUART_DMA_GetRegAddr(LPUART1, LL_LPUART_DMA_REG_DATA_RECEIVE),
                (uint32_t)rxDMA_Buf,
                LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_2));
    LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, SIZE_DMA_RX_BUFF);

    LL_LPUART_EnableDMAReq_RX(LPUART1);
    LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_2); //rx
    LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_2);
    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); //rx

    LL_LPUART_EnableDirectionRx(LPUART1);
    lpuart_event.tx_busy = 0;
}


uint8_t lpuart_start_tx(uint8_t* buff, uint16_t len ){
    if(!lpuart_event.tx_busy){
        lpuart_event.tx_busy = 1;
        if(len < SIZE_TX_BUFF){
            lpuart_event.start_tx = 1;
            tempTxBuf = buff;
            txLen = len;
        }else{
            /*  lpuart_event.start_tx = 0;
                lpuart_event.buff_full = 1;*/
            return 0;

        }
        return 1;
    }else{
        return 0;
    }


}

void lpuart_transmit(){
    memcpy(txBuf, tempTxBuf, txLen);
    setTxDataLengthDMA(txLen);
    LL_LPUART_EnableDMAReq_TX(LPUART1);
    LL_LPUART_EnableDirectionTx(LPUART1);
    LL_LPUART_EnableIT_TC(LPUART1);
    LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1);
    LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_1);
    LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
}


void lpuart_finished_tx(){
    LL_LPUART_DisableIT_TC(LPUART1);
    LL_LPUART_DisableDirectionTx(LPUART1);
    LL_DMA_DisableIT_TC(DMA1, LL_DMA_CHANNEL_1);
    LL_DMA_DisableIT_TE(DMA1, LL_DMA_CHANNEL_1);
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
    lpuart_event.txtc = 0;
    lpuart_event.dmatxtc = 0;
    lpuart_event.start_tx = 0;
    lpuart_event.tx_busy = 0;
}
void setTxDataLengthDMA(uint16_t len){
    LL_LPUART_DisableDirectionTx(LPUART1);
    LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1);
    /* Clear all flags */
    LL_DMA_ClearFlag_TC1(DMA1);
    LL_DMA_ClearFlag_TE1(DMA1);
    LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, len);
}

void check_rx_dma_buff(){
    static uint16_t old_len = SIZE_DMA_RX_BUFF;
    uint16_t current_len = LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_2);
    if(old_len != current_len ){
        if(current_len > 0){
            lpuart_event.rx_read = 1;
        }
    }
    old_len = current_len;
}
static uint16_t old_pos = 0;
uint16_t pos = 0;
void lpuart_rx(){
    lpuart_event.ext_rxBusyFlag = 1;
    if(lpuart_event.dmarxtc){
        lpuart_event.dmarxtc = 0;
    }
    if(lpuart_event.rx_read){
        lpuart_event.rx_read = 0;
    }
    pos = (uint16_t)SIZE_DMA_RX_BUFF - LL_DMA_GetDataLength(DMA1, LL_DMA_CHANNEL_2);
    if(pos > SIZE_DMA_RX_BUFF ){
            pos = SIZE_DMA_RX_BUFF;
        }
    if(pos != old_pos /* || (pos == 0 && old_pos == 0)*/){
          if (pos > old_pos) {
              RingBuffer_writeMeasBlock(&lpuart_RX_ring_buff,&rxDMA_Buf[old_pos],(pos - old_pos));
          }else{
              RingBuffer_writeMeasBlock(&lpuart_RX_ring_buff,&rxDMA_Buf[old_pos],((uint16_t)SIZE_DMA_RX_BUFF - old_pos));
              if(pos > 0){
                  RingBuffer_writeMeasBlock(&lpuart_RX_ring_buff,&rxDMA_Buf[0],pos);
              }
          }
    }
    old_pos = pos;
    lpuart_event.ext_rxBusyFlag = 0;

}
t_fsm_row rowInit = {INIT,ev_no_event, ev_no_event, lpuart_init, no_action, READY };
t_fsm_row rowReady = {READY,ev_start_tx, ev_no_event, lpuart_transmit, no_action, BUSY };
t_fsm_row rowBusy = {BUSY,ev_dmatxtc, ev_txtc, lpuart_finished_tx, no_action, READY};


t_fsm_table lpuart_fsm_table = {INIT,INIT, {}};
void fsm_table_init(){
    lpuart_fsm_table.current_state = INIT;
    lpuart_fsm_table.stt_row[0] = rowInit;
    lpuart_fsm_table.stt_row[1] = rowReady;
    lpuart_fsm_table.stt_row[2] = rowBusy;
    lpuart_event.is_fsm_table_init = 1;
    lpuart_fsm_table.number_of_rows = 3;
}

void lpuar_tx_fsm(){
    uint8_t ev = 0;

    for(uint16_t rowIndex = 0; rowIndex < lpuart_fsm_table.number_of_rows; rowIndex++){

        if(lpuart_fsm_table.current_state == lpuart_fsm_table.stt_row[rowIndex].present_state){
            ev = lpuart_fsm_table.stt_row[rowIndex].event1() && lpuart_fsm_table.stt_row[rowIndex].event2();
            if(ev){
                lpuart_fsm_table.stt_row[rowIndex].action1();
                lpuart_fsm_table.stt_row[rowIndex].action2();
                lpuart_fsm_table.current_state =  lpuart_fsm_table.stt_row[rowIndex].next_state;
                lpuart_fsm_table.previous_state = lpuart_fsm_table.stt_row[rowIndex].present_state;
            }

        }
    }
}

void lpuar_read_task(){
    check_rx_dma_buff();
    if(ev_rx_read()){
        lpuart_rx();
    }

}
void lpuart_task(){

    if(!lpuart_event.is_fsm_table_init){
        fsm_table_init();
    }
    //else{
        lpuar_tx_fsm();
        lpuar_read_task();
    //}

}
void LPUART_TX_TC_ISR_CALLBACK(void){
    lpuart_event.txtc = 1;
    LL_LPUART_ClearFlag_TC(LPUART1);

}

void LPUART_DMA_TX_TC_CALLBACK(void){
    lpuart_event.dmatxtc = 1;
    LL_DMA_ClearFlag_TC1(DMA1);
}

void LPUART_DMA_RX_TC_CALLBACK(void){
    if(LL_DMA_IsActiveFlag_TC2(DMA1)){
        LL_DMA_ClearFlag_TC2(DMA1);
        lpuart_event.dmarxtc = 1;
        lpuart_rx();
    }
    if(LL_DMA_IsActiveFlag_TE2(DMA1)){
        LL_DMA_ClearFlag_TE2(DMA1);
    }

}

中断程序文件stm32g4xx_it.c:

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32g4xx_it.h"
#include "lpuart.h"

 extern _func_clbck lpuart_tx_tc_isr_clback;
//_func_clbck lpuart_rx_rne_isr_clback = LPUART_RX_RXNE_ISR_CALLBACK;
 extern _func_clbck lpuart_dma_tx_tc_isr_clback;
 extern _func_clbck lpuart_dma_rx_tc_isr_clback;

void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 0 */

  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
}

void DMA1_Channel2_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel2_IRQn 0 */
    lpuart_dma_rx_tc_isr_clback();
    //LPUART_DMA_RX_TC_CALLBACK();
  /* USER CODE END DMA1_Channel2_IRQn 0 */

  /* USER CODE BEGIN DMA1_Channel2_IRQn 1 */

  /* USER CODE END DMA1_Channel2_IRQn 1 */
}

我在这里省略了一些代码。我确信我还没有完全理解函数指针是如何工作的。能否请您给我建议或解决方案。

我正在使用: 语言:C11 Compiler/build 工具:STM32 的 GNU 工具(7-2018-q2-更新) IDE:STM32立方体IDE

如果您需要更多信息,请告诉我。提前致谢。

根据@Lundin 的建议,我在 lpuart_dma_rx_tc_isr_clback 函数指针变量上放置了一个观察点。它暴露了我的代码中的索引错误。该错误在 main.c.

中的 while 循环内
 rxIndex = RingBuffer_available(&lpuart_RX_ring_buff);
 for(i = rxOldIndex ; i < (rxIndex+rxOldIndex) ; i++ ){
    rxBuff[i] = RingBuffer_readMeas(&lpuart_RX_ring_buff);
     ....
  }

也有人指出函数指针变量不应该在flash中。