Skip to content

Conversation

@mmerklinger
Copy link
Collaborator

  • Cleans up register, field, and status definitions
  • Changes name of typedef
  • Refactors the request function into multiple functions

This is a refactor for future features.

@mmerklinger mmerklinger added the devel Makes development easier label Dec 13, 2021
@mmerklinger mmerklinger self-assigned this Dec 13, 2021
// Send message and check responses
bool mailbox_request (volatile unsigned int * data_ptr, channel_t channel);
bool mailbox_request (volatile unsigned int * buffer, channel_t channel);
unsigned int mailbox_message_to_register_value (mailbox_message_t * message);
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
unsigned int mailbox_message_to_register_value (mailbox_message_t * message);
unsigned int mailbox_message_to_register_value (mailbox_message_t message);

mailbox_message_t is 4 bytes long, there's no need to pass it as pointer. Generally, as long as structs are 8 bytes maximum, you can safely pass them by value - after all, the pointer you'd pass otherwise is 8 bytes.

Passing by value ensures no modifications happen and, since the compiler can reason about this and doesn't need another indirection, is likely to be faster.

If you do want to pass by reference, you should probably at least make it mailbox_message const * message, as promise that you don't modify it.

The same goes for mailbox_read and mailbox_write; none of these modify message

}

unsigned int mailbox_message_to_register_value (mailbox_message_t * message) {
return ((unsigned int) ((long) message->data) & ~0xF) | (message->channel & 0xF);
Copy link
Owner

Choose a reason for hiding this comment

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

As far as I can tell, what you try to do here is to merge 28 bits of data with 4 bits of channel into the 32 bit message the mailbox expects. I.e., you try to combine message into this format:

|            data            |chnl|
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^|^^^^|
|-------------28-------------|--4-|

Now, have a look at the structure of mailbox_message_t:

typedef struct {
    unsigned int data    : 28;// most significant bits contain shared memory address
    channel_t    channel : 4; // least four significant bits contain channel
} mailbox_message_t;

Incidentally, this structure is 4 bytes long and gets packed into this format:

|            data            |chnl|
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^|^^^^|
|-------------28-------------|--4-|

That means the data is already in the proper format; all we have to do now is tell the compiler that it is what it should be:

  • Casting (assuming you pass message by value, otherwise omit the &):
Suggested change
return ((unsigned int) ((long) message->data) & ~0xF) | (message->channel & 0xF);
return * (unsigned int *) & message;
  • Bit-wise OR:
Suggested change
return ((unsigned int) ((long) message->data) & ~0xF) | (message->channel & 0xF);
return (unsigned int) (message->data << 4) | message->channel; // no need to specifically clear bits

Copy link
Owner

Choose a reason for hiding this comment

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

I just realised this issue was caused by me not communicating clearly how mailbox_message_t should be used -
message.data is supposed to store the 28 most significant bits of the memory address after it has been truncated to a 32bit integer. We know the 4 least significant bits are 0 anyways. I should've made that clear and provide an appropriate Initialise function.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I changed the source to pass mailbox_message_t by value. Unfortunately, the cast you suggested compiled, but didn't work on the running machine. I had errors on the console. Therefore, I simplified it to return (message.data & ~0xF) | message.channel;.

Copy link
Owner

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I saw that, but see my comment below. As soon as I do the cast like this the boot hangs at src/common/rng.c:15:[0] Initialised RNG successfully.

Copy link
Owner

Choose a reason for hiding this comment

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

as for why it hangs is because if data doesn't point to a proper message, the mailbox doesn't do anything

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, because otherwise the above mentioned crash happens. In the function where I cast the mailbox message for the register I zero out the 4 Bit.

Copy link
Owner

Choose a reason for hiding this comment

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

so you get the crash if 1) you shift and 2) you do not zero out the 4 LSB in the register function?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Correct.

Copy link
Owner

Choose a reason for hiding this comment

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

okay, then leave it be for now. Maybe I'll have a look at it tomorrow, the error is probably more subtle

// Wait until we can write
while (get32 (MBOX0 + MBOX_STATUS) & MBOX_WRITE_FULL)
;
mailbox_message_t message = {buffer, channel};
Copy link
Owner

@anarchuser anarchuser Dec 13, 2021

Choose a reason for hiding this comment

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

Suggested change
mailbox_message_t message = {buffer, channel};
mailbox_message_t message = {(unsigned int) buffer >> 4, channel}; // remove least significant 4 bits of buffer

see my explanation for mailbox_message_to_register_value

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This fails to compile with invalid operands to binary >> (have ‘volatile unsigned int *’ and ‘int’). Tried to solve it with a cast to type long.

Copy link
Owner

Choose a reason for hiding this comment

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

preferably cast to unsigned int but both should work

Copy link
Owner

Choose a reason for hiding this comment

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

I updated the suggestion

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In that case I got a compiler warning because unsigned int is not necessarily same length as the pointer. This is why I took long.

Copy link
Owner

Choose a reason for hiding this comment

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

fair. In the end, we cast it to 32 bit implicitly

mmerklinger and others added 5 commits December 13, 2021 14:25
Co-authored-by: Aaron Alef <aaron.alef@code.berlin>
Co-authored-by: Aaron Alef <aaron.alef@code.berlin>
Before, heap started above CPU 0 stack and grew into CPU 1 stack
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

devel Makes development easier

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants