?? bdm.c
字號:
/*
Open Source BDM - BDM communication
/* Prominent Notice-This software was modified from TBDML software - 12/05
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "MC68HC908JB16.h"
#include "hidef.h"
#include "bdm.h"
#include "commands.h"
#include "usb.h"
/* i, j & k are used as timing and general purpose variables in the Tx & Rx routines */
/* must be placed into the direct segment */
static unsigned char i;
static unsigned char j;
static unsigned char k;
/* pointers to Rx & Tx routines, tables for selection */
unsigned char (*bdm_rx_ptr)(void) = bdm_empty_rx_tx;
void (*bdm_tx_ptr)(unsigned char) = bdm_empty_rx_tx;
/* when SYNC length expressed in 60MHz ticks is ABOVE OR EQUAL to the value in the table, the correspnding pointer is selected */
/* if SYNC is shother than the first entry, the target runs too fast */
/* if SYNC is longer or equal to the last entry, the target runs too slow */
const unsigned int bdm_tx_sel_tresholds[]=
{600, 1129, 1335, 1541, 1747, 1952, 2157, 2465, 2877, 3288,
3800, 4418, 5136, 6059, 7189, 8524, 10066, 11814, 13867, 16988};
void (* const bdm_tx_sel_ptrs[])(unsigned char)=
{bdm_tx1, bdm_tx2, bdm_tx3, bdm_tx4, bdm_tx5, bdm_tx6, bdm_tx7, bdm_tx8, bdm_tx9, bdm_tx10,
bdm_tx11,bdm_tx12,bdm_tx13,bdm_tx14,bdm_tx15,bdm_tx16,bdm_tx17,bdm_tx18,bdm_tx19,bdm_empty_rx_tx};
const unsigned int bdm_rx_sel_tresholds[]=
{600, 1101, 1347, 1592, 1837, 2202, 2694, 3303, 4042, 4897,
5998, 7346, 9055, 11257, 13952, 17919};
unsigned char (* const bdm_rx_sel_ptrs[])(void)=
{bdm_rx1, bdm_rx2, bdm_rx3, bdm_rx4, bdm_rx5, bdm_rx6, bdm_rx7, bdm_rx8, bdm_rx9, bdm_rx10,
bdm_rx11,bdm_rx12,bdm_rx13,bdm_rx14,bdm_rx15,bdm_empty_rx_tx};
/* status of the BDM communication */
bdm_status_t bdm_status;
/* private macros */
#define ACKN_CLR asm (BCLR T1SC0_CH0F_BITNUM,T1SC0); /* clear timer capture flag, in assembly to make sure the compiler does not mess it up... */
/* functions */
unsigned char bdm08_stat(void) {
unsigned char bdm_sts;
/* try the ACKN feature */
BDM08_CMD_READSTATUS(&bdm_sts);
if ((bdm_sts&0x40)==0) {
return(0);
}
return(1);/* connection established */
}
unsigned char bdm08_connect(void) {
unsigned char bdm_sts;
bdm_status.ackn = WAIT; /* clear the ACKN feature */
bdm_status.reset = NO_RESET_ACTIVITY; /* clear the reset flag */
/* first wait until both RESET and BDM are high */
T1MOD = RESET_WAIT * BUS_FREQUENCY * 16; /* this is by 2.4% longer than (RESET_WAIT * BUS_FREQUENCY * 1000)/64, but cannot do that in 16-bit math */
T1SC = T1SC_TRST_MASK | T1SC_PS1_MASK | T1SC_PS2_MASK; /* reset the timer and start counting @ bus clock divided by 64 */
T1SC_TOF = 0;
while(((RESET_IN==0)||(BDM_IN==0))&&(T1SC_TOF==0)); /* wait for reset and bdm to rise or timeout */
if (T1SC_TOF) return(1); /* timeout */
if (bdm_sync_meas()) {
/* trying to measure SYNC was not successful */
return(1);
}
if (bdm_rx_tx_select()) return(1); /* if at least one of the two methods succeeded, we can select the right Rx and Tx routines */
bdm_ackn_init(); /* try the ACKN feature */
BDM08_CMD_READSTATUS(&bdm_sts);
if ((bdm_sts&0x80)==0) BDM08_CMD_WRITECONTROL(0x80|bdm_sts); /* if BDM not enabled yet, enable it so it can be made active */
return(0); /* connection established */
}
/* connect to HC12 or HCS12 target */
/* returns 0 on succes or 1 on failure */
unsigned char bdm12_connect(void) {
unsigned char bdm_sts;
bdm_status.ackn = WAIT; /* clear the ACKN feature */
bdm_status.reset = NO_RESET_ACTIVITY; /* clear the reset flag */
/* first wait until both RESET and BDM are high */
T1MOD = RESET_WAIT * BUS_FREQUENCY * 16; /* this is by 2.4% longer than (RESET_WAIT * BUS_FREQUENCY * 1000)/64, but cannot do that in 16-bit math */
T1SC = T1SC_TRST_MASK | T1SC_PS1_MASK | T1SC_PS2_MASK; /* reset the timer and start counting @ bus clock divided by 64 */
T1SC_TOF = 0;
while(((RESET_IN==0)||(BDM_IN==0))&&(T1SC_TOF==0)); /* wait for reset and bdm to rise or timeout */
if (T1SC_TOF) return(1); /* timeout */
if (bdm_sync_meas()) {
/* trying to measure SYNC was not successful */
return(1);
}
if (bdm_rx_tx_select()) return(1); /* if at least one of the two methods succeeded, we can select the right Rx and Tx routines */
bdm_ackn_init(); /* try the ACKN feature */
BDM12_CMD_BDREADB(BDM12_STS_ADDR,&bdm_sts);
if ((bdm_sts&0x80)==0) BDM12_CMD_BDWRITEB(BDM12_STS_ADDR,0x80|bdm_sts); /* if BDM not enabled yet, enable it so it can be made active */
return(0); /* connection established */
}
/* resets the target */
/* mode == 0 -> reset to special mode, mode == 1 -> reset to normal mode */
/* returns zero on success and non-zero if reset signal stuck to ground */
unsigned char bdm_softreset(unsigned char mode) {
if(mode ==0){
BDM08_CMD_Res(0x1801,0x01);
BDM_OUT = 0; /* drive BDM low */
asm{
MOV #01,BDM_DIR2_PORT /* start driving the BDM */
}
T1MOD = RESET_SETTLE * BUS_FREQUENCY; /* time to wait for signals to settle */
T1SC = T1SC_TRST_MASK; /* reset the timer and start counting @ bus clock */
T1SC_TOF = 0;
while(T1SC_TOF==0); /* wait for timeout */
T1MOD = RESET_SETTLE * BUS_FREQUENCY; /* time to wait for signals to settle */
T1SC = T1SC_TRST_MASK; /* reset the timer and start counting @ bus clock */
T1SC_TOF = 0;
while(T1SC_TOF==0); /* wait for timeout */
asm {
CLRX /* point to PTA */
CLRH
LDA #BDM_DIR1_MASK + BDM_OUT_MASK + RESET_OUT_MASK
STA ,X /* bring BDM high */
AND #0xEF
STA ,X /* stop driving the BDM */
/* it took 4 cycles from bringing BDM high to stop driving it and that is fast enough up to 16*3/4 = 12 MHz of BDM frequency on JB8 */
}
/* wait one more settling time before allowing anythig else to happen on the BDM */
T1MOD = RESET_SETTLE * BUS_FREQUENCY; /* time to wait for signals to settle */
T1SC = T1SC_TRST_MASK; /* reset the timer and start counting @ bus clock */
T1SC_TOF = 0;
while(T1SC_TOF==0);
bdm_tx_finish();
}
if (mode ==1){
BDM08_CMD_WRITEB(0x1801,0x01);
}
}
/* resets the target */
/* mode == 0 -> reset to special mode, mode == 1 -> reset to normal mode */
/* returns zero on success and non-zero if reset signal stuck to ground */
unsigned char bdm_reset(unsigned char mode) {
BDM_DIR1 = 0; /* stop driving the BDM */
KBSCR_IMASKK = 1; /* mask KBD interrupts */
T1MOD = RESET_WAIT * BUS_FREQUENCY * 16; /* this is by 2.4% longer than (RESET_WAIT * BUS_FREQUENCY * 1000)/64, but cannot do that in 16-bit math */
T1SC = T1SC_TRST_MASK | T1SC_PS1_MASK | T1SC_PS2_MASK; /* reset the timer and start counting @ bus clock divided by 64 */
T1SC_TOF = 0;
while((RESET_IN==0)&&(T1SC_TOF==0)); /* wait for reset to rise or timeout */
if (T1SC_TOF) return(1);
if (mode==0) {
BDM_OUT = 0; /* drive BDM low */
BDM_DIR1 = 1;
T1MOD = RESET_SETTLE * BUS_FREQUENCY; /* time to wait for signals to settle */
T1SC = T1SC_TRST_MASK; /* reset the timer and start counting @ bus clock */
T1SC_TOF = 0;
while(T1SC_TOF==0); /* wait for timeout */
}
//Switch To A to B to drive Reset
RESET_DR = 1; //Default is B to A for Input
RESET_DR_DDR |= RESET_DR_MASK; // Set as output to Drive the buffer
RESET_OUT = 0; /* start driving RESET */
RESET_OUT_DDR |= RESET_OUT_MASK;
T1MOD = RESET_LENGTH * BUS_FREQUENCY * 16; /* time of the RESET pulse */
T1SC = T1SC_TRST_MASK | T1SC_PS1_MASK | T1SC_PS2_MASK; /* reset the timer and start counting @ bus clock divided by 64 */
T1SC_TOF = 0;
while(T1SC_TOF==0); /* wait for timeout */
RESET_OUT = 1; /* stop driving the RESET */
RESET_OUT_DDR &= ~RESET_OUT_MASK; /* and make the pin input again so nothing interferes with it */
//Switch To B to A
RESET_DR = 0; //Default is B to A for Input
T1MOD = RESET_WAIT * BUS_FREQUENCY * 16; /* time to wait for reset to rise */
T1SC = T1SC_TRST_MASK | T1SC_PS1_MASK | T1SC_PS2_MASK; /* reset the timer and start counting @ bus clock divided by 64 */
T1SC_TOF = 0;
while((RESET_IN==0)&&(T1SC_TOF==0)); /* wait for reset to rise or timeout */
if (T1SC_TOF) return(1);
if (mode==0) {
T1MOD = RESET_SETTLE * BUS_FREQUENCY; /* time to wait for signals to settle */
T1SC = T1SC_TRST_MASK; /* reset the timer and start counting @ bus clock */
T1SC_TOF = 0;
while(T1SC_TOF==0); /* wait for timeout */
asm {
CLRX /* point to PTA */
CLRH
LDA #BDM_DIR1_MASK + BDM_OUT_MASK + RESET_OUT_MASK
STA ,X /* bring BDM high */
AND #0xEF
STA ,X /* stop driving the BDM */
/* it took 4 cycles from bringing BDM high to stop driving it and that is fast enough up to 16*3/4 = 12 MHz of BDM frequency on JB8 */
}
}
/* wait one more settling time before allowing anythig else to happen on the BDM */
T1MOD = RESET_SETTLE * BUS_FREQUENCY; /* time to wait for signals to settle */
T1SC = T1SC_TRST_MASK; /* reset the timer and start counting @ bus clock */
T1SC_TOF = 0;
while(T1SC_TOF==0); /* wait for timeout */
KBSCR_ACKK=1; /* acknowledge KBD interrupt */
KBSCR_IMASKK = 0; /* enable KBD interrupts again */
return(0);
}
/* interrupt function servicing the KBD interrupt from RESET_IN assertion */
void interrupt bdm_reset_sense(void) {
KBSCR_ACKK=1; /* acknowledge the interrupt */
bdm_status.reset=RESET_DETECTED; /* record the fact that reset was asserted */
}
/* measures the SYNC length and writes the result into bdm_status structure */
/* returns 0 on succes and non-zero on timeout */
unsigned char bdm_sync_meas(void) {
unsigned int time;
bdm_status.speed = NO_INFO; /* indicate that we do not have a clue about target speed at the moment... */
T1MOD = BDM_SYNC_REQ * BUS_FREQUENCY; /* load T1MOD with the longest SYNC REQUEST possible */
BDM_DIR1 = 0; /* stop driving the BDM */
T1SC = T1SC_TRST_MASK; /* restart the timer */
T1SC_TOF = 0; /* clear TOF */
while((T1SC_TOF==0)&&(BDM_IN==0)); /* wait for the BDM to come high or timeout */
if (T1SC_TOF) return(1); /* timeout ! */
BDM_OUT = 0;
BDM_DIR1 = 1; /* bring BDM low */
T1SC = T1SC_TRST_MASK; /* restart the timer */
T1SC_TOF = 0; /* clear TOF */
while(T1SC_TOF==0); /* wait for timeout */
T1SC_TOF = 0; /* clear the TOF flag */
T1SC0 = T1SC0_ELS0B_MASK; /* capture falling edges */
T1SC0_CH0F=0; /* clear capture flag */
//this is not fast enough, the target will start driving 16 BDM cycles after the pin comes high
//BDM_OUT_PORT = BDM_OUT_MASK; /* bring BDM high */
//BDM_DIR1_PORT = BDM_OUT_MASK | BDM_DIR1_MASK; /* stop driving it */
asm {
CLRX /* point to PTA */
CLRH
LDA #BDM_DIR1_MASK + BDM_OUT_MASK + RESET_OUT_MASK
STA ,X /* bring BDM high */
AND #0xEF
STA ,X /* stop driving the BDM */
/* it took 4 cycles from bringing BDM high to stop driving it and that is fast enough up to 16*3/4 = 12 MHz of BDM frequency on JB8 */
}
while ((T1SC0_CH0F==0)&&(T1SC_TOF==0)); /* wait for capture or timeout */
time=T1CH0; /* capture start of the SYNC */
T1SC0 = T1SC0_ELS0A_MASK; /* capture rising edge, clear capture flag */
/* it takes 32 cycles to reenable capture (worst case) which is good enough up to 128*3/32 = 12 MHz again on JB8 */
while ((T1SC0_CH0F==0)&&(T1SC_TOF==0)); /* wait for capture or timeout */
time=T1CH0-time; /* calculate length of the SYNC */
if (T1SC_TOF) return(2); /* timeout ! */
#if (BUS_FREQUENCY==3)
bdm_status.sync_length=(time<<2)+(time<<4); /* multiply by 20 to get the time in 60MHz ticks */
#elif (BUS_FREQUENCY==6)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -