lin_frame_management.c
来自「芯科原厂所有c8051fxx程序的例子。」· C语言 代码 · 共 792 行 · 第 1/2 页
C
792 行
l_u8 l_sch_tick_std_ifc (void)
{
l_u8 status, retval, frame_id;
l_u8 frame_data[8];
l_frame * frame_ptr;
retval = 0;
// If the number of system ticks remaining for the current frame to complete
// is zero, send the next frame.
if (schedule_controller_std_ifc.current_frame_ticks_remaining == 0)
{
// Get the status of the LIN bus.
status = l_get_status ();
// If the last transmission was successful, check to see if this node is
// a subscriber of the frame. If so, unload the data and update all
// corresponding signals and flags.
if (status & TX_SUCCESS)
{
// Set the bus activity bit of the status variable.
status_std_ifc |= BUS_ACTIVITY;
if (frame_direction == IN_FRAME)
{
// Handle the received frame.
l_ifc_rx_std_ifc ();
// If rx_valid_data is FALSE, then the data is invalid.
// Clear the TX_SUCCESS bit and set TX_FRAME_ERROR.
if (rx_valid_data == FALSE)
{
status |= TX_FRAME_ERROR;
status &= ~TX_SUCCESS;
}
}
else
{
// Handle the transmission complete event.
l_ifc_tx_std_ifc ();
}
}
// If there was an error and the current frame is an event-triggered
// frame, point to the associated collision resolution schedule.
else if (status & TX_FRAME_ERROR)
{
// Set the bus activity bit of the status variable.
status_std_ifc |= BUS_ACTIVITY;
// Get the frame ID of the received packet.
frame_id = l_read_frame_id ();
// Get the frame with ID frame_id.
frame_ptr = l_get_frame (frame_id);
if ((frame_ptr != L_NULL_FRAME) &&
(frame_ptr->frame_type == EVENT_TRIGGERED_FRAME))
{
// Save the current schedule and schedule counter.
l_sch_save_std_ifc ();
// Set the next schedule to the collision resolution schedule
// for this frame.
l_sch_set_std_ifc ((l_schedule) frame_ptr->collision_resolution_schedule, 0);
// Set the global collision bit.
collision = 1;
// Update the status with invalid data.
l_ifc_update_status_std_ifc (FALSE);
}
else
{
// Update the status with valid data.
l_ifc_update_status_std_ifc (TRUE);
}
}
else
{
// Update the status with valid data.
l_ifc_update_status_std_ifc (TRUE);
}
// Point to the next entry in the schedule table.
l_sch_increment_schedule_controller_std_ifc ();
// Transmit the next Frame ID in the schedule if the schedule is not
// L_NULL_SCHEDULE.
if (schedule_controller_std_ifc.current_schedule != L_NULL_SCHEDULE)
{
// Get the frame ID.
frame_id = schedule_controller_std_ifc.current_schedule[schedule_controller_std_ifc.current_schedule_counter].frame_ptr->frame_id;
// Point to the frame.
frame_ptr = l_get_frame (frame_id);
// Set frame_direction to the direction of the currently selected frame.
frame_direction = frame_ptr->frame_direction;
// Check to see if the master is transmitting data.
if (frame_direction == OUT_FRAME)
{
// If frame is a sporadic frame, get the frame ID of the
// unconditional frame to send.
if (frame_ptr->frame_type == SPORADIC_FRAME)
{
frame_id = l_get_sporadic_frame_id (frame_id);
// Get a pointer to the frame to send.
frame_ptr = l_get_frame (frame_id);
}
// If the frame_id is a Master Request Frame, get the data to send.
if (frame_id == MASTER_REQUEST_FRAME_ID)
{
l_get_diagnostic_tx_frame_data (frame_data);
}
// Get the data to send in frame_data and set any corresponding flags.
else if (!l_get_tx_frame_data (frame_id, frame_data))
{
frame_direction = IN_FRAME;
}
}
// Send out the frame header unless this frame slot should be silent.
if (frame_id != SILENT_FRAME_SLOT)
{
// Transmit the frame.
l_master_transmit_frame (frame_id,
frame_ptr->frame_len,
frame_data,
frame_ptr->frame_checksum,
frame_direction);
// Update the number of ticks this frame will take to complete transmission.
schedule_controller_std_ifc.current_frame_ticks_remaining =
schedule_controller_std_ifc.current_schedule[schedule_controller_std_ifc.current_schedule_counter].delay_num_ticks;
// Set the bus activity bit of the status variable.
status_std_ifc |= BUS_ACTIVITY;
}
else
{
// For an empty frame slot, clear the status bits
l_clear_status ();
// Set current_frame_ticks_remaining to be zero on the next frame tick.
schedule_controller_std_ifc.current_frame_ticks_remaining = 1;
}
}
else
{
// Clear the status information for the previous transaction.
l_clear_status ();
// If the current schedule is L_NULL_SCHEDULE, set
// current_frame_ticks_remaining to 1 so the next call of
// l_sch_tick_std_ifc () will increment the current schedule pointer.
schedule_controller_std_ifc.current_frame_ticks_remaining = 1;
}
}
// If the next call of l_sch_tick_std_ifc () will start a new transaction,
// return the entry number of that entry in the schedule table.
if (schedule_controller_std_ifc.current_frame_ticks_remaining == 1)
{
if (schedule_controller_std_ifc.next_schedule == L_NULL_SCHEDULE)
retval = 0;
else if (schedule_controller_std_ifc.current_schedule == schedule_controller_std_ifc.next_schedule)
{
if (schedule_controller_std_ifc.current_schedule[schedule_controller_std_ifc.current_schedule_counter + 1].frame_ptr != L_NULL_FRAME)
{
retval = schedule_controller_std_ifc.current_schedule_counter + 2;
}
else
{
retval = 1;
}
}
else
{
retval = schedule_controller_std_ifc.next_schedule_counter;
}
}
// Decrement the number of system ticks remaining for the current frame every
// time l_sch_tick_std_ifc is called until it reaches zero.
schedule_controller_std_ifc.current_frame_ticks_remaining--;
return (retval);
}
//-----------------------------------------------------------------------------
// l_sch_increment_schedule_controller_std_ifc ()
//-----------------------------------------------------------------------------
//
// Increments schedule_controller_std_ifc to point to the next frame in the
// schedule.
//
// Returns the entry number of the next entry in the schedule table.
//
l_u8 l_sch_increment_schedule_controller_std_ifc (void)
{
// If there is no next schedule selected, update current_schedule_counter
// to point to the next entry in current_schedule.
if (schedule_controller_std_ifc.next_schedule == schedule_controller_std_ifc.current_schedule)
{
// Point to the next entry in the schedule table.
if (schedule_controller_std_ifc.current_schedule[schedule_controller_std_ifc.current_schedule_counter + 1].frame_ptr != L_NULL_FRAME)
{
// If schedule_controller_std_ifc has not reached the end of
// current_schedule, increment schedule_counter.
schedule_controller_std_ifc.current_schedule_counter++;
}
else
{
// If the end of current_schedule is reached and it is a collision
// resolution schedule, point back to the original schedule.
if (schedule_controller_std_ifc.current_schedule_type == COLLISION_RESOLUTION_SCHEDULE)
{
schedule_controller_std_ifc.current_schedule =
schedule_controller_std_ifc.saved_schedule;
schedule_controller_std_ifc.current_schedule_counter =
schedule_controller_std_ifc.saved_schedule_counter;
schedule_controller_std_ifc.current_schedule_type = NORMAL_SCHEDULE;
schedule_controller_std_ifc.next_schedule =
schedule_controller_std_ifc.current_schedule;
// Clear the EVENT_TRIGGERED_FRAME_COLLISION bit in status_std_ifc.
status_std_ifc &= ~EVENT_TRIGGERED_FRAME_COLLISION;
}
// Otherwise, point to the beginning of current_schedule.
else
{
schedule_controller_std_ifc.current_schedule_counter = 0;
}
}
}
// If there is a next_schedule selected, point to the entry point in
// next_schedule.
else
{
schedule_controller_std_ifc.current_schedule = schedule_controller_std_ifc.next_schedule;
schedule_controller_std_ifc.current_schedule_counter = schedule_controller_std_ifc.next_schedule_counter;
schedule_controller_std_ifc.next_schedule = schedule_controller_std_ifc.current_schedule;
if (!collision)
{
schedule_controller_std_ifc.current_schedule_type = NORMAL_SCHEDULE;
}
else
{
schedule_controller_std_ifc.current_schedule_type = COLLISION_RESOLUTION_SCHEDULE;
collision = 0;
}
}
return (schedule_controller_std_ifc.current_schedule_counter);
}
//-----------------------------------------------------------------------------
// l_sch_set_std_ifc ()
//-----------------------------------------------------------------------------
//
// Set the schedule for interface std_ifc.
//
// Parameters:
//
// 1. next_schedule_std_ifc - Handle to the next schedule to
// run on std_ifc
//
// 2. entry - Starting entry point in the new schedule.
//
void l_sch_set_std_ifc (l_schedule_handle next_schedule_std_ifc, l_u8 entry)
{
// Point to the next schedule.
schedule_controller_std_ifc.next_schedule = next_schedule_std_ifc;
// If entry if 0 or 1, it should start at the first entry in next_schedule.
// Otherwise, it should start at element (entry - 1).
if(entry != 0)
entry--;
// Set the entry point for the next schedule.
schedule_controller_std_ifc.next_schedule_counter = entry;
}
//-----------------------------------------------------------------------------
// l_sch_save_std_ifc ()
//-----------------------------------------------------------------------------
//
// Saves the current schedule. If the master task switches to a collision
// resolution schedule, it should call this function first to save the
// current schedule so it can return to this schedule once the collision
// resolution is complete.
//
void l_sch_save_std_ifc (void)
{
schedule_controller_std_ifc.saved_schedule =
schedule_controller_std_ifc.current_schedule;
schedule_controller_std_ifc.saved_schedule_counter =
schedule_controller_std_ifc.current_schedule_counter;
}
#elif (LIN_MODE == LIN_SLAVE)
//-----------------------------------------------------------------------------
// l_data_requested ()
//-----------------------------------------------------------------------------
//
// Reads the frame ID and determines if the slave should transmit, receive or
// ignore the frame.
//
void l_data_requested (void)
{
l_u8 frame_id;
l_frame * frame_ptr;
l_u8 frame_data[8];
// Update the bus activity bit of the status variable.
status_std_ifc |= BUS_ACTIVITY;
// Get the received frame ID.
frame_id = l_read_frame_id ();
// Get the frame with ID frame_id.
frame_ptr = l_get_frame (frame_id);
// Set frame_direction.
frame_direction = IN_FRAME;
if (frame_ptr != L_NULL_FRAME)
{
if (frame_ptr->frame_direction == IN_FRAME)
{
// Configure the device to receive the frame.
l_slave_receive_frame (frame_ptr->frame_len,
frame_ptr->frame_checksum);
}
else if (frame_ptr->frame_direction == OUT_FRAME)
{
// Get the data to send for frame with ID frame_id.
// Only send the data if l_get_tx_frame_data returns 1.
if(l_get_tx_frame_data (frame_id, frame_data))
{
// Set frame_direction.
frame_direction = OUT_FRAME;
// Transmit the frame.
l_slave_transmit_frame (frame_ptr->frame_len, frame_data, frame_ptr->frame_checksum);
}
else
{
// If l_get_tx_frame_data () returns 0, ignore the frame.
l_slave_ignore_frame ();
}
}
else
{
// If the device is neither a publisher nor a subscriber of the
// frame, ignore it.
l_slave_ignore_frame ();
}
}
else
{
// If the frame was not found in the frame descriptor table, ignore it.
l_slave_ignore_frame ();
}
}
#endif // LIN_MODE == LIN_SLAVE
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?