主頁 > 企業開發 > 函式指標正在改變自己的地址

函式指標正在改變自己的地址

2022-02-25 01:04:05 企業開發

我第一次使用函式指標并遇到了一個奇怪的問題。我正在為 STM32G4xx 撰寫代碼。主要思想是通過LPUART發送和接收資料。我已經實作了簡單的 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 */

函式指標的定義MX_LPUART1_UART_Init()在main.c檔案的function中。

#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 回圈中,我陳述句之后lpuart_start_tx(buf, 9);呼叫該函式。這會導致函式指標的地址發生變化,但其他兩個函式指標不會改變其地址并且作業正常。當接收到資料時引發中斷時,它嘗試執行導致硬故障,因為它的地址被修改。請注意,如果我之前打電話,那么一切正常。我不明白可能是什么問題。if(!lpuart_isTxBusy())lpuart_dma_rx_tc_isr_clbacklpuart_dma_rx_tc_isr_clbacklpuart_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 編譯器/構建工具:STM32 的 GNU 工具(7-2018-q2-update)IDE:STM32CubeIDE

如果您需要更多資訊,請告訴我。提前致謝。

uj5u.com熱心網友回復:

根據@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);
     ....
  }

還指出函式指標變數不應該在閃存中。

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/431679.html

標籤:C 指针 stm32 UART 伊斯尔

上一篇:如何將calloc指標從C回傳到C ?

下一篇:如何在wordpress專案cpanel中集成laravel8專案?

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more