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 *********************/