/* * Copyright (c) 2015-2018 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Licensed 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 * * 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. */ #include "Driver_CAN.h" #define ARM_CAN_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0) // CAN driver version // Driver Version static const ARM_DRIVER_VERSION can_driver_version = { ARM_CAN_API_VERSION, ARM_CAN_DRV_VERSION }; // Driver Capabilities static const ARM_CAN_CAPABILITIES can_driver_capabilities = { 32U, // Number of CAN Objects available 1U, // Supports reentrant calls to ARM_CAN_MessageSend, ARM_CAN_MessageRead, ARM_CAN_ObjectConfigure and abort message sending used by ARM_CAN_Control. 0U, // Does not support CAN with Flexible Data-rate mode (CAN_FD) 0U, // Does not support restricted operation mode 1U, // Supports bus monitoring mode 1U, // Supports internal loopback mode 1U, // Supports external loopback mode }; // Object Capabilities static const ARM_CAN_OBJ_CAPABILITIES can_object_capabilities = { 1U, // Object supports transmission 1U, // Object supports reception 0U, // Object does not support RTR reception and automatic Data transmission 0U, // Object does not support RTR transmission and automatic Data reception 1U, // Object allows assignment of multiple filters to it 1U, // Object supports exact identifier filtering 0U, // Object does not support range identifier filtering 1U, // Object supports mask identifier filtering 3U // Object can buffer 3 messages }; static uint8_t can_driver_powered = 0U; static uint8_t can_driver_initialized = 0U; static ARM_CAN_SignalUnitEvent_t CAN_SignalUnitEvent = NULL; static ARM_CAN_SignalObjectEvent_t CAN_SignalObjectEvent = NULL; // // Functions // static ARM_DRIVER_VERSION CAN_GetVersion (void) { // Return driver version return can_driver_version; } static ARM_CAN_CAPABILITIES CAN_GetCapabilities (void) { // Return driver capabilities return can_driver_capabilities; } static int32_t CAN_Initialize (ARM_CAN_SignalUnitEvent_t cb_unit_event, ARM_CAN_SignalObjectEvent_t cb_object_event) { if (can_driver_initialized != 0U) { return ARM_DRIVER_OK; } CAN_SignalUnitEvent = cb_unit_event; CAN_SignalObjectEvent = cb_object_event; // Add code for pin, memory, RTX objects initialization // .. can_driver_initialized = 1U; return ARM_DRIVER_OK; } static int32_t CAN_Uninitialize (void) { // Add code for pin, memory, RTX objects de-initialization // .. can_driver_initialized = 0U; return ARM_DRIVER_OK; } static int32_t CAN_PowerControl (ARM_POWER_STATE state) { switch (state) { case ARM_POWER_OFF: can_driver_powered = 0U; // Add code to disable interrupts and put peripheral into reset mode, // and if possible disable clock // .. case ARM_POWER_FULL: if (can_driver_initialized == 0U) { return ARM_DRIVER_ERROR; } if (can_driver_powered != 0U) { return ARM_DRIVER_OK; } // Add code to enable clocks, reset variables enable interrupts // and put peripheral into operational // .. can_driver_powered = 1U; break; default: // Other states are not supported return ARM_DRIVER_ERROR_UNSUPPORTED; } return ARM_DRIVER_OK; } uint32_t CAN_GetClock (void) { // Add code to return peripheral clock frequency // .. } static int32_t CAN_SetBitrate (ARM_CAN_BITRATE_SELECT select, uint32_t bitrate, uint32_t bit_segments) { if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; } // Add code to setup peripheral parameters to generate specified bitrate // with specified bit segments // .. return ARM_DRIVER_OK; } static int32_t CAN_SetMode (ARM_CAN_MODE mode) { if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; } switch (mode) { case ARM_CAN_MODE_INITIALIZATION: // Add code to put peripheral into initialization mode // .. break; case ARM_CAN_MODE_NORMAL: // Add code to put peripheral into normal operation mode // .. break; case ARM_CAN_MODE_RESTRICTED: // Add code to put peripheral into restricted operation mode // .. break; case ARM_CAN_MODE_MONITOR: // Add code to put peripheral into bus monitoring mode // .. break; case ARM_CAN_MODE_LOOPBACK_INTERNAL: // Add code to put peripheral into internal loopback mode // .. break; case ARM_CAN_MODE_LOOPBACK_EXTERNAL: // Add code to put peripheral into external loopback mode // .. break; default: // Handle unknown mode code return ARM_DRIVER_ERROR_UNSUPPORTED; } return ARM_DRIVER_OK; } ARM_CAN_OBJ_CAPABILITIES CAN_ObjectGetCapabilities (uint32_t obj_idx) { // Return object capabilities return can_object_capabilities; } static int32_t CAN_ObjectSetFilter (uint32_t obj_idx, ARM_CAN_FILTER_OPERATION operation, uint32_t id, uint32_t arg) { if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; } switch (operation) { case ARM_CAN_FILTER_ID_EXACT_ADD: // Add code to setup peripheral to receive messages with specified exact ID break; case ARM_CAN_FILTER_ID_MASKABLE_ADD: // Add code to setup peripheral to receive messages with specified maskable ID break; case ARM_CAN_FILTER_ID_RANGE_ADD: // Add code to setup peripheral to receive messages within specified range of IDs break; case ARM_CAN_FILTER_ID_EXACT_REMOVE: // Add code to remove specified exact ID from being received by peripheral break; case ARM_CAN_FILTER_ID_MASKABLE_REMOVE: // Add code to remove specified maskable ID from being received by peripheral break; case ARM_CAN_FILTER_ID_RANGE_REMOVE: // Add code to remove specified range of IDs from being received by peripheral break; default: // Handle unknown operation code return ARM_DRIVER_ERROR_UNSUPPORTED; } return ARM_DRIVER_OK; } static int32_t CAN_ObjectConfigure (uint32_t obj_idx, ARM_CAN_OBJ_CONFIG obj_cfg) { if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; } switch (obj_cfg) { case ARM_CAN_OBJ_INACTIVE: // Deactivate object // .. break; case ARM_CAN_OBJ_RX_RTR_TX_DATA: // Setup object to automatically return data when RTR with it's ID is received // .. break; case ARM_CAN_OBJ_TX_RTR_RX_DATA: // Setup object to send RTR and receive data response // .. break; case ARM_CAN_OBJ_TX: // Setup object to be used for sending messages // .. break; case ARM_CAN_OBJ_RX: // Setup object to be used for receiving messages // .. break; default: // Handle unknown object configuration code return ARM_DRIVER_ERROR_UNSUPPORTED; } return ARM_DRIVER_OK; } static int32_t CAN_MessageSend (uint32_t obj_idx, ARM_CAN_MSG_INFO *msg_info, const uint8_t *data, uint8_t size) { if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; } // Add code to send requested message // .. return ((int32_t)size); } static int32_t CAN_MessageRead (uint32_t obj_idx, ARM_CAN_MSG_INFO *msg_info, uint8_t *data, uint8_t size) { if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; } // Add code to read previously received message // (reception was started when object was configured for reception) // .. return ((int32_t)size); } static int32_t CAN_Control (uint32_t control, uint32_t arg) { if (can_driver_powered == 0U) { return ARM_DRIVER_ERROR; } switch (control & ARM_CAN_CONTROL_Msk) { case ARM_CAN_ABORT_MESSAGE_SEND: // Add code to abort message pending to be sent // .. break; case ARM_CAN_SET_FD_MODE: // Add code to enable Flexible Data-rate mode // .. break; case ARM_CAN_SET_TRANSCEIVER_DELAY: // Add code to set transceiver delay // .. break; default: // Handle unknown control code return ARM_DRIVER_ERROR_UNSUPPORTED; } return ARM_DRIVER_OK; } static ARM_CAN_STATUS CAN_GetStatus (void) { // Add code to return device bus and error status // .. } // IRQ handlers // Add interrupt routines to handle transmission, reception, error and status interrupts // .. // CAN driver functions structure ARM_DRIVER_CAN Driver_CAN = { CAN_GetVersion, CAN_GetCapabilities, CAN_Initialize, CAN_Uninitialize, CAN_PowerControl, CAN_GetClock, CAN_SetBitrate, CAN_SetMode, CAN_ObjectGetCapabilities, CAN_ObjectSetFilter, CAN_ObjectConfigure, CAN_MessageSend, CAN_MessageRead, CAN_Control, CAN_GetStatus };