bam_eep.c
/****************************************************************************/ /* MODULE: bam_eep.c */ /* FUNCTION: EEPROM Programming routines. */ /* PROCESSOR: 8xC196KC */ /* CONTAINS: */ /* HISTORY: 4-3-96 L.R. Erickson - Original */ /****************************************************************************/ #define SRC_BAM_EEP #include "jkc_defs.h" #include "jkc_sfrs.h" #include "jkc_extr.h" #include "jkc_func.h" #include "bam_loop.h" #include "bam_main.h" #include "bam_defs.h" #include "bam_ser.h" #include "bam_comm.h" #include "bam_eep.h" #pragma interrupt(eep_transmit=24) #pragma interrupt(eep_receive=25) /* File Global Vars */ EEP_TX_struct *tx_data_ptr ; EEP_RX_struct *rx_data_ptr ; /********************************************************/ /* ROUTINE: eep_main */ /* FUNCTION:The EEPROM programming routine. */ /* */ /********************************************************/ void eep_main(void) { EEP_TX_struct tx_data ; EEP_RX_struct rx_data ; tx_data_ptr = &tx_data ; rx_data_ptr = &rx_data ; init_eep_data() ; // Wait for startup time out or char. while(!eep_chk_ch_bit(fixed_status,FIXED_STAT_GOON)) { // char received? if(rx_data.head_index != rx_data.tail_index) { // yes - reset time out. disable() ; fixed_num_overflows = 0 ; enable() ; // and process char. process_eep_char() ; } // Check for TX hung. if(tx_data.tx_busy && (fixed_num_overflows > 500)) { // If hung let WDT time out. disable() ; while(1) ; } } // end while } /********* end of eep_main *****************************/ /********************************************************/ /* ROUTINE: eep_transmit */ /* FUNCTION:The EEPROM programming transmit interrupt */ /* handler. */ /********************************************************/ void eep_transmit(void) { unsigned char local_stat ; // // Stack pointer check: If bad, loop till wdt reset // while ( (sp>STACK_TOP) || (sp<STACK_BOT) ); // Not sure if this is necessary, but will // read status to make sure interrupt is cleared. // Also clears RB8. local_stat = sp_stat ; // Char to send? if(tx_data_ptr->tail_index == tx_data_ptr->head_index) { tx_data_ptr->tx_busy = FALSE ; return ; } // Fall thru means yes send char. sbuf = tx_data_ptr->tx_buf[tx_data_ptr->tail_index] ; tx_data_ptr->tail_index++ ; } /************** end of eep_transmit *********************/ /********************************************************/ /* ROUTINE: eep_receive */ /* FUNCTION: The EEPROM programming receive */ /* interrupt handler. */ /********************************************************/ void eep_receive(void) { unsigned char rx_char, tst_index, local_stat ; // // Stack pointer check: If bad, loop till wdt reset // while ( (sp>STACK_TOP) || (sp<STACK_BOT) ); // Read the uart. This also clears the // interrupt. local_stat = sp_stat & (RB8_BIT | FE_BIT | OE_BIT) ; rx_char = sbuf ; // Check 9th bit if(eep_chk_ch_bit(local_stat,RB8_BIT)) { // Our address? if(rx_char == mc_address) { // Switch to receive all. serial_mode(3) ; } else { // Put in cmd listen mode. serial_mode(2) ; return ; } } // End if RB8 // Fall thru means we have a char to process. // Higher level process will handle errors. rx_data_ptr->rx_stat[rx_data_ptr->head_index] = local_stat ; rx_data_ptr->rx_buf[rx_data_ptr->head_index] = rx_char ; // Setup for next. if(++rx_data_ptr->head_index >= EEP_RX_BUF_SIZE) rx_data_ptr->head_index = 0 ; // check for buffer overflow if((rx_data_ptr->head_index == rx_data_ptr->tail_index) || (rx_data_ptr->rx_crash > 0)) rx_data_ptr->rx_crash ++ ; else rx_data_ptr->rx_crash = 0 ; } /**************** end of eep_receive *******************/ /********************************************************/ /* ROUTINE: init_eep_data */ /* FUNCTION:Initialize the EEPROM programming data */ /* structures. */ /********************************************************/ void init_eep_data(void) { tx_data_ptr->tx_busy = FALSE ; rx_data_ptr->head_index = 0 ; rx_data_ptr->tail_index = 0 ; rx_data_ptr->rx_crash = 0 ; rx_data_ptr->rx_proc_state = EEP_WT_CMD_STATE ; } /**************** end of init_eep_data *****************/ /********************************************************/ /* ROUTINE: process_eep_char */ /* FUNCTION:Process the EEPROM programming received */ /* data */ /********************************************************/ void process_eep_char(void) { unsigned char proc_byte, err_flags ; // Check rx buf integrity. if(rx_data_ptr->rx_crash > 1) { // advise send_eep_msg(EEP_BUF_ERR) ; // flush buf & reset rx disable() ; rx_data_ptr->head_index = 0 ; rx_data_ptr->tail_index = 0 ; rx_data_ptr->rx_crash = 0 ; enable() ; rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ; return ; } // get byte and status from buffer proc_byte = rx_data_ptr->rx_stat[rx_data_ptr->tail_index] ; err_flags = rx_data_ptr->rx_buf[rx_data_ptr->tail_index] ; // Setup for next. if(++rx_data_ptr->tail_index >= EEP_RX_BUF_SIZE) rx_data_ptr->tail_index = 0 ; /************ Start of RX error checking ***************/ // Check for cmd state error. if((eep_chk_ch_bit(err_flags,RB8_BIT)) && (rx_data_ptr->rx_proc_state != EEP_WT_MSG_STATE)) { // advise. send_eep_msg(EEP_CMD_STATE_ERR) ; // and go ahead and process. rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ; } // Check WT_MSG_STATE errors. if(rx_data_ptr->rx_proc_state == EEP_WT_MSG_STATE) { // Check 9th bit & errors if((!eep_chk_ch_bit(err_flags,RB8_BIT)) || eep_chk_ch_bit(err_flags,FE_BIT) || eep_chk_ch_bit(err_flags,OE_BIT)) { // going to ignore. If not cmd error already reported. // Replying to wrong address would screw up commo lines. return ; } } else if(eep_chk_ch_bit(err_flags,FE_BIT)) { // advise. send_eep_msg(EEP_FE_ERR) ; // abort processing. rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ; return ; } else if(eep_chk_ch_bit(err_flags,OE_BIT)) { // advise. send_eep_msg(EEP_OE_ERR) ; // abort processing. rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ; return ; } /*************** Start of processing state machine. *******/ switch(rx_data_ptr->rx_proc_state) { case EEP_WT_MSG_STATE: // RX isr has checked address. rx_data_ptr->rx_proc_chksum = proc_byte ; rx_data_ptr->rx_proc_state = EEP_WT_CMD_STATE ; break ; case EEP_WT_CMD_STATE: rx_data_ptr->rx_proc_cmd = proc_byte ; rx_data_ptr->rx_proc_chksum += proc_byte ; switch(rx_data_ptr->rx_proc_cmd) { case EEP_PROG_CMD: rx_data_ptr->rx_proc_state = EEP_WT_CNT_STATE ; break; default: send_eep_msg(EEP_UNK_CMD_ERR) ; rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ; return ; } break ; case EEP_WT_CNT_STATE: if(proc_byte > MAX_PROG_CHARS) { send_eep_msg(EEP_MAX_CNT_ERR) ; rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ; return ; } rx_data_ptr->rx_proc_cnt = proc_byte ; rx_data_ptr->rx_proc_chksum += proc_byte ; rx_data_ptr->rx_proc_state = EEP_WT_HI_ADD_STATE ; break ; case EEP_WT_HI_ADD_STATE: rx_data_ptr->rx_proc_ld_add = (unsigned int) proc_byte ; rx_data_ptr->rx_proc_ld_add = (rx_data_ptr->rx_proc_ld_add << 8) ; rx_data_ptr->rx_proc_chksum += proc_byte ; rx_data_ptr->rx_proc_state = EEP_WT_LO_ADD_STATE ; break ; case EEP_WT_LO_ADD_STATE: rx_data_ptr->rx_proc_ld_add |= (unsigned int) proc_byte ; rx_data_ptr->rx_proc_chksum += proc_byte ; rx_data_ptr->rx_data_cnt = 0 ; rx_data_ptr->rx_proc_state = EEP_WT_DATA_STATE ; break ; case EEP_WT_DATA_STATE: rx_data_ptr->rx_prog_chars[rx_data_ptr->rx_data_cnt] = proc_byte ; rx_data_ptr->rx_proc_chksum += proc_byte ; if(++rx_data_ptr->rx_data_cnt >= rx_data_ptr->rx_data_cnt) rx_data_ptr->rx_proc_state = EEP_WT_CHK_STATE ; break ; case EEP_WT_CHK_STATE: rx_data_ptr->rx_proc_chksum += proc_byte ; if(rx_data_ptr->rx_proc_chksum != 0) { send_eep_msg(EEP_CHK_SUM_ERR) ; rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ; return ; } send_eep_msg(EEP_PROG_CMD_ACK) ; // Go write program. if(write_eeprom()) send_eep_msg(EEP_PROG_CMD_DONE) ; else send_eep_msg(EEP_PROG_CMD_FAIL) ; rx_data_ptr->rx_proc_state = EEP_WT_MSG_STATE ; break ; default: // Something seriously wrong if we get here. // We'll let the WDT time out. disable() ; while(1) ; } // end switch rx_proc_state. } /**************** end of process_eep_char *****************/ /********************************************************/ /* ROUTINE: send_eep_msg */ /* FUNCTION: send a msg to the master computer. */ /* */ /********************************************************/ void send_eep_msg(int msg_num) { unsigned char chk_sum ; // Check for TX hung. while(tx_data_ptr->tx_busy) { if(fixed_num_overflows > 500) { // If hung let WDT time out. disable() ; while(1) ; } } //Initialize tx_data_ptr->head_index = 0 ; tx_data_ptr->tail_index = 0 ; chk_sum = mc_address ; // Load msg bytes. chk_sum += EEP_REPLY ; tx_data_ptr->tx_buf[tx_data_ptr->head_index] = EEP_REPLY ; tx_data_ptr->head_index++ ; chk_sum += msg_num ; tx_data_ptr->tx_buf[tx_data_ptr->head_index] = msg_num ; tx_data_ptr->head_index++ ; chk_sum += 0 ; tx_data_ptr->tx_buf[tx_data_ptr->head_index] = 0 ; tx_data_ptr->head_index++ ; chk_sum += 0 ; tx_data_ptr->tx_buf[tx_data_ptr->head_index] = 0 ; tx_data_ptr->head_index++ ; chk_sum = ~chk_sum ; chk_sum++ ; tx_data_ptr->tx_buf[tx_data_ptr->head_index] = chk_sum ; tx_data_ptr->head_index++ ; // Start UART tx_data_ptr->tx_busy = TRUE ; _set_SFRbit_(sp_con, SET_BIT_8) ; sbuf = mc_address ; // All done. Ints will take care of rest. } /**************** end of send_eep_msg *****************/ /********************************************************/ /* ROUTINE: eep_chk_ch_bit */ /* FUNCTION: nondestructive char bit set check. */ /* */ /********************************************************/ unsigned char eep_chk_ch_bit(unsigned char tst_byte, unsigned char bit_num ) { return(checkbit(tst_byte, bit_num)) ; } /**************** end of eep_chk_ch_bit *****************/ /********************************************************/ /* ROUTINE: write_eeprom */ /* FUNCTION: write the chars to the eeprom. */ /* */ /********************************************************/ unsigned char write_eeprom(void) { volatile unsigned char *wr_prot_add_1 = (unsigned char *) (0x5555 + 0x8fff) ; volatile unsigned char *wr_prot_add_2 = (unsigned char *) (0x2aaa + 0x8fff) ; unsigned char write_offset ; // Do write protect. // *wr_prot_add_1 = 0xaa ; // *wr_prot_add_2 = 0x55 ; // *wr_prot_add_1 = 0xa0 ; write_offset = 0 ; while(write_offset < rx_data_ptr->rx_data_cnt) { *(char *)(rx_data_ptr->rx_proc_ld_add + write_offset) = rx_data_ptr->rx_prog_chars[write_offset] ; write_offset++ ; } // Index back to last byte. write_offset-- ; // Wait till EEPROM done. while(*(char *)(rx_data_ptr->rx_proc_ld_add + write_offset) != rx_data_ptr->rx_prog_chars[write_offset]) { if(fixed_num_overflows > 100) return(FALSE) ; } return(TRUE) ; } /**************** end of write_eeprom *********************/