Embedded wizard application in combination with HID device

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

Embedded wizard application in combination with HID device

Jump to solution
1,652 Views
mail6
Contributor II

Hallo,

I am using the NXP LPCXpresso54628. I have created a graphical interface in embedded wizard that runs on the LPCXpresso54628. Simultaneously I want the device to act as a USB HID device.

This is what I have done so far:

1) I have compiled the lpcxpresso54628_dev_hid_generic_bm example and got the USB HID device working on the USB FS connector. This is a BM project.

2) I compiled the Embedded wizard GUI and have the GUI program running on the LPCXpresso. This is also a BM project.

3) I merged all the source files from both projects into a new project.

4) When I run the following main program the HID device works in this merged project

int main( void )
{

/* attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
BOARD_InitPins();
BOARD_BootClockFROHF96M();
BOARD_InitDebugConsole();

POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*< Turn on USB Phy */
CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false);
CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
/* enable usb0 host clock */
CLOCK_EnableClock(kCLOCK_Usbhsl0);
/*According to reference mannual, device mode setting has to be set by access usb host register */
*((uint32_t *)(USBFSH_BASE + 0x5C)) |= USBFSH_PORTMODE_DEV_ENABLE_MASK;
/* disable usb0 host clock */
CLOCK_DisableClock(kCLOCK_Usbhsl0);


USB_DeviceApplicationInit();

while (1U)
{

}

return 0;


}

5) When I run the following code the GUI program works in the merged project

int main( void )
{

/* initialize system */
EwBspSystemInit();

/* initialize Embedded Wizard application */
if ( EwInit() == 0 )
{
return 0;
}

/* process the Embedded Wizard main loop */
while( EwProcess())
{

}

/* de-initialize Embedded Wizard application */
EwDone();

/* terminate the system */
EwBspSystemDone();

return 0;


}

I want to have both programs running at the same time, so that I have a GUI on the screen and simultaneously have a USB HID device. When I merge the two main function both applications stop to work. A closer look into 

EwBspSystemInit(); which contains:

/*******************************************************************************
* FUNCTION:
* EwBspSystemInit
*
* DESCRIPTION:
* The function EwBspSystemInit initializes the system components.
* (CPU clock, memory, qspi, ...)
*
* ARGUMENTS:
* None
*
* RETURN VALUE:
* None
*
*******************************************************************************/
void EwBspSystemInit( void )
{
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);

/* attach 12 MHz clock to FLEXCOMM2 (I2C master for touch controller) */
CLOCK_AttachClk(kFRO12M_to_FLEXCOMM2);
CLOCK_EnableClock(kCLOCK_Gpio2);

BOARD_InitPins();

BOARD_BootClockPLL180M();

/* attach 12 MHz clock to SPI3 */
CLOCK_AttachClk(kFRO12M_to_FLEXCOMM9);

BOARD_InitDebugConsole();
BOARD_InitSDRAM();

#if EW_USE_EXTERNAL_FLASH == 1
{
spifi_config_t config = {0};
uint32_t sourceClockFreq;

/* Set SPIFI clock source */
CLOCK_AttachClk(kMAIN_CLK_to_SPIFI_CLK);
sourceClockFreq = CLOCK_GetSpifiClkFreq();

/* Set the clock divider */
CLOCK_SetClkDiv(kCLOCK_DivSpifiClk, sourceClockFreq / EXAMPLE_SPI_BAUDRATE - 1U, false);

/* Initialize SPIFI */
SPIFI_GetDefaultConfig(&config);
SPIFI_Init(EXAMPLE_SPIFI, &config);

/* Reset to memory command mode */
SPIFI_ResetCommand(EXAMPLE_SPIFI);
SPIFI_SetMemoryCommand(EXAMPLE_SPIFI, &command[READ]);

}
#endif
}

shows that here the BOARD_BootClockPLL180M(); is loaded and in the USB HID program the BOARD_BootClockFROHF96M(); is loaded. How do I proceed in merging the two programs ?

 

Many thanks in advance,

Jim

0 Kudos
1 Solution
1,487 Views
mail6
Contributor II

Hi mykepredkomimetics

Thanks for getting back to me.

I solved the problem by simply setting the FRO_HF clock from 48 MHz to 96 MHz.

Hereafter I ran into trouble when creating the second task, xTaskCreate returned the error errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY. This was solved by increasing the heap size by changing

#define configTOTAL_HEAP_SIZE                   ( ( size_t ) ( 25 * 1024 ) ) // from 10 to 25

Next the GUI did still not work properly... The screen was empty. This was solved by changing the priority of the tasks.

Now the GUI tasks runs at priority (UBaseType_t uxPriority ) 2 and the HID device at priority 1.

Thanks for your help.

View solution in original post

6 Replies
1,487 Views
mail6
Contributor II

Dear mykepredkomimetics and ZhangJennie,

Thank you for the help so far. First of all mykepredkomimetics, I started using FREE RTOS but this seemed complicated at first (+ I had some difficulties debugging) so I decided to switch to BM. After reading your post I decided to switch back to FREERTOS since this will keep the project easily adaptable.

So I switched back to FREE RTOS and followed the steps mentioned by ZhangJennie. I have added the project (see porject.rar) and two main files (main_not_working.c and main_working.c)

In the main_working.c I have split the main function in two parts by using the definition ( #define EMBEDDED_WIZZARD 1).

When ( EMBEDDED_WIZZARD 1 ) the program compiles and the GUI application is started and everything works as expected.

When ( EMBEDDED_WIZZARD  0 ) the program compiles and the HID application is started and everything works as expected.

Now I want both tasks to run simultaneously and I removed the following statements from the main file:

#if (defined EMBEDDED_WIZZARD) && (EMBEDDED_WIZZARD)

#else

#endif

If I do this both tasks do not work anymore. I think it has something todo with the GUI program is using :

BOARD_BootClockPLL180M();

and the HID task is using:

BOARD_BootClockFROHF96M();

Looking forward to your help.

Best,

Jim

0 Kudos
1,487 Views
myke_predko
Senior Contributor III

Hi mail@jimfranssen.nl‌,

I don't have the time to do a deep dive into your code but I think you're going to have to understand how each of the code modules work and which parts need to be installed and working and which parts are to be put into tasks.  Along with that, I think you're going to need to take some time to figure out your system initialization - I cringed a bit when I saw:

// This code is already present in EwBspSystemInit();
//* attach 12 MHz clock to FLEXCOMM0 (debug console) */
//CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
//BOARD_InitPins();
//BOARD_InitDebugConsole();

Maybe the code is already present, but I think you should make sure you understand what is going on here before taking out the system generated code.  

On the point of clocks, how are you validating that they are correct?  It took me a long time to be comfortable with the Clocks Tool in MCUXpresso and I don't think it works very easily/intuitive/correctly but it does generate correct code once you have it set in the two views to provide you with the clocks that you are looking for.  The same thing with the Pins tool.  I'm emphasizing clocks because of how critical it is for USB.  

To give you an example of what I mean in terms of understanding the BM code, I've included my USB CDC code (modified from the BM example code) and note that when I receive a packet, I format it inside the ISR to create a text string that is sent to my Command task that executes the request: 

if ((0 != s_recvSize) && (0xFFFFFFFF != s_recvSize)) {
  for (i = 0; (s_recvSize + 0) > i; ++i) {
    if (0 != usbBlockCountDown) {
       usbCMDMsg.msg[usbCMDMsgSize++] = s_currRecvBuf[i];
       --usbBlockCountDown;
    }
    else if (usbBlockFlag) {
       usbBlockCountDown = (uint32_t)(usbCMDMsg.msg[usbCMDMsgSize++] = s_currRecvBuf[i]);
       usbBlockFlag = FALSE;
    }
    else if ('@' == s_currRecvBuf[i]) {
       usbCMDMsg.msg[usbCMDMsgSize++] = s_currRecvBuf[i];
       usbBlockFlag = TRUE;
    }
    else if ('\b' == s_currRecvBuf[i]) {
       --usbCMDMsgSize;
    }
    else if ('\r' == s_currRecvBuf[i]) {
       usbCMDMsg.msg[usbCMDMsgSize++] = '\r';
       usbCMDMsg.msg[usbCMDMsgSize] = '\0';
       usbCMDMsg.header = CMD_REQUEST_CHARS;
       usbCMDMsg.source = CMD_SOURCE_USB;
      CMDMSGISR(usbCMDMsg)
       usbCMDMsgSize = 0;
    }
    else if ((CMD_MESSAGE_SIZE - 2) > usbCMDMsgSize) {
       usbCMDMsg.msg[usbCMDMsgSize++] = s_currRecvBuf[i];
    }
  }
   s_recvSize = 0;
   error = USB_DeviceCdcAcmRecv(handle
                              , USB_CDC_VCOM_BULK_OUT_ENDPOINT
                              , s_currRecvBuf
                              , g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize);
}

The macro for sending the full packet (terminated with a '\r') is:

#define CMDMSGISR(txMsg)                       \
{                                              \
BaseType_t xHigherPriorityTaskWoken = pdFALSE; \
xQueueSendFromISR(cmdQUEUE_Handle              \
, (void*)&txMsg                                \
, &xHigherPriorityTaskWoken);                  \
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);  \
}

And when the Command task is sending a packet out through the USB, I have the separate task:

void USBTX_task(void *pvParameters) {
struct replyQueueMsg mainMsg;
usb_status_t error;


#if (2 != SDK_DEBUGCONSOLE)
  PRINTF("\nUSBTX_task");
#endif

  for (;;) {
    xQueueReceive(usbOUTQUEUE_Handle
                , (void*)&mainMsg
                , portMAX_DELAY);

    error = USB_DeviceCdcAcmSend(s_cdcVcom.cdcAcmHandle
                               , USB_CDC_VCOM_BULK_IN_ENDPOINT
                               , mainMsg.msg
                               , mainMsg.size);
    if (error != kStatus_USB_Success) {
      /* Failure to send Data Handling code here */
    }
  }

}

Maybe I oversold the work in my original reply as being easy, but with a few hours understanding the operation of the two tasks/applications along with their resources (with an emphasis on clocking) you should be able to get something that works well.  

myke

0 Kudos
1,488 Views
mail6
Contributor II

Hi mykepredkomimetics

Thanks for getting back to me.

I solved the problem by simply setting the FRO_HF clock from 48 MHz to 96 MHz.

Hereafter I ran into trouble when creating the second task, xTaskCreate returned the error errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY. This was solved by increasing the heap size by changing

#define configTOTAL_HEAP_SIZE                   ( ( size_t ) ( 25 * 1024 ) ) // from 10 to 25

Next the GUI did still not work properly... The screen was empty. This was solved by changing the priority of the tasks.

Now the GUI tasks runs at priority (UBaseType_t uxPriority ) 2 and the HID device at priority 1.

Thanks for your help.

1,487 Views
myke_predko
Senior Contributor III

Great job mail@jimfranssen.nl‌!

It's never as simple as it could/should be but it's never as hard as it can be.  

Keep us informed as to how you're doing!

myke

0 Kudos
1,487 Views
myke_predko
Senior Contributor III

Hi mail@jimfranssen.nl‌,

I just saw ZhangJennie‌'s reply and I think it's a good start but could I ask why are you not implementing this in a RTOS?  

If you GUI function and HID function are independent of each other then you could (reasonably) simply turn them into two tasks and run them under the RTOS.  If you go the RTOS route there's also the added benefit of intertask communications which allows data to be passed without affecting their operation.  

Just curious - I always like to understand the reasons why people approach problems in certain ways.

myke

0 Kudos
1,487 Views
ZhangJennie
NXP TechSupport
NXP TechSupport

Hi

First you need make sure both GUI program and HID program works separately.

then you import your HID code into your GUI program.

steps:

1. add USB component to your GUI project

pastedImage_1.png

pastedImage_2.png

2. after import you will see USB driver added in project:

pastedImage_3.png

Thus you have imported all USB device driver source codes into your project.

next you can either add your HID application source code into your project directly. 

or

refer this document from step 5 to create your HID application

https://community.nxp.com/docs/DOC-347301 


Have a great day,
Jun Zhang

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

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos