2

I am first time using function pointers and ran into a weird problem. I am writing a code for STM32G4xx. The main idea is to transmit and receive data through LPUART. I have implemented simple FSM to handle TX and RX. LPUART configured in DMA interrupt mode. I have typedef the function pointer and declared the three function pointer variables (ISR handles) in main.h file as follow:

#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 */

The definition of the function pointer is in function MX_LPUART1_UART_Init() in the main.c file.

#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 */

}

In main function, in while loop, I am calling the lpuart_start_tx(buf, 9); function just after the if(!lpuart_isTxBusy()) statement. This causes change of the address of the function pointer lpuart_dma_rx_tc_isr_clback but other two function pointers don't change its addresses and work fine. When an intrrupt raised on the reception of the data, it tried to execute lpuart_dma_rx_tc_isr_clback which causes the hard fault because its address was modified. Note that if I call lpuart_start_tx(buf, 9); before if(!lpuart_isTxBusy()), then everything works fine. I don't understand what could be an issue.

I have checked the CFSR register and every time different flag was raised. I have noticed that out of three flags, such as IBUSERR, IACCVOIL, and INVSTATE, one of them was raised. I have not included the full main.c file.

LPUART FSM implementation is as follow: lpuart.h file

#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);
    }

}

Intrrupt routine file 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 */
}

Some of the code I have ommitted here. I am sure that I have not fully understood how function pointers work. Could you please give me suggestions or a solution.

I am using: language: C11 Compiler/build tools: GNU tools for STM32 (7-2018-q2-update) IDE: STM32CubeIDE

Please let me know if you require more info. Thanks in advance.

TheThirdFriend
  • 59
  • 1
  • 1
  • 7
  • 5
    I would prefer more focused and less info. Could you try for a more [mre] ? At least all those C++ shenanigans should be removable.... as well as irrelevant comments. – Yunnosch Feb 16 '22 at 09:45
  • 2
    If you have a half-decent debugger, set a write breakpoint on each function pointer, then watch the trace to see who destroyed it. When variables change values randomly, it is usually either stack overflow, array out of bounds access or runaway code. Notably it doesn't make sense to allocate those function pointers in RAM, but it's a good thing that you did since it exposed this bug. You need to track the bug down before moving them to flash where they belong. – Lundin Feb 16 '22 at 12:46
  • @Lundin and where the op suppose to run debugger on compiled code on x86-64? Are u sure? Me learning too this and comments like yours does not fit well with my understanding of embedded development. What's the point of ur comment I like to see means which debugger can run on stm32 architecture. Or can I somehow run my cross compiled code on my ubuntu and debug it – user786 Feb 16 '22 at 13:49
  • @user786 I have no idea what you are on about. Nobody has spoken of x86 until you arrived here... Don't mix up the development system (which is pretty much always x86 Windows PC) with the target system. – Lundin Feb 16 '22 at 13:54
  • Anyway, the various Eclipse hellspawns do most definitely not come with a debugger of "half-decent" or better quality though. I'd advise to uninstall such broken toolchains and buy proper tools - you get what you pay for. – Lundin Feb 16 '22 at 13:56
  • 1
    @Lundin Thanks a lot. found out the bug. I have put watchpoint on that function pointer variable. It exposed array out of bounds access error in my code. – TheThirdFriend Feb 16 '22 at 15:29
  • Ok nice. If the bug is in the posted code you could post an answer to your own question pointing it out. Otherwise we can also close the question. – Lundin Feb 16 '22 at 15:32
  • 1
    Regarding allocating function pointers correctly in flash, I'd recommend this: `typedef void (_func_clbck)(void);` ... `_func_clbck* const name = ...;` – Lundin Feb 16 '22 at 15:33
  • I will write the solution. please don't close it. Thanks again. – TheThirdFriend Feb 16 '22 at 16:29

1 Answers1

0

As per @Lundin's suggestion, I have put a watchpoint on lpuart_dma_rx_tc_isr_clback function pointer variable. It exposed the out of index bug in my code. The bug is inside while loop in main.c.

 rxIndex = RingBuffer_available(&lpuart_RX_ring_buff);
 for(i = rxOldIndex ; i < (rxIndex+rxOldIndex) ; i++ ){
    rxBuff[i] = RingBuffer_readMeas(&lpuart_RX_ring_buff);
     ....
  }

It was also pointed out that function pointer variable shouldn't be in flash.

TheThirdFriend
  • 59
  • 1
  • 1
  • 7