2024-01-23 4:24 AM
Hey. I'm trying to create a program that receives 4 bytes long strings from my pc and transfer them through an spi connection to a peripheral device, throught a usb connection.
I've set my stm32 nucleo board up as a usb device and generated the required file. The thing that i noticed though is that i could use the cdc_transmit_hs function inside the main.c super loop, if declared as extern, but i couldn't do the same with the receive counterpart. The only thing that i tried and seemed to work is echoing the data inside the receive function, meaning :
static int8_t CDC_Receive_HS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 11 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceHS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceHS);
  uint8_t rxMessage[40]={'\0'};
  sprintf(rxMessage, "Command is %c,%d,%d,%d\r\n",Buf[0],Buf[1], Buf[2], Buf[3] );
  CDC_Transmit_HS(rxMessage,sizeof(rxMessage));
  return (USBD_OK);
  /* USER CODE END 11 */
}Is there an actual way to use this function inside the main?Should i use a global array and a flag to signal the main file, that some data is being received, or is it not thread safe ?
Solved! Go to Solution.
2024-01-23 6:56 AM
USB data is received via an interrupt in the CDC_Receive_HS function. This is in usbd_cdc_if.c. Implement that with what you need.
static int8_t CDC_Receive_HS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 11 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceHS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceHS);
  memcpy(rxMessage, Buf, Len); // <----- your implementation
  return (USBD_OK);
  /* USER CODE END 11 */
}Set a flag so your main loop is aware that data has come in and should be processed.
> Should i use a global array and a flag to signal the main file, that some data is being received, or is it not thread safe ?
Yes, exactly this. It will be thread safe if you write it as such. Consider the case where more data comes in while you're still processing the old data.
2024-01-23 6:56 AM
USB data is received via an interrupt in the CDC_Receive_HS function. This is in usbd_cdc_if.c. Implement that with what you need.
static int8_t CDC_Receive_HS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 11 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceHS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceHS);
  memcpy(rxMessage, Buf, Len); // <----- your implementation
  return (USBD_OK);
  /* USER CODE END 11 */
}Set a flag so your main loop is aware that data has come in and should be processed.
> Should i use a global array and a flag to signal the main file, that some data is being received, or is it not thread safe ?
Yes, exactly this. It will be thread safe if you write it as such. Consider the case where more data comes in while you're still processing the old data.
2024-01-24 1:08 AM
Is it safe to use functions like spi_transfer, or further cdc transfers inside the callback, or will the program hang ?
I tried doing something like this inside the callback function :
static volatile uint8_t newDataAvailable=0;
static uint8_t receivedDataBuffer[100];
static int8_t CDC_Receive_HS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 11 */
  memcpy(receivedDataBuffer, Buf, *Len);
  newDataAvailable = 1;
  USBD_CDC_SetRxBuffer(&hUsbDeviceHS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceHS);
  return (USBD_OK);
  /* USER CODE END 11 */
}Na something like this inside the main.c :
extern volatile uint8_t newDataAvailable;
extern uint8_t receivedDataBuffer[100];
 while (1)
  {
	  if (newDataAvailable)
	  {
	 		uint8_t rxMessage[100]={'\0'};
	 		sprintf(rxMessage, "Command is %c,%d,%d,%d\r\n",receivedDataBuffer[0],receivedDataBuffer[1], receivedDataBuffer[2], receivedDataBuffer[3] );
	 		CDC_Transmit_HS(rxMessage,sizeof(rxMessage));
	 	    newDataAvailable = 0;
	 	  }
  }But i get Undefined errors for both of the extern variables.
2024-01-24 6:02 AM
> Is it safe to use functions like spi_transfer, or further cdc transfers inside the callback, or will the program hang ?
Generally, it fine to use whatever functions you need as long as they complete quickly.
> But i get Undefined errors for both of the extern variables.
Remove "static" from the variable definition. Global variables defined with "static" cannot be seen in other compilation groups (i.e. other *.c files).
Probably also want to move your code to after the two USBD_CDC_* calls, not before.
