libusb: libusb_control_transfer freezing the program - c

I am trying to get the firmware version of my usb device. As per the specification:
When using the USB interface, the commands are sent as CONTROL READ requests, where the request byte is the command, and the Index and Value are additional parameters sent to the Device. If the PC is requesting data, it will be returned in the endpoint 0 IN buffer.
Command Description Device Response / Notes
a Request firmware version The device returns 4 bytes containing the version number in ASCII.
Now to request firmware version, I do the following:
char buffer[4];
unsigned char a = 'a';
r = libusb_control_transfer(dev_handle,0,a,0,0,buffer,4,0);
But the program stops responding, and I can't get any result.

There are two things I see that could be wrong here:
The character value 'a' is equal to 0x61, I think what you want is 0x0A for your bRequest parameter.
Also, since you are getting data from the device you probably want to setup bmRequestType properly. 0x80 is the mask that represents data going from the device to the host, right now you are specifying that you are giving data to the device.
In these cases a USB analyzer is highly useful, so you can look at the bus to get an idea of exactly what the setup packet contains that is sent to your device as well as what it's response to the host is.
Here is the modified code:
char buffer[4];
r = libusb_control_transfer(dev_handle,0x80,0x0a,0,0,buffer,4,0);

Related

Modbus calls returning same frame over and over again

I'm having a dickens of an issue with this one.
I have a remote installation with a raspberry pi installed in it (specifically a Kunbus RevPi connect) that is hooked up to an RS485 Modbus network with a total of 6 sensors on it. 4 Of these sensors are Dat3018 devices which serve to digitize thermocouples and make their values available over the network.
I wrote a C program that performs the following:
Sends a sync command (specified in the data sheet) to the dat3018 which causes them all to read values into their internal memory
Perform some other stuff
Read the saved values in to the raspberry pi over Modbus.
All is well and good, and I'm able to talk to each of the devices, no issues as far as I can tell on the physical communication link. The issue appears when I actually run the software and observe the Modbus request and response.
The first loop of the program runs normally, the sync command goes out, a request and response is received from each of the target slaves on the network. Starting with the second run of the loop each request results in the program receiving the exact same frame it did during the first run of the loop even through there should be at least some values changing. This continues for however long the program runs, always sending the same request from the server and always receiving the same values back.
As per the data sheet for the Modbus devices the following command is sent:
[FF][06][00][00][00][0A][1C][13]
I verified with the company that makes the device that this was the right call to request the device to sync. I also verified that calling this again will cause new values to be read into the synced value registers, meaning that when I read them again there is a very low chance that they are all exactly the same.
I send the following modbus command with the following code:
int read_tempature_synced_values(modbus_t *RTU_context, int slave_addr, uint16_t output[]){
modbus_set_slave(RTU_context, slave_addr);
return modbus_read_registers(RTU_context, _temp_sync_tempatures_start_addr-1, 8, output); //Decrement to account for the inherient +1 from the library
}
For slave # 20:
[14][03][00][16][00][08][A7][0D]
Restarting the program pulls in new values for the first run of the loop before having the same issue.
I wrote a python script to call the sync command and pull in all the measurements from the same registers and that script gives me changing values as I make more calls. That would seem to indicate to me that the issue is somewhere in the Modbus code.
The part of the code that calls the above function looks like this:
//Read in the temperature measurements
for (int i = 0; op_args->settings_instance->tempatureSlaveAddr[i] != -1; ++i){
uint16_t *raw_measures = malloc(8 * sizeof(uint16_t));
read_tempature_synced_values(op_args->modbus_instance, op_args->settings_instance->tempatureSlaveAddr[i], raw_measures);
usleep(op_args->settings_instance->delay_ms);
for (int u = 0; u <= 7; ++u){
if(valid_sensors[i][u] == FALSE){ //Check that there is a valid sensor for this measurement
measurements[measurements_taken].TYPE = TEMPATURE_MEASUREMENT_TYPE;
measurements[measurements_taken].bankNumber = i;
measurements[measurements_taken].sensorNumber = u;
measurements[measurements_taken].measurementTime = sync_time;
measurements[measurements_taken].tempatueReading = ((float)raw_measures[u])/10;
measurements_taken += 1;
}
}
free(raw_measures);
modbus_flush(op_args->modbus_instance);
}
It seems to me that there is something that is remembering what the responses to the calls were and then bouncing them back to me. I can't see any way that the code I have wrote could be doing this.
One other strange thing:
When running my code on the raspberry pi (and only on the pi) my program will randomly print out the two following lines at the start and then at seemingly random times:
ERROR Connection timed out: select
ERROR Connection timed out: select
This happens before the loading/connection to the serial port or sqlite database that I am using. Googling this issue did not appear to give me anything that makes sense in the context of where it is occuring.
Any help would be greatly appreciated
Edit -> The sync command is run at the start of every loop
I verified with the company that makes the device that this was the right call to request the device to sync. I also verified that calling this again will cause new values to be read into the synced value registers, meaning that when I read them again there is a very low chance that they are all exactly the same.
That's how the device works. The SYNC command tells the device(s) to latch the values into a register.
When you do the read, the devices return the latched value and not the "current" value.
From https://www.datexel.com/datexel-user-guides/dat3018-thermocouple-input-to-rs485-modbus.pdf we have:
SYNCHRONISM
The Synchronism function is performed by a command sent to all devices connected on the net. When the devices receive the Sync command, all
input states are saved in the relative register, to be read after time. Doing this, it is possible to read the value of all inputs at the Sync command time.
To send the synchronism command, write the value 10 in the “Test” register (40001) at the address 255.
NOTE: The sync values are not saved in EPROM.
So, for every new value you want you have to send a new SYNC command:
while (1) {
send SYNC command
for (x in all_devices)
read(x)
}

STM32 USB CDC Long packet receive

I need to send data from the PC to my STM32F3, so I decided to use a built-in USB in uC.
But now I have a problem - I want to send to stm32 big amount of data at once - I mean something like 200-500 Bytes.
When I send from PC with minicom packets which have less than 64 chart - everything is fine - callback CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) occurs once - it enables UsbRxFlag, just to inform the running program that there is data available.
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
/* USER CODE BEGIN 6 */
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
if( (Buf[0] == 'A') & (Buf[1] == 'T') ){
GPIOB->BSRR = (uint32_t)RX_Led_Pin;
UsbRxFlag = 1;
}
return (USBD_OK);
/* USER CODE END 6 */
}
But when I try to send more data (just long text from minicom ) to uC, something weird happens - sometimes uC doesn't react at all - sometimes it doesn't take into account some data.
How can I handle sending to STM32F3 more than 64Bytes over USB-CDC?
The maximum packet length for full-speed USB communication is 64 bytes. So the data will be transferred in chunks of 64 bytes and needs to be reassembled on the other end.
USB CDC is based on bulk transfer endpoints and implements a data stream (also known as pipe), not a message stream. It's basically a stream of bytes. So if you send 200 bytes, do not expect any indication of where the 200 bytes end. Such information is not transmitted.
Your code looks a bit suspicious:
You probably meant '&&' instead of '&' as pointed out by Reinstate Monica.
Unless you change buffers, USBD_CDC_SetRxBuffer only needs to be called once at initialization.
When CDC_Receive_FS is called, a data packet has already been received. Buf will point to the buffer you have specified with USBD_CDC_SetRxBuffer. Len provides the length of the packet. So the first thing you would do is process the received data. Once the data has been processed and the buffer can be reused again, you would call USBD_CDC_ReceivePacket to indicate that you are ready to receive the next packet. So move USBD_CDC_SetRxBuffer to another function (unless you want to use several buffers) and move USBD_CDC_ReceivePacket to the end of CDC_Receive_FS.
The incorrect order of the function calls could likely have led to the received data being overwritten while you are still processing it.
But the biggest issue is likely that you expect that the entire data is received in a single piece if you sent is as a single piece, or that it at least contains an indication of the end of the piece. That's not the case. You will have to implement this yourself.
If you are using a text protocol, you could buffer all incoming data until you detect a line feed. Then you know that you have a complete command and can execute it.
The following is a general purpose implementation for reading an arbitrary number of bytes: https://github.com/philrawlings/bluepill-usb-cdc-test.
The full code is a little too long to post here, but this essentially modifies usb_cdc_if.c to create a circular buffer and exposes additional functions (CDC_GetRxBufferBytesAvailable_FS(), CDC_ReadRxBuffer_FS() and CDC_FlushRxBuffer_FS()) which can be consumed from main.c. The readme.md text shown on the main page describes all the code changes required.
As mentioned by #Codo, you will need to either add termination characters to your source data, or include a "length" value (which itself would be a fixed number of bytes) at the beginning to then indicate how many bytes are in the data payload.

Why does read not terminate for my USB device?

I have an USB-device connected with my RaspberryPi 3 B+ (Raspbian Buster Lite 2019-07-10). I also write an small program to read data from the USB Device. The device has an custom, CDC conform firmware, so the device is detected correctly by the OS and and tty is attached.
But when I call 'read' for the device, the syscall never terminates. The odd thing is, when I access the device with MiniCom, CuteCom or even H-Term, it works correct.
I already tried the answers from the following questions:
Reading and writing to serial port in C on Linux
How to open, read, and write from serial port in C?
C program to read data from USB device connected to the system
None of them worked.
I also tried to flush the tty with tcflush and tcdrain.
int dev = open("/dev/ttyACM0", O_RWDR | O_NOCTTY);
// I tried to adapt the device parameters with termios, see above
uint8_t req[] = {0x21, 0x42, 0x00, 0x12}; // the actual request
write(dev, req, 4);
uint8_t resp[12];
read(dev, resp, 8); // does not terminate
I expect a result, 12 bytes long, but read just blocks. If I try the O_NONBLOCK/O_NDELAY option, read terminates with the EAGAIN error.
Of course I checked the result values from every syscall and library function, they all returned/terminated as expected. And as I mentioned above, when connected with a terminal program the device works how it should, so it can't be the firmware.
Also I traced with strace what minicom and cutecom did, but they also did nothing more than open, write and read and of course I tried everything with sudo, so the rights are not the problem.
Seems like the device has never taken the request, so its never processing and getting blocked. so, something prob in the way the request is written. Did you try setting the speed of the port/interface?
I found the Answer myself: the ICANON bit in the termios struct, c_lflag field musst be cleared and the VMIN field in the c_cc array should be set to 1.
Further explanations are found here:
https://www.gnu.org/software/libc/manual/html_node/Local-Modes.html#Local-Modes
https://www.gnu.org/software/libc/manual/html_node/Mode-Data-Types.html
(be carefull, some parts of this documentary are a little bit outdated, for example the CCTS_OFLOW Flag does not exist on Raspbian-Buster)

Where can I find the device specific JTAG instructions for Cortex-M3?

I'm trying to communicate with a Cortex-M3 based microcontroller (LPC1769) through JTAG. I already have the hardware required, and have managed to get an example program to work, but to progress further, I need to know the device-specific JTAG instructions that are available in this case. I have read the corresponding section of the Cortex-M3 technical reference manual (link), and all that told me, was that the device uses a standard CoreSight debug port. In particular, I'd like to read the device ID with the IDCODE instruction. Some sites suggest, that the IDCODE might be b0001 or b1110 for this device, but neither of them seem to work. b0001 seems more likely to me, as that's the value I read from the IR after the TAP has been reset.
I also considered the possibility, that the instruction I'm using is correct, and I'm just not reading the device ID register properly. I'm using an FTDI cable with the FT232H chip, and the application I'm using is based on FTDI's AN129 example code (link), using MPSSE commands. I use the 0x2A command to clock data in from the TAP, the 0x1B command to clock data out to the TAP, and the 0x3B command to do both simultaneously. If anyone could provide some insight, as to what I'm doing wrong (or whether I'm using the right IDCODE instruction at all), that would be much appreciated.
*EDIT:
I made some progress, but the IDCODE instruction still eludes me. I managed to read the Device ID after setting the TAP controller to Test-Logic-Reset state (which loads the IDCODE instruction in the IR). However, I tried all possible (16) instructions, and while some of them resulted in different reads from the DR, none loaded the Device ID register.
This is the function I use to insert the instruction, once the TAP controller is in Shift-IR state:
int clockOut(FT_HANDLE* ftHandle, BYTE data, BYTE length)
{
FT_STATUS ftStatus = FT_OK;
BYTE byOutputBuffer[1024]; // Buffer to hold MPSSE commands and data to be sent to the FT232H
DWORD dwNumBytesToSend = 0; // Index to the output buffer
DWORD dwNumBytesSent = 0; // Count of actual bytes sent - used with FT_Write
byOutputBuffer[dwNumBytesToSend++] = 0x1B;
// Clock data out through Shift-DR
byOutputBuffer[dwNumBytesToSend++] = length - 1;
// Number of clock pulses = (length - 1) + 1; This way, the length given as the parameter of the function is the actual number of clock pulses.
byOutputBuffer[dwNumBytesToSend++] = data;
// Shift out data
ftStatus = FT_Write(*ftHandle, byOutputBuffer, dwNumBytesToSend, &dwNumBytesSent);
// Send off the TMS command
return ftStatus;
}
The length parameter is set to 4, and the data parameter is set to 0x0X (where I tried all possible values for X, neither of which led to success)
I managed to get it to work. The problem was, that when I sent out 4 bits to the IR, it in fact received 5. After finishing the transmission, the next rising edge of TCK was supposed to change the state of the TAP controller, but as it was still in the Shift-IR state, it not only changed the state, but also sampled the TDI, and did another (fifth) shift. To countermand this, I only shifted the lower 3 bits of the instruction, and then used a 0x4B MPSSE command, to simultaneously clock out a TMS signal (to change the state), and send out the MSB of the command.

Flash Memory writing and reading through SPI

It's the first time I try to use the SPI protocol. I am trying to understand an example code that came with my development kit (which has a STM32F207VCT6 microcontroller). This code implements communication (reading and writing) with a AT45DB041D flash memory.
Every time this example code manages to read the memory it not only sends information about what to be read but also asks to receive data rigth away. This data received isn't used for any purpose (apparently). The real data to be read will be asked again by the receive command later by sending a 0x00 byte first. The following code shows that:
void AT45DBXX_Read_ID(u8 *IData){
u8 i;
AT45DBXX_BUSY();
AT45DBXX_Enable; //Chip Select drive to low
SPIx_Send_byte(Read_ID);
for(i=0;i<4;i++)
{
IData[i] = SPIx_Receive_byte();
}
AT45DBXX_Disable; //Chip Select drive to high
}
Definitions:
void SPIx_Send_byte(u16 data){
while(SPI_I2S_GetFlagStatus(Open207V_SPIx, SPI_I2S_FLAG_TXE)==RESET);
SPI_I2S_SendData(Open207V_SPIx,data);
while(SPI_I2S_GetFlagStatus(Open207V_SPIx, SPI_I2S_FLAG_RXNE)==RESET);
SPI_I2S_ReceiveData(Open207V_SPIx);
}
u16 SPIx_Receive_byte(void){
while(SPI_I2S_GetFlagStatus(Open207V_SPIx, SPI_I2S_FLAG_TXE)==RESET);
SPI_I2S_SendData(Open207V_SPIx,0x00);
while(SPI_I2S_GetFlagStatus(Open207V_SPIx, SPI_I2S_FLAG_RXNE)==RESET);
return SPI_I2S_ReceiveData(Open207V_SPIx);
}
As you can see the SPIx_Send_byte code is not only sending what to be read but also receiving information that won't be used.
Can someone help me understand why that needs to be done and why its needed to send the 0x00 byte to actually receive the data?
Thanks!
SPI is a full-duplex, bi-directional bus where data is both sent to the slave and received from the slave at the same time. Your SPI controller doesn't know if a given byte is glong from the master, or from the slave, or both. Therefore, whenever you send a byte, you must also read a byte, if only to throw it away. By the same token, you cannot receive a byte without sending a byte, even if the slave will throw it away.
Take a look at Wikipedia.
So, what you code is doing is
Sending Read_ID to the slave.
Reading and throwing away the byte simultaneously read out of the slave.
Write 0 to the slave to enable the slave to send a byte of data.
Read the data byte that was simultaneously read out of the slave.
Loop back to #3.
By the way, such questions would be better suited for the EE Stack Exchange as it is more about the hardware protocol as opposed to programming.

Resources