?? frag.c
字號:
/*****************************************************************************
*
* Microchip DeviceNet Stack (Connection Object Fragmentation Source)
*
*****************************************************************************
* FileName: frag.c
* Dependencies:
* Processor: PIC18F with CAN
* Compiler: C18 02.20.00 or higher
* Linker: MPLINK 03.40.00 or higher
* Company: Microchip Technology Incorporated
*
* Software License Agreement
*
* The software supplied herewith by Microchip Technology Incorporated
* (the "Company") is intended and supplied to you, the Company's
* customer, for use solely and exclusively with products manufactured
* by the Company.
*
* The software is owned by the Company and/or its supplier, and is
* protected under applicable copyright laws. All rights are reserved.
* Any use in violation of the foregoing restrictions may subject the
* user to criminal sanctions under applicable laws, as well as to
* civil liability for the breach of the terms and conditions of this
* license.
*
* THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
* WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
* IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
*
* This file contains unacknowledged fragmentation support. Refer to
* section 4-4 of Volume 1 of the DeviceNet specification.
*
*
*
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Ross Fosler 04/28/03 ...
*
*****************************************************************************/
#include "dnet.def" // Global definitions file
#include "typedefs.h"
#if FRAGMENTATION_UNACK
#include "conn.h" // Internal definitions
#include "services.h" // Service codes
#include "errors.h" // Error codes
#include "class.h" // Class codes
#include "dnet.h" // Global symbols defined by the DeviceNet Obj
#include "CAN.h" // CAN driver
#define _STATE_NOACK_PRODUCE_FIRST_FRAG 0
#define _STATE_NOACK_PRODUCE_MID_FRAG 1
#define _STATE_NOACK_PRODUCE_LAST_FRAG 2
#define _STATE_NOACK_CONSUME_WAIT_FOR_FIRST_FRAG 0
#define _STATE_NOACK_CONSUME_WAIT_FOR_FRAG 1
// Control flags for fragmented processing
// <TX/RX><ACK/IO><RES><RES><RES><TXLOCK><ERR><FIN>
#if USE_ACCESS == TRUE
#pragma udata access _A_FRAG_REGISTERS
#endif
NEAR FRAG _aFrag;
NEAR UINT _timer;
#pragma udata
/*********************************************************************
* Function: void _FragNoAckConsume(void)
*
* PreCondition: The fragment structure must be loaded with the
* last known state of the calling connection.
*
* Input: none
*
* Output: none
*
* Side Effects: _aFrag is updated.
*
* Overview: This function handles unacknowledged reception
* of fragmented data.
*
* Note: This function only receives data and does not
* free the CAN driver to receive. It is up to the
* calling function to release the hardware to
* receive data.
********************************************************************/
void _FragNoAckConsume(void)
{
unsigned char frag, type, len;
unsigned char *pRxData;
// Get a pointer to the buffer
pRxData = CANGetRxDataPtr();
// Get the fragmentation control byte then point to the data
frag = *pRxData; //pRxData++;
// Get the fragment type
type = frag & 0xC0;
switch (type)
{
// First fragment received
case 0x00:
// Is this the first or only fragment
if (frag == 0x3F || frag == 0)
{
// Store the length minus the fragment control byte
_aFrag.rx.len = CANGetRxCnt() - 1;
// Copy this fragment to the buffer
CANGetRxDataTyp1(_aFrag.rx.pMsg);
// *((_MSG_DATA_IO_FRAG *)_aFrag.rx.pMsg) = *((_MSG_DATA_IO_FRAG *)pRxData);
// Is this the only fragment
if (frag == 0x3F)
{
// Set the finish flag
_aFrag.rx.fragFlags.bits.b0 = 1;
}
else
{
// Change the state
_aFrag.rx.fragState = _STATE_NOACK_CONSUME_WAIT_FOR_FRAG;
_aFrag.rx.oldFrag = 0;
}
}
else
{
// This is an error
_aFrag.rx.fragFlags.bits.b1 = 1;
}
break;
// Middle or last fragment
case 0x40:
case 0x80:
// Has the first fragment been received
if (_aFrag.rx.fragState == _STATE_NOACK_CONSUME_WAIT_FOR_FRAG)
{
// Is this the next fragment in the sequence
if (((frag ^ (_aFrag.rx.oldFrag + 1)) & 0x3F) == 0)
{
// Remember the fragment control byte
_aFrag.rx.oldFrag = frag;
// Copy the length
len = _aFrag.rx.len;
// Adjust the length
_aFrag.rx.len += (CANGetRxCnt() - 1);
// Check the size of the buffer
if (_aFrag.rx.len <= _aFrag.rx.lenMax)
{
// Copy this fragment to the buffer
CANGetRxDataTyp1(_aFrag.rx.pMsg + len);
// *((_MSG_DATA_IO_FRAG *)(_aFrag.rx.pMsg + len)) =
// *((_MSG_DATA_IO_FRAG *)pRxData);
// Is this the last fragment
if (type == 0x80)
{
// Set the finish flag
_aFrag.rx.fragFlags.bits.b0 = 1;
// Change to the beginning state
_aFrag.rx.fragState = _STATE_NOACK_CONSUME_WAIT_FOR_FIRST_FRAG;
}
}
// Too much data to copy to the buffer
else
{
// This is an error
_aFrag.rx.fragFlags.bits.b1 = 1;
// Go back to the first fragment
_aFrag.rx.fragState = _STATE_NOACK_CONSUME_WAIT_FOR_FIRST_FRAG;
}
}
// Received a fragment out of sequence
else
{
// This is an error
_aFrag.rx.fragFlags.bits.b1 = 1;
// Go back to the first fragment
_aFrag.rx.fragState = _STATE_NOACK_CONSUME_WAIT_FOR_FIRST_FRAG;
}
}
break;
// Received an acknowledge fragment, which is invalid for this
// type of fragmentation
case 0xC0:
// This is an error
_aFrag.rx.fragFlags.bits.b1 = 1;
// Go back to the first fragment
_aFrag.rx.fragState = _STATE_NOACK_CONSUME_WAIT_FOR_FIRST_FRAG;
break;
}
}
/*********************************************************************
* Function: void _FragNoAckProduce(void)
*
* PreCondition: The fragment structure must be loaded with the
* last known state of the calling connection.
*
* Input: none
*
* Output: none
*
* Side Effects: _aFrag is updated.
*
* Overview: This function handles unacknowledged transmission
* of fragmented data.
*
* Note: This function does not issue any requests to the
* driver to send data. It is up to the calling
* to issue the transmit request.
********************************************************************/
void _FragNoAckProduce(void)
{
unsigned char *pTxData;
// Get a pointer to the buffer
pTxData = CANGetTxDataPtr();
switch (_aFrag.tx.fragState)
{
// Send an unacknowledged first fragment
case _STATE_NOACK_PRODUCE_FIRST_FRAG:
// If the whole message is less than the max fragment size
// then send the only fragment
if (_aFrag.tx.len < 8)
{
// Set the fragment control byte and point to the next data location
*pTxData = 0x3F; pTxData++;
// Copy this fragment to the transmit buffer
CANPutTxDataTyp1(_aFrag.tx.pMsg);
// *((_MSG_DATA_IO_FRAG *)pTxData) =
// *((_MSG_DATA_IO_FRAG *)(_aFrag.tx.pMsg));
// Set the length of the data to send
CANPutTxCnt(_aFrag.tx.len + 1);
// Indicate the process is finished
_aFrag.tx.fragFlags.bits.b0 = 1;
}
// Else send the first fragment of the whole message
else
{
// Set the fragment control byte and point to the next data location
*pTxData = _aFrag.tx.oldFrag = 0; //pTxData++;
// Copy this fragment to the transmit buffer
CANPutTxDataTyp1(_aFrag.tx.pMsg);
// *((_MSG_DATA_IO_FRAG *)pTxData) =
// *((_MSG_DATA_IO_FRAG *)(_aFrag.tx.pMsg));
// Adjust the index
_aFrag.tx.index = 7;
// Set the length of the data to send
CANPutTxCnt(8);
// Set the next state
if ((_aFrag.tx.len - _aFrag.tx.index) > 8)
_aFrag.tx.fragState = _STATE_NOACK_PRODUCE_MID_FRAG;
else
_aFrag.tx.fragState = _STATE_NOACK_PRODUCE_LAST_FRAG;
}
break;
// Send a middle fragment
case _STATE_NOACK_PRODUCE_MID_FRAG:
// Set the fragment control byte and point to the next data location
*pTxData = _aFrag.tx.oldFrag = ((_aFrag.tx.oldFrag + 1) & 0x3F) | 0x40;
// pTxData++;
// Copy this fragment to the transmit buffer
CANPutTxDataTyp1(_aFrag.tx.pMsg + _aFrag.tx.index);
// *((_MSG_DATA_IO_FRAG *)pTxData) =
// *((_MSG_DATA_IO_FRAG *)(_aFrag.tx.pMsg + _aFrag.tx.index));
// Adjust the index
_aFrag.tx.index += 7;
// Set the length of the data to send
CANPutTxCnt(8);
// Set the next state
if ((_aFrag.tx.len - _aFrag.tx.index) > 8)
_aFrag.tx.fragState = _STATE_NOACK_PRODUCE_MID_FRAG;
else
_aFrag.tx.fragState = _STATE_NOACK_PRODUCE_LAST_FRAG;
break;
// Send the last fragment
case _STATE_NOACK_PRODUCE_LAST_FRAG:
// Set the fragment control byte and point to the next data location
*pTxData = _aFrag.tx.oldFrag = ((_aFrag.tx.oldFrag + 1) & 0x3F) | 0x80;
// pTxData++;
// Copy this fragment to the transmit buffer
CANPutTxDataTyp1(_aFrag.tx.pMsg + _aFrag.tx.index);
// *((_MSG_DATA_IO_FRAG *)pTxData) =
// *((_MSG_DATA_IO_FRAG *)(_aFrag.tx.pMsg + _aFrag.tx.index));
// Set the length of the data to send
CANPutTxCnt(_aFrag.tx.len - _aFrag.tx.index + 1);
// Indicate the process is finished
_aFrag.tx.fragFlags.bits.b0 = 1;
// Fallout state, should never get here except through the last fragment
default:
_aFrag.tx.fragState = _STATE_NOACK_PRODUCE_FIRST_FRAG;
}
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -