if you are using preemption
Yes I am. An RTOS without that would not do much useful stuff. However I write all code to yield when waiting.
yielding will not allow lower priority tasks to run.
I didn't know that, but
taskYIELD() is used to request a context switch to another task. However, if there are no other tasks at a higher or equal priority to the task that calls taskYIELD() then the RTOS scheduler will simply select the task that called taskYIELD() to run again.
is better than just hanging there, isn't it, because just hanging there will completely waste CPU time until the next 1ms tick.
Only a RTOS delay (vTaskDelay()/vTaskDelayUntil()) will permit lower priority tasks to run, at least until the delay expires.
OK; that's good news. I was using osDelay(x) before I moved to taskyield, believing the latter to be better in some cases because if the RTOS has no other tasks to run, it will come back to me
before x. Well, I was right, except that yielding doesn't allow lower priority tasks to run, whereas osDelay does. That's a good lesson for me

There is more detail: almost all my RTOS tasks run at IDLE priority anyway, so the above is moot.
Also osDelay(1), which I used generally, isn't really 1ms. It is anything from near-zero (depending on how soon is the next tick) to 1ms. If you want 1ms then you need to settle for 1-2ms, with osDelay(2). Or use other non-RTOS delay means of course... there are several options.
Yes STM32 USB stack is really complicated. I tend to use tinyusb - might not be 100% complete and perfect, but it is way easier to make it work, with or without an RTOS.
I just set it up for a CDC on an iMX RT1062, FreeRTOS and works like a charm.
This project was set up by someone else a few years ago. That USB code seems to have come entirely from the Cube MX code generator. And it has been working OK. The MSC (removable drive, done with FatFS) portion is solid, and the CDC output (data
to PC) is solid (if rather low performance, but ok for debugs). I think the data rate
from PC is poor, of the order of tens of bytes/sec if sending single bytes.
I have decided to not waste more days on the CDC
from PC code. The code is so convoluted I don't even understand some of the C. And I certainly don't understand the program flow. It works well enough for another (undocumented) debug function where I can discard incoming non-ascii bytes (the corrupted bytes are mostly non-ascii). It is 90% reliable, increasing to 99% with that RTOS yield line removed (which is a worryingly bad timing dependency, I think, but the rest of the product is rock solid).
It would not surprise me if nobody has tested this CDC feature before.