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

📄 mbusman.cpp

📁 coldfire5206芯片的boot程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include  "bastype.h"
#include  "mcf5206.h"
//#include  "systypes.h"
#include  "syscfg.h"
#include  "mbuspack.h"
#include  "mbusman.h"


/**
 *  This module contains functions for MBUS operation, which including
 *  four MBUS chip's communication protocol, MCF5206 MBUS module
 *  initialization code, MBUS interrupt service routine.
 */

/**
 *  External varibales declare.
 */
extern MBusPackQueType gCAT24C021ReadPackQue;
extern MBusPackQueType gCAT24C021WritePackQue;


/**
 *  static variables define
 */
static MBusInfoType  sMBusInfo = {
                       OPMODE_QUERY,  // initialize to query mode.
                       0,             // current packet processing finished.
                       0,             // error count clear
                       0,             // clear transferFail
                       RTC_NO         // No Real-Time Clock
                     };

/**
 *  The following static variables was used for processing a full data transfer
 */

// Commands to be processed
static  UCHAR  sMBusCmds[600];

// current command to be processed
static  INT16 sCurrentCmd;

// where is the data to be transmitted
static  UCHAR  *sTransmitPtr;

// where is the data received to be saved.
static  UCHAR  *sReceivePtr;

// because all queue are processed in turning, so remember these queues
static MBusPackQueType *sMBusPackQues[PACKQUE_NUMBER] = {
                         &gCAT24C021ReadPackQue,
                         &gCAT24C021WritePackQue
                      };

// A DRAM memory map of EEPROM for calculating checkSum
static UCHAR sMemoryMap[EEPROM_SIZE];
static UCHAR sCheckSum;


/**
 *  Initialize MBUS module.
 */
VOID MBusInit(VOID)
{
   INT32 i; 
   UCHAR status;

   // Problem:
   //   The I2C bus is hanging. When the ColdFire is reset during
   //   an access to an I2C slave device the MBB bit in the MBSR
   //   register is set and we can't communicate with the peripheral
   //   device. What do we do to re-start communications?

   // Solution:
   //   During the initialization of the M-Bus module, the user should
   //   check the MBB bit of the MBSR register. If the MBB bit is set
   //   when the M-Bus module is enabled, then the follow code sequence
   //   should be executed before proceeding with your normal initialization
   //   code. This will issue a STOP command to the slave device which
   //   will then place it into the idle mode state as if it were just
   //   power cycled on.
   //      MBCR = $0
   //      MBCR = $A0
   //      dummy read of MBDR
   //      MBSR = $0
   //      MBCR = $0

   *(UCHAR*)MBCR = 0;
   *(UCHAR*)MBCR = 0xA0;
   status = *(UCHAR*)MBDR;
   for(i = 0; i < 10000; i ++)
      ;
   *(UCHAR*)MBSR = 0;
   *(UCHAR*)MBCR = 0;

   // Reset MBUS.
   *(UCHAR*)MBCR = 0;

   // MBUS interrupt level and priority define:
   // 100 011 00: autovector and level 3, priority 0
   // *(UCHAR*)MBUS_ICR = 0x8c;

   // SCL freqency setting: 51.6096M / 640 = 80640.
   // Note: the index of prescalar value 640 is 0x38.
   *(UCHAR*)MFDR = 0x38;

   // The slave address of MBUS module in MCF5206 is 0x11 when it addressed
   // as a slave. Can it be deleted.
   *(UCHAR*)MADR = 0x11;

   // enable MBUS, but interrupt was disabled
   *(UCHAR*)MBCR = 0x80;

   // enable MBUS and its interrupt
   //*(UCHAR*)MBCR = 0xc0;

   // Set operation mode to query.
   sMBusInfo.mode = OPMODE_QUERY;

   sMBusInfo.currPackFinished = 1;

   // generate stop signal
   status  = *(UCHAR*)MBCR;
   status &= 0xd7;
   *(UCHAR*)MBCR = status;

}


/**
 *  Mixed MBUS interrupt with other interrupt(using the same interrupt
 *  vector), Know the MBUS interrupt is occurred by inspecting MIF.

extern "C" VOID MBusMixedLisr(VOID)
{
   // If MBUS operation in interrupt mode, call LISR
   if ( OPMODE_INTERRUPT == sMBusInfo.mode)
      Mbus_Lisr(0);
}
*/

/**
 *   MBus interrupt service routine
 */
extern "C" VOID Mbus_Lisr(int vector)
{
   UCHAR status, ackNotDetected;

   //clear MIF(M-Bus interrupt flag)
   status  = *(UCHAR*)MBSR;

   // return if MIF is not set.
   if (2 != (status&2) )
      return;

   status &= 0xfd;
   *(UCHAR*)MBSR = status;

   // No error detected.
   ackNotDetected = 0;

   sCurrentCmd ++;

   // Check acknowledge signal when current command is not CMD_RECEIVE_STOP,
   // because acknowledge signal will not be generated in the situation.
   if (CMD_RECEIVE_STOP != sMBusCmds[sCurrentCmd])
   {
      if ( 1 == (status&1))
      {
         sMBusInfo.noAckError ++;
         ackNotDetected = 1;

         // cause system to generate stop signal
         sMBusCmds[sCurrentCmd] = CMD_TRANSMIT_STOP;
      }
   }

   switch (sMBusCmds[sCurrentCmd])
   {
     // normal transmit
     case CMD_TRANSMIT:
        *(UCHAR*)MBDR = *sTransmitPtr ++;
        break;

     // a stop after transmitting
     case CMD_TRANSMIT_STOP:
        status  = *(UCHAR*)MBCR;
        status &= 0xd7;             // d7->df, why use d7? TXAK = 0?
        *(UCHAR*)MBCR = status;

        if( (1 == ackNotDetected) && (1 == RepeatTransfer()) )
        {
           // do nothing
        }
        else
        {
           // If work in query mode, don't check packet queue
           if (OPMODE_QUERY == sMBusInfo.mode)
              sMBusInfo.currPackFinished = 1;
	/*
           else
              if (0 == ProcessNext() )
                 sMBusInfo.currPackFinished = 1;
	*/
        }
        break;

     // change to receive mode after transmitted
     case CMD_TRANSMIT_RECEIVE:
        // change to receive mode
        status  = *(UCHAR*)MBCR;
        status &= 0xef;
        *(UCHAR*)MBCR = status;

        if (CMD_RECEIVE_STOP == sMBusCmds[sCurrentCmd+1])
        {
           // don't acknowledge it because it's the last byte to be received
           status  = *(UCHAR*)MBCR;
           status |= 0x8;
           *(UCHAR*)MBCR = status;
        }

        // Dummy read to generate clock signal
        status = *(UCHAR*)MBDR;
        break;

     // restart then transmit
     case CMD_RESTART_TRANSMIT:
        // restart
        status  = *(UCHAR*)MBCR;
        status |= 0x04;
        *(UCHAR*)MBCR = status;

        // then transmit
        *(UCHAR*)MBDR = *sTransmitPtr ++;
        break;

     // receive with acknowledge
     case CMD_RECEIVE_ACK:
        *sReceivePtr ++ = *(UCHAR*)MBDR;
        break;

     // receive without acknowledge
     case CMD_RECEIVE_NOACK:
        // don't generate acknowledge signal
        status  = *(UCHAR*)MBCR;
        status |= 0x08;
        *(UCHAR*)MBCR = status;

        *sReceivePtr ++ = *(UCHAR*)MBDR;
        break;

     // receive then stop
     case CMD_RECEIVE_STOP:
        // generate stop signal
        status  = *(UCHAR*)MBCR;
        status &= 0xd7;             // d7->df, why use d7? TXAK = 0?
        *(UCHAR*)MBCR = status;

        *sReceivePtr ++ = *(UCHAR*)MBDR;

        // If work in query mode, don't check packet queue
        if (OPMODE_QUERY == sMBusInfo.mode)
           sMBusInfo.currPackFinished = 1;
	/*
        else
           if (0 == ProcessNext() )
              sMBusInfo.currPackFinished = 1;
	*/

        break;

     default:
        break;
   }
}


/**
 *  Process next packet: check whether there is some packets that not been
 *  processed.
 *
 *  @return  0  if not packet to be processed.
 *  @return  1  if there are packets to be processed.
 */
 /*
static INT16  ProcessNext(VOID)
{
   static INT16  currentQue;

   MBusPackType  *thePack = 0;
   CHAR  i;

   // if MBUS is not free until function return, transfer stop
   if (0 == WaitForMBusFree())
      return 0;

   // search a packQue that has packet to be processed.
   for (i = 0; i < PACKQUE_NUMBER; i ++)
   {
      currentQue ++;
      if (PACKQUE_NUMBER <= currentQue)
         currentQue = 0;

      if (1 == MBusPackQueGet(sMBusPackQues[currentQue], &thePack) )
         break;
   }

   // if no packet to be processed, return
   if (0 == thePack)
      return 0;

   // Remember the pack being transfered.
   sMBusInfo.currPack = *thePack;

   ConstructSequence(thePack);
   StartTransfer();

   return 1;
}
*/

/**
 *  Repeat transfer for given times.
 *  processed.
 *
 *  @return  0  if repeat is not need or mbus is busy.
 *  @return  1  if repeat processed.
 */
static INT16  RepeatTransfer(VOID)
{

   // if MBUS is not free until function return, transfer stop
   if (0 == WaitForMBusFree())
      return 0;

   if (0 < sMBusInfo.currPack.repeatTimes)
   {
      sMBusInfo.currPack.repeatTimes --;
      ConstructSequence(&sMBusInfo.currPack);
      StartTransfer();
      return 1;
   }
   else
   {
      sMBusInfo.transferFail ++;
      return 0;
   }
}


/**
 *  Construct command sequence according to the pack given,
 *  the command sequence will processed in MBus interrupt.
 *
 *  @param pack  the packet to be processed.
 */
static VOID ConstructSequence(MBusPackType  *pack)
{
   INT16  i, cmdNumber;

   // The number of commands is 0
   cmdNumber = 0;

   // Commands are type of CMD_TRANSMIT at early.
   for ( i = 0; i < pack->txLen1 - 1; i ++)
      sMBusCmds[cmdNumber++] = CMD_TRANSMIT;

   // If txLen2 is greater than 0, it means that there is a RESTART signal
   // should insert here.
   if (0 < pack->txLen2)
   {
      sMBusCmds[cmdNumber++] = CMD_RESTART_TRANSMIT;

      // copy the other TRANSMIT command, remember here: the RESTART command
      // was connected with a TRANSMIT command, so (pack->txLen2 - 1) is
      // present here.
      for ( i = 0; i < pack->txLen2 - 1; i ++)
         sMBusCmds[cmdNumber++] = CMD_TRANSMIT;
   }

   // If want receive some characters.
   if (0 < pack->rxLen)
   {
      // The last command is change mode to receive
      sMBusCmds[cmdNumber++] = CMD_TRANSMIT_RECEIVE;

      // If only receive one character, STOP after RECEIVE
      if (1 == pack->rxLen)
         sMBusCmds[cmdNumber++] = CMD_RECEIVE_STOP;
      else
      {
         for ( i = 0; i < pack->rxLen - 2; i ++)
            sMBusCmds[cmdNumber++] = CMD_RECEIVE_ACK;

         // The second last command is CMD_RECEIVE_NOACK
         sMBusCmds[cmdNumber++] = CMD_RECEIVE_NOACK;

         // The last command is CMD_RECEIVE_STOP
         sMBusCmds[cmdNumber++] = CMD_RECEIVE_STOP;
      }
   }
   // Don't want receive any character, change the last command from
   // TRANSMIT to TRANSMIT_STOP
   else
      sMBusCmds[cmdNumber++] = CMD_TRANSMIT_STOP;

   sCurrentCmd  = -1;
   sTransmitPtr = &pack->txData[0];
   sReceivePtr  = pack->rxData;
}


/**
 *  Start a MBUS data transfer procedure.
 */
static VOID StartTransfer(VOID)
{
   UCHAR status, data;
   
   //clear MIF(M-Bus interrupt) flag
   status  = *(UCHAR*)MBSR;
   status &= 0xfd;
   *(UCHAR*)MBSR = status;

   status  = *(UCHAR*)MBCR;

   // transmit mode selected
   status |= 0x10;
   *(UCHAR*)MBCR = status;

   // master mode selected.
   status |= 0x20;
   *(UCHAR*)MBCR = status;

   // BUG: if interrupt occurred after data being put into MBDR and 
   //      sTransmitPtr has not been increased, the first byte will be
   //      transmitted for twice. MBUS will will be locked.
   //*(UCHAR*)MBDR = *sTransmitPtr ++;
   data = *sTransmitPtr ++;
   *(UCHAR*)MBDR = data;
}


/**
 *  If MBUS is not busy, make it transfer another packet.
 */
/*
static VOID EnterInterrupt(VOID)
{
   // return if operate in query mode
   if (OPMODE_QUERY == sMBusInfo.mode)
      return;

   // Processing finished, start interrupt
   if (1 == sMBusInfo.currPackFinished)
   {
      // Make the following code is used exclusively
      sMBusInfo.currPackFinished = 0;

      if (0 == ProcessNext() )
         // It's impossible that program will go here, because there is new
         // packet in the queue.
         sMBusInfo.currPackFinished = 1;
   }
}
*/

/**
 *  CAT24C021 initialize: Load the EEPROM to make a copy in DRAM and check the checkSum.
 *  this function must be called before any writing operation to CAT24C021
 *  with checkSum, or the check sum will be wrong.
 *
 *  @return   1   load memoryMap and stored checkSum succeeded and checkSum is right
 *            0   load memoryMap or stored checkSum failed
 *            2   load memoryMap and stored checkSum succeeded but checkSum is wrong
 *
CHAR  CAT24C021Initialize(VOID)
{
   // Load the memory map from CAT24C021
   return CAT24C021LoadMemoryMap(sMemoryMap);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -