Can control endpoint receive IN and OUT packets
as a normal endpoint ? Or it can
only receive IN and OUT packets which follow SETUP packets?
Setup packets are always a part of control transfers.
The host always initiates the control transfer by sending a setup packet. The IN or OUT data will follow it. Usually the USB API for control transfers includes the setup packet and the data buffer. For instance, the libusb function looks as follows:
int libusb_control_transfer (libusb_device_handle * dev_handle,
uint8_t bmRequestType,
uint8_t bRequest,
uint16_t wValue,
uint16_t wIndex,
unsigned char *data,
uint16_t wLength,
unsigned int timeout
)
bmRequestType, bRequest, wValue, wIndex and wLength parameters are for the setup packet.
The following document by Microsoft should also help understanding how the control transfers work:
https://learn.microsoft.com/en-us/windows-hardware/drivers/usbcon/usb-control-transfer
Related
I am trying to play around with stm32 uart in polling mode. the transmission part is working properly and I read proper characters that I send from the MCU, however the reception part is not working properly.
This is a welcome message
ÿÿÿÿ
The first line is send from MCU to PC, the MCU then waits for reception. As I understand that HAL_USART_Receive is a blocking call so it should wait for user to input character from the terminal, however before i can write any characters and send them over to MCU, it moves over to the next line which is an infinite while loop. I cant understand why is it not pausing at the receive method. I debugged and checked the live expression windows, during initialization I set the receive buffer to '\0' however after passing through the HAL_Receive method the value of the buffer becomes 127. see the attached image for value stored in the buffer.
output
Can you please help me understand what am I doing wrong. My code is shown below
HAL_Init(); // Initializing HAL.
SystemClockConfig();
USART3_Init();
uint8_t tx_data[] = "This is a welcome message\r\n";
uint16_t tx_len = sizeof(tx_data);
HAL_USART_Transmit(&husart3, tx_data, tx_len, HAL_MAX_DELAY);
uint8_t rx_data[5]={0};
uint16_t rx_len = sizeof(rx_data);
HAL_USART_Receive(&husart3, rx_data, rx_len, HAL_MAX_DELAY);
while(1)
{
}
You said you are using the USART in UART mode (I assume you mean asynchronous mode) but your Handle (husart) is synchronous, and the HAL methods you are using are synchronous as well?
Your RX pin on your STM32 is held high which is why you get 0xFF (127) in your buffer when you call your receive function.
I think you have selected an incorrected setting in your code generator, are you using CubeIDE? If so, go to USART and choose "asynchronous" from the options and regenerate. You'll notice your handle change from husart to huart. The HAL functions for sending and transmitting are HAL_UART_Transmit() and HAL_UART_Receive(). Using these the same way in your current code will give the results you are looking for.
I have a third party device that is UART programmable.
I need to create a USB - UART bridge with a functional password (programming only after entering the correct password)
generated the code using the latest version of STM32CubeMX for Atollic TrueSTUDIO for STM32 9.3.0 ...
I transfer data between USB and UART through a buffer (one for usb-uart, and another one for uart-usb)
when I try to transfer several characters everything is OK, but when I try to transfer a large data packet, problems start due to the fact that the USB speed is much higher than the UART ...
there are two questions:
1.How do I tell USB that I need to stop transferring data and wait until the UART (buffer) is busy
2.How on the side of the microcontroller to get the baud rate set on the PC (set when the terminal is connected to the virtual COM port)
USB provides flow control. That's what you need to implement. A general introduction can be found here:
https://medium.com/#manuel.bl/usb-for-microcontrollers-part-4-handling-large-amounts-of-data-f577565c4c7d
Basically, the setup for the USB-to-UART direction should be:
Indicate that the code is ready to receive a USB packet
Receive a USB packet
Indicate that you are no longer ready to receive a USB packet
Transmit the data via UART
Start over
Step 0: Initial setup
Call USBD_CDC_SetRxBuffer to set the buffer for receiving the USB data. Unless you use several buffers to achieve higher throughput, a single call at the start of the program is sufficient.
Step 1: Ready to receive data
Call USBD_CDC_ReceivePacket. Other than what the name implies, this function indicates that the app is ready to receive data. It immediately returns before the data has actually been received.
Step 2: Receive a USB packet
You don't need to do anything here. It will happen automatically. Once it's complete, CDC_Itf_Receive will be called.
Step 3: Indicate that you are no longer ready to receive a USB packet
Nothing to do here. This happens automatically whenever a packet has been received (and double buffering is not enabled).
Step 4: Transmit the data via UART
I guess you know how to do this. It's up to you whether you want to do it in a blocking fashion or using DMA.
Since a callback is involved, you cannot put this code into the main loop. It might be possible to put all code into CDC_Itf_Receive if blocking UART is used. It would appear in the order 2, 3, 4, 1. Additionally, initialization is needed (0 and 1).
In the UART-to-USB direction, you would need to implement flow control on the UART. The USB flow control is managed by the host. Even though USB is much faster than UART, flow control is relevant as the application on the host can process data as slow as it likes to.
Regarding question 2: I'm not sure I understand it... The microcontroller cannot set the baud rate on the host. Either the host can specify a baud rate (transmitted over USB and applied to UART), or if the UART has a fixed baud rate, you can ignore baud rate (any baud rate set on the host side will work as it does not apply to USB).
I got this snippet of code from the Blueduino board manufacturer's page. It works fantastically for two-way communication, it seemed simple but after much searching I can't understand what it is doing.
This is the code:
// read from port 1, send to port 0:
if (Serial1.available()) {
int inByte = Serial1.read();
Serial.write(inByte);
}
// read from port 0, send to port 1:
if (Serial.available()) {
int inByte = Serial.read();
Serial1.write(inByte);
}
It's obvious it's writing the in to the out and vice-versa (Rx to Tx I believe) but I am not sure why.
This code is working and when I write in the serial monitor it is received on the phone, but I'm not sure how this code is taking the message I send in the serial monitor and inserting it in the stream.
Thanks in advance for your help.
This code is forwarding messages from one serial device to another.
Most likely between your Arduinos serial interface (to your pc) to the blueduino board.
You cannot connect your PC to the Phone directly and you cannot wire the blueduino-board directly to the serial lines of your PC.
Hence you need something in between. (your arduino) that forwards every single byte.
The code you have basically does the same for both ports. If a byte is in the serial receive buffer, read it and send it to the other port.
I have a game server. He communicates with the client via packet. I want to send line
#define From the server to the client with a packet.
In this way not I be forced to recompile the source to the client always.
Basically I can activate functions that are source directly from server to client.
I just need an example about this. :D Please help.
typedef struct define_packet_send {
BYTE header;
int define_max_len[20];
long data;
}
But how to send the define in a specific file. I hope you guys you understand what i mean.
I have to send file byte-by-byte to serially connected AT89s52 from computer (VB.NET).
Every sended byte have some job to do in microcontroller what require some time.
Here is relevant part of my C code to receiving bytes:
SCON = 0x50;
TMOD = 0x20; // timer 1, mode 2, 8-bit reload
TH1 = 0xFD; // reload value for 9600 baud
TR1 = 1;
TI = 1;
again:
while(RI!=0)
{
P1=SBUF; // show data on led's
RI=0;
receivedBytes++;
}
if (key1==0)
{
goto exitreceive; // break receiving
}
show_lcd_received_bytes(receivedBytes);
// here is one more loop
// with different duration for every byte
goto again;
And here is VB.NET code for sending bytes:
For a As Integer = 1 To 10
For t As Integer = 0 To 255
SerialPort1.Write(Chr(t))
Next t
Next a
Problem is that mC have some job to do after every received byte and VB.NET don't know for that and send bytes too fast so in mC finishes just a part of all bytes (about 10%).
I can incorporate "Sleep(20)" in VB loop ant then thing will work but I have many of wasted time because every byte need different time to process and that would be unacceptable slow communication.
Now, my question is if 8051 can set some busy status on UART which VB can read before sending to decide to send byte or not.
Or how otherwise to setup such communication as described?
I also try to receive bytes with serial interrupt on mC side with same results.
Hardware is surely OK because I can send data to computer well (as expected).
Your problem is architectural. Don't try to do processing on the received data in the interrupt that handles byte Rx. Have your byte Rx interrupt only copy the received byte to a separate Rx data buffer, and have a background task that does the actual processing of the incoming data without blocking the Rx interrupt handler. If you can't keep up due to overall throughput issue, then RTS/CTS flow control is the appropriate mechanism. For example, when your Rx buffer gets 90% full, deassert the flow control signal to pause the transmit side.
As #TJD mentions hardware flow control can be used to stop the PC from sending characters while the microcomputer is processing received bytes. In the past I have implemented hardware flow by using an available port line as an output. The output needs to be connected to an TTL to RS-232 driver(if you are currently using a RS-232 you may have and extra driver available). If you are using a USB virtual serial port or RS-422/485 you will need to implement software flow control. Typically a control-S is sent to tell the PC to stop sending and a control-Q to continue. In order to take full advantage of flow control you most likely will need to also implement a fully interrupt driven FIFO to receive/send characters.
If you would like additional information concerning hardware flow control, check out http://electronics.stackexchange.com.
Blast from the past, I remember using break out boxes to serial line tracers debugging this kind of stuff.
With serial communication, if you have all the pins/wires utililzed then there is flow control via the RTS (Ready To Send) and DTR (Data Terminal Ready) that are used to signal when it is OK to send more data. Do you have control over that in the device you are coding via C? IN VB.NET, there are events used to receive these signals, or they can be queried using properties on the SerialPort object.
A lot of these answers are suggesting hardware flow control, but you also have the option of enhancing your transmission to be more robust by using software flow control. Currently, your communication is strong, but if you start running a higher baud rate or a longer distance or even just have a noisy connection, characters could be received that are incorrect, or characters could be dropped.
You could add a simple two-byte ACK sequence upon completion of whatever action is set to happen. It could look something like this:
Host sends command byte: <0x00>
Device echoes command byte: <0x00>
Device executes whatever action is needed
Device sends ACK/NAK byte (based on result):
This would allow you to see on the host side if communication is breaking down. The echoed character may mismatch what was sent which would alert you to an issue. Additionally, if a character is not received by the host within some timeout, the host can try retransmitting. Finally, the ACK/NAK gives you the option of returning a status, but most importantly it will let the host know that you've completed the operation and that it can send another command.
This can be extended to include a checksum to give the device a way to verify that the command received was valid (A simple logical inverse sent alongside the command byte would be sufficient).
The advantage to this solution is that it does not require extra lines or UART support on either end for hardware flow control.