MK60 Processor Expert USB enumeration issue on reset step

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

MK60 Processor Expert USB enumeration issue on reset step

Jump to solution
2,001 Views
LRawlyk
Contributor III

Hello,

I have a board that uses the MK60FN1M0VLQ12 processor with a USB3300 PHY where I want to interface USBHS communication.

So as an initial attempt to get this USB device responsive to USB enumeration I made a Processor Expert project with an USB component and implemented a Device Descriptor response to the USB enumeration initial reset.

However the USB enumeration fails: bLength of 0 incorrect, should be 18, and all descriptor fields are empty. And doing USB packet sniffing confirms no packet is ever exchanged between the device and the host.

However in the MCU I verify that the USB1_OnDeviceReset() routine is called upon an incoming reset, and the USB1_DeviceInitEndpoint() routine used to send the descriptor finishes without errors. Consequently the USB1_OnDeviceSetupPacket() routine is never called.

What am I doing wrong? I'm wrting my main.c and Events.c down here as well as attaching the project.

main.c:

/* ###################################################################
** Filename : main.c
** Project : USB_interface_PE
** Processor : MK60FN1M0VLQ12
** Version : Driver 01.01
** Compiler : GNU C Compiler
** Date/Time : 2022-02-16, 11:41, # CodeGen: 0
** Abstract :
** Main module.
** This module contains user's application code.
** Settings :
** Contents :
** No public methods
**
** ###################################################################*/
/*!
** @file main.c
** @version 01.01
** @brief
** Main module.
** This module contains user's application code.
*/
/*!
** @addtogroup main_module main module documentation
** @{
*/
/* MODULE main */


/* Including needed modules to compile this module/procedure */
#include "Cpu.h"
#include "Events.h"
#include "USB1.h"
/* Including shared modules, which are used for whole project */
#include "PE_Types.h"
#include "PE_Error.h"
#include "PE_Const.h"
#include "IO_Map.h"
/* User includes (#include below this line is not maintained by Processor Expert) */

LDD_TDeviceData* usb;
int user_data;

LDD_TError USB_initControlEndpoint(void)
{
LDD_USB_TDevDescriptor device_descriptor;

device_descriptor.bLength = sizeof(device_descriptor);
device_descriptor.bDescriptorType = LDD_USB_DT_DEVICE;
device_descriptor.bcdUSB = 0x0200; // USB2.0
device_descriptor.bDeviceClass = 0xff; // class code is vendor specified
device_descriptor.bDeviceSubClass = 0x00;
device_descriptor.bDeviceProtocol = 0x00;
device_descriptor.bMaxPacketSize0 = 64;
device_descriptor.idVendor = 0x0424;
device_descriptor.idProduct = 0x0004;
device_descriptor.bcdDevice = 1; // device version
device_descriptor.iManufacturer = 1;
device_descriptor.iProduct = 2;
device_descriptor.iSerialNumber = 3;
device_descriptor.bNumConfigurations = 1;

return USB1_DeviceInitEndpoint(usb, (LDD_USB_TEpDescriptor*)&device_descriptor, 0);
}

/*lint -save -e970 Disable MISRA rule (6.3) checking. */
int main(void)
/*lint -restore Enable MISRA rule (6.3) checking. */
{
/* Write your local variable definition here */

/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization. ***/

/* Write your code here */

usb = USB1_Init(&user_data);

LDD_TError err_enable, err_disable;
err_enable = USB1_Enable(usb);

/*** Don't write any code pass this line, or it will be deleted during code generation. ***/
/*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
#ifdef PEX_RTOS_START
PEX_RTOS_START(); /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
#endif
/*** End of RTOS startup code. ***/
/*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
for(;;){}
/*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/

/* END main */
/*!
** @}
*/
/*
** ###################################################################
**
** This file was created by Processor Expert 10.5 [05.21]
** for the Freescale Kinetis series of microcontrollers.
**
** ###################################################################
*/

Events.c:

/* ###################################################################
** Filename : Events.c
** Project : USB_interface_PE
** Processor : MK60FN1M0VLQ12
** Component : Events
** Version : Driver 01.00
** Compiler : GNU C Compiler
** Date/Time : 2022-02-16, 11:41, # CodeGen: 0
** Abstract :
** This is user's event module.
** Put your event handler code here.
** Contents :
** Cpu_OnNMIINT - void Cpu_OnNMIINT(void);
**
** ###################################################################*/
/*!
** @file Events.c
** @version 01.00
** @brief
** This is user's event module.
** Put your event handler code here.
*/
/*!
** @addtogroup Events_module Events module documentation
** @{
*/
/* MODULE Events */

#include "Cpu.h"
#include "Events.h"

#ifdef __cplusplus
extern "C" {
#endif

/* User includes (#include below this line is not maintained by Processor Expert) */

LDD_TError USB_initControlEndpoint(void);
LDD_TError reset_error;

/*
** ===================================================================
** Event : Cpu_OnNMIINT (module Events)
**
** Component : Cpu [MK60FN1M0LQ15]
*/
/*!
** @brief
** This event is called when the Non maskable interrupt had
** occurred. This event is automatically enabled when the [NMI
** interrupt] property is set to 'Enabled'.
*/
/* ===================================================================*/
void Cpu_OnNMIINT(void)
{
/* Write your code here ... */
}

/*
** ===================================================================
** Event : USB1_OnDeviceReset (module Events)
**
** Component : USB1 [USB1_LDD]
*/
/*!
** @brief
** Called after the reset signal is detected on the USB1 bus,
** OnDeviceReset() event is enabled and USB1 module is enabled.
** See SetEventMask() and GetEventMask() methods. All pending
** transfers are cancelled and all EPs are disabled before this
** event is called. Device address is set to "0".
** @param
** UserDataPtr - User data pointer. This
** pointer is passed as the parameter of Init
** method.
*/
/* ===================================================================*/
void USB1_OnDeviceReset(LDD_TUserData *UserDataPtr)
{
/* Write your code here ... */
reset_error = USB_initControlEndpoint();
}

/*
** ===================================================================
** Event : USB1_OnDeviceSpeedDetect (module Events)
**
** Component : USB1 [USB1_LDD]
*/
/*!
** @brief
** Called after the device detects bus speed, OnBusSpedDetect()
** event is enabled and USB1 module is enabled. See
** SetEventMask() and GetEventMask() methods. EP 0 should be
** enabled and configured after the USB1 speed is known.
** @param
** UserDataPtr - User data pointer. This
** pointer is passed as the parameter of Init
** method.
** @param
** CurrentSpeed - Current device speed.
*/
/* ===================================================================*/
void USB1_OnDeviceSpeedDetect(LDD_TUserData *UserDataPtr, LDD_USB_TBusSpeed CurrentSpeed)
{
/* Write your code here ... */
}

/*
** ===================================================================
** Event : USB1_OnDeviceSuspend (module Events)
**
** Component : USB1 [USB1_LDD]
*/
/*!
** @brief
** Called after the suspend condition is met, OnDeviceSuspend()
** event is enabled and USB1 module is enabled. See
** SetEventMask() and GetEventMask() methods.
** @param
** UserDataPtr - User data pointer. This
** pointer is passed as the parameter of Init
** method.
*/
/* ===================================================================*/
void USB1_OnDeviceSuspend(LDD_TUserData *UserDataPtr)
{
/* Write your code here ... */
}

/*
** ===================================================================
** Event : USB1_OnDeviceResume (module Events)
**
** Component : USB1 [USB1_LDD]
*/
/*!
** @brief
** Called after the resume signaling is done, OnDeviceResume()
** event is enabled and USB1 module is enabled. See
** SetEventMask() and GetEventMask() methods.
** @param
** UserDataPtr - User data pointer. This
** pointer is passed as the parameter of Init
** method.
*/
/* ===================================================================*/
void USB1_OnDeviceResume(LDD_TUserData *UserDataPtr)
{
/* Write your code here ... */
}

/*
** ===================================================================
** Event : USB1_OnDeviceSetupPacket (module Events)
**
** Component : USB1 [USB1_LDD]
*/
/*!
** @brief
** Called after the setup packet is received into the internal
** buffer, OnSetupPacket() event is enabled and USB1 module is
** enabled. See SetEventMask() and GetEventMask() methods. Use
** the method GetSetupPacket() to copy setup packet to the user
** buffer.
** @param
** UserDataPtr - User data pointer. This
** pointer is passed as the parameter of Init
** method.
** @param
** EpNum - Endpoint number.
*/
/* ===================================================================*/
void USB1_OnDeviceSetupPacket(LDD_TUserData *UserDataPtr, uint8_t EpNum)
{
/* Write your code here ... */
}

/* END Events */

#ifdef __cplusplus
} /* extern "C" */
#endif

/*!
** @}
*/
/*
** ###################################################################
**
** This file was created by Processor Expert 10.5 [05.21]
** for the Freescale Kinetis series of microcontrollers.
**
** ###################################################################
*/

Labels (2)
0 Kudos
1 Solution
1,075 Views
LRawlyk
Contributor III

I had forgotten to make an update to conclude this post.

Finally, there were 2 issues:

  • the device descriptor struct being declared as const, making it be place in the .text memory section and thus not reachable by the DMA.
  • the USB cable had a few centimeters of flying wires that disturbed the communication while on High Speed

View solution in original post

0 Kudos
8 Replies
1,076 Views
LRawlyk
Contributor III

I had forgotten to make an update to conclude this post.

Finally, there were 2 issues:

  • the device descriptor struct being declared as const, making it be place in the .text memory section and thus not reachable by the DMA.
  • the USB cable had a few centimeters of flying wires that disturbed the communication while on High Speed
0 Kudos
1,988 Views
LRawlyk
Contributor III

It turns out setting the device data rate parameter of the USB PE component to "Full Speed" instead of "Dual Speed" makes the device pass the reset part of the enumeration, receiving a setup packet.

However after implementing basic setup packet handling, I can't seem to send packets to the host, even though all routines finish with no error.

Also from what I understand configuring the USB PE component like this forces the communication to be in USB Full Speed instead of High Speed, which I'm not excited about since in my application I was looking for the highest data throughput possible...

0 Kudos
1,926 Views
LRawlyk
Contributor III

I have reviewed the documentation on the USB HS OTG Controller module from the reference manual and this document on the EHCI data structures, which are used in the PE module, as well as done some extensive debugging but have not been able to find the issue.

I have been using FS since it gets further into the enumeration. I find it hard to be a hardware problem since I notice receive a well formed setup packet in the MCU. From the host side I find, through USB packet sniffing, that I do seem to send packets from the MCU, but my responses are filled with FFs.

wireshark_screenshot.png

@jiri_rezler  I've seen you resolve a similar issue with an Internal USB module for the MK64 on Processor Expert. Would you have an idea for my issue? 

I've made small changes to my project so I'm attaching it again.

 
0 Kudos
1,919 Views
bobpaddock
Senior Contributor III

Consider using TinyUSB in place of the NXP stack.

I found it easer to get working than the NXP stack, and it worked better on some poorly designed hardware that I inherited.

https://www.tinyusb.org

 

0 Kudos
1,905 Views
LRawlyk
Contributor III

Thanks for the suggestion. It does seem like it would require me to do some porting for the MK60 since it's not supported. On which MCU did you use the TinyUSB stack?

0 Kudos
1,901 Views
bobpaddock
Senior Contributor III

TinyUSB comes with a FRDM-KL25 example.  

I have it running on the KL27 now and working on getting it running on the KL43 and the K32L as time permits.

I need to get those submitted back to TinyUSB.

Unless the MK60 is radically different than those, or other ColdFire decedents, it comes down to having the correct initialization code.  TinyUSB takes care of the rest.

Then it comes down to calling tp5_tinyusb_task() someplace in the main loop that is fast enough:

//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
void USB_IRQHandler(void);
void USB_IRQHandler(void)
{
tud_int_handler(0);
}

static inline void watchdog_service( void )
{
SIM->SRVCOP = SIM_SRVCOP_SRVCOP( 0x55U ); /* Refresh Watchdog to stop it resetting us */
SIM->SRVCOP = SIM_SRVCOP_SRVCOP( 0xAAU );
}

void tp5_tinyusb_task( void )
{
watchdog_service();

tinyusb_task_main();

watchdog_service();
}

Along with appropriate descriptor.

0 Kudos
1,989 Views
bobpaddock
Senior Contributor III

"...USB Full Speed instead of High Speed, which I'm not excited about since in my application I was looking for the highest data throughput possible..."

What is your actual application?

FS is 12 Mbps bus speed and is what most USB 2.0 devices are.
HS is 480 Mbps bus speed.

Not really as simple as flipping compile switch to make things go faster.


0 Kudos
1,980 Views
LRawlyk
Contributor III

I want to use USB 2.0 HS capabilities to dump large external NAND Flash devices, so I'm using the USB3300 PHY which is supposedly HS compatible and setup the PE USB module SIE_Module setting as USBHS.

0 Kudos