📄 ccp.c
字号:
/*----------------------------------------------------------------------------
| File:
| ccp.c
|
| Project:
| CCP driver
|
| Description:
| CCP driver main module
|
----------------------------------------------------------------------------*/
/* CCP Definitions and Parameters */
#include "ccp.h"
#ifndef C_DISABLE_CCP
/* Version History:
V1.29, 24.9.2000
- new define CCP_CHECKSUM_BLOCKSIZE
V1.30, 29.11.2000
- #ifndef CCP_EXTERNAL_STATION_ID
V1.31, 08.02.2001,
- new define CCP_DAQ_BASE_ADDR
- new function ccpGetDaqPointer
V1.32, 30.05.2001,
- Reserved word "data" in KEIL Compiler for C5x5
- Prefix CCP_ for all #defines
V1.33, 14.09.2001
- #define CCP_ODT_ENTRY_SIZE
- #define CCP_INTEL,CCP_MOTOROLA
V1.34, 28.10.2001
- ccpSend return value removed
Transmission error handling should be done by the user
V1.35, 8.4.2002
- #define CCP_CPUTYPE_32BIT
- Max checksum block size is DWORD on 32 bit CPUs
V1.36, 2.6.2002
- #undef CCP_DAQ for drivers without DAQ fixed
- double - float conversion for SHORT_UPLOAD, DNLOAD and DAQ
V1.37, 17.7.2002
- Fixed the version nr. because the version was in the comment 1.36 but 135
- was define.
- Set #define CCP_DRIVER_VERSION to 137
*/
#define CCP_DRIVER_VERSION 137
/*--------------------------------------------------------------------------*/
/* Performance measurements */
#ifndef CCP_PROFILE
#define SET_PORT_BIT(i)
#define RST_PORT_BIT(i)
#else
/*
t[0] - ccpCommand
t[1] - ccpCallBack
t[2] - ccpBackground
t[3] - ccpDaq
*/
unsigned int t0[4],t[4];
#define SET_PORT_BIT(i) t0[i-1]=ccpGetTimestamp();
#define RST_PORT_BIT(i) t[i-1]=T3-t0[i-1];
#endif
/*--------------------------------------------------------------------------*/
/* Test */
#ifdef CCP_TESTMODE
#include <stdio.h>
static void ccpPrintCANapeSettings( void );
static void ccpPrintDaqList( CCP_BYTE daq );
#endif
/*--------------------------------------------------------------------------*/
/* ROM */
/*--------------------------------------------------------------------------*/
/*
Identification
Must be 0 terminated !!
This string is used by CANape as the ASAP2 database filename
The extension .A2L or .DB is added by CANape
*/
#ifdef CCP_EXTERNAL_STATION_ID
extern ROM CCP_BYTE ccpStationId[];
#else
CCP_ROM CCP_BYTE ccpStationId[] = CCP_STATION_ID;
#endif
/*--------------------------------------------------------------------------*/
/* RAM */
/*--------------------------------------------------------------------------*/
/*
The following structure containes all RAM locations needed by the CCP driver
It has to be word aligned on a C167 !!!
*/
CCP_RAM struct ccp ccp;
/*--------------------------------------------------------------------------*/
/* CODE */
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
/* Transmit */
/*--------------------------------------------------------------------------*/
/* Send a CRM, if no other message is pending */
void ccpSendCrm( void ) {
CCP_DISABLE_INTERRUPT;
if (ccp.SendStatus&CCP_SEND_PENDING) {
ccp.SendStatus |= CCP_CRM_REQUEST;
} else {
ccp.SendStatus |= CCP_CRM_PENDING;
ccpSend(ccp.Crm);
}
CCP_ENABLE_INTERRUPT;
}
/* Send a DTM, if no other message is pending */
#ifdef CCP_DAQ
#ifndef CCP_SEND_QUEUE
static void ccpSendDtm( void ) {
CCP_DISABLE_INTERRUPT;
if (ccp.SendStatus&CCP_SEND_PENDING) {
ccp.SendStatus |= CCP_DTM_REQUEST;
} else {
ccp.SendStatus |= CCP_DTM_PENDING;
ccpSend(ccp.Dtm);
}
CCP_ENABLE_INTERRUPT;
}
#endif
#endif
/*--------------------------------------------------------------------------*/
/* Transmit Queue */
/*--------------------------------------------------------------------------*/
#ifdef CCP_SEND_QUEUE
void ccpQueueInit(void) {
ccp.Queue.len = 0;
ccp.Queue.rp = 0;
}
CCP_BYTE ccpQueueWrite(ccpMsg_t *msg) {
if (ccp.Queue.len>=CCP_SEND_QUEUE_SIZE) return 0;
ccp.Queue.msg[(ccp.Queue.rp+ccp.Queue.len)%CCP_SEND_QUEUE_SIZE] = *msg;
ccp.Queue.len++;
return 1;
}
#endif
/*--------------------------------------------------------------------------*/
/* Handle MTAs (Memory-Transfer-Address) */
/*--------------------------------------------------------------------------*/
/* Assign a pointer to a MTA */
#define ccpSetMTA(n,p) ccp.MTA[n] = p;
/* Write n bytes */
static CCP_BYTE ccpWriteMTA( CCP_BYTE n, CCP_BYTE size, CCP_BYTEPTR d ) {
/* EEPROM write access */
#ifdef CCP_WRITE_EEPROM
CCP_BYTE r = ccpCheckWriteEEPROM(ccp.MTA[n],size,d);
if (r) { /* EEPROM write access */
ccp.MTA[n] += size;
return r;
}
#endif
/* Checked ram memory write access */
#ifdef CCP_WRITE_PROTECTION
if (!ccpCheckWriteAccess(ccp.MTA[n],size)) {
ccp.MTA[n] += size;
return CCP_WRITE_DENIED;
}
#endif
/* double conversion */
#ifdef CCP_DOUBLE_FLOAT
if (size==8) {
*(double*)ccp.MTA[n] = *(float*)d;
#ifdef CCP_TESTMODE
if (gDebugLevel>=2) CCPPRINT("[ccpWriteMTA] conversion -> double %g\n",*(double*)ccp.MTA[n]);
#endif
ccp.MTA[n] += 8;
return CCP_WRITE_OK;
}
#endif
while (size-->0) {
/* COSMIC Compiler Bug: *(ccp.MTA[n]++) = *(d++); */
*(ccp.MTA[n]) = *d;
ccp.MTA[n]++;
d++;
}
return CCP_WRITE_OK;
}
/* Read n bytes */
static void ccpReadMTA( CCP_BYTE n, CCP_BYTE size, CCP_BYTEPTR d ) {
/* EEPROM read access */
#ifdef CCP_READ_EEPROM
if (ccpCheckReadEEPROM(ccp.MTA[n],size,d)) {
ccp.MTA[n] += size;
return;
}
#endif
/* double conversion */
#ifdef CCP_DOUBLE_FLOAT
if (size==8) {
*(float*)d = (float)(*(double*)(ccp.MTA[n]));
#ifdef CCP_TESTMODE
if (gDebugLevel>=2) CCPPRINT("[ccpReadMTA] conversion -> float %g\n",(double)(*(float*)d));
#endif
return;
}
#endif
while (size-->0) {
*d = *(ccp.MTA[n]);
d++;
ccp.MTA[n]++;
}
}
/*--------------------------------------------------------------------------*/
/* Data Aquisition Setup */
/*--------------------------------------------------------------------------*/
#ifdef CCP_DAQ
/* Clear DAQ list */
static CCP_BYTE ccpClearDaqList( CCP_BYTE daq ) {
CCP_BYTEPTR p;
CCP_BYTEPTR pl;
if (daq>=CCP_MAX_DAQ) return 0;
/* Clear this daq list to zero */
p = (CCP_BYTEPTR)&ccp.DaqList[daq];
pl = p+sizeof(ccpDaqList_t);
while (p<pl) *p++ = 0;
/* @@@@ Not DAQ list specific */
ccp.SessionStatus |= SS_DAQ;
#ifdef CCP_SEND_SINGLE
ccp.CurrentDaq = 0;
ccp.CurrentOdt = 0;
#endif
#ifdef CCP_SEND_QUEUE
ccpQueueInit();
#endif
return CCP_MAX_ODT;
}
/* Prepare DAQ */
static CCP_BYTE ccpPrepareDaq( CCP_BYTE daq, CCP_BYTE last, CCP_BYTE eventChannel, CCP_WORD prescaler ) {
if (daq>=CCP_MAX_DAQ) return 0;
ccp.DaqList[daq].eventChannel = eventChannel;
if (prescaler==0) prescaler = 1;
ccp.DaqList[daq].prescaler = prescaler;
ccp.DaqList[daq].cycle = 1;
ccp.DaqList[daq].last = last;
ccp.DaqList[daq].flags = DAQ_FLAG_PREPARED;
return 1;
}
/* Start DAQ */
static CCP_BYTE ccpStartDaq( CCP_BYTE daq ) {
if (daq>=CCP_MAX_DAQ) return 0;
ccp.DaqList[daq].flags = DAQ_FLAG_START;
ccp.SessionStatus |= SS_RUN;
#ifdef CCP_TIMESTAMPING
ccpClearTimestamp();
#endif
return 1;
}
/* Start all prepared DAQs */
static void ccpStartAllPreparedDaq(void) {
CCP_BYTE q;
for (q=0;q<CCP_MAX_DAQ;q++) {
if (ccp.DaqList[q].flags==DAQ_FLAG_PREPARED) ccp.DaqList[q].flags = DAQ_FLAG_START;
}
ccp.SessionStatus |= SS_RUN;
#ifdef CCP_TIMESTAMPING
ccpClearTimestamp();
#endif
}
/* Stop DAQ */
static void ccpStopDaq ( CCP_BYTE daq ) {
CCP_BYTE i;
if (daq>=CCP_MAX_DAQ) return;
ccp.DaqList[daq].flags = 0;
/* check if all DAQ lists are stopped */
for (i=0;i<CCP_MAX_DAQ;i++) {
if (ccp.DaqList[i].flags&DAQ_FLAG_START) return;
}
ccp.SessionStatus &= ~SS_RUN;
}
/* Stop all DAQs */
static void ccpStopAllDaq( void ) {
CCP_BYTE q;
for (q=0;q<CCP_MAX_DAQ;q++) ccp.DaqList[q].flags = 0;
ccp.SessionStatus &= ~SS_RUN;
}
/*--------------------------------------------------------------------------*/
/* Data Aquisition Processor */
/*--------------------------------------------------------------------------*/
#ifndef CCP_SEND_SINGLE
/* Sample and transmit a DTM */
static int ccpSampleAndTransmitDtm( CCP_BYTE pid, CCP_BYTE daq, CCP_BYTE odt ) {
#ifdef CCP_SEND_QUEUE
CCP_BYTE dtm[8];
#else
#define dtm ccp.Dtm
#endif
#ifdef CCP_DAQ_BASE_ADDR
CCP_BYTEPTR p;
#else
CCP_DAQBYTEPTR p;
#endif
#ifdef CCP_ODT_ENTRY_SIZE
CCP_BYTE s;
CCP_BYTE *d,*dl;
ccpOdtEntry_t *e,*el;
#else
CCP_BYTE i;
ccpOdtEntry_t *e;
#endif
/* PID */
dtm[0] = pid;
/* Assure data consistency */
CCP_DISABLE_INTERRUPT;
/* Sample */
#ifdef CCP_ODT_ENTRY_SIZE
e = &ccp.DaqList[daq].odt[odt][0];
el = e+8;
d = &dtm[1];
dl = d+7;
while (d<dl && e<el && e->ptr) {
#ifdef CCP_DAQ_BASE_ADDR
p = (CCP_BYTEPTR)( e->ptr ) + CCP_DAQ_BASE_ADDR;
#else
p = e->ptr;
#endif
s = e->siz;
#ifdef CCP_DOUBLE_FLOAT
if (s==8) {
*(float*)d = (float)(*(double*)p);
s = 4;
#ifdef CCP_TESTMODE
if (gDebugLevel>=2) CCPPRINT("[ccpSampleAndTransmitDtm] conversion -> float %g\n",*(float*)d);
#endif
} else
#endif
if (s==4) {
*(CCP_DWORD*)d = *(CCP_DWORD*)p;
} else if (s==2) {
*(CCP_WORD*)d = *(CCP_WORD*)p;
} else {
*d = *p;
}
d += s;
e++;
}
#else
e = &ccp.DaqList[daq].odt[odt][0];
for (i=1;i<8;i++) {
#ifdef CCP_DAQ_BASE_ADDR
p = (CCP_BYTEPTR)( (e++)->ptr ) + CCP_DAQ_BASE_ADDR;
#else
p = (e++)->ptr;
#endif
if (p) dtm[i] = *p;
}
#endif
/* Optional for CANape: Put a timestamp in the first ODT (Byte6+7) of each DAQ */
#ifdef CCP_TIMESTAMPING
if (odt==0) {
*(CCP_WORD*)&dtm[6] = ccpGetTimestamp();
}
#endif
/* Queue or transmit the DTM */
#ifdef CCP_SEND_QUEUE
if (ccp.SendStatus&CCP_SEND_PENDING) {
if (!ccpQueueWrite((ccpMsg_t*)dtm)) {
/* Overun */
CCP_ENABLE_INTERRUPT;
return 0;
}
} else {
ccp.SendStatus |= CCP_DTM_PENDING;
ccpSend(dtm);
}
#else
if (ccp.SendStatus&CCP_DTM_REQUEST) {
/* Overun */
CCP_ENABLE_INTERRUPT;
return 0;
}
if (ccp.SendStatus&CCP_SEND_PENDING) {
ccp.SendStatus |= CCP_DTM_REQUEST;
} else {
ccp.SendStatus |= CCP_DTM_PENDING;
ccpSend(dtm);
}
#endif
CCP_ENABLE_INTERRUPT;
return 1;
}
#else
/* Sample and transmit the next DTM in SEND_SINGLE mode */
static void ccpSampleAndSendNextDtm( void ) {
CCP_BYTE i,j;
CCP_DAQBYTEPTR p;
ccpOdtEntry_t *e;
/* Request for DTM transmission pending */
if (ccp.SendStatus&CCP_DTM_REQUEST) return;
/* Find a DAQ list marked for transmission */
for (i=0;i<CCP_MAX_DAQ;i++) {
if (ccp.DaqList[ccp.CurrentDaq].flags&DAQ_FLAG_SEND) {
/* PID */
ccp.Dtm[0] = ccp.CurrentDaq*CCP_MAX_ODT+ccp.CurrentOdt;
/* Sample */
e = &ccp.DaqList[ccp.CurrentDaq].odt[ccp.CurrentOdt][0];
for (j=1;j<8;j++) {
p = (e++)->ptr;
if (p) ccp.Dtm[j] = *p;
}
/* Send */
ccpSendDtm();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -