Skip to content

Commit cee0d36

Browse files
nicola-mazzucato-armadeaarm
authored andcommitted
RSE: mhu_wrapper_v3_x: Relax 4-byte align in buffer size
The MHU wrapper handles the data from and to the driver with a 4-byte alignment. This may not fit the caller, which may need to transfer a buffer or arbitrary size. Add some logic to internally handle the case where the buffer size is not multiple of 4 bytes. Signed-off-by: Nicola Mazzucato <nicola.mazzucato@arm.com> Change-Id: I93d0853078e69a4ae5ca83983fd1b4d3d8ed4454
1 parent 739a60d commit cee0d36

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

platform/ext/target/arm/rse/common/native_drivers/mhu.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,9 @@ enum mhu_error_t mhu_init_receiver(void *mhu_receiver_dev);
8282
*
8383
* \return Returns mhu_error_t error code.
8484
*
85-
* \note The send_buffer must be 4-byte aligned and its length must be at least
86-
* (4 - (size % 4)) bytes bigger than the data size to prevent buffer
87-
* over-reading.
85+
* \note For MHUv2, the send_buffer must be 4-byte aligned and its length must
86+
* be at least (4 - (size % 4)) bytes bigger than the data size to
87+
* prevent buffer over-reading.
8888
*/
8989
enum mhu_error_t mhu_send_data(void *mhu_sender_dev,
9090
const uint8_t *send_buffer,
@@ -111,12 +111,12 @@ enum mhu_error_t mhu_wait_data(void *mhu_receiver_dev);
111111
* \param[in,out] size As input the size of the receive_buffer,
112112
* as output the number of bytes received.
113113
* As a limitation, the size of the buffer
114-
* must be a multiple of 4.
114+
* must be a multiple of 4 for MHUv2.
115115
*
116116
* \return Returns mhu_error_t error code.
117117
*
118-
* \note The receive_buffer must be 4-byte aligned and its length must be a
119-
* multiple of 4.
118+
* \note For MHUv2, the receive_buffer must be 4-byte aligned and its length
119+
* must be a multiple of 4.
120120
*/
121121
enum mhu_error_t mhu_receive_data(void *mhu_receiver_dev,
122122
uint8_t *receive_buffer,

platform/ext/target/arm/rse/common/native_drivers/mhu_wrapper_v3_x.c

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,12 @@ enum mhu_error_t clear_and_wait_for_signal (
156156
/**
157157
* @brief For simplicity, require:
158158
* - the buffer address to be 4-byte aligned.
159-
* - the buffer size to be a multiple of 4.
160159
*/
161160
static enum mhu_error_t validate_buffer_params(uintptr_t buf_addr,
162161
size_t buf_size)
163162
{
164163
if ((buf_addr == 0) ||
165164
(!IS_ALIGNED(buf_addr, 4)) ||
166-
(!IS_ALIGNED(buf_size, 4)) ||
167165
(buf_size == 0)) {
168166
return MHU_ERR_VALIDATE_BUFFER_PARAMS_INVALID_ARG;
169167
}
@@ -284,6 +282,8 @@ enum mhu_error_t mhu_send_data(void *mhu_sender_dev, const uint8_t *send_buffer,
284282
uint8_t num_channels;
285283
uint8_t chan = 0;
286284
uint32_t *buffer;
285+
uint32_t t_buffer;
286+
size_t bytes_left;
287287

288288
assert(dev != NULL);
289289
assert(dev->base != (uintptr_t)NULL);
@@ -307,11 +307,23 @@ enum mhu_error_t mhu_send_data(void *mhu_sender_dev, const uint8_t *send_buffer,
307307
chan++;
308308

309309
buffer = (uint32_t *)send_buffer;
310-
for (size_t i = 0; i < size; i += 4) {
311-
mhu_v3_err = mhu_v3_x_doorbell_write(dev, chan, *buffer++);
310+
bytes_left = size;
311+
while (bytes_left > 0) {
312+
if (bytes_left >= 4) {
313+
t_buffer = *buffer++;
314+
bytes_left -= 4;
315+
} else {
316+
/* a few bytes still to send, pad the remaining bytes */
317+
t_buffer = 0;
318+
memcpy(&t_buffer, (uint32_t *)buffer, bytes_left);
319+
320+
bytes_left = 0;
321+
}
322+
mhu_v3_err = mhu_v3_x_doorbell_write(dev, chan, t_buffer);
312323
if (mhu_v3_err != MHU_V_3_X_ERR_NONE) {
313324
return mhu_v3_err;
314325
}
326+
315327
if (++chan == (num_channels - 1)) {
316328
/* Using the last channel for notifications */
317329
mhu_err = signal_and_wait_for_clear(dev, MHU_NOTIFY_VALUE);
@@ -368,6 +380,8 @@ enum mhu_error_t mhu_receive_data(void *mhu_receiver_dev,
368380
uint8_t num_channels;
369381
uint8_t chan = 0;
370382
uint32_t *buffer;
383+
uint32_t t_buffer;
384+
size_t bytes_left;
371385

372386
assert(dev != NULL);
373387
assert(dev->base != (uintptr_t)NULL);
@@ -401,14 +415,25 @@ enum mhu_error_t mhu_receive_data(void *mhu_receiver_dev,
401415
}
402416

403417
buffer = (uint32_t *)receive_buffer;
404-
for (size_t i = 0; i < msg_len; i += 4) {
405-
mhu_v3_err = mhu_v3_x_doorbell_read(dev, chan, buffer++);
418+
bytes_left = msg_len;
419+
while (bytes_left > 0) {
420+
if (bytes_left >= 4) {
421+
mhu_v3_err = mhu_v3_x_doorbell_read(dev, chan, buffer++);
422+
bytes_left -= 4;
423+
} else {
424+
/* a few bytes still to receive, pad the remaining bytes */
425+
t_buffer = 0;
426+
mhu_v3_err = mhu_v3_x_doorbell_read(dev, chan, &t_buffer);
427+
428+
memcpy((uint32_t *)buffer, &t_buffer, bytes_left);
429+
bytes_left = 0;
430+
}
406431
if (mhu_v3_err != MHU_V_3_X_ERR_NONE) {
407432
return mhu_v3_err;
408433
}
409434

410435
/* Only wait for next transfer if there is still missing data. */
411-
if (++chan == (num_channels - 1) && (msg_len - i) > 4) {
436+
if ((++chan == (num_channels - 1)) && (bytes_left > 0)) {
412437
/* Busy wait for next transfer */
413438
mhu_err = clear_and_wait_for_signal(dev, MHU_NOTIFY_VALUE);
414439
if (mhu_err != MHU_ERR_NONE) {

0 commit comments

Comments
 (0)