Author Topic: CH32V203 + FreeRTOS + USB CDC  (Read 2248 times)

0 Members and 1 Guest are viewing this topic.

Offline ali_asadzadehTopic starter

  • Super Contributor
  • ***
  • Posts: 1969
  • Country: ca
CH32V203 + FreeRTOS + USB CDC
« on: December 31, 2024, 03:24:42 pm »
Hi,
In my quest to be able to have FreeRTOS + USB CDC I got so many problems and here How I'm going there,
I created a new project in MRS for CH32V203 with FreeRTOS support.

Then I enable timer 3 for free running to enable Delay_Us in debug.c module
the code for the time is like this

Code: [Select]
    //enable us delay
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );
    TIM_TimeBaseInitTypeDef myTim3 ={0};
    myTim3.TIM_Prescaler = SystemCoreClock / 1000000 - 1;
    myTim3.TIM_Period = 0xFFFF;
    TIM_TimeBaseInit( TIM3, &myTim3);
    TIM_Cmd(TIM3, ENABLE);
    TIM_SetCounter(TIM3,0);


Code: [Select]
void Delay_Us(uint32_t n)
{
    TIM3->CNT = 0;
    while(TIM3->CNT <n);
}

and modify the Delay_Ms in debug.c to use vTaskDelay

then I add the USBLIB and UART files from the Simulate CDC example from ch32v20x\EVT\EXAM\USB\USBD\SimulateCDC github repo to the project

then I add these codes to the task2_task function

Code: [Select]
RCC_Configuration( );
TIM2_Init( );
UART2_Init( 1, DEF_UARTx_BAUDRATE, DEF_UARTx_STOPBIT, DEF_UARTx_PARITY );
   
Set_USBConfig();
USB_Init();    
USB_Interrupts_Config();   

    while(1)
    {
        UART2_DataRx_Deal( );
        UART2_DataTx_Deal( );
        vTaskDelay(1);
    }

then I add  void TIM2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast"))); to the ch32v20x_it.c file
and add these codes there


Code: [Select]
/*********************************************************************
 * @fn      TIM2_IRQHandler
 *
 * @brief   This function handles TIM2 exception.
 *
 * @return  none
 */
void TIM2_IRQHandler( void )
{
    GET_INT_SP();
    portDISABLE_INTERRUPTS();
    /* uart timeout counts */
    Uart.Rx_TimeOut++;
    Uart.USB_Up_TimeOut++;

    /* clear status */
    TIM2->INTFR = (uint16_t)~TIM_IT_Update;

    portENABLE_INTERRUPTS();
    FREE_INT_SP();
}

It does not work, I will get constant crashes and I noticed something maybe would change SysTick->CMP value, you can take a look at the modified code, any Ideas on what am I doing wrong?
ASiDesigner, Stands for Application specific intelligent devices
I'm a Digital Expert from 8-bits to 64-bits
 

Offline peter-h

  • Super Contributor
  • ***
  • Posts: 4409
  • Country: gb
  • Doing electronics since the 1960s...
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #1 on: January 01, 2025, 09:43:23 am »
IME, FreeRTOS is very straightforward to get going and to use.

Make sure this is solid first. There is an issue with Systick. From my project notes:

INTERRUPTS

Interrupt priority is normally set with HAL_NVIC_SetPriority().

Note that interrupts are not disabled with portENTER_CRITICAL(). That just stops RTOS task switching. If you really want a traditional DI/EI, use CPSID / CPSIE assembler.

SysTick runs at 1kHz and drives the RTOS.

The Systick interrupt is set up in the RTOS code in vPortSetupTimerInterrupt(). Frequency and priority are set by configTICK_RATE_HZ (1kHz), and configLIBRARY_LOWEST_INTERRUPT_PRIORITY.

The handler for the Systick interrupt is xPortSysTickHandler().

TIM6 runs at 1kHz and drives the 1kHz tick which is used for the various timers outside of the RTOS.

The reason why SysTick could not be used for both above is due to an interrupt priority issue and this solution was recommended by FreeRTOS. See here
https://www.digikey.com/en/maker/projects/getting-started-with-stm32-introduction-to-freertos/ad275395687e4d85935351e16ec575b1
and here
https://community.st.com/s/question/0D50X0000A4nQxpSQE/when-freertos-is-used-it-is-strongly-recommended-to-use-a-hal-time-base-source-other-than-the-systick-
In general, because tasks are scheduled from the SysTick interrupt at a low priority which may call HAL functions that use delays and timeouts which need to come from a higher priority timer interrupt.
The RTOS sets SysTick priority to the lowest (15).

The priority of TIM6 interrupt is set when calling InitTIM6Tick() (in main.c) and currently is set to 1. This is a high priority.

USB is entirely interrupt driven, with foreground code doing initialisation and VCP debugs.



USB CDC (VCP) is immensely complicated. Do a search here; I posted various threads on USB in the past. Also ST USB code is buggy.
« Last Edit: January 01, 2025, 10:11:43 am by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 
The following users thanked this post: SteveThackery

Offline ali_asadzadehTopic starter

  • Super Contributor
  • ***
  • Posts: 1969
  • Country: ca
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #2 on: January 02, 2025, 11:40:49 am »
peter-h thanks for the feedback, I'm trying to port FreeRTOS to use another timer and see if it can coexist with the CDC example.
ASiDesigner, Stands for Application specific intelligent devices
I'm a Digital Expert from 8-bits to 64-bits
 

Offline peter-h

  • Super Contributor
  • ***
  • Posts: 4409
  • Country: gb
  • Doing electronics since the 1960s...
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #3 on: January 02, 2025, 12:31:34 pm »
I suggest creating some RTOS tasks and make sure they run fine, use timers, etc, before diving into USB which is a massive chunk of code and so complicated that almost nobody understands it, and it is very hard to debug without a deep understanding of USB.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline ali_asadzadehTopic starter

  • Super Contributor
  • ***
  • Posts: 1969
  • Country: ca
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #4 on: January 04, 2025, 09:13:19 am »
I managed to port it, and I found the problem, we should convert every __attribute__((interrupt("WCH-Interrupt-fast"))) to __attribute__((interrupt())) so It would work,
why is that?

Also the next step is to remove the Actual physical UART bulshit and make it send and receive data in sram buffers, any Hints or ideas?
ASiDesigner, Stands for Application specific intelligent devices
I'm a Digital Expert from 8-bits to 64-bits
 
The following users thanked this post: pardo-bsso

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4831
  • Country: nz
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #5 on: January 04, 2025, 10:52:49 am »
I managed to port it, and I found the problem, we should convert every __attribute__((interrupt("WCH-Interrupt-fast"))) to __attribute__((interrupt())) so It would work,
why is that?

Because you didn't use WCH's modified compiler which adds their custom interrupt attribute.

It's possible to use it with a standard compiler with a bit more work, discussed in other posts here.
 
The following users thanked this post: pardo-bsso

Offline ali_asadzadehTopic starter

  • Super Contributor
  • ***
  • Posts: 1969
  • Country: ca
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #6 on: January 04, 2025, 12:49:35 pm »
thanks brucehoult, I'm using MounRiver, where can I find  the thread and what should I do?
Also I could manage to send and received data in sram buffers, using Termite terminal to test it, But when I use brays terminal, it does not work and the terminal program would crash, I have investigated it and noticed that the brays terminal would send data 1 bye in a single endpoint, and when I try to input single characters into the termite, the Receive endpoint would not get the second character!!! I'm totally confused and out of Ideas,

Here are the modified parts of the code

I defined these in the main.c
Code: [Select]
#define BUFFER_SIZE 64


uint8_t  UART_Rx_Buf[ 1024 ];  /* Serial port 2 receive data buffer */
uint8_t  UART_Tx_Buf[ 1024 ];  /* Serial port 2 transmit data buffer */

uint16_t txBufferIndex = 0;
uint16_t rxBufferIndex = 0;

extern uint8_t USBD_Endp3_Busy;

I modified the usb_endp.c for EP2_OUT_Callback like this


Code: [Select]
void EP2_OUT_Callback (void)
{
    uint32_t len;
    len = GetEPRxCount(EP2_OUT & 0x7F);
    PMAToUserBufferCopy(UART_Rx_Buf + rxBufferIndex, GetEPRxAddr(EP2_OUT & 0x7F), len);
    rxBufferIndex += len;
    SetEPRxValid(ENDP2);


}

this is the send function which is not working for more than 64 bytes for now and I do not know what has caused it

Code: [Select]
void send_data(uint8_t *buffer, uint16_t length)
{
    while (length > 0) {
        if (!USBD_Endp3_Busy) {
            uint16_t len = (length > BUFFER_SIZE) ? BUFFER_SIZE : length;
            USBD_ENDPx_DataUp(ENDP3, buffer, len);
            buffer += len;
            length -= len;
        }
    }
}

and this is the task2 body that would receive and answer some strings for testing


Code: [Select]
void task2_task(void *pvParameters)
{
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE );
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );
    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );

   
Set_USBConfig();
    USB_Init();    
  USB_Interrupts_Config();   

    // Wait for USB to be configured
    while (bDeviceState != CONFIGURED) {
        vTaskDelay(10);
    }

    while(1)
    {

        // Send data if available
        if (txBufferIndex > 0) {
            send_data(UART_Tx_Buf, txBufferIndex);
            txBufferIndex = 0;
        }

        // Receive data
        //if (rxBufferIndex > 0) {
        if(UART_Rx_Buf[0] =='N' && UART_Rx_Buf[1]== 'A' && UART_Rx_Buf[2]=='M'){
            // Process received data
            // Clear the buffer after processing
            memset(UART_Rx_Buf, 0, sizeof(UART_Rx_Buf));
            rxBufferIndex = 0;
            // Copy received data to transmit buffer
            memcpy(UART_Tx_Buf, "my name is ASiDeigner hello how are you? what do you do with this code and what's the plan? are you sure it's working? have you seen seasnon 2", 60);
            txBufferIndex = 60;
        }
        else if(rxBufferIndex>10){
            // Clear the buffer after processing
            memset(UART_Rx_Buf, 0, sizeof(UART_Rx_Buf));
            rxBufferIndex = 0;

            memcpy(UART_Rx_Buf, "Error", 5);
            txBufferIndex = 5;
        }

        vTaskDelay(1); // Delay to avoid flooding the terminal
    }
}

ASiDesigner, Stands for Application specific intelligent devices
I'm a Digital Expert from 8-bits to 64-bits
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4831
  • Country: nz
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #7 on: January 04, 2025, 12:52:06 pm »
thanks brucehoult, I'm using MounRiver, where can I find  the thread and what should I do?

Oh! In that case __attribute__((interrupt("WCH-Interrupt-fast"))) should compile ok.
 

Offline ali_asadzadehTopic starter

  • Super Contributor
  • ***
  • Posts: 1969
  • Country: ca
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #8 on: January 05, 2025, 11:07:32 am »
Quote
Oh! In that case __attribute__((interrupt("WCH-Interrupt-fast"))) should compile ok.
It compiles ok, But if it's used with freeRTOS, I would get constant crashes, do you have any clue why?
ASiDesigner, Stands for Application specific intelligent devices
I'm a Digital Expert from 8-bits to 64-bits
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4831
  • Country: nz
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #9 on: January 05, 2025, 12:18:00 pm »
Quote
Oh! In that case __attribute__((interrupt("WCH-Interrupt-fast"))) should compile ok.
It compiles ok, But if it's used with freeRTOS, I would get constant crashes, do you have any clue why?

I don't know what freeRTOS does -- or your code. If you are returning from the interrupt as normally then there should be no problem. If you are trying to do some fancy task switching from an interrupt handler by e.g. switching the stack pointer before returning then it stands to reason that things would be mucked up because half of your registers are stored in internal shadow registers in the CPU, not on the stack.

I would expect everything to work fine on the CH32V003 because it does the hardware register saving on the normal stack, but the 203 and above have an internal stack not accessible to the user.
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15893
  • Country: fr
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #10 on: January 05, 2025, 11:21:41 pm »
I have written a small "RTOS" and adapted it to the CH32V307. The "hardware stack" was enabled. I didn't notice any issue saving and restoring all registers on context switching and I do the context switching from within an interrupt. I'm curious what exact sequence FreeRTOS could use that would explain a problem here, or why I didn't encounter any.
 

Offline ali_asadzadehTopic starter

  • Super Contributor
  • ***
  • Posts: 1969
  • Country: ca
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #11 on: January 06, 2025, 11:51:24 am »
I have attached the project till this point, it works if I only send more than 1 character and also use termite program, I did not done anything fancy in interrupts, you can take a look and if you have CH32V203 test it too.
ASiDesigner, Stands for Application specific intelligent devices
I'm a Digital Expert from 8-bits to 64-bits
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4361
  • Country: us
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #12 on: January 07, 2025, 10:02:51 am »
Quote
if it's used with freeRTOS, I would get constant crashes

Is your freeRTOS also compiled with the WCH compiler, or was it provided with pre-built library binaries?
 

Offline ali_asadzadehTopic starter

  • Super Contributor
  • ***
  • Posts: 1969
  • Country: ca
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #13 on: January 07, 2025, 10:18:25 am »
Quote
Is your freeRTOS also compiled with the WCH compiler, or was it provided with pre-built library binaries?
Yes it's shipped with wch compiler, I only changed it's timer
ASiDesigner, Stands for Application specific intelligent devices
I'm a Digital Expert from 8-bits to 64-bits
 

Offline ali_asadzadehTopic starter

  • Super Contributor
  • ***
  • Posts: 1969
  • Country: ca
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #14 on: January 09, 2025, 01:36:36 pm »
Guys do you have any idea what might be wrong for 1 character? also I wonder if General GPIO's are 5v tolerant, I could not find any info in the datasheet.
ASiDesigner, Stands for Application specific intelligent devices
I'm a Digital Expert from 8-bits to 64-bits
 

Offline TomS_

  • Frequent Contributor
  • **
  • Posts: 854
  • Country: gb
Re: CH32V203 + FreeRTOS + USB CDC
« Reply #15 on: January 11, 2025, 09:33:56 am »
In my experience with FreeRTOS, crashes are due to improper handling of interrupts.

The tick interrupt must be the lowest priority of all interrupts, and you must not call any FreeRTOS APIs from interrupts above the maximum system interrupt priority.

You could also try enabling stack monitoring to ensure your aren't overflowing any task stack and blowing away something critical, like an adjacent tasks TCB.

As long as interrupts are handled correctly, and the stack is not being corrupted, there's generally no reason for FreeRTOS to crash.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf