I keep receiving 0 in the output no matter what I send - c

I am working on a project where I have to establish a communication between my microprocessor and a Bluetooth device. I established a communication, but no matter what I send, I only get 0 when I print it. Thanks for the help !
#include <asf.h>
#include <string.h>
#include <stdio.h>
#include "usart.h"
/**
* Configure serial console.
*/
static void configure_console(void)
{
const usart_serial_options_t uart_serial_options = {
.baudrate = CONF_UART_BAUDRATE,
#ifdef CONF_UART_CHAR_LENGTH
.charlength = CONF_UART_CHAR_LENGTH,
#endif
.paritytype = CONF_UART_PARITY,
#ifdef CONF_UART_STOP_BITS
.stopbits = CONF_UART_STOP_BITS,
#endif
};
/* Configure console. */
stdio_serial_init(CONF_UART, &uart_serial_options);
}
volatile uint32_t ul_ms_ticks = 0;
static void mdelay(uint32_t ul_dly_ticks)
{
uint32_t ul_cur_ticks;
ul_cur_ticks = ul_ms_ticks;
while ((ul_ms_ticks - ul_cur_ticks) < ul_dly_ticks) {
}
}
void SysTick_Handler(void)
{
ul_ms_ticks++;
}
#define USART_SERIAL USART1
#define USART_SERIAL_ID ID_USART1 //USART1 for sam4l
#define USART_SERIAL_BAUDRATE 9600
#define USART_SERIAL_CHAR_LENGTH US_MR_CHRL_8_BIT
#define USART_SERIAL_PARITY US_MR_PAR_NO
#define USART_SERIAL_STOP_BIT US_MR_NBSTOP_1
int main(void)
{
/* Initialize the SAM system */
sysclk_init();
board_init();
/* Initialize the console uart */
configure_console();
uint32_t a= 1234;
int bit_rx = 6;
if (SysTick_Config(sysclk_get_cpu_hz() / 1000)) {
while (1) { /* Capture error */
}
}
const sam_usart_opt_t usart_console_settings = {
USART_SERIAL_BAUDRATE,
USART_SERIAL_CHAR_LENGTH,
USART_SERIAL_PARITY,
USART_SERIAL_STOP_BIT,
US_MR_CHMODE_NORMAL
};
#if SAM4L
sysclk_enable_peripheral_clock(USART_SERIAL);
#else
sysclk_enable_peripheral_clock(USART_SERIAL_ID);
#endif
usart_enable_tx(USART_SERIAL);
usart_enable_rx(USART_SERIAL);
while (1) {
printf("%d \n", bit_rx );
usart_getchar(USART_SERIAL, &a);
bit_rx = a;
printf("%d \n",bit_rx );
if (a != 0) {
ioport_set_pin_level(LED_0_PIN, LED_0_ACTIVE);
} else {
ioport_set_pin_level(LED_0_PIN, !LED_0_ACTIVE);
}
}
}

Perhaps you shouldn't call usart_getchar() until usart_is_rx_ready() returns 1.

Thanks everyone !
I tried to cast the received variable first : bit_rx = (int) a;
And then I found that I needed this to make it work :
static usart_serial_options_t usart_options = {
.baudrate = USART_SERIAL_BAUDRATE,
.charlength = USART_SERIAL_CHAR_LENGTH,
.paritytype = USART_SERIAL_PARITY,
.stopbits = USART_SERIAL_STOP_BIT
};
usart_serial_init(USART_SERIAL, &usart_options);
And I disabled the stop bit, because my bluetooth didn't have one :
#define USART_SERIAL_STOP_BIT false
Now it works like a charm. Thanks all for your help !

Related

Incorrect timing in delay is observed

The below code is to generate a single line signal with two different timings, doing good if we give more than 10ms in vTaskDelay(), i.e getting perfect delay is observed but if we give lesser than 10ms the perfect signal is not observed. Please help me in this regard.
#include <stdio.h>
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include <stdbool.h>
#include "esp_err.h"
#include "sdkconfig.h"
#include "driver/timer.h"
#define GPIO_OUTPUT_IO 2
#define TIMER_GROUP 0
#define TIMER_INDEX 0
uint64_t task_counter_value;
void turn_off(void *pvParameters);
void turn_on(void *pvParameters);
void turn_on(void *pvParameters)
{
gpio_set_level(GPIO_OUTPUT_IO, 1);
vTaskDelay(pdMS_TO_TICKS(30));
xTaskCreate(&turn_off, "turn_off", 2048, NULL, 10, NULL);
vTaskDelete(NULL);
}
void turn_off(void *pvParameters)
{
gpio_set_level(GPIO_OUTPUT_IO, 0);
vTaskDelay(pdMS_TO_TICKS(8));
xTaskCreate(&turn_on, "turn_on", 2048, NULL, 10, NULL);
vTaskDelete(NULL);
}
void app_main(void)
{
timer_config_t config;
config.alarm_en = false;
config.auto_reload = true;
config.counter_dir = TIMER_COUNT_UP;
config.intr_type = TIMER_INTR_LEVEL;
config.counter_en = TIMER_PAUSE;
config.divider = 80;
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << GPIO_OUTPUT_IO);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
timer_init(TIMER_GROUP, TIMER_INDEX, &config);
xTaskCreate(&turn_on, "turn_on", 2048, NULL, 10, NULL);
while (true)
{
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}

The function pointer is changing its own address

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.

How are pins defined for sensors in embedded C?

I have a Nordic nRF52840DK board that needs to be connected to an LSM6DSL accelerometer. I am using the Zephyr RTOS and the sample code from Zephyr is shown below:
/*
* Copyright (c) 2018 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <device.h>
#include <drivers/sensor.h>
#include <stdio.h>
#include <sys/util.h>
static inline float out_ev(struct sensor_value *val)
{
return (val->val1 + (float)val->val2 / 1000000);
}
static int print_samples;
static int lsm6dsl_trig_cnt;
static struct sensor_value accel_x_out, accel_y_out, accel_z_out;
static struct sensor_value gyro_x_out, gyro_y_out, gyro_z_out;
#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
static struct sensor_value magn_x_out, magn_y_out, magn_z_out;
#endif
#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
static struct sensor_value press_out, temp_out;
#endif
#ifdef CONFIG_LSM6DSL_TRIGGER
static void lsm6dsl_trigger_handler(const struct device *dev,
struct sensor_trigger *trig)
{
static struct sensor_value accel_x, accel_y, accel_z;
static struct sensor_value gyro_x, gyro_y, gyro_z;
#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
static struct sensor_value magn_x, magn_y, magn_z;
#endif
#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
static struct sensor_value press, temp;
#endif
lsm6dsl_trig_cnt++;
sensor_sample_fetch_chan(dev, SENSOR_CHAN_ACCEL_XYZ);
sensor_channel_get(dev, SENSOR_CHAN_ACCEL_X, &accel_x);
sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Y, &accel_y);
sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Z, &accel_z);
/* lsm6dsl gyro */
sensor_sample_fetch_chan(dev, SENSOR_CHAN_GYRO_XYZ);
sensor_channel_get(dev, SENSOR_CHAN_GYRO_X, &gyro_x);
sensor_channel_get(dev, SENSOR_CHAN_GYRO_Y, &gyro_y);
sensor_channel_get(dev, SENSOR_CHAN_GYRO_Z, &gyro_z);
#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
/* lsm6dsl external magn */
sensor_sample_fetch_chan(dev, SENSOR_CHAN_MAGN_XYZ);
sensor_channel_get(dev, SENSOR_CHAN_MAGN_X, &magn_x);
sensor_channel_get(dev, SENSOR_CHAN_MAGN_Y, &magn_y);
sensor_channel_get(dev, SENSOR_CHAN_MAGN_Z, &magn_z);
#endif
#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
/* lsm6dsl external press/temp */
sensor_sample_fetch_chan(dev, SENSOR_CHAN_PRESS);
sensor_channel_get(dev, SENSOR_CHAN_PRESS, &press);
sensor_sample_fetch_chan(dev, SENSOR_CHAN_AMBIENT_TEMP);
sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp);
#endif
if (print_samples) {
print_samples = 0;
accel_x_out = accel_x;
accel_y_out = accel_y;
accel_z_out = accel_z;
gyro_x_out = gyro_x;
gyro_y_out = gyro_y;
gyro_z_out = gyro_z;
#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
magn_x_out = magn_x;
magn_y_out = magn_y;
magn_z_out = magn_z;
#endif
#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
press_out = press;
temp_out = temp;
#endif
}
}
#endif
void main(void)
{
int cnt = 0;
char out_str[64];
struct sensor_value odr_attr;
const struct device *lsm6dsl_dev = device_get_binding(DT_LABEL(DT_INST(0, st_lsm6dsl)));
if (lsm6dsl_dev == NULL) {
printk("Could not get LSM6DSL device\n");
return;
}
/* set accel/gyro sampling frequency to 104 Hz */
odr_attr.val1 = 104;
odr_attr.val2 = 0;
if (sensor_attr_set(lsm6dsl_dev, SENSOR_CHAN_ACCEL_XYZ,
SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr) < 0) {
printk("Cannot set sampling frequency for accelerometer.\n");
return;
}
if (sensor_attr_set(lsm6dsl_dev, SENSOR_CHAN_GYRO_XYZ,
SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr) < 0) {
printk("Cannot set sampling frequency for gyro.\n");
return;
}
#ifdef CONFIG_LSM6DSL_TRIGGER
struct sensor_trigger trig;
trig.type = SENSOR_TRIG_DATA_READY;
trig.chan = SENSOR_CHAN_ACCEL_XYZ;
if (sensor_trigger_set(lsm6dsl_dev, &trig, lsm6dsl_trigger_handler) != 0) {
printk("Could not set sensor type and channel\n");
return;
}
#endif
if (sensor_sample_fetch(lsm6dsl_dev) < 0) {
printk("Sensor sample update error\n");
return;
}
while (1) {
/* Erase previous */
printk("\0033\014");
printf("LSM6DSL sensor samples:\n\n");
/* lsm6dsl accel */
sprintf(out_str, "accel x:%f ms/2 y:%f ms/2 z:%f ms/2",
out_ev(&accel_x_out),
out_ev(&accel_y_out),
out_ev(&accel_z_out));
printk("%s\n", out_str);
/* lsm6dsl gyro */
sprintf(out_str, "gyro x:%f dps y:%f dps z:%f dps",
out_ev(&gyro_x_out),
out_ev(&gyro_y_out),
out_ev(&gyro_z_out));
printk("%s\n", out_str);
#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
/* lsm6dsl external magn */
sprintf(out_str, "magn x:%f gauss y:%f gauss z:%f gauss",
out_ev(&magn_x_out),
out_ev(&magn_y_out),
out_ev(&magn_z_out));
printk("%s\n", out_str);
#endif
#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
/* lsm6dsl external press/temp */
sprintf(out_str, "press: %f kPa - temp: %f deg",
out_ev(&press_out), out_ev(&temp_out));
printk("%s\n", out_str);
#endif
printk("loop:%d trig_cnt:%d\n\n", ++cnt, lsm6dsl_trig_cnt);
print_samples = 1;
k_sleep(K_MSEC(2000));
}
}
From my previous experience working with Arduino, you need to define the pins before the main function, but there isn't any definition on pins in this code example. So my question is: How does the board know which pins to use when connected to the sensor?
Thanks in advance!
In embedded C (bare metal and some RTOS), the developer is expected to know what is connected where and which registers to use to access the connected hardware by driving the right pins.
In the specific case of Zephyr (as well as Das U-Boot and Linux on some architectures), the system configuration (among other things pins, but not only) is described by a device-tree. It is a "a data structure for describing hardware", which allows the firmware code to become independent of the actual hardware.
The device-tree will describe many things, the most important being:
the device's memory map
the list of CPUs and their properties (frequency, caches, ...)
the peripherals, as well as their configuration
Zephyr does have a very good introduction to device-tree.
In the code you posted, Zephyr does retrieve the device information from the device-tree when executing the following line:
const struct device *lsm6dsl_dev = device_get_binding(DT_LABEL(DT_INST(0, st_lsm6dsl)));

Embedded C (FreeRTOS)

Trying to create a reaction timer. Timer rand counts down from 10. LED is red and turns green when the user has pressed the switch. The user has to press either sw2 or sw3 when prompted has a 5 second gap to press switch. Once switch is pressed, the time is recorded and printed to putty. Game then resets and user can play again.
I'm current stuck trying to implement the LED and rand timer, could anyone help:
#include "freeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "queue.h"
#include "timers.h"
#include "event_groups.h"
#include <stdio.h>
#include "board.h"
#include "peripherals.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "MK64F12.h"
#include "fsl_debug_console.h"
#include "fsl_UART.h"
#include "fsl_device_registers.h"
/* TODO: insert other definitions and declarations here. */
QueueHandle_t switchQueue = NULL;
TaskHandle_t displayHandle = NULL, UARTHandle =NULL, LED_TaskHandle = NULL;
static void displayTask(void * pvParameters);
static void LED_Task(void *pvParameters);
static EventGroupHandle_t SW_Group = NULL;
#define SW2_bit 1<<0
#define SW3_bit 1<<1
/*
* #brief Application entry point.
*/
void BOARD_SW2_IRQ_HANDLER(){
static int8_t count = 0;
static uint32_t buffer[5];
BaseType_t xHigherPriorityTaskWoken;
PORT_ClearPinsInterruptFlags(BOARD_SW2_PORT, 1<<BOARD_SW2_GPIO_PIN);
buffer[count] = xTaskGetTickCountFromISR()*(1000/configTICK_RATE_HZ);
printf("\n\rSW2 pressed at %d", buffer[count]);
/* if(GPIO_PinRead(BOARD_INITPINS_SW2_GPIO,BOARD_INITPINS_SW2_PIN)== 0)
{
PRINTF("Switch pressed!.\r\n");
xEventGroupSetBits(SW_Group, SW2_bit);
while(GPIO_PinRead(BOARD_INITPINS_SW2_GPIO,BOARD_INITPINS_SW2_PIN) == 0){}
//vTaskSuspend(NULL);
if(++count==5){
count=0;
xHigherPriorityTaskWoken = pdFALSE;
//send copy of buffer to queue
xQueueSendFromISR(switchQueue, buffer, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}*/
vTaskDelay(pdMS_TO_TICKS(100));
}
int main(void) {
/* Init board hardware. */
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitBootPeripherals();
/* Init FSL debug console. */
BOARD_InitDebugConsole();
BOARD_InitLEDsPins();
//configure sw2 interrupt
NVIC_SetPriority(BOARD_SW2_IRQ, 10);
NVIC_ClearPendingIRQ(BOARD_SW2_IRQ);
NVIC_EnableIRQ(BOARD_SW2_IRQ);
SW_Group = xEventGroupCreate();
switchQueue = xQueueCreate(5,20); //5 item queue of 20 bytes per item
if(xTaskCreate(displayTask, "Time Display", 100, NULL, 3, &displayHandle)== pdFALSE)
{
printf("UART task not created\n\r");
while(1)
;
}
if (xTaskCreate(LED_Task, "LED_Task", configMINIMAL_STACK_SIZE + 10, NULL, 4, &LED_TaskHandle) != pdPASS)
{
PRINTF("LED_Task creation failed!.\r\n");
while (1)
;
}
vTaskStartScheduler();
volatile static int i = 0;
/* Enter an infinite loop, just incrementing a counter. */
while(1){
i++;
}
return 0 ;
}
static void displayTask(void * pvParameters){
uint32_t rxBuffer[5];
printf("Starting display task\n\r");
while(1){
if(xQueueReceive(switchQueue, &rxBuffer, portMAX_DELAY) == pdTRUE){
//print data
printf("\n\n\rData Received from Queue:");
int x;
for(x=0;x<5;x++){
printf("\n\rData %d: %d",x,rxBuffer[x]);
}
vTaskDelay(pdMS_TO_TICKS(100));
}
}
}
void LED_Task(void *pvParameters)
{
EventBits_t event_bits;
for (;;) //no conditions in the for loop, will run forever
{
event_bits = xEventGroupWaitBits(SW_Group, SW2_bit | SW3_bit, pdTRUE, pdFALSE, portMAX_DELAY);
if(event_bits & SW2_bit){
PRINTF("Event bit set, RED LED Toggled!.\r\n");
LED_RED_TOGGLE();
}
else if(event_bits & SW3_bit){
PRINTF("Event bit set, GREEN LED Toggled!.\r\n");
LED_GREEN_TOGGLE();
}
}
}

Unable to Break Out of if Statement After Button Depression - Microchip

I'm unable to break out of an if statement after a button has been depressed. The button activates a relay and the depression turns the relay off.
Here is my full code: I'm new to C so all comments and suggestions are much appreciated.
#include "mcc_generated_files/mcc.h"
#define FCY 8000000UL
#include <libpic30.h>
//#define baudrate 19200
int main(void)
{
// Initialise the device
SYSTEM_Initialize();
while(1)
{
LED4_SetLow(); // Turn on 3v3 LED
LED12v_SetHigh();
LED3_SetHigh();
LED1_SetHigh();
int button;
button = UART5_Read();
if (button == 0x08)
{
RLY1_SetHigh();
RLY3_SetHigh();
if (button == 0x00)
goto finished;
}
finished:
RLY1_SetLow();
RLY3_SetLow();
}
return (0);
}
I have now edited the code as follows. The relays are able to be set high but the condition 0x00 is never reached. Can someone please explain?
#include "mcc_generated_files/mcc.h"
#define FCY 8000000UL
#include <libpic30.h>
//#define baudrate 19200
int main(void)
{
// Initialise the device
SYSTEM_Initialize();
while(1)
{
LED4_SetLow(); // Turn on 3v3 LED
LED12v_SetHigh();
LED3_SetHigh();
LED1_SetHigh();
int button;
int release;
button = UART5_Read();
release = UART5_Read();
if (button == 0x08)
{
RLY1_SetHigh();
RLY3_SetHigh();
}
if (release == 0x00)
{
RLY1_SetLow();
RLY3_SetLow();
}
__delay_ms(1000);
}
return (0);
}
I haven't used this MCU nor its libs, but I believe correct code should look something along the lines of this:
#include "mcc_generated_files/mcc.h"
#include <libpic30.h>
#include <stdint.h>
#define BUTTON_CODE 0x8u // use named constants instead of magic numbers
void main (void)
{
// Initialise the device
SYSTEM_Initialize();
for(;;)
{
uint8_t data;
LED4_SetLow(); // Turn on 3v3 LED
LED12v_SetHigh();
LED3_SetHigh();
LED1_SetHigh();
if(UART5_Data_Ready())
{
data = UART5_Read();
if(data == BUTTON_CODE)
{
RLY1_SetHigh();
RLY3_SetHigh();
}
else
{
RLY1_SetLow();
RLY3_SetLow();
}
}
}
}

Resources