2025-06-30 4:45 AM
Hello everyone,
I am implementing a DDS-based pulse generator using DMA double buffer technique on my STM32H7. When I run this pulse generator as a standalone project, it works perfectly — the output pulse frequency is accurate and stable.
However, when I integrate LwIP into the same project, I notice that the generated pulse frequency occasionally changes unexpectedly and produces wrong output values. It looks like there is interference or resource conflict when both the DDS pulse generator and LwIP run together.
Has anyone faced similar issues? Is there a recommended way to isolate or manage DMA, timers, and LwIP to avoid such conflicts on STM32H7?
Any suggestions would be greatly appreciated.
Thank you!
2025-06-30 5:10 AM - edited 2025-06-30 6:13 AM
Hello,
I think it's an interrupt priority issue or Task priority issue. That depends on your implementation.
Try to increase the interrupts resources linked to your DDS (TIM, DMA?)
If your DDS implementation is task dependent, increase its task priority.
2025-06-30 12:37 PM - last edited on 2025-07-01 12:44 AM by mƎALLEm
Dear mEALLEm
I already set highest priority for DDS
but no change result.
I used github provided lwip freeRTOS example and aditional TIM1 confige as 1Mhz trigering frequency use DMA circular memory to peripheral TIM1-UP update-event priority very high then main.C declear bufferA & bufferB size is 1000 like this
#define DDS_BUFFER_SIZE 1000
#define DDS_TABLE_SIZE 1024
#define PWM_RESOLUTION 1000 // Timer counts from 0 to 999
uint16_t dmaBuffer[2][DDS_BUFFER_SIZE]; // Double buffer
uint16_t *currentBuffer;
float ddsTable[DDS_TABLE_SIZE];
float phaseAccumulator = 0.0f;
float phaseStep; // Controls frequency
void FillDDSBuffer(uint16_t *buffer)
{
for (int i = 0; i < DDS_BUFFER_SIZE; i++) {
uint32_t index = (uint32_t)phaseAccumulator % DDS_TABLE_SIZE;
buffer[i] = (uint16_t)ddsTable[index];
phaseAccumulator += phaseStep;
if (phaseAccumulator >= DDS_TABLE_SIZE)
phaseAccumulator -= DDS_TABLE_SIZE;
}
}
void HAL_TIM_PWM_PulseFinishedHalfCpltCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM1) {
FillDDSBuffer(dmaBuffer[0]);
}
}
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == TIM1) {
FillDDSBuffer(dmaBuffer[1]);
}
}
inside main function add
FillDDSBuffer(dmaBuffer[0]);
FillDDSBuffer(dmaBuffer[1]);
HAL_DMAEx_MultiBufferStart_IT(
htim1.hdma[TIM_DMA_ID_CC2], // DMA handle linked to TIM1_CH2
(uint32_t)dmaBuffer[0], // Buffer A start
(uint32_t)&TIM1->CCR2, // Peripheral address (CCR2)
(uint32_t)dmaBuffer[1], // Buffer B start
DDS_BUFFER_SIZE // Size of each buffer
);
to start task but not clearly work if we remove lwip from project without any changing ,we can run DDS fully accurate
please help to solve this problem or give me sample project combined lwip with DDS pulse generator
2025-06-30 12:47 PM - last edited on 2025-07-01 12:44 AM by mƎALLEm
this is corectly working code
define BUFFER_SIZE 1000
#define DDS_ACCUMULATOR_BITS 32
#define DDS_CLOCK 1000000UL // TIM1 update rate = 1 MHz
uint32_t pulseBufferA[BUFFER_SIZE];
uint32_t pulseBufferB[BUFFER_SIZE];
TIM_HandleTypeDef htim1;
DMA_HandleTypeDef hdma_tim1_up;
volatile uint32_t dds_accumulator = 0;
uint32_t dds_tuning_word = 0;
// Forward declarations
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_DMA_Init(void);
void MX_TIM1_Init(void);
void FillDDSBuffer(uint32_t *buffer)
{
for (int i = 0; i < BUFFER_SIZE; i++)
{
dds_accumulator += dds_tuning_word;
if (dds_accumulator & 0x80000000)
buffer[i] = GPIO_PIN_0; // PB0 high
else
buffer[i] = 0; // PB0 low
}
}
void SetDDSFrequency(float freq)
{
dds_tuning_word = (uint32_t)((freq * ((uint64_t)1 << DDS_ACCUMULATOR_BITS)) / DDS_CLOCK);
}
void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma)
{
if (hdma->Instance == DMA1_Stream0)
{
FillDDSBuffer(pulseBufferA);
}
}
void HAL_DMA_XferM1CpltCallback(DMA_HandleTypeDef *hdma)
{
if (hdma->Instance == DMA1_Stream0)
{
FillDDSBuffer(pulseBufferB);
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_TIM1_Init();
SetDDSFrequency(5000.0f); // 5 kHz output
FillDDSBuffer(pulseBufferA);
FillDDSBuffer(pulseBufferB);
HAL_TIM_Base_Start(&htim1);
HAL_DMAEx_MultiBufferStart_IT(&hdma_tim1_up,
(uint32_t)pulseBufferA,
(uint32_t)&(GPIOB->ODR),
(uint32_t)pulseBufferB,
BUFFER_SIZE);
__HAL_TIM_ENABLE_DMA(&htim1, TIM_DMA_UPDATE);
while (1)
{
// Optionally update frequency with SetDDSFrequency(new_freq);
}
}
// Minimal peripheral init code follows