Messaging Unit library

The Messaging Unit (MU) library is intended to be used by other drivers for messaging

Runs on:

QNX OS

Location:

$BSP_ROOT_DIR/src/lib/hw_vendor/nxp/imx8/mu

Description:

Though the MU library is intended to be used by other drivers, it can be also used in an application. For example, it can be used for an application that communicates with the Cortex-M core user firmware.

The library should be linked statically ($BSP_ROOT_DIR/src/lib/mu/aarch64/a-le/libmu-imx.a) or dynamically ($BSP_ROOT_DIR/src/lib/mu/aarch64/so-le/libmu-imx.so). For more information, see Using libraries chapter in the QNX OS Programmer's Guide.

Example:

Here's an example of a use case (in pseudo code), provided by NXP. In this example, the interrupts for the first three receive registers are disabled, whereas the interrupt for the fourth and last receive register are enabled. The registers are then written in sequential order (n = 0, 1, 2, 3), the write of the first three registers (n = 0, 1, 2) will not generate an interrupt to the receiving core, it is until the fourth and last receive register (n = 3) is written that the receiving core will be notified by an interrupt. The receiving core can now service the interrupt and read back the data transmitted on the four registers:
int main (void)
{
  /* Uses MU10A, other side (like Cortex-M) uses MU10B */
  mu = imx_mu_init(IMX_MU10A_BASE, IMX_MU10A_IRQ);

  /* Dummy read with interrupt disabled */
  imx_mu_read(mu, 0, &value, 100, IMX_MU_FLAG_BLOCK);
  imx_mu_read(mu, 1, &value, 100, IMX_MU_FLAG_BLOCK);
  imx_mu_read(mu, 2, &value, 100, IMX_MU_FLAG_BLOCK);
  imx_mu_read(mu, 3, &value, 100, IMX_MU_FLAG_BLOCK);

  while (1) {
    /* Read Sequence :
       Processor receives the Receive 3 interrupt and starts reading the
       message transferred from the receive registers.
       After Receive Register 3 is read, the interrupt bit is cleared.
     */
    /* Continuously receive data in interrupt mode.
       Will sleep in InterruptWait() */
    if (imx_mu_read(mu, 3, &value3, 0, 0) ==  0) {
       /* Read Reg0 with interrupt disabled */
       status = imx_mu_read(mu, 0, &value0, 100, IMX_MU_FLAG_BLOCK)
       if (status != 0) {
         /* Timeout. No data in Reg0 */
       }
       /* Read Reg1 with interrupt disabled */
       status = imx_mu_read(mu, 1, &value1, 100, IMX_MU_FLAG_BLOCK);
       if (status != 0) {
         /* Timeout. No data in Reg1 */
       }
       /* Read Reg2 with interrupt disabled */
       status = imx_mu_read(mu, 2, &value2, 100, IMX_MU_FLAG_BLOCK);
       if (status != 0) {
          /* Timeout. No data in Reg2 */
       }
       ...
       ...
       /* Do something with values or shared buffers 
          if used for data transfers */
       ...
       ...
       /* The Processor writes the message information sequentially to its
          Transmit Registers 0, 1, 2.
        */
       status = imx_mu_send(mu, 0, value0, 100, IMX_MU_FLAG_BLOCK);
       if (status != 0) {
         /* Timeout. TX register is full. Other side probably did not
            read previous data from TX register */
       }
       status = imx_mu_send(mu, 1, value1, 100, IMX_MU_FLAG_BLOCK);
       if (status != 0) {
         /* Timeout. The TX register is full. Other side probably did not
            read previous data from the TX register */
       }
       status = imx_mu_send(mu, 2, value2, 100, IMX_MU_FLAG_BLOCK);
       if (status != 0) {
         /* Timeout. The TX register is full. Other side probably did not
            read previous data from TX register */
       }
       /* When the write to the Transmit Register 3 occurs, 
          the RF3 bit of the xSR is set after synchronization, and it
          immediately triggers the Receive 3 interrupt to the 
          other Processor.
        */
       status = imx_mu_send(mu, 3, value3, 100, IMX_MU_FLAG_BLOCK);
       if (status != 0) {
         /* Timeout. The TX register is full. Other side probably did not 
            read previous data from the TX register */
       }
     }
  }
}
Page updated: