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 + -
显示快捷键?