#include <stdio.h>
#include <string.h>
#include "cyhal.h"
#include "cy_pdl.h"
#include "cybsp.h"
#include "cy_retarget_io.h"
/*******************************************************************************
* Macros
*******************************************************************************/
/* CAN-FD message identifier 1*/
#define CANFD_NODE_1 1
/* CAN-FD message identifier 2 (use different for 2nd device) */
#define CANFD_NODE_2 2
/* message Identifier used for this code */
#define USE_CANFD_NODE CANFD_NODE_1
/* CAN-FD channel number used */
#define CANFD_HW_CHANNEL 0
/* CAN-FD data buffer index to send data from */
#define CANFD_BUFFER_INDEX 0
/* Maximum incoming data length supported */
#define CANFD_DLC 8
#define CANFD_INTERRUPT canfd_0_interrupts0_0_IRQn
#define GPIO_INTERRUPT_PRIORITY (7u)
/*******************************************************************************
* Global Variables
*******************************************************************************/
/* This is a shared context structure, unique for each can-fd channel */
static cy_stc_canfd_context_t canfd_context;
/* Variable which holds the button pressed status */
volatile bool gpio_intr_flag = false;
cyhal_gpio_callback_data_t gpio_btn_callback_data;
/* Populate the configuration structure for CAN-FD Interrupt */
cy_stc_sysint_t canfd_irq_cfg =
{
/* Source of interrupt signal */
.intrSrc = CANFD_INTERRUPT,
/* Interrupt priority */
.intrPriority = 1U,
};
/*******************************************************************************
* Function Prototypes
*******************************************************************************/
/* can-fd interrupt handler */
static void isr_canfd (void);
/* button press interrupt handler */
static void gpio_interrupt_handler(void *handler_arg, cyhal_gpio_event_t event);
/* handler for general errors */
void handle_error(uint32_t status);
/*******************************************************************************
* Function Definitions
*******************************************************************************/
/*******************************************************************************
* Function Name: main
********************************************************************************
* Summary:
* This is the main function. It initializes the CAN-FD channel and interrupt.
* User button and User LED are also initialized. The main loop checks for the
* button pressed interrupt flag and when it is set, a CAN-FD frame is sent.
* Whenever a CAN-FD frame is received from other nodes, the user LED toggles and
* the received data is logged over serial terminal.
*
* Parameters:
* none
*
* Return:
* int
*
*******************************************************************************/
int main(void)
{
cy_rslt_t result;
cy_en_canfd_status_t status;
/* Initialize the device and board peripherals */
result = cybsp_init();
/* Board init failed. Stop program execution */
handle_error(result);
/* Initialize retarget-io for uart logging */
result = cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX,
CY_RETARGET_IO_BAUDRATE);
/* Retarget-io init failed. Stop program execution */
handle_error(result);
printf("===========================================================\r\n");
printf("Welcome to CAN-FD example\r\n");
printf("===========================================================\r\n\n");
printf("===========================================================\r\n");
printf("CAN-FD Node-%d (message id)\r\n", USE_CANFD_NODE);
printf("===========================================================\r\n\n");
/* Hook the interrupt service routine */
(void) Cy_SysInt_Init(&canfd_irq_cfg, &isr_canfd);
/* enable the CAN-FD interrupt */
NVIC_EnableIRQ(CANFD_INTERRUPT);
/* Initialize the user LED */
result = cyhal_gpio_init(CYBSP_USER_LED, CYHAL_GPIO_DIR_OUTPUT,
CYHAL_GPIO_DRIVE_STRONG, CYBSP_LED_STATE_OFF);
/* User LED init failed. Stop program execution */
handle_error(result);
/* Initialize the user button */
result = cyhal_gpio_init(CYBSP_USER_BTN, CYHAL_GPIO_DIR_INPUT,
CYBSP_USER_BTN_DRIVE, CYBSP_BTN_OFF);
/* User button init failed. Stop program execution */
handle_error(result);
/* Configure GPIO interrupt */
gpio_btn_callback_data.callback = gpio_interrupt_handler;
cyhal_gpio_register_callback(CYBSP_USER_BTN,
&gpio_btn_callback_data);
cyhal_gpio_enable_event(CYBSP_USER_BTN, CYHAL_GPIO_IRQ_FALL,
GPIO_INTERRUPT_PRIORITY, true);
/* Enable global interrupts */
__enable_irq();
/* Initialize CAN-FD Channel */
status = Cy_CANFD_Init(CANFD_HW, CANFD_HW_CHANNEL, &CANFD_config,
&canfd_context);
handle_error(status);
/* Setting Node(message) Identifier to global setting of "USE_CANFD_NODE" */
CANFD_T0RegisterBuffer_0.id = USE_CANFD_NODE;
for(;;)
{
if (true == gpio_intr_flag)
{
/* Sending CAN-FD frame to other node */
status = Cy_CANFD_UpdateAndTransmitMsgBuffer(CANFD_HW,
CANFD_HW_CHANNEL,
&CANFD_txBuffer_0,
CANFD_BUFFER_INDEX,
&canfd_context);
if(CY_CANFD_SUCCESS == status)
{
printf("CAN-FD Frame sent with message ID-%d\r\n\r\n",
USE_CANFD_NODE);
}
else
{
printf("Error sending CAN-FD Frame with message ID-%d\r\n\r\n",
USE_CANFD_NODE);
}
gpio_intr_flag = false;
}
}
}
void canfd_rx_callback (bool msg_valid, uint8_t msg_buf_fifo_num,
cy_stc_canfd_rx_buffer_t* canfd_rx_buf)
{
/* Array to hold the data bytes of the CAN-FD frame */
uint8_t canfd_data_buffer[CANFD_DLC];
/* Variable to hold the data length code of the CAN-FD frame */
uint32_t canfd_dlc;
/* Variable to hold the Identifier of the CAN-FD frame */
uint32_t canfd_id;
if (true == msg_valid)
{
/* Checking whether the frame received is a data frame */
if(CY_CANFD_RTR_DATA_FRAME == canfd_rx_buf->r0_f->rtr)
{
cyhal_gpio_toggle(CYBSP_USER_LED);
canfd_dlc = canfd_rx_buf->r1_f->dlc;
canfd_id = canfd_rx_buf->r0_f->id;
printf("%d bytes received with message identifier %d\r\n\r\n",
(int)canfd_dlc,
(int)canfd_id);
memcpy(canfd_data_buffer,canfd_rx_buf->data_area_f,canfd_dlc);
printf("Rx Data : ");
for (uint8_t msg_idx = 0U; msg_idx < canfd_dlc ; msg_idx++)
{
printf(" %d ", canfd_data_buffer[msg_idx]);
}
printf("\r\n\r\n");
}
}
}