> it's quite frustrating that the interface gets SO CLOSE, but doesn't go the whole way.
Yes, there are reasons why I'm not using it.
> I hope STM intends on extending the functionality rather than leaving it as an intro program to get people into the ecosystem.
I think they should rather fix the supposedly existing functionality first. It's a lot more frustrating when even the basic clock setup is messed up so bad that the MCU locks up solid.
> If someone could please take a look and let me know what I'm doing wrong that would be great.
Sorry, I can't decipher HAL code. If you post the relevant peripheral registers (RCC, DMA, DMAMUX, TIM8, GPIOA), I might be able to notice if something is missing.
> I've stepped through with the debugger and everything gets set up as you'd expect. The DMA addresses and modes are correct, everything gets initialized etc. yet nothing seems to happen.
Is the timer running, i.e. CNT value changing? Are there any flags set in the timer or DMA status registers? Can you read back the register values you've set?
> Nothing in the datasheet indicates that this shouldn't work.
Neither the datasheet nor the reference manual documents what HAL functions do, and how are they supposed to be used. The HAL documentation describes a few common use cases, the rest should be treated as undocumented, i.e. even if a functionality seems to work now, it might stop working anytime.
Anyway, here is what I think should work, but I don't have a G4 to test it. I've omitted GPIO pin setup, set them to outputs in GPIOA->MODER.
1. Make sure that all peripherals used (GPIO, TIM, DMA and DMAMUX) are enabled in RCC.
RCC->AHB1ENR |= RCC_AHB1ENR_DMAMUX1EN | RCC_AHB1ENR_DMA1EN;
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;
RCC->APB2ENR |= RCC_APB2ENR_TIM8EN;
2. Set up a DMA channel to copy from the array of memory to BSRR.
DMA1_Channel2->CMAR = gpio_data;
DMA1_Channel2->CPAR = &GPIOA->BSRR;
DMA1_Channel2->CNDTR = GPIO_DATA_LENGTH;
DMA1_Channel2->CCR =
DMA_CCR_MSIZE_1 | // memory data size 32 bits
DMA_CCR_PSIZE_1 | // peripheral data size 32 bits
DMA_CCR_CIRC | // circular mode
DMA_CCR_MINC | // increment memory pointer
DMA_CCR_DIR | // direction memory to peripheral
DMA_CCR_EN | // enable channel
0);
3. Connect the timer update DMA request to the DMA channel.
DMAMUX1_Channel2->CCR = (DMA_REQUEST_TIM8_UP << DMAMUX_CxCR_DMAREQ_ID_Pos);
4. Set the timer prescaler, period, enable DMA and start.
TIM8->PSC = 1000 - 1;
TIM8->EGR = TIM_EGR_UG; // required to load the prescaler
TIM8->ARR = 17000 - 1;
TIM8->BDTR = TIM_BDTR_MOE; // required on advanced timers
TIM8->SR = 0; // clear status after TIM_EGR_UG
TIM8->DIER = TIM_DIER_UDE; // enable DMA on timer update (overflow)
TIM8->CR1 = TIM_CR1_CEN; /// start the timer
After each step, check that the register values are actually written, that they don't contain anything but the reset values in the datasheet modified with what you've written. Step through the code and check status registers at each step.