cancel
Showing results for 
Search instead for 
Did you mean: 

lwip freeRTOS with DAM DDS dubble buffer pulse generator

sumanga
Associate II

 

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!

3 REPLIES 3
mƎALLEm
ST Employee

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.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

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 

sumanga
Associate II

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