STM32 HAL_TIM_PWM_PulseFinishedCallback not being called. Suspect that problem is related to use of struct or union pointers

I’m writing a Neopixel driver for STM32 based on the example provided here.

In summary, the pixels aren’t lighting correctly. My latest attempt had the first row of 8 pixels light up green before it stalled. This doesn’t happen every time, but regardless, this assortment of LEDs light up eventually, always in the same colors: Neopixel Shield incorrect.

These are the related functions in the driver I’m working on:

#define NUM_PIXELS 40
#define RGBW_DMA_BUFF_SIZE (NUM_PIXELS * 32) + 1

typedef union
{
  struct
  {
    uint8_t w;
    uint8_t b;
    uint8_t r;
    uint8_t g;
  } color;
  uint32_t data;
} PixelRGBW_t;

/*
 * Note, must use a 32bit timer channel to work.
 */
typedef struct
{
    TIM_HandleTypeDef timer;
    uint32_t timer_channel;
    uint32_t pixel_length;
    uint32_t buf_length;
}PixelDRV_t;

uint8_t pixelRGBW_init(PixelDRV_t *strip, PixelRGBW_t *color, TIM_HandleTypeDef setTIMER, uint32_t setCHANNEL, uint32_t setLENGTH, uint32_t *Pbuff)
{

    strip->timer = setTIMER;
    strip->timer_channel = setCHANNEL;
    strip->pixel_length = setLENGTH;
    strip->buf_length = (setLENGTH * 32) + 1;
    for(int x = 0; x < setLENGTH; x++)
    {
        for (int b = 31; b >= 0; b--)
        {
            if ((color->data >> b) & 0x01)
            {
                *Pbuff = NEOPIXEL_RGBW_ONE;
            }
            else
            {
                *Pbuff = NEOPIXEL_RGBW_ZERO;
            }

            Pbuff++;
        }
        color++;
    }
    return HAL_OK;
}

uint8_t setPixelColorMonoRGBW(PixelDRV_t *strip, PixelRGBW_t *color, uint32_t pixel, uint8_t red, uint8_t green, uint8_t blue, uint8_t white)
{
    color[pixel].color.r = red;
    color[pixel].color.g = green;
    color[pixel].color.b = blue;
    color[pixel].color.w = white;
    return HAL_OK;
}
uint8_t setPixelLengthColorMonoRGBW(PixelDRV_t *strip, PixelRGBW_t *color, uint8_t red, uint8_t green, uint8_t blue, uint8_t white)
{
    for(int a = 0; a < strip->pixel_length; a++)
    {
        color[a].color.r = red;
        color[a].color.g = green;
        color[a].color.b = blue;
        color[a].color.w = white;
    }
    return HAL_OK;
}
/*
Sets the relevant "1" and "0" bits into the buffer to be written to the Neopixels via PWM. Must set whole strip's values, even if you are only updating one LED in one pixel, since all pixels need to know their RGB values, even if they are zero.
*/
uint8_t setPixelBufRGBW(PixelDRV_t *strip, PixelRGBW_t *color, uint32_t *Pbuff)
{
    for(int x = 0; x < strip->pixel_length; x++)
    {
        for (int b = 31; b >= 0; b--)
        {
            if ((color[x].data >> b) & 0x01)
            {
                *Pbuff = NEOPIXEL_RGBW_ONE;
            }
            else
            {
                *Pbuff = NEOPIXEL_RGBW_ZERO;
            }
            Pbuff++;
        }
    }
    return HAL_OK;
}

uint8_t transmitPixelBufRGBW(PixelDRV_t *strip, PixelRGBW_t *color, uint32_t *Pbuff)
{
    HAL_TIM_PWM_Start_DMA(&strip->timer, strip->timer_channel, Pbuff, strip->buf_length);
    return HAL_OK;
}

And this is the related code in the main file I’m using to test/troubleshoot it.

PixelRGBW_t STRIP1;
PixelRGBW_t* strip1 = &STRIP1;

PixelDRV_t PIXEL_DRV1;
PixelDRV_t* pixel_drv1 = &PIXEL_DRV1;

uint32_t dmaBuffer[RGBW_DMA_BUFF_SIZE] = {0};
uint32_t *pBuff = &dmaBuffer;

void Init_NeoPixels();
void ascendingRed();
void descendingRed();
void ascendingGreen();
void descendingGreen();
void ascendingBlue();
void descendingBlue();

void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
  HAL_TIM_PWM_Stop_DMA(&htim2, TIM_CHANNEL_3);
}

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();

  /* 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_USART2_UART_Init();
  MX_I2C1_Init();
  MX_I2S3_Init();
  MX_DMA_Init();
  MX_TIM2_Init(); //timer being used for neopixels.
  MX_SPI2_Init();
  /* USER CODE BEGIN 2 */
  Init_NeoPixels();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      ascendingRed();
      HAL_Delay(1000);
      descendingRed();
      HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

void Init_NeoPixels()
{
    pixelRGBW_init(pixel_drv1, strip1, htim2, TIM_CHANNEL_3, 40, pBuff);
}

void ascendingRed()
{
    for(int x = 0; x < pixel_drv1->pixel_length; x++)
    {
        setPixelColorMonoRGBW(pixel_drv1, strip1, x, 255, 0, 0, 0);
        setPixelBufRGBW(pixel_drv1, strip1, pBuff);
        transmitPixelBufRGBW(pixel_drv1, strip1, pBuff);
        HAL_Delay(125);
    }
}

void descendingRed()
{
    for(int x = pixel_drv1->pixel_length; x >= 0; x--)
    {
        setPixelColorMonoRGBW(pixel_drv1, strip1, x, 0, 0, 0, 0);
        setPixelBufRGBW(pixel_drv1, strip1, pBuff);
        transmitPixelBufRGBW(pixel_drv1, strip1, pBuff);
        HAL_Delay(125);
    }
}

The goal is to light up the LEDs in one solid color, one after the other, then turn them off in the opposite direction. Instead, I’m getting whatever nonsense is happening in the image I showed above.

My initial assumption was that I wasn’t using the union pointer within the functions properly (and that’s still in the back of my mind), but as I did more troubleshooting, I noticed that HAL_TIM_PWM_PulseFinishedCallback was only being called once, the very first time in ascendingRed’s for loop, and never again. Normally that means the Pulse value (CC1) hasn’t been reached.

I compared the contents of htim3 during what appears to be the first successful cycle with its contents on all the subsequent ones and saw this in the debugger:

These two images are before and during the successful call for HAL_TIM_PWM_PulseFinishedCallback respectivelyBefore entering HAL_TIM_PWM_PulseFinishedCallback for the first time

HAL_TIM_PWM_PulseFinishedCallback being called

And afterwards:

Every loop onward
Loop 3

I’m pretty sure the problem is in pointer structs I’m using to keep all the information grouped together. Does anyone see anything I’ve missed?

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật