Working fork to test F0 application

Dependents:   ppCANOpen_Example

Fork of CANnucleo by Zoltan Hudak

Revision:
0:e29bc8e0dddd
Child:
1:eb04f7f0478d
diff -r 000000000000 -r e29bc8e0dddd can_api.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/can_api.c	Sun Jul 19 09:06:26 2015 +0000
@@ -0,0 +1,353 @@
+/*
+ can_api.c for STMicroelectronics mbed boards equipped with Controller Area Network interface:
+
+ NUCLEO-F070RB
+ NUCLEO-F072RB
+ NUCLEO-F103RB
+ NUCLEO-F302R8
+ NUCLEO-F334R8
+ NUCLEO-F303RE
+ NUCLEO-F091RC
+ DISCO-F334C8
+ DISCO-F746NG
+
+ Copyright (c) 2015 Zoltan Hudak <hudakz@inbox.com>
+ All rights reserved.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+  */
+#include "stm32f1xx_hal.h"
+#include "can_api.h"
+#include "can_helper.h"
+#include "pinmap.h"
+
+extern void (*rxCompleteCallback) (void);
+extern CAN_HandleTypeDef    _canHandle;
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void can_init(can_t* obj, PinName rd, PinName td) {
+    initCAN(obj, rd, td);
+    can_filter(obj, 0, 0, CANAny, 0);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void can_free(can_t* obj) {
+    HAL_CAN_MspDeInit(obj);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+int can_frequency(can_t* obj, int hz) {
+
+    /* Disable the NVIC for CAN reception */
+
+    HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
+
+#if defined(TARGET_NUCLEO_F103RB) || \
+    defined(TARGET_NUCLEO_F302R8) || \
+    defined(TARGET_NUCLEO_F334R8) || \
+    defined(TARGET_NUCLEO_F303RE) || \
+    defined(TARGET_DISCO_F334C8)
+    // APB1 pheripheral clock = 36000000Hz
+
+    switch(hz) {
+    case 1000000:
+        // 1000kbps bit rate
+        _canHandle.Init.Prescaler = 3;      // number of time quanta = 36000000/3/1000000 = 12
+        _canHandle.Init.SJW = CAN_SJW_1TQ;
+        _canHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
+        _canHandle.Init.BS2 = CAN_BS2_3TQ;
+        break;
+
+    case 500000:
+        // 500kbps bit rate
+        _canHandle.Init.Prescaler = 6;      // number of time quanta = 36000000/6/500000 = 12
+        _canHandle.Init.SJW = CAN_SJW_1TQ;
+        _canHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
+        _canHandle.Init.BS2 = CAN_BS2_3TQ;
+        break;
+
+    case 250000:
+        // 250kbps
+        _canHandle.Init.Prescaler = 9;      // number of time quanta = 36000000/9/250000 = 16
+        _canHandle.Init.SJW = CAN_SJW_1TQ;
+        _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
+        _canHandle.Init.BS2 = CAN_BS2_4TQ;
+        break;
+
+    case 125000:
+        // 125kbps
+        _canHandle.Init.Prescaler = 18;     // number of time quanta = 36000000/18/125000 = 16
+        _canHandle.Init.SJW = CAN_SJW_1TQ;
+        _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
+        _canHandle.Init.BS2 = CAN_BS2_4TQ;
+        break;
+
+    default:
+        // 125kbps (default)
+        printf("Unknown frequency specified!\r\n");
+        printf("Using default 125kbps\r\n");
+        _canHandle.Init.Prescaler = 18;     // number of time quanta = 36000000/18/125000 = 16
+        _canHandle.Init.SJW = CAN_SJW_1TQ;
+        _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
+        _canHandle.Init.BS2 = CAN_BS2_4TQ;
+    }
+
+#elif defined(TARGET_NUCLEO_F070RB) || \
+      defined(TARGET_NUCLEO_F072RB) || \ 
+      defined(TARGET_NUCLEO_F091RC)
+    // APB1 pheripheral clock = 48000000Hz
+
+    switch(hz) {
+    case 1000000:
+        // 1000kbps bit rate
+        _canHandle.Init.Prescaler = 4;      // number of time quanta = 48000000/4/1000000 = 12
+        _canHandle.Init.SJW = CAN_SJW_1TQ;
+        _canHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
+        _canHandle.Init.BS2 = CAN_BS2_3TQ;
+        break;
+
+    case 500000:
+        // 500kbps bit rate
+        _canHandle.Init.Prescaler = 8;      // number of time quanta = 48000000/8/500000 = 12
+        _canHandle.Init.SJW = CAN_SJW_1TQ;
+        _canHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
+        _canHandle.Init.BS2 = CAN_BS2_3TQ;
+        break;
+
+    case 250000:
+        // 250kbps
+        _canHandle.Init.Prescaler = 12;     // number of time quanta = 48000000/12/250000 = 16
+        _canHandle.Init.SJW = CAN_SJW_1TQ;
+        _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
+        _canHandle.Init.BS2 = CAN_BS2_4TQ;
+        break;
+
+    case 125000:
+        // 125kbps
+        _canHandle.Init.Prescaler = 24;     // number of time quanta = 48000000/24/125000 = 16
+        _canHandle.Init.SJW = CAN_SJW_1TQ;
+        _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
+        _canHandle.Init.BS2 = CAN_BS2_4TQ;
+        break;
+
+    default:
+        // 125kbps (default)
+        printf("Unknown frequency specified!\r\n");
+        printf("Using default 125kbps\r\n");
+        _canHandle.Init.Prescaler = 24;     // number of time quanta = 48000000/24/125000 = 16
+        _canHandle.Init.SJW = CAN_SJW_1TQ;
+        _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
+        _canHandle.Init.BS2 = CAN_BS2_4TQ;
+    }
+#endif
+    HAL_CAN_Init(&_canHandle);
+    HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void can_irq_init(can_t* obj, can_irq_handler handler, uint32_t id) {
+    if(HAL_CAN_Receive_IT(&_canHandle, CAN_FIFO0) != HAL_OK) {
+        printf("CAN reception initialization error\r\n");
+    }
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void can_irq_free(can_t* obj) {
+    rxCompleteCallback = NULL;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+//void can_irq_set(can_t* obj, CanIrqType irq, uint32_t enable)
+//{
+
+//}
+void can_irq_set(void (*fptr) (void)) {
+    rxCompleteCallback = fptr;
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+int can_write(can_t* obj, CAN_Message msg, int cc) {
+    int i = 0;
+
+    if(msg.format == CANStandard) {
+        _canHandle.pTxMsg->StdId = msg.id;
+        _canHandle.pTxMsg->ExtId = 0x00;
+    }
+    else {
+        _canHandle.pTxMsg->StdId = 0x00;
+        _canHandle.pTxMsg->ExtId = msg.id;
+    }
+
+    _canHandle.pTxMsg->RTR = msg.type == CANData ? CAN_RTR_DATA : CAN_RTR_REMOTE;
+    _canHandle.pTxMsg->IDE = msg.format == CANStandard ? CAN_ID_STD : CAN_ID_EXT;
+    _canHandle.pTxMsg->DLC = msg.len;
+
+    for(i = 0; i < msg.len; i++)
+        _canHandle.pTxMsg->Data[i] = msg.data[i];
+
+    if(HAL_CAN_Transmit(&_canHandle, 10) != HAL_OK) {
+        printf("Transmission error\r\n");
+    }
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+int can_read(can_t* obj, CAN_Message* msg, int handle) {
+    int i = 0;
+
+    msg->id = _canHandle.pRxMsg->IDE == CAN_ID_STD ? _canHandle.pRxMsg->StdId : _canHandle.pRxMsg->ExtId;
+    msg->type = _canHandle.pRxMsg->RTR == CAN_RTR_DATA ? CANData : CANRemote;
+    msg->format = _canHandle.pRxMsg->IDE == CAN_ID_STD ? CANStandard : CANExtended;
+    msg->len = _canHandle.pRxMsg->DLC;
+    for(i = 0; i < msg->len; i++)
+        msg->data[i] = _canHandle.pRxMsg->Data[i];
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+int can_mode(can_t* obj, CanMode mode) {
+    switch(mode) {
+    case MODE_RESET:
+        return HAL_ERROR;
+
+    case MODE_NORMAL:
+        _canHandle.Init.Mode = CAN_MODE_NORMAL;
+        break;
+
+    case MODE_SILENT:
+        _canHandle.Init.Mode = CAN_MODE_SILENT;
+        break;
+
+    case MODE_TEST_GLOBAL:
+        _canHandle.Init.Mode = CAN_MODE_LOOPBACK;
+        break;
+
+    case MODE_TEST_LOCAL:
+        _canHandle.Init.Mode = CAN_MODE_LOOPBACK;
+        break;
+
+    case MODE_TEST_SILENT:
+        _canHandle.Init.Mode = CAN_MODE_SILENT_LOOPBACK;
+        break;
+    }
+
+    _canHandle.Init.Mode = CAN_MODE_NORMAL;
+    return HAL_CAN_Init(&_canHandle);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+int can_filter(can_t* obj, uint32_t id, uint32_t mask, CANFormat format /*=CANAny*/, int32_t handle /*=0*/ ) {
+    CAN_FilterConfTypeDef   sFilterConfig;
+
+    sFilterConfig.FilterNumber = handle;
+    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
+    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
+    sFilterConfig.FilterIdHigh = (((id) >> 16) & 0xFFFF);
+    sFilterConfig.FilterIdLow = ((id) & 0xFFFF);
+    sFilterConfig.FilterMaskIdHigh = (((mask) >> 16) & 0xFFFF);
+    sFilterConfig.FilterMaskIdLow = ((mask) & 0xFFFF);
+    sFilterConfig.FilterFIFOAssignment = 0;
+    sFilterConfig.FilterActivation = ENABLE;
+    sFilterConfig.BankNumber = 14;
+    HAL_CAN_ConfigFilter(&_canHandle, &sFilterConfig);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void can_reset(can_t* obj) {
+    __HAL_CAN_RESET_HANDLE_STATE(&_canHandle);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+unsigned char can_rderror(can_t* obj) {
+    return HAL_CAN_GetError(&_canHandle);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+unsigned char can_tderror(can_t* obj) {
+    return HAL_CAN_GetError(&_canHandle);
+}
+
+/**
+ * @brief
+ * @note
+ * @param
+ * @retval
+ */
+void can_monitor(can_t* obj, int silent) {
+
+    // not implemented
+}