2024-06-19 06:33 AM - edited 2024-06-19 07:14 AM
Hello!
I'm a university student with some experience with STM.
I'm working on an STM32WB55 DevBoard and an STM32WB5MMG-based custom board, they both are programmed with same code when i compile and works perfectly.
Regardless, the specific board names are irrelevant (And not worth discussing), just know that i'm working in general with STM32WB BLE products to make the following:
-The ADC Samples a value read from a single pin at a frequency of 10kHz, driven via TRGO by TIM2 Timer.
-The Sampling occurs with DMA (ADC started with HAL_ADC_Start_DMA), and after it fills an array, the sampling operation stops and restarts on a second array.
-In the while the sampling has started on the second array, the first array of samples is transferred via SPI to a Micro SD Card.
-Once the second array is filled, sampling is restarted on the first array, and the second is transferred via SPI to a Micro SD Card.
-This double buffering ping-pongs from the moment ADC reading with DMA and TIM are started and lasts for some seconds ( Timed imprecisely by "HAL_Delay(10000)" ), after which the TIM and Adc Reading with DMA are stopped and the file is closed.
All of this worked perfectly, with decent precision, as i was able to generate a Sinewave with a specific frequency (1kHz, 2kHz, 5kHz..) with an external signal generator apparatus, wire it to the ADC pin, and after the data was collected and put the SD Card in the PC, I could see the peaks that i wanted in the FFT/Signal Spectrum at the right frequency.
As it worked, it makes no sense discussing the methodology of this before someone decides to go full stackoverflow and give tips to irrelevant matters.
The problem came however when I decided to have this operation triggered by bluetooth using the BLE Stack of STM32WB, so that i could start several tests at my command via BLE without the need of plugging/unplugging the power to the board to force the restart.
These operations occur without any issue until i make the STM32 Sequencer work, by looping in the while MX_APPE_Process();.
It already happened to me when using the STM32WL family (LoRa) that i had to discard the sequencer as any operation i tried to register as a task that required the use of DMA or simply reading from external peripherals (like USART) would simply not work and generate errors in transfer, no matter the priority settings i changed in the NVIC settings on the IOC file.
I tried nevertheless to implement this on the P2P Server example, and have the ADC reading with DMA and the TIM start when i send a certain digit over a BLE service.
No matter what i tried, although the commands of HAL_ADC_Start_DMA and HAL_TIM_Base_Start are executed in a task of the sequencer (and later stopped by another task), the callback HAL_ADC_ConvCpltCallback gets never called,
and for what i could see from debugging the program setting breakpoints, registers report a transfer error in DMA.
I've tried the following:
-Set everything else on max priority 1, DMA, TIM, and SPI on priority 0 on NVIC settings.
-Through an if statement, the sequencer (MX_APPE_Process) is not called in the while loop in main when the the reading of ADC is occurring on that moment, the if becomes true again (calling the sequencer) when the seconds of desired reading time have been reached and the ADC reading has been stopped.
-DMA priority changed to very high, even made this change in the registers during debug.
-Disabling the BLE Stack (all of them) tasks while doing the reading.
-Data width changes on DMA (I believe them unnecessary as it worked without changing them before).
-Disabled all the Critical Sections in the UTIL_SEQ_Run, in case they interfered with the interrupts of DMA.
And many more things i've likely forgot, but the result was always the same: the DMA error (DMA BUSY, i think?), reading doesn't occur.
Please, i need help. Ask for anything and i shall send it.
Summary / TL;DR :
I was sampling ADC with DMA, controlled by TIM (TRGO) at 10kHz without issues before running the sequencer utility.
After the UTIL_SEQ Sequencer ("MX_APPE_Process()" command) has run at least once I'm unable to read anything with from ADC with DMA anymore, and that even if i refuse to execute the sequencer commands while performing the readings.
2024-06-20 05:22 AM
Anyone?
Here's the code if you wonder, from the BLE p2p Server Application.
Some Functions/comments were removed (UART initializations etc...) because it wouldn't fit the char limit.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file p2p_server_app.c
* @author MCD Application Team
* @brief Peer to peer Server Application
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "app_common.h"
#include "dbg_trace.h"
#include "ble.h"
#include "p2p_server_app.h"
#include "stm32_seq.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "app_fatfs.h"
#include "utilities_conf.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef struct{
uint8_t Device_Led_Selection;
uint8_t Led1;
}P2P_LedCharValue_t;
typedef struct{
uint8_t Device_Button_Selection;
uint8_t ButtonStatus;
}P2P_ButtonCharValue_t;
typedef struct
{
uint8_t Notification_Status; /* used to check if P2P Server is enabled to Notify */
P2P_LedCharValue_t LedControl;
P2P_ButtonCharValue_t ButtonControl;
uint16_t ConnectionHandle;
} P2P_Server_App_Context_t;
/* USER CODE END PTD */
/* Private defines ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macros -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/**
* START of Section BLE_APP_CONTEXT
*/
static P2P_Server_App_Context_t P2P_Server_App_Context;
static uint8_t TimerMeasurement_Id;
//ADC POLLING
uint16_t adc_val;
uint8_t ADCTest[2];
//ADC DMA/TIM2
extern __IO uint16_t* aADCxConvertedData;
extern ADC_HandleTypeDef hadc1;
extern TIM_HandleTypeDef htim2;
extern FIL fil;
extern int sequencermayrun;
uint32_t primask_bit;
/**
* END of Section BLE_APP_CONTEXT
*/
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
static void P2PS_Send_Notification(void);
static void P2PS_APP_LED_BUTTON_context_Init(void);
//ADDITIONS
static void ADCStart( void );
static void ADCSend( void );
static void ADCSendIssue( void );
/* USER CODE END PFP */
/* Functions Definition ------------------------------------------------------*/
void P2PS_STM_App_Notification(P2PS_STM_App_Notification_evt_t *pNotification)
{
/* USER CODE BEGIN P2PS_STM_App_Notification_1 */
/* USER CODE END P2PS_STM_App_Notification_1 */
switch(pNotification->P2P_Evt_Opcode)
{
/* USER CODE BEGIN P2PS_STM_App_Notification_P2P_Evt_Opcode */
#if(BLE_CFG_OTA_REBOOT_CHAR != 0)
case P2PS_STM_BOOT_REQUEST_EVT:
APP_DBG_MSG("-- P2P APPLICATION SERVER : BOOT REQUESTED\n");
APP_DBG_MSG(" \n\r");
*(uint32_t*)SRAM1_BASE = *(uint32_t*)pNotification->DataTransfered.pPayload;
NVIC_SystemReset();
break;
#endif
/* USER CODE END P2PS_STM_App_Notification_P2P_Evt_Opcode */
case P2PS_STM__NOTIFY_ENABLED_EVT:
/* USER CODE BEGIN P2PS_STM__NOTIFY_ENABLED_EVT */
P2P_Server_App_Context.Notification_Status = 1;
APP_DBG_MSG("-- P2P APPLICATION SERVER : NOTIFICATION ENABLED on ADC\n");
APP_DBG_MSG(" \n\r");
/* USER CODE END P2PS_STM__NOTIFY_ENABLED_EVT */
break;
case P2PS_STM_NOTIFY_DISABLED_EVT:
/* USER CODE BEGIN P2PS_STM_NOTIFY_DISABLED_EVT */
P2P_Server_App_Context.Notification_Status = 0;
APP_DBG_MSG("-- P2P APPLICATION SERVER : NOTIFICATION DISABLED on ADC\n");
APP_DBG_MSG(" \n\r");
//ADDITIONS
//HW_TS_Stop(TimerMeasurement_Id);
/* USER CODE END P2PS_STM_NOTIFY_DISABLED_EVT */
break;
case P2PS_STM_WRITE_EVT:
/* USER CODE BEGIN P2PS_STM_WRITE_EVT */
if(pNotification->DataTransfered.pPayload[0] == 0x00){ /* ALL Deviceselected - may be necessary as LB Routeur informs all connection */
if(pNotification->DataTransfered.pPayload[1] == 0x01)
{
APP_DBG_MSG("-- P2P APPLICATION SERVER : LED1 ON/TIMER FIRED\n");
APP_DBG_MSG(" \n\r");
P2P_Server_App_Context.LedControl.Led1=0x01; /* LED1 ON */
UTIL_SEQ_SetTask( 1<<CFG_TASK_ADC_START_ID, CFG_SCH_PRIO_0);
}
if(pNotification->DataTransfered.pPayload[1] == 0x00)
{
APP_DBG_MSG("-- P2P APPLICATION SERVER : LED1 OFF/TIMER HALTED\n");
APP_DBG_MSG(" \n\r");
P2P_Server_App_Context.LedControl.Led1=0x00; /* LED1 OFF */
}
}
#if(P2P_SERVER1 == 0)
if(pNotification->DataTransfered.pPayload[0] == 0x01){ /* end device 1 selected - may be necessary as LB Routeur informs all connection */
if(pNotification->DataTransfered.pPayload[1] == 0x01)
{
//BSP_LED_On(LED_BLUE);
APP_DBG_MSG("-- P2P APPLICATION SERVER 1 : LED1 ON\n");
APP_DBG_MSG(" \n\r");
P2P_Server_App_Context.LedControl.Led1=0x01; /* LED1 ON */
}
if(pNotification->DataTransfered.pPayload[1] == 0x00)
{
BSP_LED_Off(LED_BLUE);
APP_DBG_MSG("-- P2P APPLICATION SERVER 1 : LED1 OFF\n");
APP_DBG_MSG(" \n\r");
P2P_Server_App_Context.LedControl.Led1=0x00; /* LED1 OFF */
}
}
#endif
/* USER CODE END P2PS_STM_WRITE_EVT */
break;
default:
break;
}
return;
}
void P2PS_APP_Notification(P2PS_APP_ConnHandle_Not_evt_t *pNotification)
{
switch(pNotification->P2P_Evt_Opcode)
{
case PEER_CONN_HANDLE_EVT :
APP_DBG_MSG("CALLING CONNECTION UPDATE to 7.5/15 ms Intervals");
UTIL_SEQ_SetTask( 1<<CFG_TASK_CONN_UPDATE_REG_ID, CFG_SCH_PRIO_0);
break;
case PEER_DISCON_HANDLE_EVT :
break;
default:
break;
}
return;
}
void P2PS_APP_Init(void)
{
/* USER CODE BEGIN P2PS_APP_Init */
UTIL_SEQ_RegTask( 1<< CFG_TASK_SW1_BUTTON_PUSHED_ID, UTIL_SEQ_RFU, P2PS_Send_Notification );
P2P_Server_App_Context.Notification_Status=0;
P2PS_APP_LED_BUTTON_context_Init();
//ADDITIONS
UTIL_SEQ_RegTask( 1<< CFG_TASK_ADC_START_ID, UTIL_SEQ_RFU, ADCStart );
UTIL_SEQ_RegTask( 1<< CFG_TASK_ADC_SEND_ID, UTIL_SEQ_RFU, ADCSend );
HW_TS_Create(CFG_TIM_PROC_ID_ISR, &(TimerMeasurement_Id), hw_ts_SingleShot, ADCSendIssue);
APP_DBG_MSG(" Timers Created and Initialized.\r\n");
/* USER CODE END P2PS_APP_Init */
return;
}
/* USER CODE BEGIN FD */
void P2PS_APP_LED_BUTTON_context_Init(void){
//BSP_LED_Off(LED_BLUE);
APP_DBG_MSG("LED BLUE OFF\n");
#if(P2P_SERVER1 != 0)
P2P_Server_App_Context.LedControl.Device_Led_Selection=0x01; /* Device1 */
P2P_Server_App_Context.LedControl.Led1=0x00; /* led OFF */
P2P_Server_App_Context.ButtonControl.Device_Button_Selection=0x01;/* Device1 */
P2P_Server_App_Context.ButtonControl.ButtonStatus=0x00;
#endif
}
void P2PS_APP_SW1_Button_Action(void)
{
return;
}
/* USER CODE END FD */
/*************************************************************
*
* LOCAL FUNCTIONS
*
*************************************************************/
/* USER CODE BEGIN FD_LOCAL_FUNCTIONS*/
static void ADCSendIssue(void){
sequencermayrun=1;
UTIL_SEQ_SetTask( 1<<CFG_TASK_ADC_SEND_ID, CFG_SCH_PRIO_0);
return;
}
static void ADCStart(void){
P2PS_STM_App_Update_Char(P2P_NOTIFY_CHAR_UUID, (uint8_t *)"ii");
sequencermayrun=0;
UTIL_SEQ_PauseTask(1<<CFG_TASK_CONN_UPDATE_REG_ID);
UTIL_SEQ_PauseTask(1<<CFG_TASK_ADV_CANCEL_ID);
UTIL_SEQ_PauseTask(1<<CFG_TASK_HCI_ASYNCH_EVT_ID);
UTIL_SEQ_PauseTask(1<<CFG_LAST_TASK_ID_WITH_HCICMD);
if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)aADCxConvertedData, ADC_CONVERTED_DATA_BUFFER_SIZE) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_Base_Start(&htim2) != HAL_OK)
{
Error_Handler();
}
//ADDITIONS
HW_TS_Stop(TimerMeasurement_Id);
HW_TS_Start(TimerMeasurement_Id, (10000000/CFG_TS_TICK_VAL));
}
static void ADCSend( void )
{
/*
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 10);
adc_val=(uint16_t) HAL_ADC_GetValue(&hadc1);
ADCTest[0] = (uint8_t) (adc_val>>8) & 0xFF;
ADCTest[1] = (uint8_t) adc_val & 0xFF;
*/
HW_TS_Stop(TimerMeasurement_Id);
HAL_ADC_Stop_DMA(&hadc1);
if (HAL_TIM_Base_Stop(&htim2) != HAL_OK)
{
Error_Handler();
}
f_close(&fil);
P2PS_STM_App_Update_Char(P2P_NOTIFY_CHAR_UUID, (uint8_t *)"aa");
UTIL_SEQ_ResumeTask(1<<CFG_TASK_CONN_UPDATE_REG_ID);
UTIL_SEQ_ResumeTask(1<<CFG_TASK_ADV_CANCEL_ID);
UTIL_SEQ_ResumeTask(1<<CFG_TASK_HCI_ASYNCH_EVT_ID);
UTIL_SEQ_ResumeTask(1<<CFG_LAST_TASK_ID_WITH_HCICMD);
APP_DBG_MSG("ADC TO SD CARD OPERATION COMPLETED");
}
void P2PS_Send_Notification(void)
{
if(P2P_Server_App_Context.ButtonControl.ButtonStatus == 0x00){
P2P_Server_App_Context.ButtonControl.ButtonStatus=0x01;
} else {
P2P_Server_App_Context.ButtonControl.ButtonStatus=0x00;
}
if(P2P_Server_App_Context.Notification_Status){
APP_DBG_MSG("-- P2P APPLICATION SERVER : INFORM CLIENT BUTTON 1 PUSHED \n ");
APP_DBG_MSG(" \n\r");
P2PS_STM_App_Update_Char(P2P_NOTIFY_CHAR_UUID, (uint8_t *)&P2P_Server_App_Context.ButtonControl);
} else {
APP_DBG_MSG("-- P2P APPLICATION SERVER : CAN'T INFORM CLIENT - NOTIFICATION DISABLED\n ");
}
return;
}
/* USER CODE END FD_LOCAL_FUNCTIONS*/
. AdcStart() starts the TIM and the ADC via DMA, AdcSend() stops it and closes the file. these are commands that worked if i had them executed before the BLE stack had run.
2024-06-20 05:23 AM
sequencermayrun becomes 0 when ADCStart is called for the first time and it's suppose to remain 0 all through the process to make sure the sequencer does not disturb TIM/ADC operations. This was one of the fixes that i attempted to adopt, but didn't change the result.
Whenver i call MX_APPE_Process at least once it's not possible anymore for me to do any such operations.
Previously, the TIM, and ADC via DMA were started and stopped (after some seconds of wait with HAL_Delay) before the while(1) loop in main, and they worked.
I put a breakpoint in HAL_ADC_ErrorCallback, and one in HAL_ADC_ConvCpltCallback, only the one in the ErrorCallback function is hit when debugging, and when in such moment i check the hadc struct i get HAL_DMA_BUSY, and CCR4 registers reporting errors.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file main.c
* @author MCD Application Team
* @brief BLE application with BLE core
*
******************************************************************************
* @attention
*
* Copyright (c) 2019-2021 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.
*
******************************************************************************
@verbatim
==============================================================================
##### IMPORTANT NOTE #####
==============================================================================
This application requests having the stm32wb5x_BLE_Stack_fw.bin binary
flashed on the Wireless Coprocessor.
If it is not the case, you need to use STM32CubeProgrammer to load the appropriate
binary.
All available binaries are located under following directory:
/Projects/STM32_Copro_Wireless_Binaries
Refer to UM2237 to learn how to use/install STM32CubeProgrammer.
Refer to /Projects/STM32_Copro_Wireless_Binaries/ReleaseNote.html for the
detailed procedure to change the Wireless Coprocessor binary.
@endverbatim
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "app_fatfs.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "app_conf.h"
/* USER CODE END Includes */
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
IPCC_HandleTypeDef hipcc;
UART_HandleTypeDef hlpuart1;
UART_HandleTypeDef huart1;
DMA_HandleTypeDef hdma_lpuart1_tx;
DMA_HandleTypeDef hdma_usart1_tx;
RNG_HandleTypeDef hrng;
RTC_HandleTypeDef hrtc;
SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_tx;
DMA_HandleTypeDef hdma_spi1_rx;
TIM_HandleTypeDef htim2;
/* USER CODE BEGIN PV */
FATFS FatFs; // FatFS work area
FRESULT res;
FIL fil; // File object
//FIL fil;
UINT br, bw; // File read/write count
extern int sequencermayrun;
int sequencermayrun = 1;
char FileBuffer[1000]={0};
//ADC Test
uint16_t adc_valtest;
// ADC / DMA Test
__IO uint16_t aADCxConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE]; /* ADC group regular conversion data (array of data) */
__IO uint16_t aADCxConvertedData2[ADC_CONVERTED_DATA_BUFFER_SIZE]; /* ADC group regular conversion data (array of data) */
__IO uint8_t ubDmaTransferStatus = 0; /* Variable set into DMA interruption callback */
/* USER CODE END PV */
void AppendFileMounted(const TCHAR *filename, const char *data, uint32_t length) {
// Open or create the file
//res = f_open(&fil, filename, FA_OPEN_ALWAYS | FA_WRITE);
UINT bytes_written;
// Write data to the file
res = f_write(&fil, data, length, &bytes_written);
if (res != FR_OK) {
// Handle error writing to file
printf("Error writing to file: %d\r\n", res);
}else{
f_sync(&fil);
}
// Close the file
}
/* 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();
/* Config code for STM32_WPAN (HSE Tuning must be done before system clock configuration) */
MX_APPE_Config();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* Configure the peripherals common clocks */
PeriphCommonClock_Config();
/* IPCC initialisation */
MX_IPCC_Init();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_RTC_Init();
MX_RNG_Init();
MX_SPI1_Init();
if (MX_FATFS_Init() != APP_OK) {
Error_Handler();
}
MX_ADC1_Init();
MX_TIM2_Init();
MX_RF_Init();
/* USER CODE BEGIN 2 */
// OPERATIONS BEGIN
if (f_mount(&FatFs, "/", 1) == FR_OK) {
printf("[WARN/ SD-ADC] Mount Ok!\r\n");
}else{
printf("[WARN/ SD-ADC] Mount ***ed up!\r\n");
}
HAL_Delay(1000);
res = f_open(&fil, "ExperimentTest2", FA_OPEN_ALWAYS | FA_WRITE);
if (res != FR_OK) {
// Handle error opening file
printf("Error opening file: %d\r\n", res);
return;
}
HAL_Delay(1000);
/* USER CODE END 2 */
/* Init code for STM32_WPAN */
MX_APPE_Init();
/* Infinite loop */
/* USER CODE BEGIN WHILE */
if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK)
{
Error_Handler();
}
while(1)
{
if(sequencermayrun){
/* USER CODE END WHILE */
MX_APPE_Process();
/* USER CODE BEGIN 3 */
}else{
HAL_Delay(100);
}
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Macro to configure the PLL multiplication factor
*/
__HAL_RCC_PLL_PLLM_CONFIG(RCC_PLLM_DIV2);
/** Macro to configure the PLL clock source
*/
__HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_HSE);
/** Configure LSE Drive Capability
*/
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSI
|RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE
|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_10;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK4|RCC_CLOCKTYPE_HCLK2
|RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.AHBCLK2Divider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLK4Divider = RCC_SYSCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief Peripherals Common Clock Configuration
* @retval None
*/
void PeriphCommonClock_Config(void)
{
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SMPS|RCC_PERIPHCLK_RFWAKEUP;
PeriphClkInitStruct.RFWakeUpClockSelection = RCC_RFWKPCLKSOURCE_LSE;
PeriphClkInitStruct.SmpsClockSelection = RCC_SMPSCLKSOURCE_HSE;
PeriphClkInitStruct.SmpsDivSelection = RCC_SMPSCLKDIV_RANGE1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN Smps */
/* USER CODE END Smps */
}
/**
* @brief ADC1 Initialization Function
* @PAram None
* @retval None
*/
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T2_TRGO;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc1.Init.DMAContinuousRequests = ENABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_47CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
/**
* @brief IPCC Initialization Function
* @PAram None
* @retval None
*/
static void MX_IPCC_Init(void)
{
/* USER CODE BEGIN IPCC_Init 0 */
/* USER CODE END IPCC_Init 0 */
/* USER CODE BEGIN IPCC_Init 1 */
/* USER CODE END IPCC_Init 1 */
hipcc.Instance = IPCC;
if (HAL_IPCC_Init(&hipcc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN IPCC_Init 2 */
/* USER CODE END IPCC_Init 2 */
}
/**
* @brief LPUART1 Initialization Function
* @PAram None
* @retval None
*/
/**
* @brief RTC Initialization Function
* @PAram None
* @retval None
*/
static void MX_RTC_Init(void)
{
/* USER CODE BEGIN RTC_Init 0 */
/* USER CODE END RTC_Init 0 */
/* USER CODE BEGIN RTC_Init 1 */
/* USER CODE END RTC_Init 1 */
/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = CFG_RTC_ASYNCH_PRESCALER;
hrtc.Init.SynchPrediv = CFG_RTC_SYNCH_PRESCALER;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
/** Enable the WakeUp
*/
if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0, RTC_WAKEUPCLOCK_RTCCLK_DIV8) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN RTC_Init 2 */
/* USER CODE END RTC_Init 2 */
}
/**
* @brief SPI1 Initialization Function
* @PAram None
* @retval None
*/
static void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
/**
* @brief TIM2 Initialization Function
* @PAram None
* @retval None
*/
static void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 16;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 9999;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMAMUX1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
/* DMA1_Channel2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
/* DMA1_Channel3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
/* DMA1_Channel4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 15, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
/* DMA2_Channel4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Channel4_IRQn, 15, 0);
HAL_NVIC_EnableIRQ(DMA2_Channel4_IRQn);
}
/**
* @brief GPIO Initialization Function
* @PAram None
* @retval None
*/
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
uint32_t tmp_index = 0;
uint16_t fullBuff[ADC_CONVERTED_DATA_BUFFER_SIZE];
void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc){
printf("ERR");
while(1);
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
printf("OK");
if (HAL_TIM_Base_Stop(&htim2) != HAL_OK)
{
Error_Handler();
}
HAL_ADC_Stop_DMA(&hadc1);
if(ubDmaTransferStatus==0){
// Start the Second buffer ADC Already
if (HAL_ADC_Start_DMA(&hadc1,
(uint32_t *)aADCxConvertedData2,
ADC_CONVERTED_DATA_BUFFER_SIZE
) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_Base_Start(&htim2) != HAL_OK)
{
Error_Handler();
}
AppendFileMounted("ExperimentTest", (uint8_t*) aADCxConvertedData, ADC_CONVERTED_DATA_BUFFER_SIZE_BYTES);
ubDmaTransferStatus=1;
}else{
// Start the First buffer ADC Already
if (HAL_ADC_Start_DMA(&hadc1,
(uint32_t *)aADCxConvertedData,
ADC_CONVERTED_DATA_BUFFER_SIZE
) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_Base_Start(&htim2) != HAL_OK)
{
Error_Handler();
}
AppendFileMounted("ExperimentTest", (uint8_t*) aADCxConvertedData2, ADC_CONVERTED_DATA_BUFFER_SIZE_BYTES);
ubDmaTransferStatus=0;
}
}
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc)
{
}
/* 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 */
while(1)
{
/* Toggle LED2 */
BSP_LED_Off(LED2);
HAL_Delay(800);
BSP_LED_On(LED2);
HAL_Delay(200);
}
/* USER CODE END Error_Handler_Debug */
}
2024-06-20 10:56 PM
I have the same problem after connection to ble
if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)aADCxConvertedData, 1000) != HAL_OK)
{
Error_Handler();
go in error !
2024-06-26 09:39 AM - edited 2024-06-26 09:59 AM
I may have found a solution, unfortunately demonstrating that the sequencer, inspite of custom priority settings for Interrupts in NVIC and in the sequencer, is not just fit to start DMA-Based operations. It almost feels like a program that cannot be executed if not as "Run as Administrator", and in this case, running it in the sequencer is like giving it only Basic User privileges. What solved was a workaround that i made that, whenever i receive via BLE the command that i've programmed to be supposed to start the ADC reading, a task will start that will set a global (extern) variable to 1, like a flag.
When this flag is set to 1, an if statement will not make run the MX_APPE_Process() function that is in the while loop in main.c, and in that loop iteration will instead start or stop the dma.
Practical example of this workaround:
/* main.c functions, main()*/
while(1)
{
if(DMA_Start == 0 && DMA_Stop == 0){
/* USER CODE END WHILE */
MX_APPE_Process();
/* USER CODE BEGIN 3 */
}else if(DMA_Start==1){
HAL_ADC_Start_DMA(&hadc1, (uint32_t) aADCxConvertedData,1000);
DMA_Start==0;
}else if(DMA_Stop==1){
HAL_ADC_Stop_DMA(&hadc1);
DMA_Stop=0;
}else{
//Whatever, error handling...
}
}
So basically: Always start DMA operations outside the Sequencer.
If these operations depend upon something occurring in the sequencer, such as desiring them to be triggered by BLE messages, you can have the sequencer trigger them, but the calls that start such operations must start outside of it. It is terrible that such a workaround should be necessary, and even if extra steps were required to achieve this inside the sequencer, it is horrible that it should be this complex.
Notice: This is not a solution, but a workaround. I'd like to know if there is indeed a way to avoid this.