Use WS2812 LED I.MX93 FRDM board

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Use WS2812 LED I.MX93 FRDM board

Use WS2812 LED I.MX93 FRDM board

Hello everyone, in this post we will control one (or more) WS2812 LEDs from a Linux UserSpace application, communicating with Cortex M33 through RPMSG. 

Required materials:

  • FRDM-IMX93
  • WS2812 LED/Strip
  • Attached wsled.c (userspace application)
  • Attached ws2812_m33_project (Source code of firmware for M33)

 

Environment:

 

This is the block diagram of the application: 

 

Diagrama sin título.drawio.png

 

 

CORTEX M33 SIDE. 

From WS2812  LED datasheet, we can see the timing must be precise, that is the reason we will use the Cortex M33 (Real time applications): 

Manuel_Salas_3-1749596540788.png

 

As we can see, the timing just accept tolerance of 150ns, that is the reason is preferred to use the Cortex M33 instead of control with Linux that is in charge of other tasks. 

 

The function that we will implement to send Zero and One is: 

void WS2812B_send_bit(uint8_t bit)
{
    if (bit)
    {
        // Send "1"
        RGPIO_PinWrite(WS2812B_LED_RGPIO, WS2812B_LED_RGPIO_PIN, 1);
        for (int i = 0; i < HIGH_ONE_CYCLES; i++) __asm__("NOP");
        RGPIO_PinWrite(WS2812B_LED_RGPIO, WS2812B_LED_RGPIO_PIN, 0);
        for (int i = 0; i < LOW_ONE_CYCLES; i++) __asm__("NOP");
    }
    else
    {
        // Send "0"
        RGPIO_PinWrite(WS2812B_LED_RGPIO, WS2812B_LED_RGPIO_PIN, 1);
        for (int i = 0; i < HIGH_ZERO_CYCLES; i++) __asm__("NOP");
        RGPIO_PinWrite(WS2812B_LED_RGPIO, WS2812B_LED_RGPIO_PIN, 0);
        for (int i = 0; i < LOW_ZERO_CYCLES; i++) __asm__("NOP");
    }
}
 

 

Testing and measuring the toggle timing with the RGPIO driver of Cortex M33, we could find the best number of NOP instructions to adjust with the required timing according to datasheet, and the results with core running at 200MHz are: 

 

Parameter 

Number of NOP times 

HIGH_ONE_CYCLES 

22  (T1H: 700 ns) 

LOW_ONE_CYCLES 

12  (T1L: 600 ns) 

LOW_ZERO_CYCLES 

20  (T0L: 800 ns) 

HIGH_ZERO_CYCLES 

6    (T0H: 350 ns) 

 

 

Zero:

Manuel_Salas_4-1749596660278.png
Manuel_Salas_5-1749596678175.png

 

One:

Manuel_Salas_6-1749596709146.png
Manuel_Salas_7-1749596723057.png

 

Taking in mind this information, we can start to develop our application. From Cortex M33, we created a little protocol, that will wait for instructions to do. 

 

For example, the expected string to fill the RPMSG buffer is: 

 

Index 

Purpose 

Example 

app_buf[0] 

Command ('c' or 't') 

'c' = store color in buffer 
't' = show colors on LEDs 

app_buf[1] 

Red component (0–255) 

0xFF 

app_buf[2] 

Green component (0–255) 

0x00 

app_buf[3] 

Blue component (0–255) 

0x80 

app_buf[4] 

LED index (target LED position) 

e.g. 0, 1, 2 

 

Commands: 

 

'c'  "Color store" 

This command stores the RGB color value into a local buffer, targeting a specific LED (app_buf[4]). 

It doesn't update the LED strip immediately, it just prepares the data. 

Example of RPMSG received buffer from Cortex A (Linux): 

 app_buf = { 'c', 0xFF, 0x00, 0x00, 2 };  // Store red color for LED 2 

  

't'  "Transfer" 

This command sends the full color buffer to the WS2812 strip, updating the LED colors. 

The RGB values in the buffer are ignored, it simply triggers an update based on previously stored data. 

Example of RPMSG received buffer from Cortex A (Linux): 

app_buf = { 't', 0, 0, 0, 0 };  // Transfer the buffered colors to the LED strip 

  

You can modify the code to add your custom commands like change number of LEDs on the strip, or change the GPIO, etc. Currently, the number of WS2812 LEDs supported is defined in software by NUM_RGB_LEDS. As default is 8 LEDs. 

 

I will attach the full code for Cortex M33 firmware, it was tested with arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi and SDK 2_15, SDK 2_16 and SDK 24. 

 

In this example, the EXP_GPIO_IO24 of FRDM-IMX93 was used to control the LED Strip.

Connection.png

 

CORTEX A55 SIDE. 

For Cortex A55 (Linux side), we developed an userspace application, that will create the structure for the buffer to send to the Cortex M33 and send through RPMSG using the imx_rpmsg_tty included on the NXP BSP. You can find the userspace application attached. 

 

As we know, the imx_rpmsg_tty creates the tty channel called ttyRPMSG31 under /dev. So, this userspace application communicates directly with the device /dev/ttyRPMSG31 to send the buffer with the required structure for Cortex M33. 

 

EXAMPLE OF USAGE. 

 

STEP 1.

Compile firmware for Cortex M33 and store in FRDM-IMX93 under /lib/firmware to use with remoteproc:

 

STEP 2. 

Compile or cross-compile the userspace application (attached.) 

To compile on the platform: 

root@imx93evk:~# gcc wsled.c -o wsled
root@imx93evk:~# ls
wsled  wsled.c

Also, we can copy the wsled under /bin to practicity.

root@imx93evk:~# wsled 
Error: -c <red> <green> <blue> is required.
WS2812
Usage:
wsled -c <red> <green> <blue> [-n <led_position>]       Load the color of exact LED to the buffer
wsled -t                                                Shows the colors to the LEDs

 

STEP 3.

To run the entire example:

boot the board and load the firmware for cortex M33 with remoteproc:

root@imx93evk:~# cd /sys/class/remoteproc/remoteproc0
root@imx93evk:/sys/class/remoteproc/remoteproc0# echo ws2812_m33.elf > firmware 
root@imx93evk:/sys/class/remoteproc/remoteproc0# echo start > state

 Then, we will receive this from Cortex M33 terminal:

RPMSG String Communication Channel FreeRTOS RTOS 
M33 clock is at: 200000000 Hz

Nameservice sent, ready for incoming messages from Cortex-A55! WSLED

 

Load the imx_rpmsg_tty module in Linux to initialize RPMSG:

root@imx93evk:~# modprobe imx_rpmsg_tty

 

Then, we will have the hello world message from Cortex A (Linux side), but with our buffer format in Cortex M33 console:

CMD: h  [1]:0x65        [2]:0x6c        [3]:0x6c                [4]: 111                 LEN = 12

 

Finally, we are ready change colors of the LEDs:

Load the buffer (LED 1 = RED, LED 2 = Green, LED 3 = Blue).

root@imx93evk:~# wsled -c 0x55 0x00 0x00 -n 1
root@imx93evk:~# wsled -c 0x00 0x55 0x00 -n 2
root@imx93evk:~# wsled -c 0x00 0x00 0x55 -n 3

 

Show colors on LEDs.

root@imx93evk:~# wsled -t

 

Manuel_Salas_8-1749597921154.png

 

Attachments
100% helpful (1/1)
Version history
Last update:
‎07-09-2025 12:09 PM
Updated by: