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.

27 REPLIES 27

Hi @Kevin HUBER​ ,

Thanks a lot for the explanation and your help. I do see the point.

I attach my dtb file here. In case you want to test my setup: It requires the midi gadget to be enabled in the linux kernel under

Device Drivers  --->
        USB support  --->
            <*>    USB Gadget Support  --->
                <m>    MIDI Gadget

And you can use the shell script from my original post.

Thanks again for looking into this and for your support!

Hello @KChar.1​ ,

Thank you for your gratitude.

I think your forgot to add the usbotg_hs configuration in your dts.

If I decompile your dtb by using the command dtc:

dtc stm32mp157d-dk1.dtb > stm32mp157d-dk1.dts

here the content of the node usb-otg that you have on your board:

	usb-otg@49000000 {
			compatible = "st,stm32mp15-hsotg\0snps,dwc2";
			reg = <0x49000000 0x10000>;
			clocks = <0x0d 0xa6>;
			clock-names = "otg";
			resets = <0x0d 0x4cc8>;
			reset-names = "dwc2";
			interrupts-extended = <0x19 0x2c 0x04>;
			g-rx-fifo-size = <0x200>;
			g-np-tx-fifo-size = <0x20>;
			g-tx-fifo-size = <0x100 0x10 0x10 0x10 0x10 0x10 0x10 0x10>;
			dr_mode = "otg";
			usb33d-supply = <0x4f>;
			power-domains = <0x1a>;
			wakeup-source;
			status = "okay";
			phys = <0x50 0x00>;
			phy-names = "usb2-phy";
			usb-role-switch;
			phandle = <0xc4>;
 
			port {
 
				endpoint {
					remote-endpoint = <0x51>;
					phandle = <0x6d>;
				};
			};
		};

You do not have for example the "dr_mode = "peripheral";" or the " switch-default-mode = "peripheral"; ".

If I look at the content of my DTB of my board (stm32mp157f-dk2) when I added the configuration usbotg_hs in stm32mp157f-dk2.dts, as explained in my yesterday message.

I have:

		usb-otg@49000000 {
			compatible = "st,stm32mp15-hsotg\0snps,dwc2";
			reg = <0x49000000 0x10000>;
			clocks = <0x0d 0xa6>;
			clock-names = "otg";
			resets = <0x0d 0x4cc8>;
			reset-names = "dwc2";
			interrupts-extended = <0x19 0x2c 0x04>;
			g-rx-fifo-size = <0x200>;
			g-np-tx-fifo-size = <0x20>;
			g-tx-fifo-size = <0x100 0x10 0x10 0x10 0x10 0x10 0x10 0x10>;
			dr_mode = "peripheral";
			otg-rev = <0x200>;
			usb33d-supply = <0x57>;
			power-domains = <0x1a>;
			wakeup-source;
			status = "okay";
			phys = <0x58 0x00>;
			phy-names = "usb2-phy";
			usb-role-switch;
			role-switch-default-mode = "peripheral";
			phandle = <0xd9>;
 
			port {
 
				endpoint {
					remote-endpoint = <0x59>;
					phandle = <0x7b>;
				};
			};
		};

You can see all the configuration from my post of yesterday.

So please can you double check that.

Once you have your dts correctly configured, if you still have the issue please follow the next part.

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

Regarding the investigation of your case, the experts showed me this errata:

https://www.st.com/resource/en/errata_sheet/es0438-stm32mp151x3x7x-device-errata-stmicroelectronics.pdf

Chapter 2.3.3

0693W00000Kb0dgQAB.png 

For testing purpose only, we will set your default MPU Frequency to 650MHz instead of 800Mhz and your VDD_CORE to 1.2V instead of 1.5V.

For doing that, please edit your file "stm32mp15xd.dtsi" (I know it's a dtsi file) in TF-A/ U-Boot / Linux and change the &cpu0_opp_table to:

&cpu0_opp_table {
		opp-650000000 {
			opp-hz = /bits/ 64 <650000000>;
			opp-microvolt = <1200000>;
			opp-supported-hw = <0x1>;
		};
};

More information on this manipulation is available on the wiki: https://wiki.st.com/stm32mpu/wiki/How_to_change_the_CPU_frequency#OPP_table

If you correctly made the change and populated your sdcard with the new binaries, you must see that the MPU Frequency of Uboot is now 650MHz:

U-Boot 2020.10-stm32mp-r2 (Mar 01 2022 - 09:45:33 -0500)
 
CPU: STM32MP157FAC Rev.Z
Model: STMicroelectronics STM32MP157F-DK2 Discovery Board
Board: stm32mp1 in trusted mode (st,stm32mp157f-dk2)
Board: MB1272 Var4.0 Rev.C-02
DRAM:  512 MiB
Clocks:
- MPU : 650 MHz
- MCU : 208.878 MHz
- AXI : 266.500 MHz
- PER : 24 MHz
- DDR : 533 MHz

and you must have several warnings during the boot of linux:

[   18.205467] ------------[ cut here ]------------
[   18.208753] WARNING: CPU: 1 PID: 110 at drivers/opp/of.c:874 _of_add_opp_table_v2+0x5ec/0x6dc
[   18.217285] Modules linked in:
[   18.220347] CPU: 1 PID: 110 Comm: kworker/1:3 Not tainted 5.10.61 #6
[   18.226618] Hardware name: STM32 (Device Tree Support)
[   18.231793] Workqueue: events deferred_probe_work_func
[   18.236988] [<c01108cc>] (unwind_backtrace) from [<c010c554>] (show_stack+0x10/0x14)
[   18.244687] [<c010c554>] (show_stack) from [<c0b97258>] (dump_stack+0xb8/0xcc)
[   18.251881] [<c0b97258>] (dump_stack) from [<c01249fc>] (__warn+0xec/0x104)
[   18.258872] [<c01249fc>] (__warn) from [<c0b926dc>] (warn_slowpath_fmt+0x64/0xc4)
[   18.266369] [<c0b926dc>] (warn_slowpath_fmt) from [<c0962ea0>] (_of_add_opp_table_v2+0x5ec/0x6dc)
[   18.275278] [<c0962ea0>] (_of_add_opp_table_v2) from [<c0962fcc>] (dev_pm_opp_of_add_table+0x3c/0x19c)
[   18.284589] [<c0962fcc>] (dev_pm_opp_of_add_table) from [<c0963164>] (dev_pm_opp_of_cpumask_add_table+0x38/0xfc)
[   18.294808] [<c0963164>] (dev_pm_opp_of_cpumask_add_table) from [<c096a8b0>] (cpufreq_init+0xb0/0x220)
[   18.304121] [<c096a8b0>] (cpufreq_init) from [<c0967818>] (cpufreq_online+0x420/0xa0c)
[   18.312021] [<c0967818>] (cpufreq_online) from [<c0967ea0>] (cpufreq_add_dev+0x8c/0xc4)
[   18.320020] [<c0967ea0>] (cpufreq_add_dev) from [<c0726670>] (subsys_interface_register+0xa4/0xf8)
[   18.329030] [<c0726670>] (subsys_interface_register) from [<c096506c>] (cpufreq_register_driver+0x158/0x378)
[   18.338847] [<c096506c>] (cpufreq_register_driver) from [<c096ad5c>] (dt_cpufreq_probe+0x2bc/0x3e4)
[   18.347856] [<c096ad5c>] (dt_cpufreq_probe) from [<c072aaa0>] (platform_drv_probe+0x48/0x98)
[   18.356360] [<c072aaa0>] (platform_drv_probe) from [<c0728380>] (really_probe+0x21c/0x508)
[   18.364561] [<c0728380>] (really_probe) from [<c0728834>] (driver_probe_device+0x78/0x16c)
[   18.372860] [<c0728834>] (driver_probe_device) from [<c072634c>] (bus_for_each_drv+0x84/0xd0)
[   18.381462] [<c072634c>] (bus_for_each_drv) from [<c07280c4>] (__device_attach+0xf0/0x188)
[   18.389660] [<c07280c4>] (__device_attach) from [<c0727114>] (bus_probe_device+0x84/0x8c)
[   18.397859] [<c0727114>] (bus_probe_device) from [<c0727684>] (deferred_probe_work_func+0x9c/0xdc)
[   18.406866] [<c0727684>] (deferred_probe_work_func) from [<c0141950>] (process_one_work+0x1dc/0x5ac)
[   18.415975] [<c0141950>] (process_one_work) from [<c0141f68>] (worker_thread+0x248/0x520)
[   18.424175] [<c0141f68>] (worker_thread) from [<c0148368>] (kthread+0x144/0x180)
[   18.431569] [<c0148368>] (kthread) from [<c0100148>] (ret_from_fork+0x14/0x2c)
[   18.438751] Exception stack(0xc2ee5fb0 to 0xc2ee5ff8)
[   18.443817] 5fa0:                                     00000000 00000000 00000000 00000000
[   18.452013] 5fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[   18.460207] 5fe0: 00000000 00000000 00000000 00000000 00000013 00000000
[   18.466860] ---[ end trace a4a11e4234f9ae26 ]---
[   18.471438] cpu cpu0: OPP table can't be empty
[   18.476102] ------------[ cut here ]------------

Once your linux boot is completed, you can verify the frequency by using the command:

root@stm32mp1:~# cat /sys/kernel/debug/clk/clk_summary | grep ck_mpu
 ck_mpu                               0        0        0   650000000          0     0  50000

And verify that you have 650000000

Now please try again your test to see if the error disappeared or not...

Hope it helps!

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 for this! Indeed, I reverted the dtb after testing and uploaded the reverted one by accident. Apologies for that.

I tried again to flash the starter package with a modified dtb based on your previous post. (I upload the correct dtb in case its useful) but unfortunately the issue remains the same.

Then I moved to the second suggestion. The note in the errata looked to match the issue. I builded a new image based on

this wiki. After applying the patches in every step

for p in $(ls -1 ../../sources/arm-ostl-linux-gnueabi/linux-stm32mp-*/*.patch); do patch -p1 < $p; done

I modified the equivalent "stm32mp15xd.dtsi" as per your suggestion. I did this for steps 5 and 6 of the wiki which included linux / tfa / u-boot. Then I flashed the new FIP_artifacts with Cube Programmer. My boot log looked very similar to yours and after boot I verified the new CPU clock as below.

0693W00000KbBZzQAN.pngThen I executed the usb-gadget script and tested. The communication was uninterrupted for almost two hours. After this I decided to test its behaviour with an HDMI connected. I plugged the HDMI and within 5 minutes the connection dropped with an unknown URB request. I run several tests (ex booting with the HDMI connected, connecting the devices in different orders, running the script on boot etc) but the behaviour is always the same, if the HDMI is connected the USB communication will drop within a short amount of time. Based on this observation I am thinking that although the note on the errata (a deterioration of the usb hs eye diagram) would match the issue it does not explain how the HDMI can affect usb communication.

In the meanwhile I implemented the alternative solution by using a teensy and sending serial from the M4 to the teensy and then to usb-midi and hardware midi. This is working fine for testing purposes. If the issue is related with AP10 or a hardware conflict I can use this solution until I design a custom board. If there is any way to verify this would be great as I can move forward with the development for now. Please let me know if you have any ideas or suggestions based on that.

Hello @KChar.1​ ,

Too bad that it still doesn't work. Well done for the alternative implementation!

To help you more on this case and to provide you an answer if the issue is really related to PA10, I made an internal ST ticket with number 124022

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.
Erwan SZYMANSKI
ST Employee

Hello @KChar.1​ 

I try to reproduce your bug from my side to make some investigations on this point.

As a starting point, I took your different device trees in order to have the same setup as yours. I confirm that USB Multicomposite Gadget is well recognized by the Linux host PC.

First, using wireshark to monitor messages, I pinged the USB interface activated on the board in loop (without HDMI connected) and the ping works well. If I stop the usb-gadget on the board, the ping is blocked (so the activity looks OK for now).

Now I have connected an HDMI screen to be it in the same situation that produces troubles from your side, but the communication looks not interrupted after 10 minutes. Could you explain how do you test your setup exactly (in term of communication), just to help me reproducing the bug ? Or maybe this situation is already supposed to make my usb-gadget down ?

Kind regards.

Erwan.

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 @Erwan SZYMANSKI​ ,

Thank so much you for looking into this! To reproduce the behaviour I am using a usb-midi gadget (the script from my original post) and alsaplayer or pure-data for generating continuous midi messages. I think that alsa is more convenient for reproducing this issue since it is coming with the wenston image.

You can download any midi file and then run it through alsa

aplaymidi -p 20:0 /home/root/miditest.mid

to find the gadget port you can use

amidi -l

On the host side I am using Midi Monitor and wireshark. The timing of the behaviour is not consistent. Some times the connection will drop after a couple of minutes and some others it can crash even after 45 minutes to an hour. When the connection is dropped I receive a URB drop request on wireshark.

Please let me know if I can provide any other information or files for making this easier.

Hello @KChar.1​ ,

Well I think I have something very close to your setup right now. Find below my Wireshark packet when we can identify USB packet when I plug to the USB-midi gadget, and then the MIDI packets that pass through when I want to play my midi piano file.

0693W00000Lx6zqQAB.pngOn board side, I plugged an HDMI monitor, quite standard, to make some HDMI activity. Should it be enough to replicate ? Do you need to have some screen activity to make it crash ?

Rgs.

Erwan

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 @Erwan SZYMANSKI​ ,

The wireshark screenshot looks identical to mine. On my setup I use the weston extended image for DK1. The only screen activity is the desktop background and a weston terminal.

Thanks again for looking into this and for your support.

@KChar.1​ ,

Thanks for your answer.

I made a script to let the USB gadget communicating in loop with sending its midi file. Unfortunately, after 2 hours of run, with some video launched on the monitor (the video available by default on the weston desktop background) to increase the screen activity, the USB-OTG did not crash.

I am actually using a STM32MP157C-DK2 (which is the same as yours but with a GPU and few IPs more) to replicate, but with your device tree to make it work as a DK1 (so it removes all the feature available on DK2 to only let the ones present on DK1).

Tomorrow I will try to get the same board reference as yours and replicate this. I hope I can replicate your problem with this board. I will make you a feedback ASAP.

Regards.

Erwan.

PS : My reference C DK2 board works at 650MHz, as yours is up to 800. I saw in the thread that you already tried to make it slow at 650MHz without any result. Can you confirm me this information ?

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.

Update : I reproduced the same setup as yesterday with an STM32MP157F-DK2 (still with device trees of DK1), just to match with your CPU frequency (800MHz). I still not have the USB-OTG crash.

Can you give me the reference of the power supply used with your board ?

Regards.

Erwan.

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.