FRDM-KL25Z now talks to Android Phone

cancel
Showing results for 
Search instead for 
Did you mean: 

FRDM-KL25Z now talks to Android Phone

5,035 Views
kai_liu
Senior Contributor I

Hi,

 

I have just finished my work on running ADB protocol on FRDM-KL25Z.

 

ADB (Android Debug Bridge) is an important debug interface used in Android, ranges from Android 1.5 to lastest 4.2.2.

 

Any MCU running ADB can talks to any Android Phone (OS version<4.2.2), that means appcessory ecosystem can be built on a low cost Cortex-M0 MCU like KL25Z.

 

I port ADB protocol from UHS project for Arduino, with a lot of re-write code to adapt to FSL USB host stack. Yes, they are using totally different approaches, not only the registers, but also program structure.

 

If anyone is interested, you can follow my step to run it on your board as well.

 

  1. Built an add-on OTG port on FRDM-KL25Z (USB host HID demo times out on FRDM-KL25Z with reproduced USB host), alternatively, you must buy FRDM RevD.
  2. Put your FRDM into MSD programmer mode, according to QSP of KL25Z.
  3. Download attached srec file (USBH_Adb.srec) into programmer driver.
  4. Put your FRDM back into PEmicro debugger mode, according to QSP of KL25Z, otherwise you lose your serial port print on terminal
  5. Install apk in ServoControl.zip file to Android Phone. (Don't use Jelly Bean 4.2.2, older phone is all right)
  6. Connect your Android Phone to add-on OTG port.

 

If successful, you can find USB activities on serial terminal. And found ADB protocol talks as well.

 

In my code, the LPTMR value will be sent to Android phone as a bar, the user can touch the red block and move it, and its co-ordinate will be sent back to KL25Z. It is a simple demo.

 

Have fun. Your comments are highly welcome.

 

==================

 

Limitations

 

  • The source code is messy, I need more time to re-organize it.
  • The ADB only works Android phone with OS 1.5+ to 4.2.1. The latest 4.2.2 has enforced RSA authentication, which is not available so far.
  • The ADK/AOA protocol is implemented.

 

Plan

  • Reorganize source code for ADB for FSL
  • Offer API interface to high level applications
  • Offer more complex demos (Video surveillance with Android phone with PTZ control)
  • Evaluate serial bootloader (AN2295) and change it to adapt with bootloader.
  • Support RSA authentication if possible
  • Support AOA/ADK w/o audio
  • A new KL25Z USB OTG board called "GAP" (Generic Android/Application Peripheral) under development, in form of Arduino or mini board.

 

Long-term Plan (more aggressive, but only with more time, effort and human resources)

  • Support USB WiFi/Blutetooth dongle.
  • Support USB CDC with Android phone.
  • Support codesourcery toolchain
  • Support Arduino/Maple IDE
  • Support license in firmware.

 

Sorry for my poor English, and I updated URL to another thread. In fact, FRDM-KL25Z RevD supports USB OTG with wiring VBUS from OpenSDA to KL25Z. But use it at your own risk.  I am not sure if I should go open source or close source like traditional approach. Before I make my decision, I will release my hex code anyway, and release a library and related header file to user application development.    Message was edited by: Kai Liu

Original Attachment has been moved to: USBH_Adb.srec.zip

Original Attachment has been moved to: ServoControl.zip

Tags (4)
14 Replies

760 Views
kirtiraje
Contributor III

Hello Kai Liu,

I am working on a project which uses FRDMK64FN board and KDS 3.2. I have used FSL USB STACK for USB communication with android device (in Host mode) and hardware USB in CDC device mode. It is working fine. In this case when I  used hardware in USB CDC DEVICE mode then I did not required AOA/ ADK protocol to communicate with android device. Now when I am looking for hardware USB act in CDC Host mode (so that it can charge android device and transfer data) and android device acts as device or accessory then it is required AOA/ADK protocol to communicate with android device. Somehow I am successful in getting the adk.h file but donot know how to use it in application.

can any one help me to get the AOA/ADK library or stack that can be used for MK64FN board and document that shows how to use that library in firmware application.

I am struggling a lot to get this AOA protocol on FRDM K64 board.

Any help is very much appreciated.

Thank you,

Kirti

0 Kudos

760 Views
jeffhaller
Contributor II

Are you planning on releasing the source code to this?  I'm mainly interested in the AOA part.

0 Kudos

760 Views
kai_liu
Senior Contributor I

Hi, Jeff,

I am considering to release it in a library for community, rather than open source. Sorry, it is part of my product.

0 Kudos

760 Views
jeffhaller
Contributor II

A library makes sense if it's part of a product.  I'm just knee deep in the USB stack trying to get a very simple AOA project up and running and was looking for some resources.

0 Kudos

760 Views
kai_liu
Senior Contributor I

Actually open source or close source has not been decided yet. However I spent quite a long time on implementation ADB on KL25Z.  At lease I want to sell my boards/designs to users to cover my cost of development.

Alternatively, I would like to share my source code with FSL community, if FSL can arrange some free samples/boards for me.:smileylaugh:

FSL should and can arrange that, since the company has enough budget to support design-in and university programs.

0 Kudos

760 Views
ASTRIHK
Contributor III

Hi Kai Liu & Mark,

I am planning to do the same thing as you but it seems there's a little bit limitation when using ADB protocol to connect any android devices. Do you think using USB CDC will be more easier? It's just a simple communication port and Android device just needs to monitor that port. Am I correct?

0 Kudos

760 Views
kai_liu
Senior Contributor I

Hi, Jackie,

There are always limitations when we connect to Android Phone, depends on the operation modes.

So far we can have following methods:

  • USB CDC device, OS > 2.3.7, and hardware support for USB OTG.
  • ADB as USB host, OS < 4.2.2, meets RSA authentication in 4.2.2, need 500mA VBUS
  • AOA/ADK as USB hsot, OS > 2.3.7, need 500mA VBUS
  • Bluetooth SPP, depends on phone stacks, We need 3rd party serivces.
  • WiFi, all, but more expensive for embedded WiFi module.
  • Audio modem, need more information for audio processing algorithm
  • NFC, depends on hardware

USB CDC is good and simple, but a lot of doesn't support USB OTG at all due to additional hardware for VBUS load switch. So, it has also limitations as well.

It seems WiFi/Bluetooth is much generic.

You can check following informaiton from:

http://ennovation.sinaapp.com/ (my blog in Chinese, but I believe you could understand it)


0 Kudos

760 Views
markwoloszyk
Contributor I

Hi Kai Liu,

Its funny, I have been doing the exact same thing you have done.  I started with the MicroBridge ServoControl demo and an Arduino example to get the ADB protocol.  I am using a Kinetis K20 and Freescale's USB Host stack and implementing a ADB class.  I started with rev 4.0.3 of the bare metal host stack and found quite a few bugs that required me to modify Freescale's code.  I just downloaded rev 4.1.1 of the usb stack the other day and it seems to address most of these bugs.  I have the protocol basically working.  I can send and receive data to and from a tablet running the MicroBridge app.

However the issue I'm having is the way Freescale's stack is structured.  When it does a receive (or send) transaction, it waits in a while loop until the transaction is complete or a timeout occurs.  The timeout is very long.  I can't have the stack stall my program for seconds at a time waiting to receive usb data.  My thought is to modify the host stack code (_usb_khci_task() in khci.c) to state machine the receive rather than just wait in a do/while loop.

It sounds like maybe you dealt with this issue and I was wondering if you had any thoughts on how to work around this issue.


0 Kudos

760 Views
kai_liu
Senior Contributor I

Hi, Mark,

Actually I am not a big fan of Freescale USB stack. I was struggling with it for several months.

I know the timeout issue for USB send/receive routines. To be frank, I have no idea why it takes so long. The constant for _usb_khci_task() is clueless, at least I don't wanna to touch the code.

I used to worry about if USB receiver is kept waiting for bytes which will not come in the same transfer until it get timeout. However, I found we can avoid that since our firmware acts as USB host, and ADB transfer always defines data length in its message body, which can be used as parameter for next usb tranfer IN.

In fact, when host sends out ADB message, it always expects to receive an ADB message (length as 24). After receiving an ADB message (A_CNXN/A_OKAY/A_AUTH/A_WRTE/A_CLSE), the host can parse data length from 0 to any value defined in its message. So you can define it as parameter in the following receiver function.

So it goes on and on. If your code find it always timeout in khci, it maybe a problem of your state machine.

The real problem is how to handle an unknown length data stream in other applications. But FSL offers many reference designs from PHDC, CDC and printer. Among them, PHDC is more generic implementation.

It is only my personal opinion. And I am not good at FSL stack. My code is just WORKING, it still requires more improvements.

ADB is a good protocol, anyway. Let us review its flowchart (o is out, i is in) :

        o>  "CNXN"

        o>  "host::microbridge"

    x   i<  "CNXN",             !connected, connection=null, message

    x   i<  "device::"          !connected, connection=null, data

       

        o>  "OPEN"

        o> "tcp:4567"

    x   i<  "OKAY"              connected, connection=valid, message

       

        o>  "WRTE"

        o>  data       

    x   i<  "OKAY"              connected, connection=valid, message

       

    x   i<  "WRTE"              connected, connection=valid, message

    x   i<  data                   connected, connection=valid, data

        o>  "OKAY"

       

        o>  "CLSE"

    x   i<  "CLSE"             connected, connection=valid, message

You will find the only issue is, A_WRTE from Android will be transferred in when we expecting A_OKAY from it for previous A_WRTE from host. That is easy to handle.

BTW, good choice for K20 based ADB design.

KL25Z has no FLEX memory and I2S, so my design is only for low-end applications.

0 Kudos

760 Views
markwoloszyk
Contributor I

Thanks Kai Liu.  I'm not a fan of Freescale's stack either.  I wasted a couple weeks assuming I was doing something wrong before I dove deep into the host stack and figured out the stack had bugs.  I have ADB working now. 

One thing that I'm unclear on is, can my receiver get out of sync with ADB?  Can a command and data be sent in the same USB packet?  I only have a little experience with USB and from what I recall, the lower layer of USB may queue data from the upper layer and send the USB packet once its sufficiently large.  So if I have a number of different messages to transmit on USB, it might buffer all those message and send it in one big USB packet, rather than a number of small packets.  So can I get a command and data in the same USB packet?  My concern is that for some reason I get out of sync and when I request to receive 24 bytes for a command I am actually receiving 24 bytes of data from a previous message.  I would be out of sync and missing commands then for the rest of that USB packet.  If this is the case, I would need to add a start/end of frame protocol around the ADB messages. Of course if commands and data are not sent in the same USB packet, then there won't be this issue.

0 Kudos

760 Views
kai_liu
Senior Contributor I

Now I understand your concerns. You think the message + data will be queued up until it meets some limitation to send out in one packet. And receive reply message and possible data will be cached in one USB IN packet as well.

I haven't debug the very low level function for register access in khci_kinetis.c. Let us check the source for _usb_khci_task().

_usb_khci_task(void)

{

......

     if ((_usb_khci_get_hot_int_tr(&msg) != 0) || (!seq_ints--))

......

     switch (msg.type)

          case TR_MSG_RECV:

               _usb_khci_atom_tr(...);

               // prinf("TR_MSG_RECV\n\t");

               // printByteStream(remain,buf);

          case TR_MSG_SEND:

               // prinf("TR_MSG_SEND\n\t");

               // printByteStream(remain,buf)

               _usb_khci_atom_tr(...);

     _usb_khci_process_tr_complete(); //->recv_data_callback() & send_data_callback()

}

You can put some printf() as real time breakpoints. Addtionally you 'd better to add some printf() in recv_data_callback() and send_data_callback().

As I know, two write_data() writes two messages into queue, and _usb_khci_task() writes out twice. However, the data coming in is not available in case TR_MSG_RECV, but in _usb_khci_process_tr_complete() and recv_data_callback().

So, it seems FSL host stack will not send multiple short messages in one USB message. Maybe I am wrong, I will spend more effort to find out and verify my points.

I doubt the sync lose issue may be caused by putting multiple write and read functions in one function. It is easy in Arduino USB stack, but it is bad practice in FSL due to its strucute.

I only put write and read in main, main() -> adb_loop() by a switch case based upon its states. And in recv_data_callback() and send_data_callback(), all write and read functions are forbidden, only state machine is allowed to update. By this approach, a call parameters to queued messages will not be damaged. 

Good luck.

0 Kudos

759 Views
markwoloszyk
Contributor I

I'm right with you Kai Liu.  I had already started peppering printf's in the host stack to see how data is received.  Today I used a USB analyzer to be able to see the individual USB packets.  It appears that a command message and data payloads are always sent in separate USB packets and are never sent together in the same USB packet.  So I'm no longer worried about getting out of sync.  In our MicroBridge example, the payloads can be combined though when it sends the position data.  I've seen it receive anywhere from 2 bytes (x and y) to 8 bytes (4 sets of x and y) in the same USB packet.  The WRTE command of course tells you that there are 2 or 8 bytes so this isn't an issue.  As I continue to develop this for my specific project, I'll use some sort of PPP type framing to be able to separate payloads that have been combined into one USB packet.

0 Kudos

759 Views
kai_liu
Senior Contributor I

Sorry, the URL for add-on OTG port is here.

USB host HID demo times out on FRDM-KL25Z with reproduced USB host

0 Kudos

760 Views
BlackNight
NXP Employee
NXP Employee

Hi Kai Liu,

that's outstanding, thanks for sharing!

0 Kudos