📄 scc_s515.c
字号:
/*------------------------------------------------------------------*-
SCC_S515.c (v1.00)
------------------------------------------------------------------
THIS IS A SHARED-SCHEDULER [CAN BASED] FOR 80C515C (etc.)
*** Both Master and Slave share the same tick rate ***
*** - See Master code for details ***
-----------------------------------------------------------
--- NOTE: 'Idle mode' must be disabled (in Sch51.C) ---
--- or the on-chip watchdog will not function correctly ---
-----------------------------------------------------------
COPYRIGHT
---------
This code is from the book:
PATTERNS FOR TIME-TRIGGERED EMBEDDED SYSTEMS by Michael J. Pont
[Pearson Education, 2001; ISBN: 0-201-33138-1].
This code is copyright (c) 2001 by Michael J. Pont.
See book for copyright details and other information.
-*------------------------------------------------------------------*/
#include "Main.h"
#include "Port.h"
#include "SCC_S515.h"
#include "TLight_B.h"
// ------ Public variable definitions ------------------------------
// Data sent from the master to this slave
tByte Tick_message_data_G[4];
// Data sent from this slave to the master
// - data may be sent on, by the master, to another slave
tByte Ack_message_data_G[4] = {'1','1','1','1'};
// ------ Public variable declarations -----------------------------
// The array of tasks (see Sch51.c)
extern sTask SCH_tasks_G[SCH_MAX_TASKS];
// The error code variable (see Sch51.c)
extern tByte Error_code_G;
// ------ Private function prototypes ------------------------------
static void SCC_A_SLAVE_Enter_Safe_State(void);
static void SCC_A_SLAVE_Send_Ack_Message_To_Master(void);
static tByte SCC_A_SLAVE_Process_Tick_Message(void);
static bit SCC_A_SLAVE_Read_Command_Bit(const tByte);
static tByte SCC_A_SLAVE_Set_Command_Bit(const tByte);
static tByte SCC_A_SLAVE_Read_Message_ID(const tByte);
static void SCC_A_SLAVE_Watchdog_Init(void);
static void SCC_A_SLAVE_Watchdog_Refresh(void) reentrant;
// ------ Private constants ----------------------------------------
// Each slave (and backup) must have a unique (non-zero) ID
#define SLAVE_ID 0x01
#define NO_NETWORK_ERROR (1)
#define NETWORK_ERROR (0)
/*------------------------------------------------------------------*-
SCC_A_SLAVE_Init_CAN()
Scheduler initialisation function. Prepares scheduler
data structures and sets up timer interrupts at required rate.
Must call this function before using the scheduler.
-*------------------------------------------------------------------*/
void SCC_A_SLAVE_Init_CAN(void)
{
tByte i;
tByte Message;
// Sort out the tasks
for (i = 0; i < SCH_MAX_TASKS; i++)
{
SCH_Delete_Task(i);
}
// Reset the global error variable
// - SCH_Delete_Task() will generate an error code,
// (because the task array is empty)
Error_code_G = 0;
// Set the network error pin (reset when tick message received)
Network_error_pin = NETWORK_ERROR;
// ------ SYSCON Register
// The access to XRAM and CAN controller is enabled.
// The signals !RD and !WR are not activated during accesses
// to the XRAM/CAN controller.
// ALE generation is enabled.
SYSCON = 0x20;
// ------------ CAN Control/Status Register --------------
// Start to init the CAN module
CAN_cr = 0x41; // INIT and CCE
// ------------ Bit Timing Register ---------------------
// Baudrate = 333.333 kbaud
// - Need 308+ kbaud plus for 1ms ticks, 8 data bytes
// - See text for details
//
// There are 5 time quanta before sample point
// There are 4 time quanta after sample point
// The (re)synchronization jump width is 2 time quanta
CAN_btr1 = 0x34; // Bit Timing Register
CAN_btr0 = 0x42;
CAN_gms1 = 0xFF; // Global Mask Short Register 1
CAN_gms0 = 0xFF; // Global Mask Short Register 0
CAN_ugml1 = 0xFF; // Upper Global Mask Long Register 1
CAN_ugml0 = 0xFF; // Upper Global Mask Long Register 0
CAN_lgml1 = 0xF8; // Lower Global Mask Long Register 1
CAN_lgml0 = 0xFF; // Lower Global Mask Long Register 0
// ------ Configure 'Tick' Message Object
// Message object 1 is valid
// enable receive interrupt
CAN_messages[0].MCR1 = 0x55; // Message Ctrl. Reg. 1
CAN_messages[0].MCR0 = 0x99; // Message Ctrl. Reg. 0
// message direction is receive
// extended 29-bit identifier
CAN_messages[0].MCFG = 0x04; // Message Config. Reg.
CAN_messages[0].UAR1 = 0x00; // Upper Arbit. Reg. 1
CAN_messages[0].UAR0 = 0x00; // Upper Arbit. Reg. 0
CAN_messages[0].LAR1 = 0x00; // Lower Arbit. Reg. 1
CAN_messages[0].LAR0 = 0x00; // Lower Arbit. Reg. 0
// ------ Configure 'Ack' Message Object
CAN_messages[1].MCR1 = 0x55; // Message Ctrl. Reg. 1
CAN_messages[1].MCR0 = 0x95; // Message Ctrl. Reg. 0
// Message direction is transmit
// extended 29-bit identifier
// 5 valid data bytes
CAN_messages[1].MCFG = 0x5C; // Message Config. Reg.
CAN_messages[1].UAR1 = 0x00; // Upper Arbit. Reg. 1
CAN_messages[1].UAR0 = 0x00; // Upper Arbit. Reg. 0
CAN_messages[1].LAR1 = 0xF8; // Lower Arbit. Reg. 1
CAN_messages[1].LAR0 = 0x07; // Lower Arbit. Reg. 0
CAN_messages[1].Data[0] = 0x00; // data byte 0
CAN_messages[1].Data[1] = 0x00; // data byte 1
CAN_messages[1].Data[2] = 0x00; // data byte 2
CAN_messages[1].Data[3] = 0x00; // data byte 3
CAN_messages[1].Data[4] = 0x00; // data byte 4
// ------ Configure other objects ------------------------------
// Configure remaining message objects (2-14) - none are valid
for (Message = 2; Message <= 14; ++Message)
{
CAN_messages[Message].MCR1 = 0x55; // Message Ctrl. Reg. 1
CAN_messages[Message].MCR0 = 0x55; // Message Ctrl. Reg. 0
}
// ------------ CAN Ctrl. Reg. ---------------------
// reset CCE and INIT
// enable interrupt generation from CAN Modul
// enable CAN-interrupt of Controller
CAN_cr = 0x02;
IEN2 |= 0x02;
// Start the watchdog
SCC_A_SLAVE_Watchdog_Init();
}
/*------------------------------------------------------------------*-
SCC_A_SLAVE_Start()
Starts the slave scheduler, by enabling interrupts.
NOTE: Usually called after all regular tasks are added,
to keep the tasks synchronised.
NOTE: ONLY THE SCHEDULER INTERRUPT SHOULD BE ENABLED!!!
-*------------------------------------------------------------------*/
void SCC_A_SLAVE_Start(void)
{
tByte Tick_00, Tick_ID;
bit Start_slave;
// Disable interrupts
EAL = 0;
// We can be at this point because:
// 1. The network has just been powered up
// 2. An error has occurred in the Master, and it is not generating ticks
// 3. The network has been damaged and no ticks are being received by this slave
//
// Try to make sure the system is in a safe state...
// NOTE: Interrupts are disabled here
SCC_A_SLAVE_Enter_Safe_State();
Start_slave = 0;
Error_code_G = ERROR_SCH_WAITING_FOR_START_COMMAND_FROM_MASTER;
SCH_Report_Status(); // Sch not yet running - do this manually
// Now wait (indefinitely) for appropriate signal from the master
do {
// Wait for 'Slave ID' message to be received
do {
SCC_A_SLAVE_Watchdog_Refresh(); // Must keep feeding the watchdog
} while ((CAN_messages[0].MCR1 & 0x03) != 0x02);
// Got a message - extract the data
if ((CAN_messages[0].MCR1 & 0x0c) == 0x08) // if MSGLST set
{
// Ignore lost message
CAN_messages[0].MCR1 = 0xf7; // reset MSGLST
}
Tick_00 = (tByte) CAN_messages[0].Data[0]; // Get data byte 0
Tick_ID = (tByte) CAN_messages[0].Data[1]; // Get data byte 1
CAN_messages[0].MCR0 = 0xfd; // reset NEWDAT, INTPND
CAN_messages[0].MCR1 = 0xfd;
if ((Tick_00 == 0x00) && (Tick_ID == SLAVE_ID))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -