Kinetis k70 usb ethernet in linux

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Kinetis k70 usb ethernet in linux

Jump to solution
2,766 Views
ethanliu
Contributor II

So I got a PCB board with Kinetis K70 and 64MB DDR ram,  the PCB board got a usb full speed OTG port and it's the only port I can use to communicate with other device. I have successfully port u-boot / uClinux on the PCB board, I also implemented USB Ethernet in u-boot. when I turn on the power, the u-boot run first, and it can do tftp load linux image via usb cable connected to my linux PC host, which looks great! 

The problem now I am facing is that I want USB Ethernet too in linux so that I can use NFS to do more. but it seems the USB Ethernet isn't work in linux, what I am seeing now is the gadget udc driver( I have implemented kinetis k70 udc driver in linux) most of the time can only response reset interrupt. and that's it, no more usb setup command receive from linux host.  sometime with luck I can see the board receive setup command and can do USB emulation.

So, in a word, usb ethernet works in u-boot, but not works in linux, my udc driver is allmost the same between u-boot and linux. I have no idea what happened in linux, I am thinking some of the causes: 1. usb BDT/buffer can only be in SRAM and linux is running in DDR ram;  2. maybe the UDC initialization need to be different between u-boot and linux; 3. power supply is not enough in linux because it enable LCD etc..

Can someone give me advice? appreciated!

Labels (2)
1 Solution
2,038 Views
ethanliu
Contributor II

Hi Mike,

I think I found the root cause to this is the wrong use of USB0_STAT register. 

According to the Spec: 

"the STAT register is actually a four byte FIFO that allows the processor core to process one transaction while
the SIE is processing the next transaction. Clearing the TOKDNE bit in the ISTAT register causes the SIE to update the STAT register with the contents of the next STAT value".

before aware of this, when use token done interrupt occurred. I read STAT register value out when I want its value. then I realized the correct way should be use a local variable to store the value first and then handle it later. Otherwise, the STAT value may not the correct value I want ( it may updated because ISTAT cleared or next token done interrupt arrived? not sure about this).

Now I can see USB Ethernet in my Linux host, all the processes of enumeration looks OK now.

As to the BDT buffer, yes, you are correct that it can be placed in external SDRAM, I allocated the buffer through DMA allocation.

Thanks a lot for your support.  Appreciated!

Thanks!

Ethan

View solution in original post

19 Replies
2,038 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi,

I have quite few experience to run K70 with ucLinux.

From the issue description, I think the K70 USB module re-initialization process with issues.

And there could bring problems when HS USB BDT/buffer located in external SDRAM, which works in SRAM.

For FS USB BDT/buffer can be placed in both SDRAM and internal SRAM.

I find the EmCraft provides Linux BSP for K70, please check here for the detailed info.

Thank you for the attention.


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
2,038 Views
ethanliu
Contributor II

Mike,

Thank you! the linux I ported on my PCB board is the one provided by EmCraft, but there's no USB device driver but only USB host driver, so I had created a new USB FS device driver for u-boot / linux, as I said, my driver works no problem in u-boot, but in linux, most of the time it just handled "reset interrupt".  I don't think it's the BDT address issue, because I have pointed BDT to SRAM by using ioremap().  I have new found recently, during mount NFS in linux, because my UDC driver is not working, so panic and timeout came out, log as below:

......

........Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
........Rebooting in 10 seconds....

if this message came out and at this point I manually unplug/plug usb cable, the USB setup/enumeration 100% ok.

I just don't get the point, I mean, it seems my UDC dirver works but it only happened in this case.

what I really want is the usb cable always plug in PC host, u-boot runs first and tftp load linux image by USB Ethernet.

then linux get started and again, mount NFS by USB Ethernet. you don't need to unplug/plug the cable anytime.

0 Kudos
2,038 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Ethan,

From the description, the USB device(K70) need be re-enumerated when boot up without disconnect USB cable from Your  Linux PC host. You could try clear and set USB Command Register (USBHS_USBCMD) [RS] bit to enable a pull-up on DP and initiate an attach event (software emulate a USB port attach event).

Wish it works.


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
2,038 Views
ethanliu
Contributor II

Hi Mike,

Are you saying I should set USB high speed port register? I am using USB full/low-speed OTG port, it's the only port I can use, that's USB0_XXX in data sheet. I did reset the port by disable/enable pull-up, but it seems not working, to be more specific, I disable DP pull-up( clear bit 4 in USB0_CONTROL) when exit u-boot, and linux start up, in linux UDC driver, I reset the USB module and re-initialize it and finally enable DP pull-up. but it seems not working, I added some debug info in my UDC drvier:

...............

usb0: eth_open
IP-Config: Complete:
device=usb0, addr=192.168.1.2, mask=255.255.255.0, gw=192.168.1.1,
host=192.168.1.2, domain=, nis-domain=(none),
bootserver=192.168.1.1, rootserver=192.168.1.1, rootpath=
Looking up port of RPC 100003/2 on 192.168.1.1
USB_Reset_Handler, 777
USB_Reset_Handler, 777
bmRequestType = 0x80
bRequest = 0x6
wValue = 0x100
wIndex = 0x0
wLength = 0x40

USB_Reset_Handler, 777
USB_Reset_Handler, 777
USB_Reset_Handler, 777
USB_Reset_Handler, 777

.......................

As you can see, sometimes, I can get setup(0x80,0x06...) command from host and I send back the USB descriptor host wanted( I don't think there's error in this part). but them it just reset again...I am not familiar with linux, just learning how to write usb gadget driver.

Thanks & Regards,

Ethan

0 Kudos
2,038 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Ethan,

For I don't know which K70 USB port you are using, I don't suggest to use K70 USB HS module.

What I want to do is to software emulate a USB port detach & attach operation.

From the debug info, it looks like the software emulate USB port plug out/in works.

Could you confirm that the Linux PC detected the USB device detached when you disable DP pull-up( clear bit 4 in USB0_CONTROL) when exit u-boot?


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
2,038 Views
ethanliu
Contributor II

Mike,

Yes, My linux PC host detects USB disconnect when exit U-BOOT, I can see the log by "dmesg".

I tried linux USBMON tool, what I found is the linux PC did send setup command to the device, but these commands isn't received by my code (sometimes it received, as the log I posted above). 

ffff88008ec31e40 3731124026 S Ci:1:000:0 s 80 06 0100 0000 0040 64 <
ffff88008ec31e40 3731124230 C Ci:1:000:0 -32 0

this is the command sent by PC host, as you can see, the error code is -32,  it maybe something wrong with the BDT/buffer setting, or the DATA/PID isn't correct, you said USB-FS(that's the USB port I am using) BDT/buffer can be placed in external DDR ram or internal SRAM, correct? if so, do you have any suggestion on how to allocate BDT/buffer address in uClinux for K70?  I am now have a space in SRAM as resources reserved then during "driver probe", use ioremap to get that location and point it to BDT/buffer, I tried use dma pool, it seems the same. 

Thanks & Regards,

Ethan

0 Kudos
2,038 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Ethan,

Sorry for the later reply.

Yes, if you are using the FS USB module, you can place BDT/buffer at external DDR SDRAM or internal SRAM.

Please pay attention to the internal SRAM, which is split into two logical arrays that are 32-bit wide

pastedImage_1.png

There with a Note about burst access SRAM memory:

pastedImage_2.png

If possible, please place the BDT/Buffer at the same SRAM logic array.

Thank you for the attention.

best regards,

Mike

0 Kudos
2,038 Views
ethanliu
Contributor II

Hi Mike,

Thanks for the help!

Since my USBFS driver works fine in U-BOOT, so I decided not configure again the USB BDT/buffer after entering linux.

but just disconnect DP pull-up when exit u-boot.  below is part of the uClinux booting log, the CPU is MK70FN1M0VMJ15.  As you can see, my BDTtable as well as the buffer is located in SRAM (around 0x1fff6400).  I believe is correct, right?   but it does the same,  the USB just keep reset and reset, ( log: USB_Reset_Handler, 784 ). from the Linux HOST usbmon log, it seems the device is not response the "set address" command correctly.

the funny thing is as I said before, when the kernel panic happened (see bottom part of the log), I pull-out/plug-in the usb cable, and the usb enumeration is always successful. it's weird....I don't know what the kernel does after "panic", but my driver seems ok after kernel "panic"...kind of embarrassed.

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

.....

.....

DSPI: controller 0 at hz=72000000,irq=26
DSPI: controller 1 at hz=72000000,irq=27
tBDTtable = 0x1fff6400
BufferPointer bEP0OUT_EVEN = 0x1fff6488
BufferPointer bEP0IN_EVEN = 0x1fff6508
k70-udc version 11 May 2018
k70_ep_alloc_request, ep0
usb0: MAC 22:a9:32:52:8e:32
usb0: HOST MAC 12:57:48:13:60:70
g_ether gadget: adding config #1 'CDC Ethernet (ECM)'/0821a3f0
g_ether gadget: adding 'cdc_ethernet'/703d8d80 to config 'CDC Ethernet (ECM)'/0821a3f0
k70_ep_alloc_request, ep1in-int
g_ether gadget: CDC Ethernet: full speed IN/ep2in-bulk OUT/ep3out-bulk NOTIFY/ep1in-int
g_ether gadget: cfg 1/0821a3f0 speeds: full/low
g_ether gadget: interface 0 = cdc_ethernet/703d8d80
g_ether gadget: interface 1 = cdc_ethernet/703d8d80
g_ether gadget: Ethernet Gadget, version: Memorial Day 2008
g_ether gadget: g_ether ready
bound to g_ether
TCP cubic registered
NET: Registered protocol family 17
ARMv7-M VFP Extension supported
usb0: eth_open
IP-Config: Complete:
device=usb0, addr=192.168.1.2, mask=255.255.255.0, gw=192.168.1.1,
host=192.168.1.2, domain=, nis-domain=(none),
bootserver=192.168.1.1, rootserver=192.168.1.1, rootpath=
Looking up port of RPC 100003/2 on 192.168.1.1
USB_Reset_Handler, 784
USB_Reset_Handler, 784
USB_Reset_Handler, 784
USB_Reset_Handler, 784
USB_Reset_Handler, 784
USB_Reset_Handler, 784
rpcbind: server 192.168.1.1 not responding, timed out
Root-NFS: Unable to get nfsd port number from server, using default
Looking up port of RPC 100005/1 on 192.168.1.1
rpcbind: server 192.168.1.1 not responding, timed out
Root-NFS: Unable to get mountd port number from server, using default
Root-NFS: Server returned error -110 while mounting /work/nfs
VFS: Unable to mount root fs via NFS, trying floppy.
List of all partitions:
No filesystem could mount root, tried: nfs
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
USB_Reset_Handler, 784
USB_Reset_Handler, 784
USB_Reset_Handler, 784
USB_SetAddress, add = 14
g_ether gadget: full speed config #1: CDC Ethernet (ECM)
k70_ep_enable, ep1in-int
g_ether gadget: init ecm
g_ether gadget: notify connect false
g_ether gadget: activate ecm
k70_ep_enable, ep2in-bulk
k70_ep_enable, ep3out-bulk
k70_ep_alloc_request, ep2in-bulk
k70_ep_alloc_request, ep2in-bulk
k70_ep_alloc_request, ep3out-bulk
k70_ep_alloc_request, ep3out-bulk
usb0: qlen 2
g_ether gadget: ecm_open
usb0: eth_start

......

......

Thanks & Regards,

Ethan

0 Kudos
2,038 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Ethan,

Sorry for the delay reply.

Could you measure the VOUT33 pin voltage when Linux PC doesn't successfully enumerate K70 device vs. Linux PC successfully enumerate K70 device?

If there exists the voltage difference?

We want to make sure the K70 VREG module works in RUN mode and USB module doesn't work in suspend state.

pastedImage_1.png


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
2,038 Views
ethanliu
Contributor II

Mike,

I checked the schematic and measured the VOUT33 voltage, there's a 10µF capacitor added to the VOUT33 pin, the voltage is 3.331v, I am not seeing the voltage change during the u-boot / uClinux start-up, however, when "panic" raised, I unplug the usb cable, the voltage drop to aroun 0.16v.  the plug in usb cable, voltage change back to 3.331v, and the enumerate is successful.

Thanks,

Ethan

0 Kudos
2,038 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Ethan,

I checked the VOUT33 output capacitor with below value at K70 datasheet:

pastedImage_1.png

pastedImage_2.png

So, I think you can refer TWR-K70 board to replace a 2.2uF capacitor with VOUT33 pin:

pastedImage_3.png

Your K70 board as USB device is self-powered device, right?

When "panic" raised, the VOUT33 with voltage drop, which indicate the VREGIN pin with Power off/on processing?


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
2,038 Views
ethanliu
Contributor II

Mike,

thank you. 

Yes, my K70 board usb device is self-powered.

what I was trying to say is that there's no change for the VOUT33 volt no matter "panic" raised or not, it's around 3.331v,  the VOUT33 volt only change if I unplug the usb cable.

I tried replace 10uF capacitor with 2.2uF, but it does the same,  although the VOUT33 volt change to around 3.26v. 

below is part of signals of my K70 board:  the USB_PWR_IN is connected directly to VBUS ( USB VDD). we don't use BACKUP_BAT_POS usually.   I haven't added any code related to USB regulator, Is there any configuration needed  for the USB regulator?

pastedImage_1.png

Thanks,

Ethan

0 Kudos
2,038 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Ethan,

Sorry for the later reply.

There without any setting at K70 USB regulator module.

From you feedback below, there shows when you unplug the USB cable, the VREGIN without power.

K70 VDD still with power at this point, right? Just make sure, K70 doesn't POR at this time.

pastedImage_1.png

Could you try to re-emulate USB device at U-BOOT phase? If it could be re-emulate successfully?

And could you print the FS USB module registers value out and check what's the different between unplug/plug USB cable?

We expect unplug USB cable just reset the USB transceiver, which doesn't modify the USB module registers setting.


Have a great day,
Mike

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
2,038 Views
ethanliu
Contributor II

Hi Mike,

for your question:  yes, K70 VDD still with power, my PCB got self power supply. my driver seems very well in U-BOOT, no matter cold power or software reset the PCB board, U-BOOT always can load kernel image through USB Ethernet.

here's some of the register value when unplug/plug USB cable:

plug:

ADDINFO = 0x1
OTGISTAT = 0x60
OTGSTAT = 0x20
OTGCTL = 0x0
ISTAT = 0x11
STAT = 0x0
CTL = 0xc3
ADDR = 0x0
USBCTRL = 0x40
CONTROL = 0x10
USBTRC0 = 0x2

unplug

ADDINFO = 0x1
OTGISTAT = 0x60
OTGSTAT = 0x20
OTGCTL = 0x0
ISTAT = 0x10
STAT = 0x0
CTL = 0x83
ADDR = 0x0
USBCTRL = 0x40
CONTROL = 0x10
USBTRC0 = 0x0

I am still thinking why my driver won't response USB set address command(or even most of the time, it won's receive this command, but the host does send it), here's what I do: after received set address command from host, send zero length packet to host, wait for another interrupt that zero packet is sent, then set USB ADDR register.  there maybe some bugs in the logic, I will continue digging my code. will let you know if I have new found.

Thanks & Regards,

Ethan

0 Kudos
2,038 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Ethan,

Thank you for the info.

Please check the MPU_CESR register value.

I checked K70 bare metal USB device project, which during USB initialization code will close the MPU (MPU is enabled default).

pastedImage_1.png

Could you try to disable the MPU after ucLinux boot up?

I know ucLinux need MPU enabled, while you could try if MPU could affect.

best regards,

Mike

0 Kudos
2,039 Views
ethanliu
Contributor II

Hi Mike,

I think I found the root cause to this is the wrong use of USB0_STAT register. 

According to the Spec: 

"the STAT register is actually a four byte FIFO that allows the processor core to process one transaction while
the SIE is processing the next transaction. Clearing the TOKDNE bit in the ISTAT register causes the SIE to update the STAT register with the contents of the next STAT value".

before aware of this, when use token done interrupt occurred. I read STAT register value out when I want its value. then I realized the correct way should be use a local variable to store the value first and then handle it later. Otherwise, the STAT value may not the correct value I want ( it may updated because ISTAT cleared or next token done interrupt arrived? not sure about this).

Now I can see USB Ethernet in my Linux host, all the processes of enumeration looks OK now.

As to the BDT buffer, yes, you are correct that it can be placed in external SDRAM, I allocated the buffer through DMA allocation.

Thanks a lot for your support.  Appreciated!

Thanks!

Ethan

2,038 Views
yechielcohen
Contributor I

Hi Ethan,

I have enjoyed reading this thread very much.

I will appreciate it, if you could please share the USB device driver (UDC driver for the K70) in u-boot and in linux? In my case I would like to bind the UDC to the storage gadget driver.

Best regards,

Yechiel

0 Kudos
2,038 Views
ethanliu
Contributor II

Hi Yechiel,

Sorry I haven't noticed your message.

Actually I haven't worked on the k70 after that as I am busy my work, the udc driver was part of my learning and experiment,  the code is not completed and got some defects in it, I don't want to confuse you.... instead, I will suggest you refer to linux provide by Emcraft, they provide some linux folk for kinetis(k70) and it contains udc driver,  here's the link you can look into:

K70: KHCI USB-FS driver implementation for device mode by aAXEe · Pull Request #6 · EmcraftSystems/l... 

Hope it help!

Regards,

Ethan

0 Kudos
2,038 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

Hi Ethan,

Glad to hear the issue fixed.

Thank you for the knowledge sharing.

best regards,

Mike

0 Kudos