📄 scu_am.c
字号:
This is the scheduler ISR. It is called at a rate determined by
the timer settings in SCU_A_MASTER_Init_T2(). This version is
triggered by Timer 2 interrupts: timer is automatically reloaded.
-*------------------------------------------------------------------*/
void SCU_A_MASTER_Update_T2(void) interrupt INTERRUPT_Timer_2_Overflow
{
tByte Task_index;
tByte Previous_slave_index;
TF2 = 0; // Must manually clear this.
// Refresh the watchdog
SCU_A_MASTER_Watchdog_Refresh();
// Default
Network_error_pin = NO_NETWORK_ERROR;
// Keep track of the current slave
// FIRST VALUE IS 0
Previous_slave_index = Current_slave_index_G;
// Assume 2-byte messages sent and received
// - it takes two ticks to deliver each message
if (Message_byte_G == 0)
{
Message_byte_G = 1;
}
else
{
Message_byte_G = 0;
if (++Current_slave_index_G >= NUMBER_OF_SLAVES)
{
Current_slave_index_G = 0;
}
}
// Check that the appropriate slave responded to the previous message:
// (if it did, store the data sent by this slave)
if (SCU_A_MASTER_Process_Ack(Previous_slave_index) == RETURN_ERROR)
{
Network_error_pin = NETWORK_ERROR;
Error_code_G = ERROR_SCH_LOST_SLAVE;
// If we have lost contact with a slave, we attempt to
// switch to a backup device (if one is available) as we reset the network
//
// NOTE: We don't do this every tick (or the the network will be constantly reset)
//
// Choose a value of SLAVE_RESET_INTERVAL to allow resets (say) every 5 seconds
if (++Slave_reset_attempts_G[Previous_slave_index] >= SLAVE_RESET_INTERVAL)
{
SCU_A_MASTER_Reset_the_Network();
}
}
else
{
// Reset this counter
Slave_reset_attempts_G[Previous_slave_index] = 0;
}
// Send 'tick' message to all connected slaves
// (sends one data byte to the current slave)
SCU_A_MASTER_Send_Tick_Message(Current_slave_index_G);
// NOTE: calculations are in *TICKS* (not milliseconds)
for (Task_index = 0; Task_index < SCH_MAX_TASKS; Task_index++)
{
// Check if there is a task at this location
if (SCH_tasks_G[Task_index].pTask)
{
if (SCH_tasks_G[Task_index].Delay == 0)
{
// The task is due to run
SCH_tasks_G[Task_index].RunMe += 1; // Increment the run flag
if (SCH_tasks_G[Task_index].Period)
{
// Schedule periodic tasks to run again
SCH_tasks_G[Task_index].Delay = SCH_tasks_G[Task_index].Period;
}
}
else
{
// Not yet ready to run: just decrement the delay
SCH_tasks_G[Task_index].Delay -= 1;
}
}
}
}
/*------------------------------------------------------------------*-
SCU_A_MASTER_Send_Tick_Message()
This function sends a tick message, over the USART network.
The receipt of this message will cause an interrupt to be generated
in the slave(s): this invoke the scheduler 'update' function
in the slave(s).
-*------------------------------------------------------------------*/
void SCU_A_MASTER_Send_Tick_Message(const tByte SLAVE_INDEX)
{
tLong Timeout;
// Find the slave ID for this slave
tByte Slave_ID = (tByte) Current_Slave_IDs_G[SLAVE_INDEX];
// Sending one byte of data at a time, depending on index value
// If Message_byte_G is 0, send first byte (the slave ID)
if (Message_byte_G == 0)
{
Timeout = 0;
while ((++Timeout) && (TI == 0));
if (Timeout == 0)
{
// UART did not respond - error
Error_code_G = ERROR_USART_TI;
return;
}
TI = 0;
TB8 = 1; // Set 'Command' bit
SBUF = Slave_ID;
}
else
{
// Message_byte_G is 1, send the data byte
Timeout = 0;
while ((++Timeout) && (TI == 0));
if (Timeout == 0)
{
// usart did not respond - error
Error_code_G = ERROR_USART_TI;
return;
}
TI = 0;
TB8 = 0;
SBUF = Tick_message_data_G[SLAVE_INDEX];
}
// Data sent - return
}
/*------------------------------------------------------------------*-
SCU_A_MASTER_Process_Ack()
Make sure the slave (SLAVE_ID) has acknowledged the previous
message that was sent. If it has, extract the message data
from the USART hardware: if not, call the appropriate error
handler.
Slave_index - The index of the slave.
RETURNS: RETURN_NORMAL - Ack received (data in Ack_message_data_G)
RETURN_ERROR - No ack received (-> no data)
-*------------------------------------------------------------------*/
bit SCU_A_MASTER_Process_Ack(const tByte Slave_index)
{
tByte Message_contents;
tByte Slave_ID;
// First time this is called there is no ack tick to check
// - we simply return 'OK'
if (First_ack_G)
{
First_ack_G = 0;
return RETURN_NORMAL;
}
// Find the slave ID for this slave
Slave_ID = (tByte) Current_Slave_IDs_G[Slave_index];
// Data should already be in the buffer
if (RI == 0)
{
// Slave has not replied to last tick message
// Set error LED
Network_error_pin = NETWORK_ERROR;
return RETURN_ERROR;
}
// There is data - get it
Message_contents = (tByte) SBUF;
RI = 0;
// This is the reply to the last message
// - reverse the message byte interpretation
if (Message_byte_G == 1)
{
// Check the 'command bit' is set
if (RB8 == 1)
{
// Check that the ID is correct
if (Slave_ID == (tByte) Message_contents)
{
// Required Ack message was received
return RETURN_NORMAL;
}
}
// Something is wrong...
// Set error LED
Network_error_pin = NETWORK_ERROR;
return RETURN_ERROR;
}
else
{
// There *ARE* data available
// Extract the data from the slave message
//
// NOTE: We *assume* these data are OK
// - you may wish to send crucial data twice, etc.
Ack_message_data_G[Slave_index] = Message_contents;
return RETURN_NORMAL; // return the slave data
}
}
/*------------------------------------------------------------------*-
SCU_A_MASTER_Reset_the_Network()
This function resets (that is, restarts) the whole network.
-*------------------------------------------------------------------*/
void SCU_A_MASTER_Reset_the_Network(void)
{
EA = 0; // Disable interrupts
while(1); // Watchdog will time out
}
/*------------------------------------------------------------------*-
SCU_A_MASTER_Shut_Down_the_Network()
This function shuts down the whole network.
-*------------------------------------------------------------------*/
void SCU_A_MASTER_Shut_Down_the_Network(void)
{
EA = 0; // Disable interrupts
Network_error_pin = NETWORK_ERROR;
SCH_Report_Status(); // Sch not running - do this manually
while(1)
{
SCU_A_MASTER_Watchdog_Refresh();
}
}
/*------------------------------------------------------------------*-
SCU_A_MASTER_Enter_Safe_State()
This is the state enterted by the system when:
(1) The node is powered up or reset
(2) The Master node cannot detect a slave
(3) The network has an error
Try to ensure that the system is in a 'safe' state in these
circumstances.
-*------------------------------------------------------------------*/
void SCU_A_MASTER_Enter_Safe_State(void)
{
// USER DEFINED - Edit as required
TRAFFIC_LIGHTS_Display_Safe_Output();
}
/*------------------------------------------------------------------*-
SCU_A_MASTER_Watchdog_Init()
This function sets up the watchdog timer.
If the Master fails (or other error develop),
no tick messages will arrive, and the scheduler
will stop.
To detect this situation, we have a (hardware) watchdog
running in the slave. This watchdog - which should be set to
overflow at around 100ms - is used to set the system into a
known (safe) state. The slave will then wait (indefinitely)
for the problem to be resolved.
NOTE: The slave will not be generating Ack messages in these
circumstances. The Master (if running) will therefore be aware
that there is a problem.
-*------------------------------------------------------------------*/
void SCU_A_MASTER_Watchdog_Init(void)
{
// INIT NOT REQUIRED FOR 1232 EXTERNAL WATCHDOG
// - May be required wwith different watchdog hardware
//
// Edit as required
}
/*------------------------------------------------------------------*-
SCU_A_MASTER_Watchdog_Refresh()
Feed the external (1232) watchdog.
Timeout is between ~60 and 250 ms (hardware dependent)
Assumes external 1232 watchdog
-*------------------------------------------------------------------*/
void SCU_A_MASTER_Watchdog_Refresh(void) reentrant
{
// Change the state of the watchdog pin
if (WATCHDOG_state_G == 1)
{
WATCHDOG_state_G = 0;
WATCHDOG_pin = 0;
}
else
{
WATCHDOG_state_G = 1;
WATCHDOG_pin = 1;
}
}
/*------------------------------------------------------------------*-
---- END OF FILE -------------------------------------------------
-*------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -