⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bdm.c

📁 Freescale的S08BDM开发工具制作资料
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
    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 + -