Added missing USB (and CRC) related code for STM32C0xx port

Use this forum for requesting small changes in ChibiOS. Large changes should be discussed in the development forum. This forum is NOT for support.
Engemil
Posts: 31
Joined: Thu Dec 19, 2024 12:50 am
Has thanked: 9 times
Been thanked: 7 times

Added missing USB (and CRC) related code for STM32C0xx port

Postby Engemil » Tue Aug 19, 2025 10:22 pm

Hi!

I got USB working on a Nucleo-C071RB board. I've added missing part for USB (and also CRC) to the STM32C0xx port, and a change in the STM32C071RB demo. All of it is simply missing USB (and CRC) code copied from the STM32G0xx port, and is validated with both STM32C071RB and STM32G0B1RE reference manuals.

For a Github based view of the changes, I made a temporary fork and commit on Github. It is based on stable_21.11.x branch: https://github.com/engemil/chibios_stm3 ... 77d8256b64

CHANGES MADE:

os/hal/ports/STM32/STM32C0xx/stm32_isr.h (line 129 to 137)

Code: Select all

/*
 * USB units.
 */
#define STM32_USB1_HP_HANDLER               Vector60
#define STM32_USB1_LP_HANDLER               Vector60
#define STM32_USB1_HP_NUMBER                8
#define STM32_USB1_LP_NUMBER                8


os/hal/ports/STM32/STM32C0xx/stm32_rcc.h (line 611 to 666)

Code: Select all

 * @name    USB peripheral specific RCC operations
 * @{
 */
/**
 * @brief   Enables the USB peripheral clock.
 *
 * @param[in] lp        low power enable flag
 *
 * @api
 */
#define rccEnableUSB(lp) rccEnableAPBR1(RCC_APBENR1_USBEN, lp)

/**
 * @brief   Disables the USB peripheral clock.
 *
 * @api
 */
#define rccDisableUSB() rccDisableAPBR1(RCC_APBENR1_USBEN)

/**
 * @brief   Resets the USB peripheral.
 *
 * @api
 */
#define rccResetUSB() rccResetAPBR1(RCC_APBRSTR1_USBRST)
/** @} */

/**
 * @name    CRC peripheral specific RCC operations
 * @{
 */
/**
 * @brief   Enables the CRC peripheral clock.
 *
 * @param[in] lp        low power enable flag
 *
 * @api
 */
#define rccEnableCRC(lp) rccEnableAHB(RCC_AHBENR_CRCEN, lp)

/**
 * @brief   Disables the CRC peripheral clock.
 *
 * @api
 */
#define rccDisableCRC() rccDisableAHB(RCC_AHBENR_CRCEN)

/**
 * @brief   Resets the CRC peripheral.
 *
 * @api
 */
#define rccResetCRC() rccResetAHB(RCC_AHBRSTR_CRCRST)
/** @} */


demos/STM32/RT-STM32C071RB-NUCLEO64/cfg/mcuconf.h (line 191)

Code: Select all

- #define STM32_USB_USB1_LP_IRQ_PRIORITY      14
+ #define STM32_USB_USB1_LP_IRQ_PRIORITY      3

(Update: I just read the "Suggestions for submitting patches", and I noticed to avoid changes to configuration files, hehe)

I haven't included the demo, however it is a simple print "hello world" over the Serial USB driver. It based on testhal/STM32/multi/USB_CDC/ , and is manually put together in my VS Code development environment. Note that the demo avoided using chThdSleepMilliseconds(), for now.

User avatar
Giovanni
Site Admin
Posts: 14704
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1146 times
Been thanked: 960 times

Re: Added missing USB (and CRC) related code for STM32C0xx port

Postby Giovanni » Wed Aug 20, 2025 4:27 am

It must be a stack overflow issue, try increasing stacks in the makefile.

Giovanni

Engemil
Posts: 31
Joined: Thu Dec 19, 2024 12:50 am
Has thanked: 9 times
Been thanked: 7 times

Re: Added missing USB (and CRC) related code for STM32C0xx port

Postby Engemil » Wed Aug 20, 2025 9:18 am

Hi Giovanni!

I tried to increase the stack (from original 0x400, doubling each step, 0x800, 0x1000, 0x2000) in the Makefile:

Code: Select all

# Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),)
  USE_PROCESS_STACKSIZE = 0x2000
endif

# Stack size to the allocated to the Cortex-M main/exceptions stack. This
# stack is used for processing interrupts and exceptions.
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
  USE_EXCEPTIONS_STACKSIZE = 0x2000
endif


However, it seem to not to fix the bug. I can confirm it works when i comment out the chThdSleepMilliseconds() calls. Here is my main.c-file for example code:

Code: Select all

#include "ch.h"
#include "hal.h"
#include "chprintf.h"

#include "portab.h"
#include "usbcfg.h"

int main(void) {
    halInit();
    chSysInit();

    portab_setup();

    sduObjectInit(&SDU1);
    sduStart(&SDU1, &serusbcfg);

    usbDisconnectBus(serusbcfg.usbp);
    //chThdSleepMilliseconds(1500);
    usbStart(serusbcfg.usbp, &usbcfg);
    usbConnectBus(serusbcfg.usbp);

    while (true) {
        chprintf((BaseSequentialStream*)&PORTAB_SDU1, "Hello World!\r\n");
        palToggleLine(LINE_LED_GREEN);
        //chThdSleepMilliseconds(500);
    }
}

Engemil
Posts: 31
Joined: Thu Dec 19, 2024 12:50 am
Has thanked: 9 times
Been thanked: 7 times

Re: Added missing USB (and CRC) related code for STM32C0xx port

Postby Engemil » Fri Aug 22, 2025 12:00 am

I've come to see that it gets stuck in the "while(true)"-loop of vt_insert_first()-function (os/rt/src/chvt.c).

I can see the if-condition never return true, screenshot added as part of debugging:

Code: Select all

if (likely(chTimeDiffX(now, newnow) < delay)) {
  break;
}


I'll try to look further during this weekend, to understand why this condition isn't met

Side note: Should I make a new thread about this under "debug"?
Attachments
Screenshot from 2025-08-13 21-52-45.png
Screenshot from 2025-08-13 21-52-45.png (257 Bytes) Viewed 2400 times

User avatar
Giovanni
Site Admin
Posts: 14704
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1146 times
Been thanked: 960 times

Re: Added missing USB (and CRC) related code for STM32C0xx port

Postby Giovanni » Fri Aug 22, 2025 5:53 am

If you suspect a bug then put a thread under "bug reports", What timer are you using for virtual timers? if it is a 16 bits timer make sure to specify 16 as system time width in chconf.h.

Giovanni

Engemil
Posts: 31
Joined: Thu Dec 19, 2024 12:50 am
Has thanked: 9 times
Been thanked: 7 times

Re: Added missing USB (and CRC) related code for STM32C0xx port

Postby Engemil » Fri Aug 22, 2025 10:09 pm

Hi Giovanni!

I'm using the default demo project parameters for system timers settings:

Code: Select all

#define CH_CFG_ST_RESOLUTION                32
#define CH_CFG_ST_FREQUENCY                 10000
#define CH_CFG_INTERVALS_SIZE               32
#define CH_CFG_TIME_TYPES_SIZE              32



Correction of the previous post:

When it comes to the if-condition for the "while(loop)" of vt_insert_first()-function

Code: Select all

if (likely(chTimeDiffX(now, newnow) < delay)) {
  break;
}


- On STM32C071RB, I get stuck (not meeting the if-conditon) in the while(true)-loop, when I us "debug stepping" to see each step until this point.
- On STM32C071RB, the if-condition gets met if I just let it run at normal speed. It is validated by having a breakpoint on the "break;".
- Note that on STM32F401RE, it does not get stuck in the while(true)-loop, even if I do "debug stepping".

Further more

I can how see that the system reaches chSchGoSleepS(newstate) in:

Code: Select all

msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout) {
  thread_t *tp = __instance_get_currthread(currcore);

  chDbgCheckClassS();

  if (TIME_INFINITE != timeout) {
    virtual_timer_t vt;

    chVTDoSetI(&vt, timeout, __sch_wakeup, (void *)tp);
    chSchGoSleepS(newstate);
    if (chVTIsArmedI(&vt)) {
      chVTDoResetI(&vt);
    }
  }
  else {
    chSchGoSleepS(newstate);
  }

  return tp->u.rdymsg;
}


And then it gets stuck on the port_wait_for_interrupt() (chibios/os/common/ports/ARMv6-M/chcore.h-file).

I'm back to zero, however, it's interesting to see how the problematic chip (STM32C071RB) doesn't handle well when "debug stepping", in comparison to the good chip (STMF401RE).

I'll try to see what else I discover, to be able to pinpoint if it is a bug or not.

Engemil
Posts: 31
Joined: Thu Dec 19, 2024 12:50 am
Has thanked: 9 times
Been thanked: 7 times

Re: Added missing USB (and CRC) related code for STM32C0xx port

Postby Engemil » Fri Aug 22, 2025 10:24 pm

I just discovered something!

I noticed that PORT_SUPPORTS_RT for ARMv6-M was defined as FALSE (in os/common/ports/ARMv6-M/chcore.h). And a quick consulting with an AI chat (always take it with a pinch of salt), I learned it is used for enabling tickless mode, virtual timing, etc.

For this I changed CH_CFG_ST_TIMEDELTA (from default 2) to 0 for the classic periodic tick, and now my code works!


I suppose this means that CH_CFG_ST_TIMEDELTA should have been originally 0 for the demos, as the ARMv6-M architecture does not support tickless mode?

And did you manage to make tickless mode work on a STM32C031xx?

User avatar
Giovanni
Site Admin
Posts: 14704
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1146 times
Been thanked: 960 times

Re: Added missing USB (and CRC) related code for STM32C0xx port

Postby Giovanni » Sat Aug 23, 2025 5:14 am

Hi,

Setting timedelta to zero disables the tickless mode, it is a fallback to classic tick mode (in tick mode you should not exceed 1000Hz tick frequency). Tickless is working for all other M0 devices so I assume it is some difference in timer handling. See in halconf.h which timer is used for system and verify it is a 32 bits timer on that device, this could be the cause.

About the debug freeze, this could be a wrong initialization in the ST driver, all STM32s have different freeze bits to be initialized.

Giovanni

Engemil
Posts: 31
Joined: Thu Dec 19, 2024 12:50 am
Has thanked: 9 times
Been thanked: 7 times

Re: Added missing USB (and CRC) related code for STM32C0xx port

Postby Engemil » Sat Aug 23, 2025 6:08 pm

Hi Giovanni!

Yeah, you are on to something there. Now I understand the config files (a bit) better!

My mcuconf.h-file was using TIM2 timer, which is the only 32-bit timer on STM32C071RB.

I changed back to tickless mode and I changed the timer to TIM17 (same as the STM32C031C6 demo example).

mcuconf.h

Code: Select all

#define STM32_ST_USE_TIMER                  17 // previous: 2


chconf.h

Code: Select all

/**
 * @brief   System time counter resolution.
 * @note    Allowed values are 16, 32 or 64 bits.
 */
#if !defined(CH_CFG_ST_RESOLUTION)
#define CH_CFG_ST_RESOLUTION                16 // previous: 32
#endif

/**
 * @brief   System tick frequency.
 * @details Frequency of the system timer that drives the system ticks. This
 *          setting also defines the system tick time unit.
 */
#if !defined(CH_CFG_ST_FREQUENCY)
#define CH_CFG_ST_FREQUENCY                 10000
#endif

/**
 * @brief   Time intervals data size.
 * @note    Allowed values are 16, 32 or 64 bits.
 */
#if !defined(CH_CFG_INTERVALS_SIZE)
#define CH_CFG_INTERVALS_SIZE               16 // previous: 32
#endif

/**
 * @brief   Time types data size.
 * @note    Allowed values are 16 or 32 bits.
 */
#if !defined(CH_CFG_TIME_TYPES_SIZE)
#define CH_CFG_TIME_TYPES_SIZE              16 // previous: 32
#endif


Result: Using sleep functions works now.

I tried to check if the STM32C071RB errata sheet had any info related to TIM2, but nothing out of ordinary for TIM2.

Hmmm, could this be considered a bug?

User avatar
Giovanni
Site Admin
Posts: 14704
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1146 times
Been thanked: 960 times

Re: Added missing USB (and CRC) related code for STM32C0xx port

Postby Giovanni » Sun Aug 24, 2025 5:15 am

If TIM2 is present and does not work then it could be a bug, it works for all other devices.

16 bits time is OK but 32 bits are recommended working at high resolutions.

Giovanni


Return to “Small Change Requests”

Who is online

Users browsing this forum: No registered users and 35 guests