[DEV] RP2040 support

This forum is dedicated to feedback, discussions about ongoing or future developments, ideas and suggestions regarding the ChibiOS projects are welcome. This forum is NOT for support.
User avatar
FXCoder
Posts: 369
Joined: Sun Jun 12, 2016 4:10 am
Location: Sydney, Australia
Has thanked: 170 times
Been thanked: 125 times

Re: [DEV] RP2040 support

Postby FXCoder » Wed Mar 31, 2021 2:05 pm

Hi,
2 x pico arrived from Element14 today along with other RPi kit.
Might have a play over the weekend.
--
Bob

User avatar
Giovanni
Site Admin
Posts: 13751
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 922 times
Been thanked: 787 times
Contact:

Re: [DEV] RP2040 support

Postby Giovanni » Wed Mar 31, 2021 2:24 pm

Great, any help is welcome.

I am proceeding with the multi-core implementation, the demo already starts both cores but ChibiOS runs on core zero the other core just loops into its main() function. The problem is the "ST" driver, it needs changes because each OS instance needs its own timer interrupt.

I don't foresee problems, just normal changes and coding, this is really the platform I needed to demonstrate full SMP capability in RT.

Giovanni

steved
Posts: 776
Joined: Fri Nov 09, 2012 2:22 pm
Has thanked: 10 times
Been thanked: 123 times

Re: [DEV] RP2040 support

Postby steved » Thu Apr 01, 2021 10:22 pm

Not sure how much you read the Raspberry Pi forums, so thought I'd just highlight that the hardware divider status needs saving in an interrupt (or the divider use gets placed in a critical section), in case that hadn't come to your attention.
https://www.raspberrypi.org/forums/view ... 5&t=306717 for chapter and verse, and also https://forums.freertos.org/t/extending ... 0/12047/13 from a freertos perspective.

Hope to clear the decks enough to try this soon.

User avatar
Giovanni
Site Admin
Posts: 13751
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 922 times
Been thanked: 787 times
Contact:

Re: [DEV] RP2040 support

Postby Giovanni » Fri Apr 02, 2021 6:21 am

I have not used the HW divider yet, I am using the usual GCC settings.

I think the best approach is to not save the divider state into the thread context (it would take lots of RAM and slow down the context switch) but use the divider within a critical section.

BTW, their hw_divider_save_state() function apparently does not save the signed registers (are signed and unsigned mirrored registers??), only the unsigned ones so the state seems to be not fully saved.... I also wonder if that branch goes in the right place.

Code: Select all

regular_func_with_section hw_divider_save_state
    push {r4, r5, lr}
    ldr r5, =SIO_BASE
    ldr r4, [r5, #SIO_DIV_CSR_OFFSET]
    # wait for results as we can't save signed-ness of operation
1:
    lsrs r4, #SIO_DIV_CSR_READY_SHIFT_FOR_CARRY
    bcc 1b
    ldr r1, [r5, #SIO_DIV_UDIVIDEND_OFFSET]
    ldr r2, [r5, #SIO_DIV_UDIVISOR_OFFSET]
    ldr r3, [r5, #SIO_DIV_REMAINDER_OFFSET]
    ldr r4, [r5, #SIO_DIV_QUOTIENT_OFFSET]
    stmia r0!, {r1-r4}
    pop {r4, r5, pc}


I will look into saving the context with an option later but probably the above code is not it.

Giovanni

User avatar
Giovanni
Site Admin
Posts: 13751
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 922 times
Been thanked: 787 times
Contact:

Re: [DEV] RP2040 support

Postby Giovanni » Fri Apr 02, 2021 8:47 am

Well... dual core mode just worked at first attempt...

In the current demo there are 2 OS instances, one for each core, core zero runs a shell thread, core one runs the blinker thread.

Note that the current dual core mode is "decoupled", meaning that the two OS instances cannot work on shared objects (semaphores, mutexes, etc) so it is like having two separate MCUs, communication is possible using HW mechanisms like: shared memory, HW spinlocks, FIFOs.

Next is the full SMP mode where multiple OS instances can also share OS objects and do cross-core synchronization transparently, this will need some more work in the port layer in order to implement spinlocks and cross-cores notifications.

There is still work to do in the HAL also, it needs to be made core-aware, this is the paradigm I plan to implement:

- Only core zero performs halInit().
- The core calling xxxStart() is the one doing IRQ processing for that driver instance, callbacks would be served by that core.
- In decoupled mode only the core that performed xxxStart() can use that driver instance, in SMP mode all cores can share access.

Of course there are lots of other problems yet to be discovered, there is fun ahead for everybody.

Anyway, multi-core ChibiOS/RT had its first run :)

Giovanni

User avatar
FXCoder
Posts: 369
Joined: Sun Jun 12, 2016 4:10 am
Location: Sydney, Australia
Has thanked: 170 times
Been thanked: 125 times

Re: [DEV] RP2040 support

Postby FXCoder » Sat Apr 03, 2021 2:47 am

Hi,
BTW I am up and running with the 2 x Pico CMSIS-DAP debug setup.
I just did an "External tool" to start openocd and then a gdb start with debug.
I'll put that together into a single debug (MCU in Eclipse allows selecting different tools per project - nice since I can specify the RPi project openocd and not mess with any of my other projects openocd).

Anyway nice work on getting to dual core running shell and blinky individually!

Since we have similar IPC requirements for STM32WBx5 & STM32WLx5 then the HAL for an "IPCC" could/should be common with RP2040?
So far I have a simple driver for STM32 IPCC with basic LLD and skeletal HLD.
The STM32 IPCC peripheral is a simple channel/interrupt manager so it is just a traffic cop in essence.
The actual IPC messages in Cube uses mailboxes in shared RAM for the data passing.
My thought is the mailbox/RAM should be abstracted at the HLD of IPCC and then at the LLD the shared memory, data passing, HSEM or whatever would be dealt with.
The WB55 introduces a rigid definition of the IPCC channels for specific protocol messages/data passing since the CPU2 runtimes are ST binaries only and not compiled in a project.
The WL55 is rather more free form since the Semtech SX127x driver is just linked in to the main code and so one "could" use different IPCC definitions versus that of Cube.

I've not read the RP2040 data sheet in detail so not clear on any IPC mechanism that is entertained therein.
--
Bob

User avatar
Giovanni
Site Admin
Posts: 13751
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 922 times
Been thanked: 787 times
Contact:

Re: [DEV] RP2040 support

Postby Giovanni » Sat Apr 03, 2021 7:25 am

I am not sure that something so STM32-specific should have a split HLD/LLD, perhaps it should be kept as an STM32-specific driver like DMAs, RCC etc

About inter-core communication, there is no standard, RP2040 has FIFOs ad HW semaphores, STM32H7 has quite different HW semaphores (more complex, not better IMHO) and I have seen also others mechanisms like mailboxes etc. Because of this variability I decided to create a specific RTOS port for RP2040, I am not yet confident enough to be able to create a good abstraction on this functionality.

About the WB contributed port, I am busy with this SMP thing right now, I consider it "strategic" so it is getting priority, if you want to start the review and code integration in trunk please go ahead, this kind of things are low risk, other ports are not impacted.

Giovanni

User avatar
Giovanni
Site Admin
Posts: 13751
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 922 times
Been thanked: 787 times
Contact:

Re: [DEV] RP2040 support

Postby Giovanni » Sat Apr 03, 2021 12:35 pm

Full SMP mode is complete and, apparently, it works (work=does not obviously crash nor it goes in deadlock on spinlocks) and executes the test suite.

Now the problem is to decide how to validate it, I think some kind of stress test is required using shared objects and lot of randomization.

In SMP mode it will become apparent the difference between chSysLock() and simply disabling interrupts (which is chSysSuspend()), the lock primitive is multicore-aware, it disables interrupts and takes the kernel spinlock, it implements a critical section for both cores. So something like:

Code: Select all

chSysLock();
i++;
chSysUnlock();


Makes sure that "i" is incremented atomically even if both cores access it, simply disabling interrupts would not guarantee this. Basically the SMP logic has been in place in ChibiOS during the last 10 years, there just was no need for it... until now. Now we can enjoy API compatibility, multicore SMP is fully transparent, "I" and "S" functions paradigm works as usual.

Giovanni

User avatar
FXCoder
Posts: 369
Joined: Sun Jun 12, 2016 4:10 am
Location: Sydney, Australia
Has thanked: 170 times
Been thanked: 125 times

Re: [DEV] RP2040 support

Postby FXCoder » Sat Apr 03, 2021 1:50 pm

Very nice.
Testing will be "interesting".

BTW a small fix for c1_main.
Init the shell (event source) else the thread crashes on ^D/exit.
--
Bob

Code: Select all

  while (true) {
    shellInit();
    thread_t *shelltp = chThdCreateFromHeap(NULL, SHELL_WA_SIZE,
                                            "shell", NORMALPRIO + 1,
                                            shellThread, (void *)&shell_cfg1);
    chThdWait(shelltp);               /* Waiting termination.             */
    chThdSleepMilliseconds(500);
  }

User avatar
FXCoder
Posts: 369
Joined: Sun Jun 12, 2016 4:10 am
Location: Sydney, Australia
Has thanked: 170 times
Been thanked: 125 times

Re: [DEV] RP2040 support

Postby FXCoder » Sun Apr 04, 2021 3:27 pm

Hi,
Been doing a bit of testing.
I implemented my integrated shell + trace message (aka console) into a fork of the RP project.
There were a few things to deal with relating to Channel Events that aren't there for SIO.
Anyway that is worked around for the present.
All seems to be working OK although I tried adding the core ID to each main thread trace message and didn't get the expected result.
Added as follows for main:

Code: Select all

  /*
   * Normal main() thread activity, in this demo it does nothing except
   * sleeping in a loop.
   */
  while (true) {
    chThdSleepMilliseconds(2000);
    CTRACE(TL_INF, TS_MAIN, "Main (C0) running on core %d", port_get_core_id());
  }
 


And for c1_main:

Code: Select all

  /*
   * Activates the Serial or SIO driver using the default configuration.
   */
  sioStart(&SIOD1, NULL);
  sioStartOperation(&SIOD1, NULL);

  /* Start console and trace message system. */
  (void) sysStartConsole((BaseSequentialStream *)&SIOD1);
  CTRACE(TL_INF, TS_INIT, "Console startup");
  /*
   * Normal main() thread activity, in this demo it does nothing except
   * sleeping in a loop (re)spawning a shell.
   */
  while (true) {
//    shellInit();
//    thread_t *shelltp = chThdCreateFromHeap(NULL, SHELL_WA_SIZE,
//                                            "shell", NORMALPRIO + 1,
//                                            shellThread, (void *)&shell_cfg1);
//    chThdWait(shelltp);               /* Waiting termination.             */
    chThdSleepMilliseconds(2000);
    CTRACE(TL_INF, TS_MAIN, "Main (C1) running on core %d", port_get_core_id());
  }
}

Interestingly the core ID is correct initially for core 0 main but then becomes 1 thereafter as follows:

Code: Select all

[       1.000][INFO ][   c1_main.c 0106][         main] INIT > Console startup
[       3.000][INFO ][      main.c 0102][         main] MAIN > Main (C0) running on core 0
[       3.004][INFO ][   c1_main.c 0121][         main] MAIN > Main (C1) running on core 1
[       5.005][INFO ][      main.c 0102][         main] MAIN > Main (C0) running on core 1
[       5.013][INFO ][   c1_main.c 0121][         main] MAIN > Main (C1) running on core 1
[       7.011][INFO ][      main.c 0102][         main] MAIN > Main (C0) running on core 1
[       7.019][INFO ][   c1_main.c 0121][         main] MAIN > Main (C1) running on core 1


I thought it may be due to SIO->CPUID not being a volatile in port_get_core_id() but that doesn't really make sense and changing it didn't change the behaviour.
Thoughts?
--
Bob


Return to “Development and Feedback”

Who is online

Users browsing this forum: No registered users and 1 guest