The function pointer is changing its own address - c

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.

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.

Related

Functions return successfully but BMX160 sensor does produce any data

I am implementing the bmi160 and bmm150 drivers from Bosch in order to get data from the BMX160 (pinout board made by DFRobot) because from what I have gathered. I changed the chip id to match the bmx160 chip id. Upon all the initializations I am given valid returns of 0 yet when I get to reading the data, I do not get good data from the chip. I have made sure the device is getting voltage and is found by my board (STM32F0). I2C clock is set to the standard mode with a default clock speed.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* #file : main.c
* #brief : Main program body
******************************************************************************
* #attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "bmm150.h"
#include "bmi160.h"
#include <stdio.h>
// #include "stm32f0xx_hal_uart.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
// UART_HandleTypeDef huart1;
struct bmi160_dev bmi;
struct bmm150_dev bmm;
struct bmm150_settings bmm_settings;
struct bmm150_mag_data mag;
struct bmi160_sensor_data accel;
struct bmi160_sensor_data gyro;
int8_t rslt, rslt1, rslt2, rslt3, rslt4, rslt5, rslt6, rslt7;
int8_t rslt_data, rslt_data1, rslt_data2;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
// static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* Auxiliary function declarations */
int8_t bmm150_aux_read(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, void *intf_ptr);
int8_t bmm150_aux_write(uint8_t reg_addr, uint8_t *aux_data, uint16_t len, void *intf_ptr);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t Buffer[25] = {0};
uint8_t Space[] = " - ";
uint8_t StartMSG[] = "Starting I2C Scanning: \r\n";
uint8_t EndMSG[] = "Done! \r\n\r\n";
int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
HAL_StatusTypeDef status = HAL_OK;
while (HAL_I2C_IsDeviceReady(&hi2c1, (uint8_t)(id << 1), 3, 100) != HAL_OK)
{
rslt = 0;
}
status = HAL_I2C_Master_Transmit(&hi2c1, (uint8_t)(id << 1), &reg_addr, 1, 1000);
if (status != HAL_OK)
{
rslt = (-1);
}
HAL_Delay(100);
status = HAL_I2C_Master_Receive(&hi2c1, (uint8_t)(id << 1), data, len, 10000);
if (status != HAL_OK)
{
rslt = (-1);
}
return rslt;
}
int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */
HAL_StatusTypeDef status = HAL_OK;
while (HAL_I2C_IsDeviceReady(&hi2c1, (uint8_t)(id << 1), 3, 100) != HAL_OK)
{
}
uint8_t tx_buffer[len + 1];
tx_buffer[0] = reg_addr;
memcpy(&tx_buffer[1], data, len);
status = HAL_I2C_Master_Transmit(&hi2c1, (uint8_t)(id << 1), tx_buffer, len + 1, 1000);
if (status != HAL_OK)
{
rslt = (-1);
}
return rslt;
}
void user_delay_ms(uint32_t period)
{
HAL_Delay(period);
}
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t i = 0, ret;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* 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_I2C1_Init();
// rslt = i2c_ping_device(&hi2c1, 0x00);
/* USER CODE BEGIN 2 */
bmi.id = BMI160_I2C_ADDR;
bmi.chip_id = BMI160_CHIP_ID;
bmi.intf = BMI160_I2C_INTF;
bmi.read = &user_i2c_read;
bmi.write = &user_i2c_write;
bmi.delay_ms = &user_delay_ms;
bmm.chip_id = BMM150_DEFAULT_I2C_ADDRESS;
bmm.intf = BMM150_I2C_INTF;
bmm.read = (bmm150_read_fptr_t)bmm150_aux_read;
bmm.write = (bmm150_write_fptr_t)bmm150_aux_write;
bmm.delay_us = &user_delay_ms;
bmm.intf_ptr = bmm.chip_id;
rslt = bmi160_init(&bmi);
// pingStatus = i2cs_ping_device(BMI160_I2C_ADDR);
bmi.aux_cfg.aux_sensor_enable = BMI160_ENABLE;
bmi.aux_cfg.aux_i2c_addr = bmm.chip_id;
bmi.aux_cfg.manual_enable = BMI160_ENABLE;
bmi.aux_cfg.aux_rd_burst_len = BMI160_AUX_READ_LEN_3;
rslt1 = bmi160_aux_init(&bmi);
rslt2 = bmm150_init(&bmm);
bmi.accel_cfg.odr = BMI160_ACCEL_ODR_100HZ;
bmi.accel_cfg.range = BMI160_ACCEL_RANGE_2G;
bmi.accel_cfg.bw = BMI160_ACCEL_BW_NORMAL_AVG4;
bmi.accel_cfg.power = BMI160_ACCEL_NORMAL_MODE;
bmi.gyro_cfg.odr = BMI160_GYRO_ODR_100HZ;
bmi.gyro_cfg.range = BMI160_GYRO_RANGE_2000_DPS;
bmi.gyro_cfg.bw = BMI160_GYRO_BW_NORMAL_MODE;
bmi.gyro_cfg.power = BMI160_GYRO_NORMAL_MODE;
rslt3 = bmi160_set_sens_conf(&bmi);
bmm_settings.preset_mode = BMM150_PRESETMODE_REGULAR;
rslt4 = bmm150_set_presetmode(&bmm_settings, &bmm);
bmm_settings.pwr_mode = BMM150_POWERMODE_FORCED;
rslt5 = bmm150_set_op_mode(&bmm_settings, &bmm);
uint8_t aux_addr = 0x42;
uint8_t mag_data[8] = {0};
uint8_t index;
bmi.aux_cfg.aux_odr = 8;
rslt6 = bmi160_config_aux_mode(&bmi);
rslt7 = bmi160_set_aux_auto_mode(BMM150_REG_CHIP_ID, &bmi);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
user_delay_ms(100);
rslt_data = bmi160_get_sensor_data((BMI160_ACCEL_SEL | BMI160_GYRO_SEL), &accel, &gyro, &bmi);
rslt_data1 = bmi160_read_aux_data_auto_mode(mag_data, &bmi);
rslt_data2 = bmm150_aux_mag_data(mag_data, &mag, &bmm);
/* USER CODE END WHILE */
printf("****************\n");
printf("ACC X: %d, Y: %d, Z: %d\n", accel.x, accel.y, accel.z);
printf("GYRO X: %d, Y: %d, Z: %d\n", gyro.x, gyro.y, gyro.z);
printf("MAG X : %d Y : %d Z : %d\n", mag.x, mag.y, mag.z);
printf("################\n");
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_SYSCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/**
* #brief I2C1 Initialization Function
* #param None
* #retval None
*/
static void MX_I2C1_Init(void)
{
/* USER CODE BEGIN I2C1_Init 0 */
/* USER CODE END I2C1_Init 0 */
/* USER CODE BEGIN I2C1_Init 1 */
/* USER CODE END I2C1_Init 1 */
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x200009FE;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C1_Init 2 */
/* USER CODE END I2C1_Init 2 */
}
// static void MX_USART1_UART_Init(void)
// {
// /* USER CODE BEGIN USART1_Init 0 */
// /* USER CODE END USART1_Init 0 */
// /* USER CODE BEGIN USART1_Init 1 */
// /* USER CODE END USART1_Init 1 */
// huart1.Instance = USART1;
// huart1.Init.BaudRate = 115200;
// huart1.Init.WordLength = UART_WORDLENGTH_8B;
// huart1.Init.StopBits = UART_STOPBITS_1;
// huart1.Init.Parity = UART_PARITY_NONE;
// huart1.Init.Mode = UART_MODE_TX;
// huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
// huart1.Init.OverSampling = UART_OVERSAMPLING_16;
// if (HAL_UART_Init(&huart1) != HAL_OK)
// {
// Error_Handler();
// }
// /* USER CODE BEGIN USART1_Init 2 */
// /* USER CODE END USART1_Init 2 */
// }
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void)
{
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* #brief This function is executed in case of error occurrence.
* #retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
int8_t bmm150_aux_read(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, void *intf_ptr)
{
int8_t rslt;
rslt = bmi160_aux_read(reg_addr, reg_data, len, &bmi);
return rslt;
}
int8_t bmm150_aux_write(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, void *intf_ptr)
{
int8_t rslt;
rslt = bmi160_aux_write(reg_addr, reg_data, len, &bmi);
return rslt;
}
#ifdef USE_FULL_ASSERT
/**
* #brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* #param file: pointer to the source file name
* #param line: assert_param error line source number
* #retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
The print statements in the while loop are supposed to provide the results. The Accel data and Gyro data both are 0 for x,y,z and 0 on the sensor time. The mag data provides -32768 for the x,y,z values. I have checked that all functions return 0 several times but still I am confused on why I am not getting good data. I am also using the latest code from Bosch's github repo for both the bmi160 and bmm150.
Here is the I2C configure that is called by the MX_12C1_INIT().
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (hi2c->Instance == I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
/**I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF1_I2C1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}
This is using a STM32F030R8T6 Processor that is supplied voltage by a st-link-v2.
When creating circuitry, a number of issues could arise during the process which we are not aware of. A common issue is powering one are of the circuit with one voltage and communicating with the circuit using a different voltage. Both sensor and PLC need to be running on same voltage over the comms channel / pins.
The next step to debugging a circuit in this case would be to ensure that your "breakout board" or the sensor have pull up resistors. I have always found (40-50 different samples) that I do not need to add pull up resistors to break out boards. I have never had to add any.
The next issue I usually run into is addressing. Most ICs / sensors have a mechanism which allows you to select which address to use. If you hold the voltage low (0v), it will have a certain address while if you hold the voltage high (3.3v or 5v or whatever) it might be a different address. If you failed to add any connector to the pin (floating), it will be invalid and sensor will not start.
Another common issue is protocol. Some chips enable certain protocols by default and you may need to modify the internal settings in order to change them. By protocol, I am referring to either I2C, SPI or U(S)ART. This is unlikely but I've added it for completeness.
The issue most people think is happening is that the sensor is fried due to ESD. The likelyhood of your circuit being damaged is wildly low and it is certainly stronger than you think. I doubt you have damaged the circuit in any way.
To answer further, i would certainly require a picture of your circuit as the driver code should not be an issue at all. I generally find that driver code, even when outdated or for an earlier model, will generally still gather simple data relative to the ealier model.

BMP280 send wrong values

I try to read temperature from BMP280 but I take a wrong values. Temperature in my room approximately 22 degrees so I expect to receive approximately 2200. But my program send me 715.
I use SPI connection. CS pin is set by shift register. I am sure that it work. And this is my code:
main.c
/* USER CODE BEGIN Header */
/**
******************************************************************************
* #file : main.c
* #brief : Main program body
******************************************************************************
* #attention
*
* Copyright (c) 2022 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include "func.h"
#include "BMP280.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi2;
UART_HandleTypeDef huart1;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI2_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* #brief The application entry point.
* #retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* 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_SPI2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
Init();
uint8_t id = 0;
BMP280_Data data;
uint8_t s[30] = {0};
uint8_t len = 0;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
ReadId(&id);
ReadAll(&data);
len = sprintf((char *)s, "Id: %i Temperature: %li ", id, data.temp);
HAL_UART_Transmit(&huart1, s, len, 0x1000);
HAL_Delay(2000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* #brief System Clock Configuration
* #retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/**
* #brief SPI2 Initialization Function
* #param None
* #retval None
*/
static void MX_SPI2_Init(void)
{
/* USER CODE BEGIN SPI2_Init 0 */
/* USER CODE END SPI2_Init 0 */
/* USER CODE BEGIN SPI2_Init 1 */
/* USER CODE END SPI2_Init 1 */
/* SPI2 parameter configuration*/
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */
/* USER CODE END SPI2_Init 2 */
}
/**
* #brief USART1 Initialization Function
* #param None
* #retval None
*/
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/**
* #brief GPIO Initialization Function
* #param None
* #retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, SR_OE_Pin|SR_L_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : SR_OE_Pin SR_L_Pin */
GPIO_InitStruct.Pin = SR_OE_Pin|SR_L_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* #brief This function is executed in case of error occurrence.
* #retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* #brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* #param file: pointer to the source file name
* #param line: assert_param error line source number
* #retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
func.c
#include "func.h"
void sr(uint8_t *confBuf){
HAL_GPIO_WritePin(SR_OE_GPIO_Port, SR_OE_Pin, GPIO_PIN_SET);
HAL_Delay(1);
HAL_SPI_Transmit(&hspi2, confBuf, 2, 0x1000);
HAL_Delay(1);
HAL_GPIO_WritePin(SR_L_GPIO_Port, SR_L_Pin, GPIO_PIN_SET);
HAL_Delay(1);
HAL_GPIO_WritePin(SR_L_GPIO_Port, SR_L_Pin, GPIO_PIN_RESET);
HAL_Delay(1);
HAL_GPIO_WritePin(SR_OE_GPIO_Port, SR_OE_Pin, GPIO_PIN_RESET);
HAL_Delay(10);
}
void dc(Devices d){
uint8_t ConfBuf[2] = {0b11111111, 0b11111111};
switch(d){
case(LSM6DSL_):
ConfBuf[0] = 0b11111110;
ConfBuf[1] = 0b11101110;
break;
case(BMP280_):
ConfBuf[0] = 0b11111101;
ConfBuf[1] = 0b11111010;
break;
default:
ConfBuf[0] = 0b11111111;
ConfBuf[1] = 0b11111111;
break;
}
sr(ConfBuf);
}
void spi_read_reg(Devices d, uint8_t Reg, uint8_t *Data, uint8_t len){
for(int i = 0; i < len; i++){
Reg |= 0b10000000;
dc(d);
HAL_SPI_Transmit(&hspi2, &Reg, 1, 0x1000);
HAL_SPI_Receive(&hspi2, Data, 1, 0x1000);
dc(0);
Reg++;
Data++;
}
}
void spi_write_reg(Devices d, uint8_t Reg, uint8_t *Data, uint8_t len){
for(int i = 0; i < len; i++){
Reg &= 0b01111111;
dc(d);
HAL_SPI_Transmit(&hspi2, &Reg, 1, 0x1000);
HAL_SPI_Transmit(&hspi2, Data, 1, 0x1000);
dc(0);
Reg++;
Data++;
}
}
func.h
#ifndef FUNC_H
#define FUNC_H
#include "main.h"
extern SPI_HandleTypeDef hspi2;
typedef enum {LSM6DSL_ = 1, BMP280_} Devices;
void sr(uint8_t *confBuf);
void dc(Devices d);
void spi_read_reg(Devices d, uint8_t Reg, uint8_t *Data, uint8_t len);
void spi_write_reg(Devices d, uint8_t Reg, uint8_t *Data, uint8_t len);
#endif
bmp280.c
#include "BMP280.h"
#include <stdio.h>
void Init(){
uint8_t conf[2] = {0b00100111, 0b00100000};
spi_write_reg(BMP280_, (uint8_t)CONFIG_L_REG, conf, 2);
}
void Reset(){
uint8_t data = (uint8_t)0xB6;
spi_write_reg(BMP280_, (uint8_t)RES_REG, &data, 1);
}
void ReadId(uint8_t *id){
spi_read_reg(BMP280_, (uint8_t)ID_REG, id, 1);
}
//0x88 / 0x89 dig_T1 unsigned short
//0x8A / 0x8B dig_T2 signed short
//0x8C / 0x8D dig_T3 signed short
//0x8E / 0x8F dig_P1 unsigned short
//0x90 / 0x91 dig_P2 signed short
//0x92 / 0x93 dig_P3 signed short
//0x94 / 0x95 dig_P4 signed short
//0x96 / 0x97 dig_P5 signed short
//0x98 / 0x99 dig_P6 signed short
//0x9A / 0x9B dig_P7 signed short
//0x9C / 0x9D dig_P8 signed short
//0x9E / 0x9F dig_P9 signed short
//0xA0 / 0xA reserved reserved
void ReadV(){
uint8_t Dig_T1[2] = {0};
uint8_t Dig_T2[2] = {0};
uint8_t Dig_T3[2] = {0};
uint8_t Dig_P1[2] = {0};
uint8_t Dig_P2[2] = {0};
uint8_t Dig_P3[2] = {0};
uint8_t Dig_P4[2] = {0};
uint8_t Dig_P5[2] = {0};
uint8_t Dig_P6[2] = {0};
uint8_t Dig_P7[2] = {0};
uint8_t Dig_P8[2] = {0};
uint8_t Dig_P9[2] = {0};
uint8_t Raw_data[6] = {0};
spi_read_reg(BMP280_, DIG_T1_L_REG, Dig_T1, 2);
dig_T1 = (Dig_T1[1] << 8) | Dig_T1[0];
spi_read_reg(BMP280_, DIG_T2_L_REG, Dig_T2, 2);
dig_T2 = (Dig_T2[1] << 8) | Dig_T2[0];
spi_read_reg(BMP280_, DIG_T3_L_REG, Dig_T3, 2);
dig_T3 = (Dig_T3[1] << 8) | Dig_T3[0];
spi_read_reg(BMP280_, DIG_P1_L_REG, Dig_P1, 2);
dig_P1 = (Dig_P1[1] << 8) | Dig_P1[0];
spi_read_reg(BMP280_, DIG_P2_L_REG, Dig_P2, 2);
dig_P2 = (Dig_P2[1] << 8) | Dig_P2[0];
spi_read_reg(BMP280_, DIG_P3_L_REG, Dig_P3, 2);
dig_P3 = (Dig_P3[1] << 8) | Dig_P3[0];
spi_read_reg(BMP280_, DIG_P4_L_REG, Dig_P4, 2);
dig_P4 = (Dig_P4[1] << 8) | Dig_P4[0];
spi_read_reg(BMP280_, DIG_P5_L_REG, Dig_P5, 2);
dig_P5 = (Dig_P5[1] << 8) | Dig_P5[0];
spi_read_reg(BMP280_, DIG_P6_L_REG, Dig_P6, 2);
dig_P6 = (Dig_P6[1] << 8) | Dig_P6[0];
spi_read_reg(BMP280_, DIG_P7_L_REG, Dig_P7, 2);
dig_P7 = (Dig_P7[1] << 8) | Dig_P7[0];
spi_read_reg(BMP280_, DIG_P8_L_REG, Dig_P8, 2);
dig_P8 = (Dig_P8[1] << 8) | Dig_P8[0];
spi_read_reg(BMP280_, DIG_P9_L_REG, Dig_P9, 2);
dig_P9 = (Dig_P9[1] << 8) | Dig_P9[0];
spi_read_reg(BMP280_, DATA_L_REG, &Raw_data[0], 1);
spi_read_reg(BMP280_, DATA_L_REG+1, &Raw_data[1], 1);
spi_read_reg(BMP280_, DATA_L_REG+2, &Raw_data[2], 1);
spi_read_reg(BMP280_, DATA_L_REG+3, &Raw_data[3], 1);
spi_read_reg(BMP280_, DATA_L_REG+4, &Raw_data[4], 1);
spi_read_reg(BMP280_, DATA_L_REG+5, &Raw_data[5], 1);
raw_temp = Raw_data[0] << 12 | Raw_data[1] << 4 | Raw_data[2]>>4;
raw_pres = Raw_data[3] << 12 | Raw_data[4] << 4 | Raw_data[5]>>4;
}
int32_t CompensateTemp(int32_t adc_T){
int32_t var1, var2, T;
var1 = ((((adc_T>>3) - ((int32_t)dig_T1<<1))) * ((int32_t)dig_T2)) >> 11;
var2 = (((((adc_T>>4) - ((int32_t)dig_T1)) * ((adc_T>>4) - ((int32_t)dig_T1))) >> 12) * ((int32_t)dig_T3)) >> 14;
t_fine = var1 + var2;
T = (t_fine * 5 + 128) >> 8;
return T;
}
int32_t CompensatePres(int32_t adc_P){
int64_t var1, var2, p;
var1 = ((int64_t)t_fine) - 128000;
var2 = var1 * var1 * (int64_t)dig_P6;
var2 = var2 + ((var1*(int64_t)dig_P5)<<17);
var2 = var2 + (((int64_t)dig_P4)<<35);
var1 = ((var1 * var1 * (int64_t)dig_P3)>>8) + ((var1 * (int64_t)dig_P2)<<12);
var1 = (((((int64_t)1)<<47)+var1))*((int64_t)dig_P1)>>33;
if(var1 == 0){
return 0; // avoid exception caused by division by zero
}
p = 1048576-adc_P;
p = (((p<<31)-var2)*3125)/var1;
var1 = (((int64_t)dig_P9) * (p>>13) * (p>>13)) >> 25;
var2 = (((int64_t)dig_P8) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (((int64_t)dig_P7)<<4);
return (uint32_t)p;
}
void ReadAll(BMP280_Data *data){
ReadV();
data->raw_temp = raw_temp;
data->raw_pres = raw_pres;
data->temp = CompensateTemp(raw_temp);
data->pres = CompensatePres(raw_pres);
}
bmp280.h
#ifndef BMP280_H
#define BMP280_H
#include "func.h"
extern UART_HandleTypeDef huart1;
#define ID_REG 0xD0
#define RES_REG 0x0E
#define DIG_T1_L_REG 0x88
#define DIG_T2_L_REG 0x8A
#define DIG_T3_L_REG 0x8C
#define DIG_P1_L_REG 0x8E
#define DIG_P2_L_REG 0x90
#define DIG_P3_L_REG 0x92
#define DIG_P4_L_REG 0x94
#define DIG_P5_L_REG 0x96
#define DIG_P6_L_REG 0x98
#define DIG_P7_L_REG 0x9A
#define DIG_P8_L_REG 0x9C
#define DIG_P9_L_REG 0x9E
#define DATA_L_REG 0xF7
#define CONFIG_L_REG 0xF4
#define TEMP_DIF 0
#define TEMP_COF 4
#define RES_DIF 0
#define PRES_COF 1
//0x88 / 0x89 dig_T1 unsigned short
//0x8A / 0x8B dig_T2 signed short
//0x8C / 0x8D dig_T3 signed short
//0x8E / 0x8F dig_P1 unsigned short
//0x90 / 0x91 dig_P2 signed short
//0x92 / 0x93 dig_P3 signed short
//0x94 / 0x95 dig_P4 signed short
//0x96 / 0x97 dig_P5 signed short
//0x98 / 0x99 dig_P6 signed short
//0x9A / 0x9B dig_P7 signed short
//0x9C / 0x9D dig_P8 signed short
//0x9E / 0x9F dig_P9 signed short
//0xA0 / 0xA reserved reserved
uint16_t dig_T1;
int16_t dig_T2;
int16_t dig_T3;
uint16_t dig_P1;
int16_t dig_P2;
int16_t dig_P3;
int16_t dig_P4;
int16_t dig_P5;
int16_t dig_P6;
int16_t dig_P7;
int16_t dig_P8;
int16_t dig_P9;
int32_t t_fine;
int32_t raw_temp;
int64_t raw_pres;
typedef struct{
int32_t raw_temp;
int32_t raw_pres;
int32_t temp;
int32_t pres;
}BMP280_Data;
void Reset();
void Init();
void ReadId(uint8_t *id);
void ReadV();
void ReadAll();
int32_t CompensateTemp(int32_t adc_T);
int32_t CompensatePres(int32_t adc_P);
#endif
I use Compensate formula from BMP280 datasheet.
Please help me and sorry for my bad english.

Issue in interfacing SPI e-ink display with PIC 18F46K22

I am using a PIC 18F46K22 in SPI master mode to communicate with a Waveshare 1.54" ePaper Module. The FOSC frequency is 8Mhz internal and SPI configuration is FOSC/4. So when I check the output on logic-analyzer some output bits are differ from expected. And there is some deviation in SCL.
#include <xc.h>
#include "config.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "main.h"
//#define _XTAL_FREQ 8000000
#define SPI1_DUMMY_DATA 0x0
#define SPI_RX_IN_PROGRESS 0x0
#define MY_BUFFER_SIZE 25
extern UBYTE EPD_Init(const unsigned char* lut);
unsigned char myWriteBuffer[100]="Hi I'm master..";
uint8_t myReadBuffer[100];
uint8_t total;
uint8_t temp;
uint8_t my_data = 0x58;
void UART_Init(void)
{
//69
SPBRG2 = 69;
TXSTA2bits.BRGH = 1;
BAUDCON2bits.BRG16 = 1; // Divisor at 8 bit
TRISDbits.TRISD6 = 0;
TRISDbits.TRISD7 = 1;
RCSTA2bits.SPEN = 1; // Enable serial port
TXSTA2bits.SYNC = 0; // Async operation
TXSTA2bits.TX9 = 0; // No tx of 9th bit
RCSTA2bits.RX9 = 0; // No rx of 9th bit
TXSTA2bits.TXEN = 1; // Enable transmitter
RCSTA2bits.CREN = 1; // Enable receiver
}
void UART_Putch(unsigned char bt)
{
while (!PIR3bits.TX2IF); // hold the program till TX buffer is free
TXREG2 = bt; //Load the transmitter buffer with the received value
}
void UART_Print(unsigned const char *ptr)
{
while (*ptr != 0)
{
UART_Putch(*ptr++);
}
}
unsigned char UART_getch() {
unsigned char temp;
if (RCSTA2bits.OERR) // check for Error
{
RCSTA2bits.CREN = 0; //If error -> Reset
//__delay_ms(10);
RCSTA2bits.CREN = 1; //If error -> Reset
}
while (!PIR3bits.RC2IF); // hold the program till RX buffer is free
temp = RCREG2;
return temp; //receive the value and send it to main function
}
void main()
{
ANSELA = 0;
ANSELB = 0;
ANSELC = 0;
ANSELD = 0;
TRISBbits.TRISB0 = 0; //RST Pin OUTPUT
TRISBbits.TRISB1 = 0; //DC Pin OUTPUT
TRISBbits.TRISB2 = 0; //CS Pin OUTPUT
TRISBbits.RB3 = 1; //BUSY Pin INPUT
// int i;
TRISD =0;/* PORT initialize as output */
EPD_RST_PIN = 0;
EPD_DC_PIN = 0;
//OSCCON = 0x72; /* Use internal osc. frequency 16 MHz */
OSCCONbits.SCS = 0b10; //Frequency & PLL SETUP
OSCCONbits.IRCF = 0b110; //8 MHz
while (!OSCCONbits.HFIOFS);
OSCTUNEbits.PLLEN = 0; //PLL disable
UART_Init();
SPI_Init_Master(); /* Initialize SPI communication as a master */
if(EPD_Init(lut_full_update) != 0) {
UART_Print("e-Paper init failed\r\n");
while(1);
}
UART_Print("e-Paper init\r\n");
for(uint8_t i = 0; i < 10; i++){
__delay_ms(10);
}
EPD_Clear();
UART_Print("e-Paper cleared\r\n");
for(uint8_t i = 0; i < 10; i++){
__delay_ms(50);
}
while(1)
{
// total = 0;
// //do
// //{
// LATAbits.LATA5=0;
// //total = SPI1_Exchange8bitBuffer(SPI1_DUMMY_DATA, MY_BUFFER_SIZE, &myReadBuffer[total]);
// total = SPI1_Exchange8bit(my_data);
//
// LATAbits.LATA5=1;
// __delay_ms(500);
// __delay_ms(500);
// // Do something else...
//
// //} while(total < MY_BUFFER_SIZE);
// //while(1);
//
// EPD_Clear();
//
// __delay_ms(500);
}
}
void SPI_Init_Master()
{
/* PORT definition for SPI pins*/
TRISCbits.TRISC4 = 1; /* RB0 as input(SDI) */
TRISCbits.TRISC3 = 0; /* RB1 as output(SCK) */
// TRISBbits.TRISB2 = 0; /* RA5 as a output(SS') */
TRISCbits.TRISC5 = 0; /* RC7 as output(SDO) */
/* To initialize SPI Communication configure following Register*/
EPD_CS_PIN = 1;
SSP1STAT=0x00; /* Data change on rising edge of clk , BF=0*/
SSP1CON1=0x20; /* Slave mode,Serial enable, idle state high for clk */
PIR1bits.SSP1IF=0;
/* Disable the ADC channel which are on for multiplexed pin
when used as an input */
ADCON0=0; /* This is for de-multiplexed the SCL
and SDI from analog pins*/
ADCON1=0x0F; /* This makes all pins as digital I/O */
}
uint8_t SPI1_Exchange8bit(uint8_t data)
{
// Clear the Write Collision flag, to allow writing
SSP1CON1bits.WCOL = 0;
SSP1BUF = data;
while(SSP1STATbits.BF == SPI_RX_IN_PROGRESS)
{
}
return (SSP1BUF);
}
uint8_t SPI1_Exchange8bitBuffer(uint8_t *dataIn, uint8_t bufLen, uint8_t *dataOut)
{
uint8_t bytesWritten = 0;
if(bufLen != 0)
{
if(dataIn != NULL)
{
while(bytesWritten < bufLen)
{
if(dataOut == NULL)
{
SPI1_Exchange8bit(dataIn[bytesWritten]);
}
else
{
dataOut[bytesWritten] = SPI1_Exchange8bit(dataIn[bytesWritten]);
}
bytesWritten++;
}
}
else
{
if(dataOut != NULL)
{
while(bytesWritten < bufLen )
{
temp = SPI1_Exchange8bit(SPI1_DUMMY_DATA);
if(temp!=SPI1_DUMMY_DATA)
{
UART_Putch(temp); //uart print
dataOut[bytesWritten] = temp;
bytesWritten++;
}
__delay_ms(5);
}
}
}
}
return bytesWritten;
}
Compare your logic analyser SCK and MOSI timing with that specified for the part at https://www.waveshare.com/wiki/1.54inch_e-Paper_Module:
Note that the MOSI (SDIN) state must be stable on the rising edge of SCK (SCLK). In your case the MOSI transitions are synchronous with the rising edge, and you have a clock transition before the MOSI has the correct D7=0 state. SPI timing is defined by both clock polarity and clock phase - giving four possible clock modes. Compare the Waveshare timing diagram with the 18F46K22 datasheet:
The Waveshare diagram suggests that either CKP=1/CKE=0, or CKP=0/CKE=1 may be used, you have:
SSP1STAT=0x00 ;
SSP1CON1=0x20 ;
Which is CKP=0/CKE=0 (which correlates with your logic analyser trace).
You need on of either:
SSP1STAT=0x20 ; // CKE=1
SSP1CON1=0x20 ; // CKP=0
or
SSP1STAT=0x00 ; // CKE=0
SSP1CON1=0x30 ; // CKP=1
Since idle state (controlled by CKP) of SCK is a don't-care, I suggest leaving that as-is and using the first suggestion - that seems more intuitive somehow.
Note also that your logic analyser must also be set to the same phase/polarity clock mode in order for its presentation of the data to be correct.

Stop Momde, Allarm and stm32L152RE

I have a NUCLEO STM32L152RE. I want to use the low power features of this board and wrote this easy example. I use CubeMX to configure the board.
I want to wake up every 3 minutes, but 6 minutes later the system freezes.
/* Private variables */
ADC_HandleTypeDef hadc;
I2C_HandleTypeDef hi2c1;
RTC_HandleTypeDef hrtc;
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim11;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
UART_HandleTypeDef huart3;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
void SystemClock_Config(void);
void Error_Handler(void);
static void MX_GPIO_Init(void);
static void MX_RTC_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_ADC_Init(void);
static void MX_I2C1_Init(void);
static void MX_TIM3_Init(void);
static void MX_TIM11_Init(void);
static void MX_USART3_UART_Init(void);
uint8_t data[]={3,3};
uint8_t data2[]={2,3};
uint8_t data3[]={5,6};
uint8_t dataS4[]={4,4};
uint8_t dataS5[]={5,5};
uint8_t dataS6[]={6,6};
uint8_t dataS7[]={9,9};
uint8_t dataD[]={7,7};
uint8_t dataS1[]={1,1};
uint8_t command1[]="default;"; //
uint8_t command2[]="up;"; // THE SYSTEM UP
int i = 0;
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
HAL_PWR_EnableBkUpAccess(); //enable PWR backup domain access (RTC,BKReg)
__HAL_RCC_RTC_ENABLE(); //Enable RTC. not created by cube because the RTC can run.
/* USER CODE END 1 */
/* MCU Configuration------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_RTC_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_ADC_Init();
MX_I2C1_Init();
MX_TIM3_Init();
MX_TIM11_Init();
MX_USART3_UART_Init();
/* USER CODE BEGIN 2 */
HAL_UART_Transmit(&huart2,data,2,1000);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// here i have code.......
HAL_Delay(500);
HAL_UART_Transmit(&huart2,dataS7,2,1000);
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON,PWR_STOPENTRY_WFI); // stop mode
}
}
RTC Initialization
/* RTC init function */
static void MX_RTC_Init(void)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
RTC_AlarmTypeDef sAlarm;
/**Initialize RTC Only */
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/**Initialize RTC and set the Time and Date */
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 0x1;
sDate.Year = 0x0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/**Enable the Alarm A */
sAlarm.AlarmTime.Hours = 0x0;
sAlarm.AlarmTime.Minutes = 0x3;
sAlarm.AlarmTime.Seconds = 0x0;
sAlarm.AlarmTime.SubSeconds = 0x0;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmMask =RTC_ALARMMASK_NONE;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.AlarmDateWeekDay = 0x1;
sAlarm.Alarm = RTC_ALARM_A;
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
}
Here I have the code for handling the interrupt:
/* interrupt callback */
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc){
RTC_AlarmTypeDef sAlarm;
HAL_RTC_GetAlarm(hrtc,&sAlarm,RTC_ALARM_A,FORMAT_BIN);
if(sAlarm.AlarmTime.Minutes>58){
sAlarm.AlarmTime.Minutes=0;
}else{
sAlarm.AlarmTime.Minutes=sAlarm.AlarmTime.Minutes+1;
}
while(HAL_RTC_SetAlarm_IT(hrtc, &sAlarm, FORMAT_BIN)!=HAL_OK){}
SystemClock_Config(); // UP THE SYSTEM
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5); //TAGGLE THE LED
HAL_UART_Transmit(&huart2,data3,2,1000);
HAL_UART_Transmit(&huart1,command2,sizeof(command2),1000);
}
I want that every 3 minutes the system wakes up and later goes in stop mode, but the system doesn't work. After 60 minutes the system doesn't do anything. Can you help me?

stm32f4 CAN receiver_IT issue

Next in my little project(stm32f407vg) is to receive can messages from another hardware(PIC 18L25K80)
I currently have working an UART to my computer so I can easily debug the chip via UART.
The problem is that I receive the message, the interruption gets triggered but what I read from rxMessage is non sense.
Test Procedure:
Simulating the emitter I use Microchip CAN BUS Analayzer, here is the screenshot of the window:
And here is what I see in the UART:
And this is what I see if I debug (I'm using Coocox 1.7.8):
Why the values of rxMessage doesn't change neither inside the HAL driver or in my code (can.c).
Thanks.
---------------------------- main.c-------------------------
#include "globals.h"
#include "stm32f4xx_hal.h"
#include "syscfg.h"
#include "can.h"
#include "usart.h"
#include "gpio.h"
#include "kernel.h"
#include <stdio.h>
int main(void){
SysIniCfg();
while (1){
kernelMotor();
usartMotor();
canMotor();
HAL_GPIO_TogglePin(LED_G_GPIO_Port,LED_G_Pin);
}
}
------------------------- end main.c -----------------------
---------------------------- syscfg.c-------------------------
#include "syscfg.h"
#include "syscfg.h"
#include "can.h"
#include "usart.h"
#include "gpio.h"
#include "kernel.h"
/*
* System Init configuration
*/
void SysIniCfg(){
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_CAN1_Init();
MX_USART1_UART_Init();
/* Initialize interrupts */
MX_NVIC_Init();
kernelInit();
}
------------------------- end syscfg.c -----------------------
---------------------------- can.h-------------------------
#include "stm32f4xx_hal.h"
#include "globals.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
typedef struct
{
CAN_HandleTypeDef Handle;
HAL_CAN_StateTypeDef *pState;
uint32_t *pErrorCode;
} t_can_control;
typedef enum{
CM_STOPPED = 0,
CM_INIT = 1,
CM_IDLE = 10,
CM_ERROR = 255
}uint8_t_canStates;
uint8_t_canStates canMotorStates;
extern CAN_HandleTypeDef hcan1;
t_can_control can_ctrl;
CanTxMsgTypeDef sTxMsg;
CanRxMsgTypeDef sRxMsg;
/* USER CODE END Private defines */
/* USER CODE BEGIN Prototypes */
extern void Error_Handler(void);
void MX_CAN1_Init(void);
------------------------- end can.h -----------------------
---------------------------- can.c-------------------------
#include "can.h"
#include "usart.h"
#include "gpio.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
CAN_HandleTypeDef hcan1;
/* CAN1 init function */
void MX_CAN1_Init(void)
{
CAN_FilterConfTypeDef sFilterConfig;
canMotorStates = CM_STOPPED;
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 20;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SJW = CAN_SJW_1TQ;
hcan1.Init.BS1 = CAN_BS1_13TQ;
hcan1.Init.BS2 = CAN_BS2_2TQ;
hcan1.Init.TTCM = DISABLE;
hcan1.Init.ABOM = DISABLE;
hcan1.Init.AWUM = DISABLE;
hcan1.Init.NART = DISABLE;
hcan1.Init.RFLM = DISABLE;
hcan1.Init.TXFP = DISABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK){
Error_Handler();
}
sFilterConfig.FilterNumber = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = 0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.BankNumber = 14;
if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK){
Error_Handler();
}
}
void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(canHandle->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspInit 0 */
/* USER CODE END CAN1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();
/**CAN1 GPIO Configuration
PA11 ------> CAN1_RX
PA12 ------> CAN1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN CAN1_MspInit 1 */
canMotorStates = CM_INIT;
/* USER CODE END CAN1_MspInit 1 */
}
}
void HAL_CAN_MspDeInit(CAN_HandleTypeDef* canHandle)
{
if(canHandle->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspDeInit 0 */
/* USER CODE END CAN1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_CAN1_CLK_DISABLE();
/**CAN1 GPIO Configuration
PA11 ------> CAN1_RX
PA12 ------> CAN1_TX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);
/* Peripheral interrupt Deinit*/
HAL_NVIC_DisableIRQ(CAN1_TX_IRQn);
HAL_NVIC_DisableIRQ(CAN1_RX0_IRQn);
HAL_NVIC_DisableIRQ(CAN1_RX1_IRQn);
HAL_NVIC_DisableIRQ(CAN1_SCE_IRQn);
}
/* USER CODE BEGIN CAN1_MspDeInit 1 */
canMotorStates = CM_STOPPED;
/* USER CODE END CAN1_MspDeInit 1 */
}
/**
* #brief Sends order for reading and reads an amount of data in no-blocking mode with Interrupt.
* #param u8can: Number of CAN instance
* #param u16std_id: CAN standard identifier
* #param pstate: Pointer to CAN state
* #param pu32error: Pointer to CAN error code
* #retval HAL status
*/
HAL_StatusTypeDef CAN_Read_wInt(uint8_t u8can, uint16_t u16std_id, HAL_CAN_StateTypeDef *pstate, uint32_t *pu32error){
HAL_StatusTypeDef status = HAL_OK;
if ((*pu32error) == HAL_CAN_ERROR_NONE)
{
/* Set Rx Message structure */
sRxMsg.StdId = (uint32_t)u16std_id;
sRxMsg.IDE = CAN_ID_STD;
sRxMsg.RTR = CAN_RTR_DATA;
sRxMsg.DLC = (uint8_t)8;
sRxMsg.FIFONumber = CAN_FIFO0;
sRxMsg.FMI = 1;
/* Put structure in the handle */
can_ctrl.Handle.pRxMsg = &sRxMsg;
/* Order to transmit in non-blocking mode */
status = HAL_CAN_Receive_IT(&hcan1, CAN_FIFO0);
if (status == HAL_OK)
{
/* Link external pointers to CAN local pointer */
can_ctrl.pState = pstate;
can_ctrl.pErrorCode = pu32error;
/* Update CAN State */
*(can_ctrl.pState) = HAL_CAN_STATE_BUSY_RX;
}
}
else
{
status = HAL_BUSY;
}
return status;
}
void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
HAL_GPIO_TogglePin(LED_Y_GPIO_Port,LED_Y_Pin);
char canOutBuffer[100];
sprintf(canOutBuffer,"-- %d : %d --", CanHandle->pRxMsg->StdId,CanHandle->pRxMsg->Data[0]);
usartPutString(canOutBuffer);
if(HAL_CAN_Receive_IT(CanHandle, CAN_FIFO0) != HAL_OK){
Error_Handler();
}
}
------------------------- end can.c -----------------------
---------------------------- main.c-------------------------
------------------------- end main.c -----------------------
I found what I was missing, in the definition of the can handle was specified the tx and rx message, so I suppose that the HAL drivers didn't do the initialization of this structures
void MX_CAN1_Init(void) {
CAN_FilterConfTypeDef sFilterConfig;
static CanTxMsgTypeDef TxMessage;
static CanRxMsgTypeDef RxMessage;
canMotorStates = CM_STOPPED;
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 20;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SJW = CAN_SJW_1TQ;
hcan1.Init.BS1 = CAN_BS1_13TQ;
hcan1.Init.BS2 = CAN_BS2_2TQ;
hcan1.Init.TTCM = DISABLE;
hcan1.Init.ABOM = DISABLE;
hcan1.Init.AWUM = DISABLE;
hcan1.Init.NART = DISABLE;
hcan1.Init.RFLM = DISABLE;
hcan1.Init.TXFP = DISABLE;
hcan1.pRxMsg = &RxMessage;
hcan1.pTxMsg = &TxMessage;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
sFilterConfig.FilterNumber = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = 0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.BankNumber = 14;
if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
{
/* Filter configuration Error */
Error_Handler();
}
}

Resources