//#############################################################################
//
// FILE:   can_ex5_transmit_receive.c
//
// TITLE:   CAN Configuration for Transmit and Receive.
//
//! \addtogroup driver_example_list
//! <h1> CAN Transmit and Receive Configurations </h1>
//!
//! This example shows the basic setup of CAN in order to transmit or receive
//! messages on the CAN bus with a specific Message ID. The CAN Controller is
//! configured according to the selection of the define.
//!
//! When the TRANSMIT define is selected, the CAN Controller acts as a
//! Transmitter and sends data to the second CAN Controller connected
//! externally.If TRANMSIT is not defined the CAN Controller acts as a Receiver
//! and waits for message to be transmitted by the External CAN Controller.
//!
//! \note CAN modules on the device need to be connected to via CAN
//!       transceivers.
//!
//! \b Hardware \b Required \n
//!  - A C2000 board with CAN transceiver.
//!
//! \b External \b Connections \n
//!  - ControlCARD CANA is on GPIO37 (CANTXA) and GPIO36 (CANRXA)
//!
//! \b Watch \b Variables \b Transmit \Configuration \n
//!  - MSGCOUNT   - Adjust to set the number of messages
//!  - txMsgCount - A counter for the number of messages sent
//!  - txMsgData  - An array with the data being sent
//!  - errorFlag  - A flag that indicates an error has occurred
//!  - rxMsgCount - Has the initial value as No. of Messages to be received
//!                 and decrements with each message.
//!
//
//#############################################################################

//
// Included Files
//
#include "driverlib.h"
#include "device.h"
#include "App_Can.h"
#include "Timer.h"
#include "diagnosticUser.h"
#include "uds_diagnostic.h"
#include "App_Flash.h"
//
// Comment to Make the CAN Controller work as a Receiver.
//
//#define TRANSMIT


#define IPC_CMD_READ_MEM        0x1001
#define IPC_CMD_RESP            0x2001



#define IPC_CMD_CM_RUNBOOT         0x1001
#define IPC_CMD_CM_RUNBOOT_ACK     0x2001

#define IPC_CMD_CM_RUNAPP          0x1002
#define IPC_CMD_CM_RUNAPP_ACK      0x2002

#define IPC_CMD_CM_PROGRAM          0x1003
#define IPC_CMD_CM_PROGRAM_ACK      0x2003

#define IPC_CMD_CPU2_RUNBOOT         0x1004
#define IPC_CMD_CPU2_RUNBOOT_ACK     0x2004

#define IPC_CMD_CPU2_RUNAPP          0x1005
#define IPC_CMD_CPU2_RUNAPP_ACK      0x2005


#define IPC_CMD_CPU2_PROGRAM          0x1006
#define IPC_CMD_CPU2_PROGRAM_ACK      0x2006

#define TEST_PASS          0x5555
#define TEST_FAIL          0xAAAA


#pragma DATA_SECTION(readData, "MSGRAM_CPU_TO_CM")
uint32_t readData[10];

IPC_MessageQueue_t messageQueue;
IPC_Message_t      TxMsg, RxMsg;
uint32_t pass;


void WaitCM_CPU2_Pro(void)
{


   // WaitCM=2;
    //WaitCPU2=2;

    if(WaitCM==1)//0:Ĭ1أ2
    {
         WaitCM=0;



         CAN_disableController(CANA_BASE);
         GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);
         GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);
        // Allocate Shared Peripheral CAN A to the CM Side.
         SysCtl_allocateSharedPeripheral(SYSCTL_PALLOCATE_CAN_A,0x1U);

         IPC_clearFlagLtoR(IPC_CPU1_L_CM_R, IPC_FLAG_ALL);

         IPC_sync(IPC_CPU1_L_CM_R, IPC_FLAG31);

         IPC_setFlagLtoR(IPC_CPU1_L_CM_R, IPC_FLAG31);

      //   IPC_initMessageQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_INT1, IPC_INT1);
//CM˸ָȴɣָ
         /*
         TxMsg.command = IPC_CMD_CM_PROGRAM;
         TxMsg.address = (uint32_t)readData;
         TxMsg.dataw1  = 10;  // Using dataw1 as data length
         TxMsg.dataw2  = 1;   // Message identifier

         IPC_sendMessageToQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
                                   &TxMsg, IPC_BLOCKING_CALL);
         IPC_readMessageFromQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_DISABLE,
                                 &RxMsg, IPC_BLOCKING_CALL);

         if((RxMsg.command == IPC_CMD_CM_PROGRAM_ACK) && (RxMsg.dataw1 == TEST_PASS) && (RxMsg.dataw2 == 1))
            pass = 1;
         else
            pass = 0;
         */
    }
         /*
         //
         // Initialize message queue
         //


         //
         // Synchronize both the cores
         //
         IPC_sync(IPC_CPU1_L_CM_R, IPC_FLAG31);

         //
         // Fill in the data to be sent
         //
         for(i=0; i<10; i++)
         {
             readData[i] = i;
         }




         TxMsg.command = IPC_CMD_CM_RUNAPP;
         TxMsg.address = (uint32_t)readData;
         TxMsg.dataw1  = 10;  // Using dataw1 as data length
         TxMsg.dataw2  = 1;   // Message identifier

         IPC_sendMessageToQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
                                   &TxMsg, IPC_BLOCKING_CALL);
         IPC_readMessageFromQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_DISABLE,
                                 &RxMsg, IPC_BLOCKING_CALL);

         if((RxMsg.command == IPC_CMD_CM_RUNAPP_ACK) && (RxMsg.dataw1 == TEST_PASS) && (RxMsg.dataw2 == 1))
            pass = 1;
         else
            pass = 0;

    }

    /*
    else if(WaitCPU2==1)//0:Ĭ1أ2
    {
       CAN_disableController(CANA_BASE);
       GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);
       GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);
      // Allocate Shared Peripheral CAN A to the CM Side.
       SysCtl_allocateSharedPeripheral(SYSCTL_PALLOCATE_CAN_A,0x0U);


    }
    //else if(WaitCM==2&&WaitCPU2==2)//ϽAPP
    else if(WaitCM==2)//ϽAPP
    {

         TxMsg.command = IPC_CMD_CM_RUNAPP;
         TxMsg.address = (uint32_t)readData;
         TxMsg.dataw1  = 10;  // Using dataw1 as data length
         TxMsg.dataw2  = 1;   // Message identifier

         IPC_sendMessageToQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
                                    &TxMsg, IPC_BLOCKING_CALL);
         IPC_readMessageFromQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_DISABLE,
                                  &RxMsg, IPC_BLOCKING_CALL);

         if((RxMsg.command == IPC_CMD_CM_RUNAPP_ACK) && (RxMsg.dataw1 == TEST_PASS) && (RxMsg.dataw2 == 1))
             pass = 1;
         else
             pass = 0;

    }
    else  //BOOT
    {
         /*TxMsg.command = IPC_CMD_CM_RUNBOOT;
         TxMsg.address = (uint32_t)readData;
         TxMsg.dataw1  = 10;  // Using dataw1 as data length
         TxMsg.dataw2  = 1;   // Message identifier

         IPC_sendMessageToQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_ENABLE,
                                    &TxMsg, IPC_BLOCKING_CALL);
         IPC_readMessageFromQueue(IPC_CPU1_L_CM_R, &messageQueue, IPC_ADDR_CORRECTION_DISABLE,
                                  &RxMsg, IPC_BLOCKING_CALL);

         if((RxMsg.command == IPC_CMD_CM_RUNBOOT_ACK) && (RxMsg.dataw1 == TEST_PASS) && (RxMsg.dataw2 == 1))
             pass = 1;
         else
             pass = 0;




    }
    */

}




// Main
//
void main(void)
{
    //
    // Initialize device clock and peripherals
    //
    uint32_t Data_APP_START_ADDR;
    uint16_t i;
    Device_init();

    WaitCM=0;
    WaitCPU2=0;

     //
     // Initialize device clock and peripherals
     //
     Device_init();

     //
     // Boot CM core
     //
 #ifdef _FLASH
     Device_bootCM(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
     Device_bootCPU2(BOOTMODE_BOOT_TO_FLASH_SECTOR0);
 #else
     Device_bootCM(BOOTMODE_BOOT_TO_S0RAM);
 #endif

     //
     // Clear any IPC flags if set already
     /*

      */




    Device_initGPIO();
    //CPU1ʹLED1
    GPIO_setPadConfig(DEVICE_GPIO_PIN_LED1, GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED1, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(DEVICE_GPIO_PIN_LED2, GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED2, GPIO_DIR_MODE_OUT);
    GPIO_setPadConfig(DEVICE_GPIO_PIN_LED3, GPIO_PIN_TYPE_STD);
    GPIO_setDirectionMode(DEVICE_GPIO_PIN_LED3, GPIO_DIR_MODE_OUT);
    //CMʹLED2
    GPIO_setMasterCore(DEVICE_GPIO_PIN_LED3, GPIO_CORE_CPU2);
    //GPIO_setMasterCore(DEVICE_GPIO_CFG_LED1, GPIO_CORE_CPU2);
    CanInit();



    TimeInit();
    sSCANRxStruct.FramCrc=0;
    Diagnostic_Init_Config();
    EINT;
    ERTM;
    GPIO_writePin(DEVICE_GPIO_PIN_LED1, 0);

    Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, 3);
    Example_CallFlashAPI();


    Data_APP_START_ADDR=*(uint32_t*)APP_EXE_FLAG_ADDR;
     if(Data_APP_START_ADDR!= 0x22221111)
     {

     }
     else
     {
         //תǰͨCM
         IPC_clearFlagLtoR(IPC_CPU1_L_CM_R, IPC_FLAG_ALL);

         IPC_sync(IPC_CPU1_L_CM_R, IPC_FLAG31);

         IPC_setFlagLtoR(IPC_CPU1_L_CM_R, IPC_FLAG31);


         DEVICE_DELAY_US(2000000);//20ms


         CAN_BOOT_JumpToApplication(APP_ENTER_ADDR);
     }

   for(i=0; i<100; i++)
   {
      if(sSCANRxStruct.ValData[2]==0x09 )   //յCAN һֽΪ0xFF
      {
            SetCurrentSession(ECU_PAOGRAM_SESSION) ;
            GPIO_writePin(DEVICE_GPIO_PIN_LED1, 0);
            break;
        }
        else
        {
            DEVICE_DELAY_US(20000);//20ms

        }
   }

    while(1)
    {
      WaitCM_CPU2_Pro();
      Task_UDS();
      Diagnostic_Proc();

    }

}




//
// CAN A ISR - The interrupt service routine called when a CAN interrupt is
//             triggered on CAN module A.
//


//
// End of File
//
