Skip to content

Use IPM for cdc-acm #552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 16, 2017
Merged

Use IPM for cdc-acm #552

merged 1 commit into from
Aug 16, 2017

Conversation

bigdinotech
Copy link
Contributor

-use the IPM instead of shared memory for passing data between ARC
and x86 cores for cdc-acm.

@bigdinotech
Copy link
Contributor Author

@eriknyquist @SidLeung ready for review

@@ -73,7 +100,9 @@ void CDCSerialClass::init(const uint32_t dwBaudRate, const uint8_t modeReg)
* Empty the Rx buffer but don't touch Tx buffer: it is drained by the
* LMT one way or another */
_rx_buffer->tail = _rx_buffer->head;


mailbox_register(6, cdc_mbox_isr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Channel 6 is exposed by the CurieMailbox library. If you use this channel, the Mailbox library and Serial will not work simultaneously.

Can we use channel 7 for both RX and TX?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my initial tests using channel 7 for both was not stable. It freezes when we are sending and receiving on both cores at a high rate

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throughput would be vastly improved if we fill all 16 bytes of the mailbox channel, instead of sending 1 message per character. Let's focus on that first, and then see if it's stable enough to use one channel for RX/TX

{
if(((uint8_t)dword) != '\0')
{
new_head = (Serial._rx_buffer->head +1) % CDCACM_BUFFER_SIZE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surely there's some kind of 'ringbuffer_add' method? we should not be re-implementing this logic for each write to the buffer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is none implemented for the cdc-acm ring buffer in shared memory

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's implement one, then.

@@ -36,6 +36,33 @@ extern void CDCSerial_Handler(void);
extern void serialEventRun1(void) __attribute__((weak));
extern void serialEvent1(void) __attribute__((weak));

static void cdc_mbox_isr(CurieMailboxMsg msg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function looks really complex for such a simple task. Can't you just do something like this;

unsigned char *ptr = (unsigned char*) msg.data;

/* Continue until 16 chars, or until NULL is seen */
for (unsigned i = 0; i < 16 && ptr[i]; ++i) {
    /* Assuming we have some kind of 'put' method for ring buffer... */
    ringbuffer_put(ptr[i]);
}

uint32_t retries = 2;

CurieMailboxMsg cdcacm_msg;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trailing whitespace

} while (retries--);

cdcacm_msg.channel = 7;
cdcacm_msg.data[0] = (uint32_t)uc_data;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the cast to uint32_t? not needed at all. remove please

}
} while (retries--);

cdcacm_msg.channel = 7;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Give it a name. You know the drill, by now I hope.....

@@ -73,7 +100,9 @@ void CDCSerialClass::init(const uint32_t dwBaudRate, const uint8_t modeReg)
* Empty the Rx buffer but don't touch Tx buffer: it is drained by the
* LMT one way or another */
_rx_buffer->tail = _rx_buffer->head;


mailbox_register(6, cdc_mbox_isr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throughput would be vastly improved if we fill all 16 bytes of the mailbox channel, instead of sending 1 message per character. Let's focus on that first, and then see if it's stable enough to use one channel for RX/TX

Copy link
Contributor

@eriknyquist eriknyquist left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still un-addressed comments in the first revision, and some new things to be addressed in the most recent revision.


size_t CDCSerialClass::write(const uint8_t *buffer, size_t size)
Copy link
Contributor

@eriknyquist eriknyquist Jun 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is super complicated.... again the nested for-loops and bit shifting is unnecessary. Also, you forgot to return the number of bytes written at the end.

Here's a different version of this same function, which is much shorter (about 50% of it is comments anyway) and easier to read, only needs a single loop, and handles the missing return as well...

/* Size in bytes of a mailbox message payload  */
#define MBOX_BYTES (CHANNEL_DATA_WORDS * sizeof(uint32_t))

...

size_t CDCSerialClass::write(const uint8_t *buffer, size_t size) {
    CurieMailboxMsg cdcacm_msg;
    unsigned int i, step, remainder;

    cdcacm_msg.channel = CDC_MAILBOX_TX_CHANNEL;
    if (!_shared_data->device_open || !_shared_data->host_open)
         return(0);

    do {
        /* Distance to next 16-byte boundary */
        remainder = i % MBOX_BYTES;

        if (i > 0 && (remainder == 0 || !buffer[i] || i == size) {
            /* Either we are copying a full 16 bytes (standard condition), or from
              * the current position to the last 16-byte boundary (end-of-input condition)*/
            step = (buffer[i] || i == size) ? MBOX_BYTES : remainder;

            /* Copy data into mailbox message */
            memset(cdcacm_msg.data, 0, sizeof(cdcacm_msg.data));
            memcpy(cdcacm_msg.data, buffer + (i - step), step);

            /* Write to mailbox*/
            mailbox_write(cdcacm_msg);
        }

    /* Continue until a null character, or max. write size, is reached*/
    } while (buffer[i] && size > i++);

     /* Return no. of bytes written */
    return i;
}

if (!_shared_data->device_open || !_shared_data->host_open)
return(0);

int msg_len = size;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

msg_len never changes, why is it needed at all? just use size directly.

-use the IPM instead of shared memory for passing data between ARC
and x86 cores for cdc-acm.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants