335 lines
9.2 KiB
C
335 lines
9.2 KiB
C
/****************************************************************************
|
|
* boards/arm/s32k3xx/mr-canhubk3/src/s32k3xx_tja1153.c
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/* Copyright 2022 NXP
|
|
*
|
|
* This TJA1153 initialization routine is intended for ENGINEERING
|
|
* DEVELOPMENT OR EVALUATION PURPOSES ONLY. It is provided as an example to
|
|
* use the TJA1153. Please refer to the datasheets and application hints
|
|
* provided on NXP.com to implement full functionality.
|
|
*/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <debug.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <net/if.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/socket.h>
|
|
#include <nuttx/can.h>
|
|
#include <netpacket/can.h>
|
|
#include <nuttx/signal.h>
|
|
|
|
#include "s32k3xx_pin.h"
|
|
#include <arch/board/board.h>
|
|
#include "mr-canhubk3.h"
|
|
|
|
#ifdef CONFIG_S32K3XX_TJA1153
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
/* Bitrate must be set to 125, 250 or 500 kbit/s for CAN 2.0 and CAN FD
|
|
* arbitration phase
|
|
*/
|
|
|
|
#ifdef CONFIG_S32K3XX_FLEXCAN4
|
|
# if CONFIG_NET_CAN_CANFD
|
|
# if CONFIG_FLEXCAN4_ARBI_BITRATE > 500000
|
|
# error "FLEXCAN4_ARBI_BITRATE > 500000"
|
|
# endif
|
|
# else
|
|
# if CONFIG_FLEXCAN4_BITRATE > 500000
|
|
# error "FLEXCAN4_BITRATE > 500000"
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
#ifdef CONFIG_S32K3XX_FLEXCAN5
|
|
# if CONFIG_NET_CAN_CANFD
|
|
# if CONFIG_FLEXCAN5_ARBI_BITRATE > 500000
|
|
# error "FLEXCAN5_ARBI_BITRATE > 500000"
|
|
# endif
|
|
# else
|
|
# if CONFIG_FLEXCAN5_BITRATE > 500000
|
|
# error "FLEXCAN5_BITRATE > 500000"
|
|
# endif
|
|
# endif
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: s32k3xx_tja1153_initialize
|
|
*
|
|
* Description:
|
|
* Initialize a TJA1153 CAN PHY connected to a FlexCAN peripheral (0-5)
|
|
*
|
|
****************************************************************************/
|
|
|
|
int s32k3xx_tja1153_initialize(int bus)
|
|
{
|
|
int sock;
|
|
struct sockaddr_can addr;
|
|
struct can_frame frame_config1;
|
|
struct can_frame frame_config2;
|
|
struct can_frame frame_config3;
|
|
struct can_frame frame_config4;
|
|
struct can_frame frame_config5;
|
|
struct ifreq ifr;
|
|
uint32_t pin_can_txd;
|
|
uint32_t pin_can_rxd;
|
|
uint32_t pin_can_enable;
|
|
uint32_t pin_can_stb_n;
|
|
int ret = 0;
|
|
|
|
/* Select interface and pins */
|
|
|
|
switch (bus)
|
|
{
|
|
#ifdef CONFIG_S32K3XX_FLEXCAN4
|
|
case 4:
|
|
{
|
|
strlcpy(ifr.ifr_name, "can4", IFNAMSIZ);
|
|
|
|
pin_can_txd = PIN_CAN4_TX;
|
|
pin_can_rxd = PIN_CAN4_RX;
|
|
pin_can_enable = PIN_CAN4_ENABLE;
|
|
pin_can_stb_n = PIN_CAN4_STB;
|
|
}
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_S32K3XX_FLEXCAN5
|
|
case 5:
|
|
{
|
|
strlcpy(ifr.ifr_name, "can5", IFNAMSIZ);
|
|
|
|
pin_can_txd = PIN_CAN5_TX;
|
|
pin_can_rxd = PIN_CAN5_RX;
|
|
pin_can_enable = PIN_CAN5_ENABLE;
|
|
pin_can_stb_n = PIN_CAN5_STB;
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
{
|
|
/* This FlexCAN is not supported (yet) */
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* First check if configuration is actually needed */
|
|
|
|
s32k3xx_pinconfig((pin_can_txd & (_PIN_PORT_MASK | _PIN_MASK)) |
|
|
GPIO_OUTPUT | GPIO_OUTPUT_ZERO);
|
|
|
|
if (s32k3xx_gpioread(pin_can_rxd))
|
|
{
|
|
_info("CAN%d TJA1153 already configured\n", bus);
|
|
|
|
s32k3xx_pinconfig(pin_can_txd); /* Restore CAN_TXD pinconfig */
|
|
return 0;
|
|
}
|
|
|
|
s32k3xx_pinconfig(pin_can_txd); /* Restore CAN_TXD pinconfig */
|
|
|
|
/* Find network interface */
|
|
|
|
ifr.ifr_ifindex = if_nametoindex(ifr.ifr_name);
|
|
if (!ifr.ifr_ifindex)
|
|
{
|
|
_err("CAN%d TJA1153: if_nametoindex failed\n", bus);
|
|
return -1;
|
|
}
|
|
|
|
/* Configure pins */
|
|
|
|
s32k3xx_pinconfig(pin_can_enable);
|
|
s32k3xx_pinconfig(pin_can_stb_n);
|
|
|
|
s32k3xx_gpiowrite(pin_can_enable, true); /* Enable TJA1153 */
|
|
s32k3xx_gpiowrite(pin_can_stb_n, false); /* Inverted, so TJA1153 is put in STANDBY */
|
|
|
|
/* Init CAN frames, e.g. LEN = 0 */
|
|
|
|
memset(&frame_config1, 0, sizeof(frame_config1));
|
|
memset(&frame_config2, 0, sizeof(frame_config2));
|
|
memset(&frame_config3, 0, sizeof(frame_config3));
|
|
memset(&frame_config4, 0, sizeof(frame_config4));
|
|
memset(&frame_config5, 0, sizeof(frame_config5));
|
|
|
|
/* Prepare CAN frames. Refer to the TJA1153 datasheets and application
|
|
* hints available on NXP.com for details.
|
|
*/
|
|
|
|
frame_config1.can_id = 0x555;
|
|
frame_config1.can_dlc = 0;
|
|
|
|
frame_config2.can_id = 0x18da00f1 | CAN_EFF_FLAG;
|
|
frame_config2.can_dlc = 6;
|
|
frame_config2.data[0] = 0x10;
|
|
frame_config2.data[1] = 0x00;
|
|
frame_config2.data[2] = 0x50;
|
|
frame_config2.data[3] = 0x00;
|
|
frame_config2.data[4] = 0x07;
|
|
frame_config2.data[5] = 0xff;
|
|
|
|
frame_config3.can_id = 0x18da00f1 | CAN_EFF_FLAG;
|
|
frame_config3.can_dlc = 6;
|
|
frame_config3.data[0] = 0x10;
|
|
frame_config3.data[1] = 0x01;
|
|
frame_config3.data[2] = 0x9f;
|
|
frame_config3.data[3] = 0xff;
|
|
frame_config3.data[4] = 0xff;
|
|
frame_config3.data[5] = 0xff;
|
|
|
|
frame_config4.can_id = 0x18da00f1 | CAN_EFF_FLAG;
|
|
frame_config4.can_dlc = 6;
|
|
frame_config4.data[0] = 0x10;
|
|
frame_config4.data[1] = 0x02;
|
|
frame_config4.data[2] = 0xc0;
|
|
frame_config4.data[3] = 0x00;
|
|
frame_config4.data[4] = 0x00;
|
|
frame_config4.data[5] = 0x00;
|
|
|
|
frame_config5.can_id = 0x18da00f1 | CAN_EFF_FLAG;
|
|
frame_config5.can_dlc = 8;
|
|
frame_config5.data[0] = 0x71;
|
|
frame_config5.data[1] = 0x02;
|
|
frame_config5.data[2] = 0x03;
|
|
frame_config5.data[3] = 0x04;
|
|
frame_config5.data[4] = 0x05;
|
|
frame_config5.data[5] = 0x06;
|
|
frame_config5.data[6] = 0x07;
|
|
frame_config5.data[7] = 0x08;
|
|
|
|
/* Open socket */
|
|
|
|
if ((sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
|
|
{
|
|
_err("CAN%d TJA1153: Failed to open socket\n", bus);
|
|
return -1;
|
|
}
|
|
|
|
/* Bring up the interface */
|
|
|
|
ifr.ifr_flags = IFF_UP;
|
|
ret = ioctl(sock, SIOCSIFFLAGS, (unsigned long)&ifr);
|
|
if (ret < 0)
|
|
{
|
|
_err("CAN%d TJA1153: ioctl failed (can't set interface flags)\n", bus);
|
|
close(sock);
|
|
return -1;
|
|
}
|
|
|
|
/* Initialize sockaddr struct */
|
|
|
|
memset(&addr, 0, sizeof(addr));
|
|
addr.can_family = AF_CAN;
|
|
addr.can_ifindex = ifr.ifr_ifindex;
|
|
|
|
/* Disable default receive filter on this RAW socket
|
|
*
|
|
* This is obsolete as we do not read from the socket at all, but for this
|
|
* reason we can remove the receive list in the kernel to save a little
|
|
* (really very little!) CPU usage.
|
|
*/
|
|
|
|
setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
|
|
|
/* Bind socket and send the CAN frames */
|
|
|
|
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
|
{
|
|
_err("CAN%d TJA1153: Failed to bind socket\n", bus);
|
|
close(sock);
|
|
return -1;
|
|
}
|
|
|
|
if (write(sock, &frame_config1, CAN_MTU) != CAN_MTU)
|
|
{
|
|
_err("CAN%d TJA1153: Failed to write frame_config1\n", bus);
|
|
close(sock);
|
|
return -1;
|
|
}
|
|
|
|
if (write(sock, &frame_config2, CAN_MTU) != CAN_MTU)
|
|
{
|
|
_err("CAN%d TJA1153: Failed to write frame_config2\n", bus);
|
|
close(sock);
|
|
return -1;
|
|
}
|
|
|
|
if (write(sock, &frame_config3, CAN_MTU) != CAN_MTU)
|
|
{
|
|
_err("CAN%d TJA1153: Failed to write frame_config3\n", bus);
|
|
close(sock);
|
|
return -1;
|
|
}
|
|
|
|
if (write(sock, &frame_config4, CAN_MTU) != CAN_MTU)
|
|
{
|
|
_err("CAN%d TJA1153: Failed to write frame_config4\n", bus);
|
|
close(sock);
|
|
return -1;
|
|
}
|
|
|
|
if (write(sock, &frame_config5, CAN_MTU) != CAN_MTU)
|
|
{
|
|
_err("CAN%d TJA1153: Failed to write frame_config5\n", bus);
|
|
close(sock);
|
|
return -1;
|
|
}
|
|
|
|
/* Sleep for 100 ms to ensure that CAN frames have been transmitted */
|
|
|
|
nxsig_usleep(100 * 1000);
|
|
|
|
/* TJA1153 must be taken out of STB mode */
|
|
|
|
s32k3xx_gpiowrite(pin_can_stb_n, true); /* Inverted, so TJA1153 comes out of STANDBY */
|
|
|
|
/* Bring down the interface */
|
|
|
|
ifr.ifr_flags = IFF_DOWN;
|
|
ret = ioctl(sock, SIOCSIFFLAGS, (unsigned long)&ifr);
|
|
if (ret < 0)
|
|
{
|
|
_err("CAN%d TJA1153: ioctl failed (can't set interface flags)\n", bus);
|
|
close(sock);
|
|
return -1;
|
|
}
|
|
|
|
close(sock);
|
|
_info("CAN%d TJA1153 configuration successful\n", bus);
|
|
return 0;
|
|
}
|
|
|
|
#endif /* CONFIG_S32K3XX_TJA1153 */
|