RISCV Mailbox Usage Reference


REVISION HISTORY

Revision No.
Description
Date
1.0 Initial release 08/18/2025

1. Overview

This module can be referred to as a mailbox, but a mailbox is also a set of registers accessible by multiple cores on-chip. By combining these registers with shared memory, inter-core communication can be implemented. Here, it is used for communication between U-Boot and FreeRTOS.

2. Keyword Explanation

  • mailbox/mbx

    mbx is the abbreviation of mailbox, specifically referring to a group of registers accessible by multiple cores on the chip, and more broadly referring to this functional module.

  • uboot

    The Linux bootloader, running before Linux starts.

3. Function Description

This module is used for simple communication between U-Boot and FreeRTOS. Since sending and receiving do not have contention protection, sending or receiving cannot occur simultaneously in multiple parallel tasks. This function is half-duplex, meaning that sending and receiving cannot occur at the same time; when one side is sending, the other cannot send. Without channel contention protection, only one side can be active, meaning that only one side can actively send, while the other side can only passively respond after receiving a message.

3.1. Principle

At initialization, the two communicating parties establish a block of shared memory through the mailbox registers. Then, two mailbox registers are used: one to report the message length from ARM to RISC-V; when this mailbox has a non-zero value of length, it indicates that there is a message of length length from ARM to RISC-V in the shared memory. The other mailbox reports the message length from RISC-V to ARM; when this mailbox has a non-zero value of length, it indicates that there is a message of length length from RISC-V to ARM in the shared memory.

Since there is only one block of shared memory, this function is half-duplex, meaning that sending and receiving cannot occur simultaneously.

The U-Boot part of the code is located at:

Alkaid/boot/drivers/sstar/riscv/drv_riscv.c

The FreeRTOS part of the code is located at:

Alkaid/riscv/kernel/rtk/proj/sc/driver/sysdriver/mbx_msg/src/mbx_msg.c

3.2. Initialization

Initialization is primarily used for both parties to establish a block of shared memory and indicate that both sides are ready through a final handshake.

3.3. Reception

Taking RISC-V as an example, the process is as follows:

3.4. Sending

Taking RISC-V as an example, the process is as follows:

Since it is half-duplex, you must ensure that reception has been completed before sending.

3.5. Channel Contention Protection

On a single end, since there is no contention protection for sending and receiving, neither sending nor receiving supports multi-tasking. On both ends, since it is half-duplex and there is no contention mechanism for the channel, for example, if RISC-V checks MBX_ARM_TO_RISCV and confirms it is 0 while ARM is concurrently sending, and just has completed the copy but has not yet written to MBX_ARM_TO_RISCV, the data written by the ARM side may be overwritten. To prevent such situations, there can only be one active side in communication; that is, only one side can actively send messages while the other can only passively reply after receiving a message.

4. Mailbox Demo

4.1. Demo Overview

The demo consists of two parts: one is the U-Boot app and the other is the app under FreeRTOS. The two apps communicate using the mailbox.

In this demo, the user manually sends messages from the U-Boot side to the FreeRTOS side. After receiving the message, the FreeRTOS side adds ": id" to the end and sends it back, where id is a counter that increments by 1 with each communication.

4.2. U-Boot App

The following configuration needs to be enabled on U-Boot:

CONFIG_SSTAR_RISCV=y

This can be configured using make menuconfig.

The demo code is located at:

Alkaid/boot/cmd/sstar/riscv.c

4.3. FreeRTOS App

In FreeRTOS, it is enabled by default, and the code is located at:

Alkaid/riscv/kernel/rtk/proj/sc/application/uboot_app/src/uboot_app.c

The result is as follows:

5. API Reference

5.1. U-Boot API Reference

This section introduces the APIs and data on U-Boot.

API Name Function
drv_riscv_init Module initialization.
drv_riscv_deinit Module de-initialization.
drv_riscv_poll Poll for pending data or readiness to send.
drv_riscv_send Send data.
drv_riscv_recv Receive data.

5.1.1. drv_riscv_init

  • Function

    Module initialization.

  • Syntax

    int drv_riscv_init(void);
    
  • Parameters

    Parameter Name Parameter Meaning Input/Output
    None None None
  • Return Value

    Return Value Description
    0 Initialization successful
    -1 Initialization failed
  • Dependencies

    • Header file: Alkaid/boot/drivers/sstar/riscv/drv_riscv.h

    • Library files

5.1.2. drv_riscv_deinit

  • Function

    Module de-initialization.

  • Syntax

    int drv_riscv_deinit(void);
    
  • Parameters

    Parameter Name Parameter Meaning Input/Output
    None None None
  • Return Value

    Return Value Description
    0 De-initialization successful
  • Dependencies

    • Header file: Alkaid/boot/drivers/sstar/riscv/drv_riscv.h

    • Library files

5.1.3. drv_riscv_poll

  • Function

    Poll for pending data or readiness to send.

  • Syntax

    int drv_riscv_poll(int flag);
    
  • Parameters

    Parameter Name Parameter Meaning Input/Output
    flag Must be either DRV_RISCV_POLLIN or DRV_RISCV_POLLOUT. DRV_RISCV_POLLIN indicates to check for pending data to receive, while DRV_RISCV_POLLOUT indicates to check if it is ready to send. Input
  • Return Value

    Return Value Description
    0 When polling for receive, indicates there is no data to receive; when polling for send, indicates it is not ready to send.
    -1 Returns this value if the input parameter is neither DRV_RISCV_POLLIN nor DRV_RISCV_POLLOUT.
    Other values When polling for receive, indicates the length of pending data; when polling for send, indicates readiness to send.
  • Dependencies

    • Header file: Alkaid/boot/drivers/sstar/riscv/drv_riscv.h

    • Library files

  • Example

    See 4.2
    

5.1.4. drv_riscv_send

  • Function

    Send data.

  • Syntax

    int drv_riscv_send(const char *msg, int len);
    
  • Parameters

    Parameter Name Parameter Meaning Input/Output
    msg Pointer to the head of the data block to be sent. Input
    len Length of the data block to be sent (in bytes). Input
  • Return Value

    Return Value Description
    0 Send successful.
    -1 Send failed.
  • Dependencies

    • Header file: Alkaid/boot/drivers/sstar/riscv/drv_riscv.h

    • Library files

  • Note

    • Before sending, first query with drv_riscv_poll(DRV_RISCV_POLLOUT) until a non-zero return value is obtained, indicating it can be sent.
  • Example

    See 4.2
    

5.1.5. drv_riscv_recv

  • Function

    Receive data.

  • Syntax

    int drv_riscv_recv(char *msg, int len);
    
  • Parameters

    Parameter Name Parameter Meaning Input/Output
    msg Pointer to the receive buffer. Input
    len Length of the receive buffer (in bytes). Input
  • Return Value

    Return Value Description
    >= 0 Length of the received data.
  • Dependencies

    • Header file: Alkaid/boot/drivers/sstar/riscv/drv_riscv.h

    • Library files

  • Note

    • Before receiving, first query with drv_riscv_poll(DRV_RISCV_POLLIN) until a non-zero return value indicates that data is available for receiving.
  • Related Topics

    None

5.2. FreeRTOS API Reference

This section introduces the API on FreeRTOS.

API Name Function
drv_mbx_msg_init Module initialization.
drv_mbx_msg_deinit Module de-initialization.
drv_mbx_msg_poll Query if it can send or if data is available to receive.
drv_mbx_msg_send Send data.
drv_mbx_msg_recv Receive data.

5.2.1. drv_mbx_msg_init

  • Function

    Module initialization.

  • Syntax

    int drv_mbx_msg_init(void);
    
  • Parameters

    Parameter Name Parameter Meaning Input/Output
    None None None
  • Return Value

    Return Value Description
    0 Success
  • Dependencies

    • Header file: Alkaid/riscv/kernel/rtk/proj/sc/driver/sysdriver/mbx_msg/mbx_msg.h

    • Library files

5.2.2. drv_mbx_msg_deinit

  • Function

    De-initialization.

  • Syntax

    int drv_mbx_msg_deinit(void);
    
  • Parameters

    Parameter Name Parameter Meaning Input/Output
    None None None
  • Return Value

    Return Value Description
    0 Success
  • Dependencies

    • Header file: Alkaid/riscv/kernel/rtk/proj/sc/driver/sysdriver/mbx_msg/mbx_msg.h

    • Library files

5.2.3. drv_mbx_msg_poll

  • Function

    Query if it can send or if data is available to receive.

  • Syntax

    int drv_mbx_msg_poll(int flag);
    
  • Parameters

    Parameter Name Parameter Meaning Input/Output
    flag Must be either DRV_MBX_MSG_POLLIN or DRV_MBX_MSG_POLLOUT. DRV_MBX_MSG_POLLIN indicates to query for pending data, while DRV_MBX_MSG_POLLOUT indicates to query if it is ready to send. Input
  • Return Value

    Return Value Description
    0 Indicates no data is available when polling for receive, cannot send when polling for send, and returns this value if the input parameter is neither DRV_MBX_MSG_POLLIN nor DRV_MBX_MSG_POLLOUT.
    Other values Indicates the length of pending data when polling for receive, indicates readiness to send when polling for send.
  • Dependencies

    • Header file: Alkaid/riscv/kernel/rtk/proj/sc/driver/sysdriver/mbx_msg/mbx_msg.h

    • Library files

5.2.4. drv_mbx_msg_send

  • Function

    Send data.

  • Syntax

    int drv_mbx_msg_send(const char *msg, int len);
    
  • Parameters

    Parameter Name Parameter Meaning Input/Output
    msg Pointer to the head of the data block to be sent. Input
    len Length of the data block to be sent (in bytes). Input
  • Return Value

    Return Value Description
    0 Send successful.
    -1 Send failed.
  • Dependencies

    • Header file: Alkaid/riscv/kernel/rtk/proj/sc/driver/sysdriver/mbx_msg/mbx_msg.h

    • Library files

  • Note

    • Before sending, use drv_mbx_msg_poll(DRV_MBX_MSG_POLLIN) to confirm there is no pending data before proceeding with drv_mbx_msg_poll(DRV_MBX_MSG_POLLOUT) confirmation for readiness to send.

5.2.5. drv_mbx_msg_recv

  • Function

    Receive data.

  • Syntax

    int drv_mbx_msg_recv(char *msg, int len);
    
  • Parameters

    Parameter Name Parameter Meaning Input/Output
    msg Pointer to the receive buffer. Input
    len Length of the receive buffer (in bytes). Input
  • Return Value

    Return Value Description
    >= 0 Length of the received data.
  • Dependencies

    • Header file: Alkaid/riscv/kernel/rtk/proj/sc/driver/sysdriver/mbx_msg/mbx_msg.h

    • Library files

  • Note

    • Before receiving, confirm with drv_mbx_msg_poll(DRV_MBX_MSG_POLLIN) to ensure data is available for receiving.

6. FAQ

N/A