cancel
Showing results for 
Search instead for 
Did you mean: 

Debugging methods for FunctionFS Usb gadget in STM32MP1: HDMI-USB C PA10 pin conflict

KChar.1
Senior

Hi,

I am working on a functionFS usb gadget based on gmidi. Following the gadget_configfs.rst and using stm32_usbotg_eth_config.sh as starting point was straight forward. After writing the shell script and modifying my device tree configuration to support high-speed OTG in the usb-c port as explained in the USB device tree guide, the usb gadget loaded with no errors and it was recognised by Mac, Windows and Linux hosts as usb-midi.

USB-MIDI Shell script:

configfs="/sys/kernel/config/usb_gadget"
g=g1 #Gadget name
c=c.1 #Configuration name
d="${configfs}/${g}" #gadget path
func_midi=midi.usb0  #Midi Function declaration
#Product and Vendor for getting recognised
VENDOR_ID="0x1d6b"
PRODUCT_ID="0x0104"
#Take the serial from the MP1 and make it a serial for our USB MIDI
get_mac_address_from_serial_number(){
    sha1sum /proc/device-tree/serial-number \
    | fold -1 \
    | sed -n '1{h;d};2{y/1235679abdef/000444888ccc/;H;d};13{g;s/\n//g;p;q};s/^/:/;N;H;d'
}
#To call the gadget
do_start() {
    #Call dependacy. We are using FunctionFS so only libcomposite is needed
    if [ ! -d ${configfs} ]; then #Check if dependancy is already enabled
        modprobe libcomposite
        if [ ! -d ${configfs} ]; then
        exit 1
        fi
    fi
    if [ -d ${d} ]; then
        exit 0
    fi
    udc=$(ls -1 /sys/class/udc/)  #Check if there is a UDC driver
    if [ -z $udc ]; then
        echo "No UDC driver registered"
        exit 1
    fi
    #Create main file structure
    mkdir "${d}"
    echo ${VENDOR_ID} > "${d}/idVendor"
    echo ${PRODUCT_ID} > "${d}/idProduct"
    echo 0x0200 > "${d}/bcdUSB"
    echo "0xEF" > "${d}/bDeviceClass"
    echo "0x02" > "${d}/bDeviceSubClass"
    echo "0x01" > "${d}/bDeviceProtocol"
    echo "0x0100" > "${d}/bcdDevice"
 
    #Sign the driver
    mkdir -p "${d}/strings/0x409"
    tr -d '\0' < /proc/device-tree/serial-number > "${d}/strings/0x409/serialnumber"
    echo "xxxx" > "${d}/strings/0x409/manufacturer"
    echo "***" > "${d}/strings/0x409/product"
 
    # Config
    mkdir -p "${d}/configs/${c}"
    mkdir -p "${d}/configs/${c}/strings/0x409"
    echo "Config 1: MIDI" > "${d}/configs/${c}/strings/0x409/configuration"
    echo 500 > "${d}/configs/${c}/MaxPower"
    echo 0xC0 > "${d}/configs/${c}/bmAttributes" # self powered device
 
        #MIDI function configuration
        mkdir -p "${d}/functions/${func_midi}"
 
        # Set up the midi device and serial after RNDIS
        ln -s "${d}/functions/${func_midi}" "${d}/configs/${c}"
 
    echo "${udc}" > "${d}/UDC" #Enable the driver
 
    sleep 0.2 # Wait a bit
 
}
#To eject the gadget
do_stop() {
 
    echo "" > "${d}/UDC" #Empty the UDC
 
    #Delete all contents based on their priorities
    rm -f "${d}/os_desc/${c}"
    [ -d "${d}/configs/${c}/${func_midi}" ] &&rm -f "${d}/configs/${c}/${func_midi}"
    [ -d "${d}/strings/0x409/" ] && rmdir "${d}/strings/0x409/"
    [ -d "${d}/configs/${c}/strings/0x409" ] && rmdir "${d}/configs/${c}/strings/0x409"
    [ -d "${d}/configs/${c}" ] && rmdir "${d}/configs/${c}"
    [ -d "${d}/functions/${func_midi}" ] && rmdir "${d}/functions/${func_midi}"
    [ -d "${d}" ] && rmdir "${d}"
}
 
case $1 in
    start)
        echo "Starting midi-usb gadget"
        do_start $2
        ;;
    stop)
        echo "Stoping midi-usb gadget"
        do_stop
        ;;
    *)
        echo "Usage: $0 (stop | start)"
        ;;
esac

The issue is that every few minutes the host stops sending and receiving messages. I tried multiple cables and hosts and the result is that midi data will stop arriving to the host and the MP1 in the same time, after a couple of minutes. If I reset the usb cable or stop and start the usb gadget data will flow again for a similar period of time.

In order to debug this issue I used usbmon on the MP1 and wireshark on a host Mac. On the host mac I could see that when the driver freezes it receives a URB with an unknown request and then a URB with an abort request. After these two messages no midi messages can go in or out but the device is still seen as a connected usb-midi device on the host.

Trying to understand why this happens I looked at f_midi.c. There I could see that an abort URB is send when hardware forces ep reset.

/* this endpoint is normally active while we're configured */
	case -ECONNABORTED:	/* hardware forced ep reset */
	case -ECONNRESET:	/* request dequeued */
	case -ESHUTDOWN:	/* disconnect from host */

At this point I am looking for ways to debug why the hardware forces ep reset and when but I can not find a way to debug this. Any ideas or points will be highly appreciated.

1 ACCEPTED SOLUTION

Accepted Solutions
KChar.1
Senior

Hi @Kevin HUBER​ ,

My sincere apologies for my very late response. I had some issues with getting a D-DK1 board in my hands. A few days ago I decided to get an F-DK2 board and I did a few tests today. After almost 5 hours I was not able to reproduce the issue. At the moment I can not confirm if this was a model specific or board specific issue. My old D-DK1 board still has the same behaviour so I will proceed with the F board.

Thank you very much for your help!

All the best,

Kyr

View solution in original post

27 REPLIES 27
KChar.1
Senior

UPDATE: After a bit of research I found out that in the default STM32MP157D-DK2 IOC file there is a warning when enabling USB_OTG high speed. It seems that the pin AP10 is assigned to both USB ID and HDMI_NRSET. I tested the USB gadget implementation with the HDMI disconnected and indeed works as intended. From a short research I was not able to figure out if there is a way to avoid the pin conflict by assigning a different pin to either USB or HDMI or changing the OTG configuration. Any ideas or directions will be really helpful.

Olivier GALLIEN
ST Employee

Hi @KChar.1​ ,

Just to be sure, did you already refer to https://wiki.st.com/stm32mpu/wiki/USB_overview#How_to_debug and exhaust all solutions proposed ?

Thanks

Olivier

Olivier GALLIEN
In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.

Hi @Community member​ ,

Thanks for the reply and suggestion. I did follow the How to debug article thoroughly and through usbmon logging and Wireshark on host machine I got the indication of the pin conflict. At this point I am looking for solutions to resolve the AP10 pin conflict as explained above.

Hello @KChar.1​ ,

Since you are talking about "STM32MP157D-DK2" and that this board doesn't exist, I think your board is a STM32MP157D-DK1 right?

----------------------

When you have a pin assignment issue, there is most of the time two possibilities to find the pin that is doing the same thing than the one is conflict:

CubeMX

By using CubeMx you can see the alternative pin by pressint ctrl + left click on the pin function:

0693W00000KZymAQAT.png 

Documentation

You can check the datasheet DS12505 v5.0 from page 65:

https://www.st.com/resource/en/datasheet/stm32mp157c.pdf

Unfortunately, you will see that USB_OTG_HS_ID is only available on PA10 (page 80):

0693W00000KZyicQAD.png 

And by looking at the User Manual of the Discovery board, UM2534 rev 1.0 page 21:

0693W00000KZyjQQAT.pngPA10 is connected to HDMI_NRST.

So you can't use the PA10 PIN for the two configurations at the same time if you are using the Discovery board.

If you create your own board, you will not have this conflict.

----------------------

Regarding the "solution", CubeMx warns you that this PIN conflict is only a problem if you want to use OTG in dual role device, in host and device at the same time.

0693W00000KZymeQAD.png 

I tried multiple cables and hosts and the result is that midi data will stop arriving to the host and the MP1

If I understand correctly your setup, you don't need to be at the same time the host and the device in your example, right?

In this case, you can select "Device_Only" in CubeMx and you will not need the PA10 pin.

The PA10 pin is needed for the DT configuration example 3.3.1 and 3.3.2 of the wiki, but not for the 3.3.3 DT configuration example as high speed OTG, with Type-C connector

or 3.3.4 DT configuration example as high-speed OTG in Host or Peripheral mode, with micro-B or Type-C connector, and with VBUS and ID left unconnected

https://wiki.st.com/stm32mpu/wiki/OTG_device_tree_configuration#DT_configuration_example_as_high-speed_OTG_in_Host_or_Peripheral_mode-2C_with_micro-B_or_Type-C_connector-2C_and_with_VBUS_and_ID_left_unconnected

In the last example, you can see that dr_mode is set to "peripheral", it forces the controller in Device only mode.

Hope it helps,

Regards,

Kevin

In order to give better visibility on the answered topics, please click on 'Select as Best' on the reply which solved your issue or answered your question. See also 'Best Answers'

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.

I advise you to also have a look at this wiki page to configure the DTS of U-Boot without the ID pin:

https://wiki.st.com/stm32mpu/wiki/How_to_configure_U-Boot_for_your_board#USB_OTG_node

Regards,

Kevin

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.

Hi @Kevin HUBER​ ,

Thank you so much for another clear and detailed answer. Indeed, I meant STM32MP157D-DK1 and a peripheral dr_mode will work just fine for my purpose.

I spend some time last couple of days to follow your suggestions. I was already using DT configuration 3.3.3. Until yesterday, I was using the stm32mp157d-dk1-extensible image from starter package 3.1.0. Checking ../u-boot source/arch/arm/dts/stm32mp157d-dk1-u-boot.dtsi pointed me to stm32mp157a-dk1-u-boot.dtsi. The usbotg_hs configuration in the dtsi was already including "force b-session-valid" which if I understand correctly forces usb-otg to not detect the USB-ID pin (PA10).

&usbotg_hs {
 	u-boot,force-b-session-valid;
 };

I modified the device tree to include dr_mode as suggested in this guide.

&usbotg_hs {
 	u-boot,force-b-session-valid;
 	dr_mode = "peripheral";
 };

I compiled a new tf-a, u-boot and fip following this guide. I flashed the new image and kept DT configuration 3.3.3. Unfortunately the issue remained the same. The usb-midi gadget will drop usb connection after a few minutes when an HDMI display is connected. Removing the HDMI will resolve the issue and the connection would work uninterrupted for several hours.

After this, I tried to implement DT configuration 3.3.4.

&usbotg_hs {
	compatible = "st,stm32mp15-hsotg", "snps,dwc2";
	phys = <&usbphyc_port1 0>;                                               
	phy-names = "usb2-phy";
	dr_mode = "peripheral";                                                 
	usb-role-switch;                                                        
	role-switch-default-mode = "peripheral";                             
	status = "okay";                                                     
};

Using this configuration without

port {
		usbotg_hs_ep: endpoint {
			remote-endpoint = <&con_usbotg_hs_ep>;            
		};
	};

Will result naturally to a phandle_references compiling error. Removing the port section from stusb1600@28 will resolve the error but the usb device would not get recognised by any hosts after boot although the FunctionFS usb-gadget is enabled.

Adding the port section to both DT configuration 3.3.4 and stusb1600@28 will get usb-c recognised but the dropping issue persists when HDMI is connected.

As an experiment I tried to remove

usb-role-switch;                                                        
role-switch-default-mode = "peripheral"; 

Without declaring usb-role-switch the usb-gadget will work as intended but an HDMI display wont get recognised.

I feel like I am missing something here. Based on the U-boot configuration OTG should not include PA10 but the issue points towards an HDMI - Usb-c OTG conflict. Any ideas or points on that would be really helpful.

Hello @KChar.1​ ,

Regarding the first point about u-boot, you are right. For the DK board

u-boot,force-b-session-valid;

is already present in "stm32mp157a-dk1-u-boot.dtsi".

You don't need to add "dr_mode = peripheral" here, the tutorial was talking about the two bold lines ;).

If you want to use the usbotg_hs in u-boot for your setup, you must have:

 	u-boot,force-b-session-valid;
 	u-boot,force-vbus-detection;

But I had a confirmation by expert that this is only mandatory if you need to use the usb otg in U-boot, which doesn't seem your case.

If you are working in the Linux, you don't need these changes.

--------------------------------

Let's go back to Linux side.

Normally you don't have to modify the .dtsi, because these files contain the default configuration related to the board. So you should not modify "stm32mp15xx-dkx.dtsi" about the usb port.

You must only modify "stm32mp157d-dk1.dts" and add your usbotg_hs configuration as below:

&usbotg_hs {
	compatible = "st,stm32mp15-hsotg", "snps,dwc2";
	phys = <&usbphyc_port1 0>;                                                /* 0: UTMI switch selects the OTG controller */
	phy-names = "usb2-phy";
	dr_mode = "peripheral";                                                   /* could be "host", see USB generic bindings [5] */
        usb-role-switch;                                                          /* see USB generic bindings [5] */role- 
        switch-default-mode = "peripheral";                                  /* could be "host", see USB generic bindings [5] */
	status = "okay";                                                          /* enable OTG */
};

usb-role-switch; is mandatory for your case

The configuration that you added in the .dts will redefine the variables.

Please can you restore all the dts, dtsi files as default.

Then only add the configuration above in "stm32mp157d-dk1.dts" without touching another file.

And tell me how it behaves.

Regards,

Kevin

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.

Hi @Kevin HUBER​ ,

Thanks a lot for looking into this and for the detailed reply! Indeed, I do not need usb otg in u-boot just on the linux side. I reverted tfa, ubot and fip back to the starter package as you suggested.

Regarding the stm32mp15xx-dkx.dtsi and stm32mp157d-dk1.dts: If I understand correctly the stm32mp15xx-dkx.dtsi is a general device tree that can be applied to all mp15 boards. To my understanding if a definition is not present in the board specific dts (ex. stm32mp15xx-dkx.dtsi) the node will get the definition from the dtsi. If my assumption is correct I am not sure how overwriting the definition in the board specific dts can have a different result but I am probably missing something here.

I reverted the linux kernel to the one from the starter package 3.1.0 just in case that any of my other modifications could be the source of the issue. After updating the kernel I just enabled the Midi Gadget ko and modified the stm32mp157d-dk1.dts as you suggested. Unfortunately the issue remains the same. The mp1 gets recognised by the host but it drops connection after a few minutes if HDMI is connected. If I disconnect the HDMI the connection is interrupted.

At this point I am not sure how to troubleshoot the issue further. I came to the conclusion that the best solution would be to solve this issue when designing a custom board. Until then I am planning to use a separate micro controller and connect it via serial to the MP1. I will use this micro controller as a midi hub to handle both usb-midi and normal midi data. It is not the most elegant solution but I think that it can work just fine for testing purposes and until I design a custom board. Any input on this temporary solution is very welcome too 🙂

Hello @KChar.1​ ,

To my understanding if a definition is not present in the board specific dts (ex. stm32mp15xx-dkx.dtsi) the node will get the definition from the dtsi. 

Yes you are right, it was just to explain you that normally, you should not modify the .dtsi, but only the .dts.

Because you talked about "Removing the port section from stusb1600@28" , I was not sure that your .dtsi files were reverted correctly.

The goal of my previous message was to retry with all the kernel files reverted to avoid any chance that you forgot something and to only add the usbotg_hs configuration in stm32mp157d-dk1.dts.

Unfortunately, it didn't help you which is strange.

Since you still have the issue, there is maybe some noise between the HDMI port and the usbotg one. I ask some expert and I come back to you when I have more information.

In the meantime, you can use your temporary solution as suggested.

Can I have your DTB file please? I will investigate directly from this one to see if I haven't thought of something.

Regards,

Kevin

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.