Programming with the USBDM API

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

Programming with the USBDM API

6,636 Views
TheMnemonic
Contributor II

Hi,

 

After I found the USBDM_API, I tried to flash my MCF51JM128 with it.

With the working example of the memory dump from USBDM_Programming, I got along.

 

So first of all I read the SDID of my chip. The received a value of 0x2C16 (under considering big endian!). Also the CFV1_FlashProgrammer got this SDID.

Unfortunately in the XML-Device-Database this SDID is 0x0C16. Why is this different to the one in the Device?

 

After that I tried to erase my controller. Here I got some problems as in the API I only got an ICP_erase, I tried an erase with the following code:

    USBDM_RebootToICP();    ICP_ErrorCode_t ICP_ans= USBDM_ICP_Erase(0,0x01FFFF); //Memoryspace of the 51JM128 is 0x01FFFF;    switch(ICP_ans){        case ICP_RC_OK:                qDebug()<< "Erased";        break;        case ICP_RC_ILLEGAL:             qDebug()<< "erase failed! Illegal";        break;        case ICP_RC_FLASH_ERR:             qDebug()<< "erase failed! Flash";        break;        case ICP_RC_VERIFY_ERR:             qDebug()<< "erase failed! Verify";        break;    default:        qDebug()<< "A strange output "<< QString::number(ICP_ans);    }    USBDM_ICP_Reboot();

 if I execute this code, i got "A strange output 29". And further my USBDM_Flasher can not be connected again (Error: Failed, Reason=USB Transfer error).

So does anybody know how to erase, program and verify a controller via the API? Does anybody have some working Code?

Thanks in advance.

 

Regards,

Roman

 

Tags (2)
18 Replies

4,297 Views
pgo
Senior Contributor V

Dear Roman,

 

The SDID is made up of several fields.  Some of these are mask  revision numbers which may change for the same chip.  The SDID given in the XML files only includes the unchanging part.  The SDID read from the actual chip is masked before comparison.

 

The USBDM_API is a very low level debugging API.  It does not include programming of the target.  Programming is a complex process involving the downloading of programming code and data to the target memory and then execution of a program on the target.

 

The ICP entry points are used to reprogram the BDM not the target. (ICP = in circuit programming ... of the BDM!)

 

It looks like you have erased part of the BDM's firmware. The BDM should detect that the flash is invalid (I hope!) and start up in BOOT mode.  You should be able to restore the firmware using the USBDM Firmware Updater.

 

The source code for the USBDM programmers is available on Sourceforge.  These include (obviously) examples of programming but it's a complex process made more complex by having to cope with many different targets.  Programming a particular chip would be somewhat easier but not a trivial process.

 

bye

0 Kudos

4,297 Views
TheMnemonic
Contributor II

Dear pgo,

 

thanks for your fast reply. Luckily my BDM still works fine, so no damage to its firmware Smiley Happy.

So to the API: I allready looked to the source on Sourceforge.... and yes it really looks complex.. this brings the question to my mind: why is this stuff not in the API? Wouldn't it be very cool if one could use the API to erase, program and verify a target? Don't get me wrong, I really like the stuff you did, and it works really great... I just wondering why you put it up like this?

 

I think it would be great and much easier if one can just write something like:

check(USBDM_SetTargetController(MCF51JM128));check(USBDM_EraseTarget(ALL));check(USBDM_ProgramTarget("C:\Project.s19"));check(USBDM_ResetTarget());

 regards,

Roman

0 Kudos

4,297 Views
pgo
Senior Contributor V

Dear Roman,

 

The USBDM API is designed for low level stuff and is general across multiple processors etc.

 

Programming is provided by the GDI layer that is in the Eclipse DLLs e.g. usbdm-hcs08-gdi.dll.  If you were (VERY) keen you could use this to program the chip in the fashion you have suggested.  However it  is also pretty complex.

 

I might abstract the programming interface into separate family-specific DLLs eventually.  But it's pretty far down the list.

 

Similar functionality can be obtained by using the  stand-alone programmers in command line mode.

 

bye

0 Kudos

4,297 Views
tyamadajp
Contributor I

Hi. I'm also trying to use USBDM(v4.9) API to create command-based HC12 programmer for Linux, but having trouble using the API. I can access memory/register without any error, but nothing is actually written and all reads just return a buffer filled with 0xFF.

 

It's not a issue with faulty BDM or board, as I have no problem using it from Windows environment, using bundled CLI/GUI hybrid programming tool.

 

I created a test code to read PartID as a starter, but even the code below (I think it's simple as it can be) returns a ID of 0xFFFF. Can anyone tell me what I'm missing?

 

// USBDM API test to read SDID#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include "USBDM_API.h"#define check(...) do {  \        err = __VA_ARGS__;  \        if (err != BDM_RC_OK) { \            puts(""); \            printf("[E] %d: %s\n", __LINE__, #__VA_ARGS__);  \            printf("[E] err=%d, %s\n", \
                   err, USBDM_GetErrorString(err)); \            USBDM_Close(); \            USBDM_Exit();  \            exit(0); \        } else { \            printf("%d ", __LINE__); \        }  \    } while (0);  \    if (err == BDM_RC_OK)int main(int argc, char **argv) {    int err;    unsigned int deviceCount;    check(USBDM_Init());    check(USBDM_FindDevices(&deviceCount));    check(USBDM_Open(0));    check(USBDM_SetTargetType(T_HCS12));    check(USBDM_SetTargetVdd(BDM_TARGET_VDD_3V3));    check(USBDM_SetSpeed(25000));    check(USBDM_TargetReset(RESET_HARDWARE|RESET_SPECIAL));    check(USBDM_Connect());    USBDMStatus_t st;    check(USBDM_GetBDMStatus(&st)) {        puts("");        printf("     target_type: %d\n", st.target_type);        printf("      ackn_state: %d\n", st.ackn_state);        printf("connection_state: %d\n", st.connection_state);        printf("     reset_state: %d\n", st.reset_state);        printf("    reset_recent: %d\n", st.reset_recent);        printf("      halt_state: %d\n", st.halt_state);        printf("     power_state: %d\n", st.power_state);        printf("     flash_state: %d\n", st.flash_state);    }#define PARTID_ADDR 0x001A    uint16_t val;    check(USBDM_ReadMemory(1, 2, PARTID_ADDR, (unsigned char *)&val)) {        puts("");        printf("PartID: 0x%X\n", val);    }    check(USBDM_Close());    check(USBDM_Exit());    puts("");    return 0;}

 

I'm feeling myself really dumb, as the API is really simple and straightforward...

0 Kudos

4,297 Views
pgo
Senior Contributor V

Dear tyamadajp,

 

A couple of minor things prevent it working I believe:

  • USBDM_SetTargetVdd(BDM_TARGET_VDD_3V3) is used to set the Target Vdd to be used - Not actually to change the Vdd.  It should be done before SetTarget() which is when it will be applied.  Obviously if you don't have a switched supply it's of no concern. BDM_TARGET_VDD_ ENABLE and BDM_TARGET_VDD_DISABLE may be used to switch the Vdd on and off.  This should be better described in the documentation.
  • USBDM_SetSpeed() should not usually be used with RS08/HCS08/HCS12 or CFV1 targets as they will in nearly all cases autodetect the target BDM speed.  If you use it, it should be the BDM communication speed which is dependent on the target clock.  25MHz is an unlikely figure.

With those changes the program worked on WIN32 using MINGW and I would expect similar results on Linux. (Well the numbers printed weren't 0xFF so I hope they were the SDID.

 

When debugging I suggest you link against the debug version of the USBDM dll.  This will produce copious debug messages.

 

Finally - There is a HCS12 programmer included in USBDM.  What features do you need that it doesn't provide?

 

bye

 

// USBDM API test to read SDID#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include "USBDM_API.h"#define check(...) do {  \        err = __VA_ARGS__;  \        if (err != BDM_RC_OK) { \            puts(""); \            printf("[E] %d: %s\n", __LINE__, #__VA_ARGS__);  \            printf("[E] err=%d, %s\n", \                   err, USBDM_GetErrorString(err)); \            USBDM_Close(); \            USBDM_Exit();  \            exit(0); \        } else { \            printf("%d ", __LINE__); \        }  \    } while (0);  \    if (err == BDM_RC_OK)int main(int argc, char **argv) {    int err;    unsigned int deviceCount;    check(USBDM_Init());    check(USBDM_FindDevices(&deviceCount));    check(USBDM_Open(0));    check(USBDM_SetTargetVdd(BDM_TARGET_VDD_3V3));    check(USBDM_SetTargetType(T_HCS12));//    check(USBDM_SetSpeed(25000));    check(USBDM_TargetReset(RESET_HARDWARE|RESET_SPECIAL));    check(USBDM_Connect());    USBDMStatus_t st;    check(USBDM_GetBDMStatus(&st)) {        puts("");        printf("     target_type: %d\n", st.target_type);        printf("      ackn_state: %d\n", st.ackn_state);        printf("connection_state: %d\n", st.connection_state);        printf("     reset_state: %d\n", st.reset_state);        printf("    reset_recent: %d\n", st.reset_recent);        printf("      halt_state: %d\n", st.halt_state);        printf("     power_state: %d\n", st.power_state);        printf("     flash_state: %d\n", st.flash_state);    }#define PARTID_ADDR 0x001A    uint16_t val;    check(USBDM_ReadMemory(1, 2, PARTID_ADDR, (unsigned char *)&val)) {        puts("");        printf("PartID: 0x%X\n", val);    }    check(USBDM_Close());    check(USBDM_Exit());    puts("");    return 0;}

 

0 Kudos

4,297 Views
tyamadajp
Contributor I

Hi pgo, thanks for commenting!

However, if I comment that line out (or set to "0" for autodetection), I get an error:

 

$ ./usbdm-sdid30 31 32 33 34 37[E] 38: USBDM_Connect()[E] err=18, Target BDM Enable failed

 

When I try with slower speed (1000 and 8000), they'll pass, but still ends up with 0xFF result, just like 25MHz case.

 

Regarding BDM speed,  my target chip/board is MC9S12NE64 on FutureElectronics NE64 PoE Badge board. This chip runs with 100Mbps Ethernet, and as stated on the datasheet, requires exact clock rate of OSCCLK = PLL-generated SYSCLK = 25MHz in that mode. Since BDMCLK = SYSCLK (I'm not using ALTCLK mode), I think 25MHz itself is fine. In another word, I think there is other cause of 0xFF issue.

 

Since I can program this chip/board from Windows with genuine USBDM programming tool, there must be some "correct" way to call the API. Is there any way I can see how Windows version is doing?

 

And finally, there are 2 reasons I want to write my own tool:

 

  1. I'm running amd64-based Linux, and I'm having difficulty running i386-based binary, especially with X11/wxWidgets/etc dependency. I was able to run it, but X11/wx depend on gtk, and gtk uses dynamic-module loading for font rendering. It failed to load amd64-binary module (which is installed on my system) and it was inoperable. To properly run this binary, I need to have much of i386-based X11/wx/gtk/etc runtime, which I want to avoid on my amd64 box.
  2. I have several boards which I want to read/save firmware before re-flashing (as I lost source code of them). While USBDM API supports reading, I believe bundled tool does not support it (yet?).

 

I'm also considering to rebuild USBDM tools for Linux/amd64, but as it is somewhat complex piece of work (I need X/wx/gtk/tcl/...), I'm first trying to write my own tool.

0 Kudos

4,297 Views
tyamadajp
Contributor I

After another hours of trial and error, I finally managed to run HCS12_FlashProgrammer (32-bit i386) properly on my Linux (64-bit amd64) system.

 

I had to setup complete i386 chroot envionment and copied needed files to amd64 system. There was an issue with pango/gtk module failing to load modules (needed for usable GUI), but I was able to workaround the issue by defining PANGO_RC_FILE environment variable to switch configuration/pathname. Resulting i386/amd64 mixed system is kind of messy, but it is working.

 

Althrough I'll still continue developing my own tool for memory read/save and other quick operations like power control, I think I can figure the detail out myself as now I can just do "ltrace HCS12_FlashProgrammer-debug" and directly see which API is called in which order (with which parameter). Once that is complete, I can happily clean up i386/amd64 mixture.

 

 

0 Kudos

4,297 Views
pgo
Senior Contributor V

Hi tyamadajp,

I tried the program with a NE64 chip under windows and it worked fine.  This board has a 25MHz crystal so bus frequency out of reset is 12.5 MHz.  The program autodetects 12.5 MHz as the communication speed which would be as expected.

I believe 25 MHz is the highest crystal frequency that can be used.  Your board may use an external clock rather than a crystal so if this was a 50 MHz then the bus clock=BDM clock would be 25MHz as you indicated. I can't conveniently test this but in any case the HCS12 programmer will indicate the connection speed when autodetecting the device.

I've attached a copy of the windows debug version of the programmer (v4.9.4).  The other needed files should already be installed on you PC. This will create a usbdm.log file with details of the low level communication with the target which may be useful.

 

I look at the Linux version some time this weekend when I can reboot.

 

I also tried loading a target program which changed the target to using a 25MHz bus speed and connection wasn't a problem at that speed.

 

Incidently - The error message may indicate that the target is secured.  Is this possible?  The programmer will ignore this in some cases as it has to deal with secured targets (obviously).  It would still be possible to read the SDID in this case - just ignore that particular error on connection.

 

bye

   

0 Kudos

4,297 Views
tyamadajp
Contributor I

Hi pgo!

 

Thanks to your help, I finally managed to use the API and read all memory.

 

As you pointed out, the problem was that I unintendedly programmed the chip in secure mode.

I recently fixed linker script to define VECTOR/BDM region to be 0xFF00-0xFFFF (it was

defined as 0xFF80-0xFFFF with the size of _256_ before, and I thought that was a bug).

But that caused FSEC to be programmed to 0xFF, enabling secure mode.

 

Once I fixed it again to program 0xFE for FSEC, the code worked perfectly.

 

I'm pasting final working code here, so other people who might be interested can read it:

// USBDM API test to dump program memory.#include <stdio.h>#include <stdlib.h>#include <stdint.h>#include "USBDM_API.h"#define call(is_fatal, ...) do { \        int err = __VA_ARGS__; \        printf("#%d: %s\n", __LINE__, #__VA_ARGS__); \        if (err != BDM_RC_OK) { \            printf("[E] err=%d, %s\n", err, USBDM_GetErrorString(err)); \            if (is_fatal) { \                USBDM_Close(); USBDM_Exit(); exit(0); \            } \        } \    } while (0)#define check(...) call(1, __VA_ARGS__)#define trace(...) call(0, __VA_ARGS__)#define dumpmem_(size, name, name_str) do { \        int val = 0; \        check(USBDM_ReadMemory(1, size, name, (void *)&val)); \        printf("%s: 0x%.*X\n", name_str, 2 * size, val); \    } while (0)#define dumpmem(size, name) dumpmem_(size, name, #name)void dumphex(uint8_t *buf, int addr, int len) {    int i, j;    for (i = 0; i < len;) {        printf("%.8X:", addr + i);        for (j = i + 16; i < j && i < len;) {            printf(" %.2X", buf[i++]);        }        printf("\n");    }}int main(int argc, char **argv) {    unsigned int deviceCount;    check(USBDM_Init());    check(USBDM_FindDevices(&deviceCount));    check(USBDM_Open(0));    check(USBDM_SetTargetVdd(BDM_TARGET_VDD_3V3));    check(USBDM_SetTargetType(T_HCS12));    check(USBDM_TargetReset(RESET_HARDWARE|RESET_SPECIAL));    // error can be ignored, if only PARTID is needed.    trace(USBDM_Connect());#define PARTID  0x001A#define FSEC    0x0101    dumpmem(2, PARTID);    dumpmem(1, FSEC);//#define ROMADDR 0x4000//#define ROMSIZE (0xFFFF - 0x4000 + 1)#define ROMADDR 0xFF00#define ROMSIZE 256    uint8_t buffer[65536] = {0};    check(USBDM_ReadMemory(1, ROMSIZE, ROMADDR, buffer));    dumphex(buffer, ROMADDR, ROMSIZE);    check(USBDM_Close());    check(USBDM_Exit());    exit(0);}

 

Best Regards,

0 Kudos

4,297 Views
tyamadajp
Contributor I

Hi pgo,

 

Regarding BDM clockrate, you are correct again, and BDMCLK is 12.5Mhz.

My board configuration for normal mode is as follows:

 

  • OSCCLK = 25MHz (supplied from external 25MHz XTAL)

  • PLLCLK = 50MHz (as it is configured as PLLCLK = 2 * OSCCLK)

  • BUSCLK = 25Mhz (as BUSCLK = PLLCLK / 2)

 

So I was assuming BDMCLK is 25MHz as registers are configured that way. But as you pointed out, once it boots into special mode, configuration will go back to default state, making BDMCLK = BUSCLK = OSCCLK /2 = 12.5Mhz (PLL disabled). So I guess it'll be in 25MHz only when issuing BDM commands during normal mode.

0 Kudos

4,297 Views
yarik111475
Contributor II

Hi pgo, if it do not take much your time, I need your help.

I try to use your library (usbdm.4.dll) in custom programming project (programming lang. is C#).

I wrote wrapper for your library, now I can read mcu (I'm working with HCS08 series, GB 60), but just can not understand, how to write mcu and calculate trim value. May be you can help me with some code source files from your project. I see that you use other programming lang., C or C++, but I can understand them.

Here is my community about that problem:

Using usbdm library in custom projects

Thanks.

0 Kudos

4,293 Views
pgo
Senior Contributor V

Hi Yaroslav,

The USBDM.4.dll only provides a low-level communication interface - it does NOT provide programming or calculation of trim values.

You have the following alternatives:

  • Use a TCL script with USBDMScript
  • Use the stand-alone programmer in command line mode. See

http://usbdm.sourceforge.net/USBDM_V4.12/USBDM_FlashProgrammers/html/index.html

  • Use the programmatic interface provided.  See this example:

https://github.com/podonoghue/usbdm-eclipse-makefiles-build/tree/master/USBDM_Programmer_API_Example

The third option appears to be closest to what you want but it requires you to be able to develop C++ programs using MINGW under Windows or the standard GCC under Linux.  The example is pretty complete and shows the process of creating a memory image, loading data from disk and programming it to the target.  To use this example it is not necessary to build USBDM - It is only necessary top extract the required DLLs from an installation.

bye

4,293 Views
cdwward
Contributor I

Hi pgo,

I found this thread really helpful and want to get up and running with your USBDM_Programmer_API_Example but am having trouble building it. I am developing on a Windows 10 machine with Eclipse and MinGW 5.3. I was able to build the USBDM_API_Example without trouble, but when building the USBDM_Programmer_API_Example I get the following linker errors:

..\usbdm-eclipse-makefiles-build\USBDM_Programmer_API_Example/../Shared_V4/src/DeviceInterface.cpp:132: undefined reference to `_imp___ZNK10DeviceData14getEraseMethodEv'
..\usbdm-eclipse-makefiles-build\USBDM_Programmer_API_Example/../Shared_V4/src/DeviceInterface.cpp:132: undefined reference to `_imp___ZN10DeviceData14setEraseMethodENS_11EraseMethodE'
..\usbdm-eclipse-makefiles-build\USBDM_Programmer_API_Example/../Shared_V4/src/DeviceInterface.cpp:133: undefined reference to `_imp___ZNK10DeviceData14getResetMethodEv'
..\usbdm-eclipse-makefiles-build\USBDM_Programmer_API_Example/../Shared_V4/src/DeviceInterface.cpp:133: undefined reference to `_imp___ZN10DeviceData14setResetMethodENS_11ResetMethodE'
USBDM_Programmer_API_Example.i386-win-gnu/DeviceInterface.o: In function `ZN15DeviceInterface12saveSettingsER11AppSettings':
..\usbdm-eclipse-makefiles-build\USBDM_Programmer_API_Example/../Shared_V4/src/DeviceInterface.cpp:158: undefined reference to `_imp___ZNK10DeviceData14getEraseMethodEv'
..\usbdm-eclipse-makefiles-build\USBDM_Programmer_API_Example/../Shared_V4/src/DeviceInterface.cpp:159: undefined reference to `_imp___ZNK10DeviceData14getResetMethodEv'

I have copied over all the dlls from my USBDM 4.12.1.170 install.

Any help or suggestions that you can give would be greatly appreciated.

Thanks!

0 Kudos

4,293 Views
pgo
Senior Contributor V

Hi Chris,

The methods mentioned are ones that have been added in 4.12.1.180 so the DLLs you are using are out of date.  Please wait a few days until the new version is released and try again.

bye

0 Kudos

4,293 Views
cdwward
Contributor I

Thanks, pgo!

I will keep an eye out for the new version to be released.

Thanks again,

Chris.

0 Kudos

4,293 Views
pgo
Senior Contributor V

Hi Chris,

 

Please try the current version - 4.12.1.180.

bye

0 Kudos

4,293 Views
cdwward
Contributor I

Worked great! Thanks, pgo.

0 Kudos

4,297 Views
cdwward
Contributor I

Hi pgo,

I have run into another snag while using the API and am hoping you can help.

I am using the API in a multithreaded environment. I've been careful to ensure that the components are created in the thread they are being used in to avoid the tcl interpreter being shared across threads. Everything is working well while the program is running; however, when the application is closed, I am getting the error "FlushChannel: damaged channel list" and the program crashes. It looks like this is a tcl error, and I am guessing it is because some tcl components are being cleaned up by the main thread on exit (and therefore not in the thread they were created in)...? I have tried resetting all the shared pointers before leaving the thread, but that has made no difference.

Any help or suggestion that you are able to provide would be really appreciated.

Chris.

0 Kudos