322 lines
9.0 KiB
C
322 lines
9.0 KiB
C
|
/*
|
||
|
* 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
|
||
|
};
|
||
|
|