Skip to content
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

cpu/samd5x: avoid the use of bitfields #20714

Merged
merged 2 commits into from
Jun 29, 2024

Conversation

dylad
Copy link
Member

@dylad dylad commented May 30, 2024

Contribution description

This PR replaces all calls of foo->bar.bit.xyz = ABCD to foo->bar.reg &= ABCD for all SAMD5x MCUs
This should not have much impact on the code but it would be good to test the CAN driver implementation as I might have break something.

Testing procedure

A careful review especially on the CAN driver is needed?
CI should catch most of the failure but feel free to run some tests on hardware.

Issues/PRs references

see #20457

@dylad dylad requested a review from kfessel May 30, 2024 14:42
@dylad dylad requested review from kaspar030 and benpicco as code owners May 30, 2024 14:42
@github-actions github-actions bot added Platform: ARM Platform: This PR/issue effects ARM-based platforms Area: cpu Area: CPU/MCU ports labels May 30, 2024
@dylad dylad force-pushed the pr/cpu/samd5x/avoid_bitfields_reg branch from a6c028a to 6324c2a Compare May 30, 2024 14:55
@kfessel
Copy link
Contributor

kfessel commented May 31, 2024

Why? -
ok i saw the issue #20457 (microchips droping the bit field support)

I think bitfields are more legible, so there must be a reason.

@dylad
Copy link
Member Author

dylad commented May 31, 2024

Why? -
ok i saw the issue #20457 (microchips droping the bit field support)
I think bitfields are more legible, so there must be a reason.

I'm not happy either but that's a needed step to tackle on our side if we want to add support to newer MCUs from Microchip at some point.

cpu/samd5x/cpu.c Outdated Show resolved Hide resolved
@@ -440,19 +440,22 @@ static int _send(candev_t *candev, const struct can_frame *frame)

if (frame->can_id & CAN_EFF_FLAG) {
DEBUG_PUTS("Extended ID");
dev->msg_ram_conf.tx_fifo_queue[can_mm.put].TXBE_0.bit.ID = frame->can_id & CAN_EFF_MASK;
dev->msg_ram_conf.tx_fifo_queue[can_mm.put].TXBE_0.bit.XTD = 1;
dev->msg_ram_conf.tx_fifo_queue[can_mm.put].TXBE_0.reg |= CAN_TXBE_0_ID(frame->can_id & CAN_EFF_MASK)
Copy link
Contributor

Choose a reason for hiding this comment

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

if bitfield operations are removed make them one write

assembble the whole id -> then write it

Comment on lines 868 to 870
uint8_t tx_err_cnt = (uint8_t)(dev->conf->can->ECR.reg & CAN_ECR_TEC_Msk);
DEBUG("tx error counter = %u\n", tx_err_cnt);
uint8_t rx_err_cnt = (uint8_t)dev->conf->can->ECR.bit.REC;
uint8_t rx_err_cnt = (uint8_t)((dev->conf->can->ECR.reg & CAN_ECR_REC_Msk)
Copy link
Contributor

Choose a reason for hiding this comment

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

one read

Comment on lines 807 to 810
uint8_t tx_err_cnt = (uint8_t)(dev->conf->can->ECR.reg & CAN_ECR_TEC_Msk);
DEBUG("tx error counter = %u\n", tx_err_cnt);
uint8_t rx_err_cnt = (uint8_t)dev->conf->can->ECR.bit.REC;
uint8_t rx_err_cnt = (uint8_t)((dev->conf->can->ECR.reg & CAN_ECR_REC_Msk)
>> CAN_ECR_REC_Pos);
Copy link
Contributor

Choose a reason for hiding this comment

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

one read

@kfessel
Copy link
Contributor

kfessel commented May 31, 2024

but the registers also changed name and from being a union of bitfield and reg to just a uint

@dylad
Copy link
Member Author

dylad commented May 31, 2024

but the registers also changed name and from being a union of bitfield and reg to just a uint

Yes. But I'd like to proceed in small steps for now. I am expecting breakages and it will be easier to deal with those if we do it step by step.
See #20457 for the step details.

@dylad dylad force-pushed the pr/cpu/samd5x/avoid_bitfields_reg branch from 2de511f to 6324c2a Compare June 4, 2024 09:29
@benpicco benpicco added the CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR label Jun 4, 2024
@dylad
Copy link
Member Author

dylad commented Jun 4, 2024

@kfessel I've added a variable here and there to avoid multiple read of the same register. I hope I didn't miss some.

@riot-ci
Copy link

riot-ci commented Jun 4, 2024

Murdock results

✔️ PASSED

26b3583 cpu/samd5x: avoid the use of bitfield in periph

Success Failures Total Runtime
10178 0 10178 16m:57s

Artifacts

cpu/samd5x/cpu.c Outdated Show resolved Hide resolved
Copy link
Contributor

@kfessel kfessel left a comment

Choose a reason for hiding this comment

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

we need more of this (.reg & REG_Msk) >> REG_Pos

seems like the other way around is hidden in these MACROS (i did not check)

I for sure have missed some places where this is needed.

@ microchip: this makes the code so much easier to read and write

cpu/samd5x/periph/can.c Outdated Show resolved Hide resolved
cpu/samd5x/periph/can.c Outdated Show resolved Hide resolved
cpu/samd5x/periph/can.c Outdated Show resolved Hide resolved
cpu/samd5x/periph/can.c Outdated Show resolved Hide resolved
cpu/samd5x/periph/can.c Show resolved Hide resolved
@dylad
Copy link
Member Author

dylad commented Jun 6, 2024

@kfessel I've addressed the new round of review.

cpu/samd5x/periph/can.c Outdated Show resolved Hide resolved
Comment on lines +876 to +882
uint32_t reg = dev->conf->can->ECR.reg;
uint8_t tx_err_cnt = (uint8_t) (reg & CAN_ECR_TEC_Msk);
DEBUG("tx error counter = %u\n", tx_err_cnt);
uint8_t rx_err_cnt = (uint8_t)dev->conf->can->ECR.bit.REC;
uint8_t rx_err_cnt = (uint8_t)((reg & CAN_ECR_REC_Msk) >> CAN_ECR_REC_Pos);
DEBUG("rx error counter = %u\n", rx_err_cnt);
/* Check the CAN error type */
uint8_t error_code = (uint8_t)dev->conf->can->PSR.bit.LEC;
uint8_t error_code = (uint8_t)(dev->conf->can->PSR.reg & CAN_PSR_LEC_Msk);
Copy link
Contributor

Choose a reason for hiding this comment

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

it is allready done here so copy

@dylad
Copy link
Member Author

dylad commented Jun 20, 2024

Latest round of review was addressed.

@dylad
Copy link
Member Author

dylad commented Jun 26, 2024

May I squash this one ?

@kfessel
Copy link
Contributor

kfessel commented Jun 27, 2024

look good please squash
look good

Signed-off-by: Dylan Laduranty <dylan.laduranty@mesotic.com>
@dylad dylad force-pushed the pr/cpu/samd5x/avoid_bitfields_reg branch from 43bbcac to bfadc44 Compare June 27, 2024 19:51
@dylad
Copy link
Member Author

dylad commented Jun 27, 2024

Rebased and squashed.

Copy link
Member

@maribu maribu left a comment

Choose a reason for hiding this comment

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

Thx a bunch!

This will actually result in more efficient machine code, as a few instances of subsequent accesses of bit-fields of the same word in memory (marked as volatile) were replaced by loading that word into a temporary (non volatile) variable, from which the fields were extracted via bit-masks. The volatile qualifier prevents the optimizer to combine memory accesses. But in the new code, the temporary variable could be allocated as a register resulting in fewer memory accesses. Quite cool!

I have an style suggestion inline. Please squash directly if you agree, or just hit merge if you don't.

Comment on lines +221 to +222
const uint32_t flags = (OSCCTRL_DPLLSTATUS_CLKRDY | OSCCTRL_DPLLSTATUS_LOCK);
while (!((OSCCTRL->Dpll[idx].DPLLSTATUS.reg & flags) == flags)) {}
Copy link
Member

Choose a reason for hiding this comment

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

This will even be more efficient. I believe normally, the optimizer would combine the two bit-field accesses on the same word to a single memory access. But since those registers are marked as volatile, the compiler is not allowed to combine memory accesses.

cpu/samd5x/periph/can.c Outdated Show resolved Hide resolved
@@ -708,26 +725,30 @@ static void _isr(candev_t *candev)

uint16_t rx_get_idx = 0;
uint16_t rx_put_idx = 0;
rx_get_idx = (dev->conf->can->RXF0S.reg >> CAN_RXF0S_F0GI_Pos) & 0x3F;
uint32_t reg = dev->conf->can->RXF0S.reg;
Copy link
Member

Choose a reason for hiding this comment

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

Again, this will produce more efficient machine code :)

@@ -847,12 +873,13 @@ static void _isr(candev_t *candev)
DEBUG_PUTS("protocol error in arbitration phase");
dev->conf->can->IR.reg |= CAN_IR_PEA;
/* Extract the Tx and Rx error counters */
uint8_t tx_err_cnt = (uint8_t)dev->conf->can->ECR.bit.TEC;
uint32_t reg = dev->conf->can->ECR.reg;
Copy link
Member

Choose a reason for hiding this comment

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

And another instance of better machine code :)

@dylad dylad force-pushed the pr/cpu/samd5x/avoid_bitfields_reg branch from bfadc44 to f36e6eb Compare June 28, 2024 09:09
@maribu maribu added this pull request to the merge queue Jun 28, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jun 28, 2024
@dylad dylad force-pushed the pr/cpu/samd5x/avoid_bitfields_reg branch from f36e6eb to 8e2369f Compare June 28, 2024 16:06
@dylad dylad enabled auto-merge June 28, 2024 16:07
@dylad
Copy link
Member Author

dylad commented Jun 28, 2024

Fixed extra character added by mistake after a semicolon.

@dylad dylad added this pull request to the merge queue Jun 28, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Jun 28, 2024
Signed-off-by: Dylan Laduranty <dylan.laduranty@mesotic.com>
@dylad dylad force-pushed the pr/cpu/samd5x/avoid_bitfields_reg branch from 8e2369f to 26b3583 Compare June 29, 2024 11:26
@dylad dylad enabled auto-merge June 29, 2024 11:28
@dylad dylad added this pull request to the merge queue Jun 29, 2024
Merged via the queue into RIOT-OS:master with commit 6b7dd90 Jun 29, 2024
25 checks passed
@maribu
Copy link
Member

maribu commented Jun 29, 2024

🎉

@dylad
Copy link
Member Author

dylad commented Jun 29, 2024

Thanks for the reviews !

With this one merged, the first step of the migration is now completed.

@dylad dylad deleted the pr/cpu/samd5x/avoid_bitfields_reg branch June 29, 2024 18:33
@mguetschow mguetschow added this to the Release 2024.07 milestone Jul 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: cpu Area: CPU/MCU ports CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Platform: ARM Platform: This PR/issue effects ARM-based platforms
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants