Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
Revision 2:bf3a2b29259a, committed 2010-12-14
- Comitter:
- Just4pLeisure
- Date:
- Tue Dec 14 21:50:35 2010 +0000
- Parent:
- 1:d5452e398b76
- Child:
- 3:92dae9083c83
- Commit message:
- Update for change to BDM DSO connection (and removed DS) fixed a bug that prevented BDM mode detecting Trionic 7 ECUs
Changed in this revision
--- a/bdm.cpp Tue Sep 14 21:02:04 2010 +0000 +++ b/bdm.cpp Tue Dec 14 21:50:35 2010 +0000 @@ -116,7 +116,7 @@ // Set some initial values to help with checking if the BDM connector is plugged in PIN_PWR.mode(PullDown); PIN_NC.mode(PullUp); - PIN_DS.mode(PullUp); +// PIN_DS.mode(PullUp); PIN_FREEZE.mode(PullUp); PIN_DSO.mode(PullUp); @@ -188,7 +188,7 @@ // printf("%02x", (BDM_PIN & 0x3f)); printf("PWR %d, ", PIN_PWR.read()); printf("NC %d, ", PIN_NC.read()); - printf("DS %d, ", PIN_DS.read()); +// printf("DS %d, ", PIN_DS.read()); printf("FREEZE %d, ", PIN_FREEZE.read()); printf("DSO %d, ", PIN_DSO.read()); return TERM_OK;
--- a/bdmcpu32.cpp Tue Sep 14 21:02:04 2010 +0000 +++ b/bdmcpu32.cpp Tue Dec 14 21:50:35 2010 +0000 @@ -73,6 +73,7 @@ bool bdm_write(const uint32_t* addr, uint16_t cmd, const uint32_t* value); //bool bdm_write_overlap(const uint32_t* addr, uint16_t cmd, const uint32_t* value, uint16_t next_cmd); void bdm_clk(uint16_t value, uint8_t num_bits); +void bdm_clk_fast(uint16_t value, uint8_t num_bits); void bdm_clear(); //----------------------------------------------------------------------------- @@ -613,7 +614,7 @@ if (!bdm_command(BDM_READ + BDM_BYTESIZE)) return TERM_ERR; // write the optional address if (addr) { - if(!bdm_address(addr)) return TERM_ERR; + if (!bdm_address(addr)) return TERM_ERR; } return TERM_OK; @@ -636,7 +637,7 @@ if (bdm_response > BDM_CMDCMPLTE) return TERM_ERR; // write the optional address if (addr) { - if(!bdm_address(addr)) return TERM_ERR; + if (!bdm_address(addr)) return TERM_ERR; } return TERM_OK; @@ -659,7 +660,7 @@ if (bdm_response > BDM_CMDCMPLTE) return TERM_ERR; // write the optional address if (addr) { - if(!bdm_address(addr)) return TERM_ERR; + if (!bdm_address(addr)) return TERM_ERR; } return TERM_OK; @@ -675,12 +676,12 @@ uint8_t memwrite_byte_cmd(const uint32_t* addr) { if (!IN_BDM) return TERM_ERR; - + // write command code if (!bdm_command(BDM_WRITE + BDM_BYTESIZE)) return TERM_ERR; // write the optional address if (addr) { - if(!bdm_address(addr)) return TERM_ERR; + if (!bdm_address(addr)) return TERM_ERR; } return TERM_OK; @@ -703,7 +704,7 @@ if (bdm_response > BDM_CMDCMPLTE) return TERM_ERR; // write the optional address if (addr) { - if(!bdm_address(addr)) return TERM_ERR; + if (!bdm_address(addr)) return TERM_ERR; } return TERM_OK; @@ -726,7 +727,7 @@ if (bdm_response > BDM_CMDCMPLTE) return TERM_ERR; // write the optional address if (addr) { - if(!bdm_address(addr)) return TERM_ERR; + if (!bdm_address(addr)) return TERM_ERR; } return TERM_OK; @@ -747,7 +748,7 @@ if (!IN_BDM) return TERM_ERR; // write the optional address if (addr) { - if(!bdm_address(addr)) return TERM_ERR; + if (!bdm_address(addr)) return TERM_ERR; } // receive the response byte return (bdm_get ((uint32_t*)result, BDM_BYTESIZE, BDM_READ + BDM_BYTESIZE)) ? TERM_OK : TERM_ERR; @@ -768,7 +769,7 @@ if (!IN_BDM) return TERM_ERR; // write the optional address if (addr) { - if(!bdm_address(addr)) return TERM_ERR; + if (!bdm_address(addr)) return TERM_ERR; } // receive the response byte return (bdm_get((uint32_t*)result, BDM_BYTESIZE, BDM_WRITE + BDM_BYTESIZE)) ? TERM_OK : TERM_ERR; @@ -789,7 +790,7 @@ if (!IN_BDM) return TERM_ERR; // write the optional address if (addr) { - if(!bdm_address(addr)) return TERM_ERR; + if (!bdm_address(addr)) return TERM_ERR; } // receive the response byte return (bdm_get((uint32_t*)result, BDM_BYTESIZE, BDM_NOP)) ? TERM_OK : TERM_ERR; @@ -810,7 +811,7 @@ if (!IN_BDM) return TERM_ERR; // write the optional address if (addr) { - if(!bdm_address(addr)) return TERM_ERR; + if (!bdm_address(addr)) return TERM_ERR; } // write the value if (!bdm_put((uint32_t*)&value, BDM_BYTESIZE)) return TERM_ERR; @@ -833,7 +834,7 @@ if (!IN_BDM) return TERM_ERR; // write the optional address if (addr) { - if(!bdm_address(addr)) return TERM_ERR; + if (!bdm_address(addr)) return TERM_ERR; } // write the value if (!bdm_put((uint32_t*)&value, BDM_BYTESIZE)) return TERM_ERR; @@ -856,7 +857,7 @@ if (!IN_BDM) return TERM_ERR; // write the optional address if (addr) { - if(!bdm_address(addr)) return TERM_ERR; + if (!bdm_address(addr)) return TERM_ERR; } // write the value if (!bdm_put((uint32_t*)&value, BDM_BYTESIZE)) return TERM_ERR; @@ -870,30 +871,21 @@ Writes 2 words to the same address The BDM commands are overlapped to make things a bit faster A BDM_NOP command is then sent to end the sequence of overlapping commands - + @param addr address value1, 2 values to write @return status flag */ uint8_t memwrite_word_write_word(const uint32_t* addr, const uint16_t value1, const uint16_t value2) { - - if (!IN_BDM) return TERM_ERR; - - // write command code - if (!bdm_command(BDM_WRITE + BDM_WORDSIZE)) return TERM_ERR; - // write the address - if (!bdm_address(addr)) return TERM_ERR; - // write the first value - if (!bdm_put((uint32_t*)&value1, BDM_WORDSIZE)) return TERM_ERR; - // wait until MCU responds and overlap the next write command - if (!bdm_ready(BDM_WRITE + BDM_WORDSIZE)) return TERM_ERR; - // write the address (same address for second word) - if (!bdm_address(addr)) return TERM_ERR; - // write the second value - if (!bdm_put((uint32_t*)&value2, BDM_WORDSIZE)) return TERM_ERR; - // wait until MCU responds - return (bdm_ready(BDM_NOP)) ? TERM_OK : TERM_ERR; + return (IN_BDM && + bdm_command(BDM_WRITE + BDM_WORDSIZE) && // write command code + bdm_address(addr) && // write the address + bdm_put((uint32_t*)&value1, BDM_WORDSIZE) && // write the first value + bdm_ready(BDM_WRITE + BDM_WORDSIZE) && // wait until MCU responds and overlap the next write command + bdm_address(addr) && // write the address (same address for second word) + bdm_put((uint32_t*)&value2, BDM_WORDSIZE) && // write the second value + bdm_ready(BDM_NOP)) ? TERM_OK : TERM_ERR; // wait until MCU responds } //----------------------------------------------------------------------------- @@ -910,21 +902,13 @@ */ uint8_t memwrite_word_read_word(uint16_t* result, const uint32_t* addr, const uint16_t value) { - - if (!IN_BDM) return TERM_ERR; - - // write command code - if (!bdm_command(BDM_WRITE + BDM_WORDSIZE)) return TERM_ERR; - // write the address - if (!bdm_address(addr)) return TERM_ERR; - // write the value - if (!bdm_put((uint32_t*)&value, BDM_WORDSIZE)) return TERM_ERR; - // wait until MCU responds and overlap the next read command - if (!bdm_ready(BDM_READ + BDM_WORDSIZE)) return TERM_ERR; - // write the address (same address for reading the result) - if (!bdm_address(addr)) return TERM_ERR; - // receive the response word - return (bdm_get((uint32_t*)result, BDM_WORDSIZE, BDM_NOP)) ? TERM_OK : TERM_ERR; + return (IN_BDM && + bdm_command(BDM_WRITE + BDM_WORDSIZE) && // write command code + bdm_address(addr) && // write the address + bdm_put((uint32_t*)&value, BDM_WORDSIZE) && // write the value + bdm_ready(BDM_READ + BDM_WORDSIZE) && // wait until MCU responds and overlap the next read command + bdm_address(addr) && // write the address (same address for reading the result) + bdm_get((uint32_t*)result, BDM_WORDSIZE, BDM_NOP)) ? TERM_OK : TERM_ERR; // receive the response word } //----------------------------------------------------------------------------- @@ -1169,19 +1153,19 @@ bool bdm_command (uint16_t cmd) { // write command code - bdm_clk(cmd, CMD_BIT_COUNT); + bdm_clk_fast(cmd, CMD_BIT_COUNT); return (bdm_response > BDM_NOTREADY) ? false : true; } bool bdm_address (const uint32_t* addr) { // write an address // first word - bdm_clk((uint16_t)((*addr) >> 16), CMD_BIT_COUNT); + bdm_clk_fast((uint16_t)((*addr) >> 16), CMD_BIT_COUNT); if (bdm_response > BDM_NOTREADY) { return false; } // second word - bdm_clk((uint16_t)(*addr), CMD_BIT_COUNT); + bdm_clk_fast((uint16_t)(*addr), CMD_BIT_COUNT); return (bdm_response > BDM_NOTREADY) ? false : true; } @@ -1194,7 +1178,7 @@ // wait while MCU prepares the response wait_cnt = ERR_COUNT; do { - bdm_clk(next_cmd, CMD_BIT_COUNT); + bdm_clk_fast(next_cmd, CMD_BIT_COUNT); } while (bdm_response == BDM_NOTREADY && --wait_cnt > 0); // save the result @@ -1212,12 +1196,12 @@ bool bdm_put (const uint32_t* value, uint8_t size) { // write the value if (size & BDM_LONGSIZE) { - bdm_clk((uint16_t)((*value) >> 16), CMD_BIT_COUNT); + bdm_clk_fast((uint16_t)((*value) >> 16), CMD_BIT_COUNT); if (bdm_response > BDM_NOTREADY) { return false; } } - bdm_clk((uint16_t)(*value), CMD_BIT_COUNT); + bdm_clk_fast((uint16_t)(*value), CMD_BIT_COUNT); return (bdm_response > BDM_NOTREADY) ? false : true; } @@ -1226,7 +1210,7 @@ uint8_t wait_cnt = ERR_COUNT; do { // read response - bdm_clk(next_cmd, CMD_BIT_COUNT); + bdm_clk_fast(next_cmd, CMD_BIT_COUNT); } while (bdm_response == BDM_NOTREADY && --wait_cnt > 0); // check if command succeeded @@ -1242,42 +1226,77 @@ */ void bdm_clk(uint16_t value, uint8_t num_bits) { // PIN_BKPT.output(); -// PIN_DSI.output(); - LPC_GPIO2->FIODIR |= 0x00000004; + PIN_DSI.output(); // clock the value via BDM bdm_response = ((uint32_t)value) << (32 - num_bits); // bool dsi; - while (num_bits--) { // falling edge on BKPT/DSCLK PIN_BKPT.write(0); - // set DSI bit PIN_DSI.write(bdm_response & 0x80000000); bdm_response <<= 1; - // read DSO bit bdm_response |= PIN_DSO.read(); - // short delay // for (uint8_t c = 1; c; c--); // wait_us(1); - // rising edge on BKPT/DSCLK PIN_BKPT.write(1); - // short delay for (uint8_t c = 1; c; c--); // wait_us(1); } - PIN_DSI.input(); -// LPC_GPIO2->FIODIR &= 0xfffffffb; } //----------------------------------------------------------------------------- /** + Writes a word to target MCU via BDM line and gets the response. + This 'fast' version can be used once the 68332 has been 'prepped' + because the BDM interface can go twice as fast once the 68332 + clock is increased from 8 MHz to 16 MHz + + @param value value to write + @param num_bits value size, bits +*/ +void bdm_clk_fast(uint16_t value, uint8_t num_bits) { + + //Set BKPT +// PIN_BKPT.write(1); +// LPC_GPIO2->FIOSET = (1 << 4); +// PIN_BKPT.output(); + +// uint32_t mask = LPC_GPIO2->FIOMASK; +// LPC_GPIO2->FIOMASK = ~((1 << 4) | (1 << 2)); + //Make DSI an output + LPC_GPIO2->FIODIR |= (1 << 2); + // clock the value via BDM + bdm_response = ((uint32_t)value) << (32 - num_bits); + while (num_bits--) { + // set DSI bit +// LPC_GPIO2->FIOPIN = ((bool)(bdm_response & 0x80000000) << 2); + if (bdm_response & 0x80000000) + LPC_GPIO2->FIOSET = (1 << 2); + else + LPC_GPIO2->FIOCLR = (1 << 2); + // falling edge on BKPT/DSCLK + LPC_GPIO2->FIOCLR = (1 << 4); +// for (uint8_t c = 1; c; c--); +// // read DSO bit +// (bdm_response <<= 1) |= (bool)((LPC_GPIO0->FIOPIN) & (1 << 11)); -- OLD CONNECTION to PIN 27 + (bdm_response <<= 1) |= (bool)((LPC_GPIO2->FIOPIN) & (1 << 1)); + // rising edge on BKPT/DSCLK + LPC_GPIO2->FIOSET = (1 << 4); + for (uint8_t c = 1; c; c--); + } + //Make DSI an input + LPC_GPIO2->FIODIR &= ~(1 << 2); +// LPC_GPIO2->FIOMASK = mask; +} +//----------------------------------------------------------------------------- +/** Clears the BDM interface after errors. */ void bdm_clear() {
--- a/bdmcpu32.h Tue Sep 14 21:02:04 2010 +0000 +++ b/bdmcpu32.h Tue Dec 14 21:50:35 2010 +0000 @@ -30,13 +30,16 @@ // MCU status macros #ifndef IGNORE_VCC_PIN - #define IS_CONNECTED (PIN_PWR) +// #define IS_CONNECTED (PIN_PWR) + #define IS_CONNECTED (bool)((LPC_GPIO1->FIOPIN) & (1 << 30)) // PIN_POWER is p19 p1.30 #else #define IS_CONNECTED true #endif // IGNORE_VCC_PIN -#define IN_BDM (PIN_FREEZE) -#define IS_RUNNING (PIN_RESET && !IN_BDM) +//#define IN_BDM (PIN_FREEZE) +#define IN_BDM (bool)((LPC_GPIO2->FIOPIN) & (1 << 0)) // FREEZE is p26 P2.0 +//#define IS_RUNNING (PIN_RESET && !IN_BDM) +#define IS_RUNNING ((bool)((LPC_GPIO2->FIOPIN) & (1 << 3)) && !IN_BDM) // PIN_RESET is P23 P2.3 // MCU management uint8_t stop_chip();
--- a/bdmtrionic.cpp Tue Sep 14 21:02:04 2010 +0000 +++ b/bdmtrionic.cpp Tue Dec 14 21:50:35 2010 +0000 @@ -110,8 +110,7 @@ if (curr_addr < *end_addr - 4) { pc.putc(TERM_OK); // light up the activity LED - // led_on(LED_ACT); - led3 = 1; + ACTIVITYLEDON; } curr_addr += 4; @@ -207,9 +206,9 @@ file_buffer[byte_count+2] = ((uint8_t)(long_value >> 8)); file_buffer[byte_count+3] = ((uint8_t)long_value); byte_count +=4; + // make the activity led twinkle + ACTIVITYLEDON; } -// make the activity led twinkle - led3 = 1; fwrite(file_buffer, 1, FILE_BUF_LENGTH, fp); if (ferror (fp)) { fclose (fp); @@ -350,8 +349,7 @@ curr_addr += 2; // light up the activity LED -// led_on(LED_ACT); - led3 = 1; + ACTIVITYLEDON; } // reset flash @@ -473,7 +471,7 @@ case AMD29F400T: case AMD29F010: printf("Erasing 29F400/010 type FLASH chips...\r\n"); - if (erase_am29() == TERM_ERR) { + if (!erase_am29()) { printf("WARNING: An error occured when I tried to erase the FLASH chips :-(\r\n"); return TERM_ERR; } @@ -484,7 +482,7 @@ case AMD28F512: case INTEL28F512: printf("Erasing 28F010/512 type FLASH chips...\r\n"); - if (erase_am28(&curr_addr, &flash_size) == TERM_ERR) { + if (!erase_am28(&curr_addr, &flash_size)) { printf("WARNING: An error occured when I tried to erase the FLASH chips :-(\r\n"); return TERM_ERR; } @@ -531,8 +529,7 @@ curr_addr += 2; // make the activity LED twinkle - led3 = 1; - + ACTIVITYLEDON; } timer.stop(); @@ -666,8 +663,7 @@ */ bool reset_am28(void) { uint32_t start_addr = 0x0; - return (memwrite_word(&start_addr, 0xffff) == TERM_OK && - memwrite_word(&start_addr, 0xffff) == TERM_OK); + return (memwrite_word_write_word(&start_addr, 0xffff, 0xffff) == TERM_OK); } //----------------------------------------------------------------------------- @@ -697,15 +693,14 @@ // // feedback to host computer // pc.putc(TERM_OK); // make the activity LED twinkle -// led3 = (addr & 0x400); - led3 = 1; + ACTIVITYLEDON; + } // erase flash addr = *start_addr; uint8_t verify_value; - uint16_t pulse_cnt = 0; if (memwrite_byte_cmd(NULL) != TERM_OK) { reset_am28(); @@ -727,7 +722,7 @@ // succeeded need to check next address addr++; // make the activity LED twinkle - led3 = 1; + ACTIVITYLEDON; } } // the erase process ends with a BDM_WRITE + BDM_BYTESIZE command left in the BDM @@ -768,13 +763,14 @@ while (++pulse_cnt < 25) { // set a mask - if ((uint8_t)verify_value == (uint8_t)value) mask_value &= 0xff00; - if ((uint8_t)(verify_value >> 8) == (uint8_t)(value >> 8)) mask_value &= 0x00ff; + if ((uint8_t)verify_value == (uint8_t)value) + mask_value &= 0xff00; + if ((uint8_t)(verify_value >> 8) == (uint8_t)(value >> 8)) + mask_value &= 0x00ff; // write the new value if (memwrite_word_write_word(addr, (0x4040 & mask_value), value) != TERM_OK) break; // NOTE the BDM interface is slow enough that there is no need for a 10us delay before verifying -// wait_us(10); // issue the verification command // NOTE the BDM interface is slow enough that there is no need for a 6us delay before reading back if (memwrite_word_read_word(&verify_value, addr, (0xc0c0 & mask_value)) != TERM_OK) break; @@ -871,8 +867,10 @@ if (memwrite_word(&am29_id[i].addr, am29_id[i].val) != TERM_OK) return false; } if (memread_long(&value, &addr) != TERM_OK) return false; - *make = (uint8_t)(value >> 24); - *type = (uint8_t)(value >> 8); +// *make = (uint8_t)(value >> 24); +// *type = (uint8_t)(value >> 8); + *make = (uint8_t)(value >> 16); + *type = (uint8_t)(value); printf("FLASH id bytes: %08x, make: %02x, type: %02x\r\n", value, *make, *type); switch (*type) { case AMD29F400B:
--- a/canutils.cpp Tue Sep 14 21:02:04 2010 +0000 +++ b/canutils.cpp Tue Dec 14 21:50:35 2010 +0000 @@ -67,7 +67,8 @@ while (CANTimer.read_ms() < timeout) { if (can.write(CANMessage(id, frame, len))) { CANTimer.stop(); - led1 = 1; + CANTXLEDON; +// led1 = 1; return TRUE; } } @@ -100,7 +101,8 @@ } printf("\n\r"); // */ - led2 = 1; + CANRXLEDON; +// led2 = 1; if (CANMsgRx.id == id) { CANTimer.stop(); // if (T5MsgRx.len != len)
--- a/common.h Tue Sep 14 21:02:04 2010 +0000 +++ b/common.h Tue Dec 14 21:50:35 2010 +0000 @@ -29,7 +29,7 @@ // constants #define FW_VERSION_MAJOR 0x1 ///< firmware version -#define FW_VERSION_MINOR 0x1 +#define FW_VERSION_MINOR 0x2 #define CR 0x0D #define NL 0x0A
--- a/interfaces.cpp Tue Sep 14 21:02:04 2010 +0000 +++ b/interfaces.cpp Tue Dec 14 21:50:35 2010 +0000 @@ -38,9 +38,9 @@ DigitalInOut PIN_BKPT(p22); // breakpoint/serial clock DigitalInOut PIN_RESET(p23); // reset signal DigitalInOut PIN_DSI(p24); // data input (to ECU) signal -DigitalIn PIN_DS(p25); // data strobe signal (not used) +DigitalIn PIN_DSO(p25); // data output (from ECU) signal DigitalIn PIN_FREEZE(p26); // freeze signal -DigitalIn PIN_DSO(p27); // data output (from ECU) signal +//DigitalIn PIN_DS(p27); // data strobe signal (not used) //LEDS @@ -54,7 +54,7 @@ Ticker ticker; void leds_off() { - led1 = 0; - led2 = 0; - led3 = 0; + CANTXLEDOFF; + CANRXLEDOFF; + ACTIVITYLEDOFF; } \ No newline at end of file
--- a/interfaces.h Tue Sep 14 21:02:04 2010 +0000 +++ b/interfaces.h Tue Dec 14 21:50:35 2010 +0000 @@ -31,9 +31,9 @@ extern DigitalInOut PIN_BKPT; // breakpoint/serial clock extern DigitalInOut PIN_RESET; // reset signal extern DigitalInOut PIN_DSI; // data input (to ECU) signal -extern DigitalIn PIN_DS; // data strobe signal (not used) +extern DigitalIn PIN_DSO; // data output (from ECU) signal extern DigitalIn PIN_FREEZE; // freeze signal -extern DigitalIn PIN_DSO; // data output (from ECU) signal +//extern DigitalIn PIN_DS; // data strobe signal (not used) //LEDS @@ -47,4 +47,15 @@ void leds_off(void); +// led control macros +// These macros use the fastio register method to control the leds +#define CANTXLEDON LPC_GPIO1->FIOSET = (1 << 18) // Turn on the CAN bus transmitter activity led (led1, P1.18) +#define CANTXLEDOFF LPC_GPIO1->FIOCLR = (1 << 18) // Turn off the CAN bus transmitter activity led (led1, P1.18) +#define CANRXLEDON LPC_GPIO1->FIOSET = (1 << 20) // Turn on the CAN bus receiver activity led (led2, P1.20) +#define CANRXLEDOFF LPC_GPIO1->FIOCLR = (1 << 20) // Turn off the CAN bus receiver activity led (led2, P1.20) +#define ACTIVITYLEDON LPC_GPIO1->FIOSET = (1 << 21) // Turn on the activity led (led3, P1.21) +#define ACTIVITYLEDOFF LPC_GPIO1->FIOCLR = (1 << 21) // Turn off the activity led (led3, P1.21) +#define ERRORLEDON LPC_GPIO1->FIOSET = (1 << 23) // Turn on the ERROR led (led3, P1.23) +#define ERRORLEDOFF LPC_GPIO1->FIOCLR = (1 << 23) // Turn off the ERROR led (led3, P1.23) + #endif // __INTERFACES_H__ \ No newline at end of file
--- a/main.cpp Tue Sep 14 21:02:04 2010 +0000 +++ b/main.cpp Tue Dec 14 21:50:35 2010 +0000 @@ -28,6 +28,25 @@ ******************************************************************************** +Version 1.2 (12/2010) - Only a very small update + +Fixed since Version 1.1: + My method of detecting the FLASH type didn't work for T7 ECUs + Now that that I have corrected this bug it is possible to + FLASH Trionic 7 ECUs using the BDM connection + See the 'get_flash_id' function in bdmtrionic.cpp + +Changes since Verion 1.2 + I have removed everything to do with the BDM DS connection + I have changed the mbed pin number for the BDM DSO connection + Now all BDM connections are part of the same MBED 'port' + Being part of one port makes it possible to change all + connections simulataneously so speeding up BDM + See 'interfaces.cpp' for details of how the mbed pins connect. + Uglybug's wiring circuit has these connections (thanks Uglybug) + +******************************************************************************** + Version 1.1 (09/2010) - Still very crude way of doing things Additions since Version 1: