cancel
Showing results for 
Search instead for 
Did you mean: 

OPENAMP send data from M4 to A7 and wait until RX buffer is free

meiss.M
Associate III

Hello,

I need to send several kilobytes of data from the M4 to the A7. However, I am experiencing data loss during this transfer. Is there a function that waits on the M4 side, until the A7 has collected all data from the tty.

/*
 * Channel direction and usage:
 *
 *  ========   <-- new msg ---=============--------<------   =======
 * ||      ||                || CHANNEL 1 ||                ||     ||
 * ||  A7  ||  ------->-------=============--- buf free-->  || M4  ||
 * ||      ||                                               ||     ||
 * ||master||  <-- buf free---=============--------<------  ||slave||
 * ||      ||                || CHANNEL 2 ||                ||     ||
 *  ========   ------->-------=============----new msg -->   =======
 */

for instance channel2 - buf free.

Many thanks!

9 REPLIES 9
Bumsik Kim
Senior

What functions are you using to send data?

AFAIK, you don't need to care about CHANNEL 2 when sending message in M4=>A7 direction.

The CHANNEL 1 is used by the M4=>A7 direction OpenAMP virtqueue whereas CHANNEL 2 is for A7=>M4 virtqueue.

Basically when you send data via a rpmsg endpoint on M4 side, the M4 triggers "new msg" interrupt on Channel 1 on A7 side, and then the Linux handles the message and triggers "buf free" back to M4 on the same Channel 1. The IPCC interrupt and IPCC_channel1_callback() should handle the interrupt and then set a "Buf free" flag variable. In the current ST's OpenAMP implementation however, you should call OPENAMP_check_for_message() or OPENAMP_Wait_EndPointready() manually to handle and reset the "Buf free" flag for each OpenAMP send/receive functions.

Also, the default maxium size of each rpmsg packets is 512 bytes. So try chopping send messages into less than 512 bytes.

Hi @Bumsik Kim​ !

Can you share more information about the use of OPENAMP_Wait_EndPointready()?

I don't understand how this functions works to handle the flag "Buf free".

I've tried something like that:

if (RxMsg_VIRT_UART1) {
            RxMsg_VIRT_UART1 = RESET;
	    while(1){
	    	OPENAMP_check_for_message();
	    	if (is_rpmsg_ept_ready(&huart1.ept)) {
	    		VIRT_UART_Transmit(&huart1, (uint8_t *)buffer, 496);
	    	}
	    }
	}

But the function is_rpmsg_ept_ready() always return 1 and I get flip string error.

Thank you!

is_rpmsg_ept_ready() is not for handling the flag "Buf free" but MAILBOX_Poll() in OPENAMP_check_for_message() or OPENAMP_Wait_EndPointready() should handle the flag. OPENAMP_check_for_message() will do just fine in most cases.

The only difference is that is_rpmsg_ept_ready() in OPENAMP_Wait_EndPointready() waits until the VIRT_UART is established with the host Linux and is able to transmit data. It is about initialization stage, not waiting for "Buf free"!

Have you seen my recent post "VIRT_UART (or RPMsg framework) on M4 cannot send messages until A7 host sends a message."?

https://community.st.com/s/question/0D50X0000BaMkj0SQC/virtuart-or-rpmsg-framework-on-m4-cannot-send-messages-until-a7-host-sends-a-message

This is exactly what is_rpmsg_ept_ready() is about. To be precise, is_rpmsg_ept_ready() starts returning 1 after the first message sent from Linux is received, making it complete the initialization stage. That is, Linux must send any data first (and only once is enough) to complete the initialization.

So your if(is_rpmsg_ept_ready()) fence in your code essentially do nothing because OPENAMP_check_for_message() will return 1 only when there are flags to be handled, including the first message from Linux.

And what do you mean "flip string error"?

By the way, if RxMsg_VIRT_UART1 is a flag by the UART rx callback, OPENAMP_check_for_message() should come before checking RxMsg_VIRT_UART.

lenonrt
Associate III

Hi thanks for answer @Bumsik Kim​ !

  1. I read your recent posts. I've got a wrong understanding of the is_rpmsg_ept_ready(). I thought that it shows me when the buffer was full. Now I understand.
  2. When I send more messages then Linux can read, I get the message: rpmsg_tty_virtio0.rpmsg-tty-channel.-1.1: No memory for tty_prepare_flip_string. Then I need to reset the target.
  3. I'm seeking a way to block message sending when buffer is full. The only way that I find to communicate is Linux asking for messages, but it costs a time and turn communication slow.

OPENAMP_check_for_message() is supposed to return 0 until "buf free" flag is received.

Well, I'm just telling the theory that I know and that sounds bad, because I'm working on OpenAMP too and I haven't tested such case.

Maybe we can work together...

Bumsik Kim
Senior

Here is my findings so far:

When you send messages, virtio tries to "kick" the A7 core in MAILBOX_Notify() callback, which is bound to the virtio during OPENAMP_Init().

The important thing is, that MAILBOX_Notify() actually waits while IPCC_CHANNEL_STATUS_OCCUPIED. I'm not sure if it is related to "Buff free" though.

meiss.M
Associate III

Sorry for the late reply. The solution for us was to implement a custom, basic scheduler and poll for new messages every ~600us. When using # screen to connect to the virtual TTY under yocto, there were lost characters and some character loss and shifts. However, to communicated with the A7, we use pyserial which works fine.

When sending data, from the M4 to the A7, I ended up with the following code:

uint8_t l;
l = strlen(s);
 
while (l > RPMSG_BUFFER_SIZE - 16)
{
	VIRT_UART_Transmit(&huart0, (uint8_t *)s, RPMSG_BUFFER_SIZE - 16);
	s += RPMSG_BUFFER_SIZE - 16;
	l = strlen(s);
	OPENAMP_check_for_message();
}
 
VIRT_UART_Transmit(&huart0, (uint8_t *)s, l);
OPENAMP_check_for_message();

skuma.9
Associate II

I want to check what is the optimal packet size to be sent over OpenAmp from M4 to A7.

any example which I can refer to check the optimal packet size.