cancel
Showing results for 
Search instead for 
Did you mean: 

How to use usb cdc_receive_hs on main() ?

AlexandrosAA
Associate III

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 ?

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

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.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

3 REPLIES 3
TDK
Guru

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.

If you feel a post has answered your question, please click "Accept as Solution".

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.

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.

If you feel a post has answered your question, please click "Accept as Solution".