pub

Fork of CANnucleo by Zoltan Hudak

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers cannucleo_api.c Source File

cannucleo_api.c

00001 /*
00002   ******************************************************************************
00003   * @file    can_api.c
00004   * @author  Zoltan Hudak
00005   * @version 
00006   * @date    04-August-2015
00007   * @brief   CAN api for NUCLEO-F103RB platform
00008   ******************************************************************************
00009   * @attention
00010   *
00011   * <h2><center>&copy; COPYRIGHT(c) 2015 Zoltan Hudak <hudakz@outlook.com>
00012   *
00013   * All rights reserved.
00014 
00015  This program is free software: you can redistribute it and/or modify
00016  it under the terms of the GNU General Public License as published by
00017  the Free Software Foundation, either version 3 of the License, or
00018  (at your option) any later version.
00019 
00020  This program is distributed in the hope that it will be useful,
00021  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  GNU General Public License for more details.
00024 
00025  You should have received a copy of the GNU General Public License
00026  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00027   */
00028 #include "cannucleo_api.h"
00029 #include "can_helper.h"
00030 #include "pinmap.h"
00031 
00032 extern void (*rxCompleteCallback)(void);
00033 extern CAN_HandleTypeDef _canHandle;
00034 
00035 static uint32_t          irq_id = 0;
00036 static can_irq_handler   irq_handler = 0;
00037 
00038 /**
00039  * @brief
00040  * @note
00041  * @param
00042  * @retval
00043  */
00044 void can_init(PinName rd, PinName td, FunctionalState abom) {
00045     initCAN(rd, td, abom);
00046     can_filter(0, 0, CANAny, 0);
00047 }
00048 
00049 /**
00050  * @brief
00051  * @note
00052  * @param
00053  * @retval
00054  */
00055 void can_free(void) {
00056     HAL_CAN_MspDeInit(&_canHandle);
00057 }
00058 
00059 /**
00060  * @brief
00061  * @note
00062  * @param
00063  * @retval
00064  */
00065 int can_frequency(int hz) {
00066     HAL_NVIC_DisableIRQ(CAN_IRQ);
00067     
00068 #if defined(TARGET_NUCLEO_F072RB) || \
00069     defined(TARGET_NUCLEO_F091RC)
00070     
00071         // APB1 peripheral clock = 48000000Hz
00072         
00073     switch(hz) {
00074     case 1000000:
00075         // 1000kbps bit rate
00076         _canHandle.Init.Prescaler = 4;      // number of time quanta = 48000000/4/1000000 = 12
00077         _canHandle.Init.SJW = CAN_SJW_1TQ;
00078         _canHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
00079         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00080         break;
00081  
00082     case 500000:
00083         // 500kbps bit rate
00084         _canHandle.Init.Prescaler = 8;      // number of time quanta = 48000000/8/500000 = 12
00085         _canHandle.Init.SJW = CAN_SJW_1TQ;
00086         _canHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
00087         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00088         break;
00089  
00090     case 250000:
00091         // 250kbps
00092         _canHandle.Init.Prescaler = 12;     // number of time quanta = 48000000/12/250000 = 16
00093         _canHandle.Init.SJW = CAN_SJW_1TQ;
00094         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00095         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00096         break;
00097  
00098     case 125000:
00099         // 125kbps
00100         _canHandle.Init.Prescaler = 24;     // number of time quanta = 48000000/24/125000 = 16
00101         _canHandle.Init.SJW = CAN_SJW_1TQ;
00102         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00103         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00104         break;
00105  
00106     default:
00107         // 125kbps (default)
00108         _canHandle.Init.Prescaler = 24;     // number of time quanta = 48000000/24/125000 = 16
00109         _canHandle.Init.SJW = CAN_SJW_1TQ;
00110         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00111         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00112     }
00113 
00114 #elif defined(TARGET_NUCLEO_F103RB) || \
00115     defined(TARGET_NUCLEO_F303RE) || \
00116     defined(TARGET_NUCLEO_F334R8) || \
00117     defined(TARGET_DISCO_F334C8)
00118     
00119     // APB1 peripheral clock = 36000000Hz
00120 
00121     switch(hz) {
00122     case 1000000:
00123         // 1000kbps bit rate
00124         _canHandle.Init.Prescaler = 3;      // number of time quanta = 36000000/3/1000000 = 12
00125         _canHandle.Init.SJW = CAN_SJW_1TQ;
00126         _canHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
00127         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00128         break;
00129 
00130     case 500000:
00131         // 500kbps bit rate
00132         _canHandle.Init.Prescaler = 6;      // number of time quanta = 36000000/6/500000 = 12
00133         _canHandle.Init.SJW = CAN_SJW_1TQ;
00134         _canHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
00135         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00136         break;
00137 
00138     case 250000:
00139         // 250kbps
00140         _canHandle.Init.Prescaler = 9;      // number of time quanta = 36000000/9/250000 = 16
00141         _canHandle.Init.SJW = CAN_SJW_1TQ;
00142         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00143         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00144         break;
00145 
00146     case 125000:
00147         // 125kbps
00148         _canHandle.Init.Prescaler = 18;     // number of time quanta = 36000000/18/125000 = 16
00149         _canHandle.Init.SJW = CAN_SJW_1TQ;
00150         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00151         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00152         break;
00153 
00154     default:
00155         // 125kbps (default)
00156 #if DEBUG
00157         printf("Unknown frequency specified!\r\n");
00158         printf("Using default 125kbps\r\n");
00159 #endif
00160         _canHandle.Init.Prescaler = 18;     // number of time quanta = 36000000/18/125000 = 16
00161         _canHandle.Init.SJW = CAN_SJW_1TQ;
00162         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00163         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00164     }
00165     
00166 #elif defined(TARGET_NUCLEO_F303K8)
00167     
00168     // APB1 peripheral clock = 32000000Hz
00169 
00170     switch(hz) {
00171     case 1000000:
00172         // 1000kbps bit rate
00173         _canHandle.Init.Prescaler = 2;      // number of time quanta = 32000000/2/1000000 = 16
00174         _canHandle.Init.SJW = CAN_SJW_1TQ;
00175         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00176         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00177         break;
00178 
00179     case 500000:
00180         // 500kbps bit rate
00181         _canHandle.Init.Prescaler = 4;      // number of time quanta = 32000000/4/500000 = 16
00182         _canHandle.Init.SJW = CAN_SJW_1TQ;
00183         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00184         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00185         break;
00186 
00187     case 250000:
00188         // 250kbps
00189         _canHandle.Init.Prescaler = 8;      // number of time quanta = 32000000/8/250000 = 16
00190         _canHandle.Init.SJW = CAN_SJW_1TQ;
00191         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00192         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00193         break;
00194 
00195     case 125000:
00196         // 125kbps
00197         _canHandle.Init.Prescaler = 16;     // number of time quanta = 32000000/16/125000 = 16
00198         _canHandle.Init.SJW = CAN_SJW_1TQ;
00199         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00200         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00201         break;
00202 
00203     default:
00204         // 125kbps (default)
00205 #if DEBUG
00206         printf("Unknown frequency specified!\r\n");
00207         printf("Using default 125kbps\r\n");
00208 #endif
00209         _canHandle.Init.Prescaler = 16;     // number of time quanta = 32000000/16/125000 = 16
00210         _canHandle.Init.SJW = CAN_SJW_1TQ;
00211         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00212         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00213     }
00214 
00215 #elif defined(TARGET_NUCLEO_F446RE)
00216     
00217     // APB1 peripheral clock = 45000000Hz
00218 
00219     switch(hz) {
00220     case 1000000:
00221         // 1000kbps bit rate
00222         _canHandle.Init.Prescaler = 5;      // number of time quanta = 45000000/5/1000000 = 9
00223         _canHandle.Init.SJW = CAN_SJW_1TQ;
00224         _canHandle.Init.BS1 = CAN_BS1_6TQ;  // sample point at: (1 + 6) / 9 * 100 = 77.78%
00225         _canHandle.Init.BS2 = CAN_BS2_2TQ;
00226         break;
00227 
00228     case 500000:
00229         // 500kbps bit rate
00230         _canHandle.Init.Prescaler = 10;      // number of time quanta = 45000000/10/500000 = 9
00231         _canHandle.Init.SJW = CAN_SJW_1TQ;
00232         _canHandle.Init.BS1 = CAN_BS1_6TQ;  // sample point at: (1 + 6) / 9 * 100 = 77.78%
00233         _canHandle.Init.BS2 = CAN_BS2_2TQ;
00234         break;
00235 
00236     case 250000:
00237         // 250kbps
00238         _canHandle.Init.Prescaler = 15;      // number of time quanta = 45000000/15/250000 = 12
00239         _canHandle.Init.SJW = CAN_SJW_1TQ;
00240         _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
00241         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00242         break;
00243 
00244     case 125000:
00245         // 125kbps
00246         _canHandle.Init.Prescaler = 30;     // number of time quanta = 45000000/30/125000 = 12
00247         _canHandle.Init.SJW = CAN_SJW_1TQ;
00248         _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
00249         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00250         break;
00251 
00252     default:
00253         // 125kbps (default)
00254 #if DEBUG
00255         printf("Unknown frequency specified!\r\n");
00256         printf("Using default 125kbps\r\n");
00257 #endif
00258         _canHandle.Init.Prescaler = 30;     // number of time quanta = 45000000/30/125000 = 12
00259         _canHandle.Init.SJW = CAN_SJW_1TQ;
00260         _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
00261         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00262     }
00263     
00264 #endif
00265 
00266     HAL_CAN_Init(&_canHandle);
00267     HAL_NVIC_EnableIRQ(CAN_IRQ);
00268    
00269     return 1;
00270 }
00271 
00272 /**
00273  * @brief
00274  * @note
00275  * @param
00276  * @retval
00277  */
00278 void can_callback(void) {
00279     irq_handler(irq_id, IRQ_RX);
00280 }
00281 
00282 /**
00283  * @brief
00284  * @note
00285  * @param
00286  * @retval
00287  */
00288 void can_irq_init(uint32_t id, can_irq_handler handler) {
00289     irq_id = id;
00290     irq_handler = handler;
00291     rxCompleteCallback = can_callback;
00292 
00293     if(HAL_CAN_Receive_IT(&_canHandle, CAN_FIFO0) != HAL_OK) {
00294 #ifdef DEBUG
00295         printf("CAN reception initialization error\r\n");
00296 #endif
00297     }
00298 }
00299 
00300 /**
00301  * @brief
00302  * @note
00303  * @param
00304  * @retval
00305  */
00306 void can_irq_free(void) {
00307     rxCompleteCallback = 0;
00308 }   
00309 
00310 /**
00311  * @brief
00312  * @note
00313  * @param
00314  * @retval
00315  */
00316 int can_write(CAN_Message msg, int cc) {
00317     int i = 0;
00318 
00319     if(msg.format == CANStandard) {
00320         _canHandle.pTxMsg->StdId = msg.id;
00321         _canHandle.pTxMsg->ExtId = 0x00;
00322     }
00323     else {
00324         _canHandle.pTxMsg->StdId = 0x00;
00325         _canHandle.pTxMsg->ExtId = msg.id;
00326     }
00327 
00328     _canHandle.pTxMsg->RTR = msg.type == CANData ? CAN_RTR_DATA : CAN_RTR_REMOTE;
00329     _canHandle.pTxMsg->IDE = msg.format == CANStandard ? CAN_ID_STD : CAN_ID_EXT;
00330     _canHandle.pTxMsg->DLC = msg.len;
00331 
00332     for(i = 0; i < msg.len; i++)
00333         _canHandle.pTxMsg->Data[i] = msg.data[i];
00334 
00335     if(HAL_CAN_Transmit(&_canHandle, 10) != HAL_OK) {
00336 #ifdef DEBUG
00337         printf("Transmission error\r\n");
00338 #endif
00339         return 0;
00340     }
00341     else
00342         return 1;
00343 }
00344 
00345 /**
00346  * @brief
00347  * @note
00348  * @param
00349  * @retval
00350  */
00351 int can_read(CAN_Message* msg, int handle) {
00352     int i;
00353     msg->id = _canHandle.pRxMsg->IDE == CAN_ID_STD ? _canHandle.pRxMsg->StdId : _canHandle.pRxMsg->ExtId;
00354     msg->type = _canHandle.pRxMsg->RTR == CAN_RTR_DATA ? CANData : CANRemote;
00355     msg->format = _canHandle.pRxMsg->IDE == CAN_ID_STD ? CANStandard : CANExtended;
00356     msg->len = _canHandle.pRxMsg->DLC;
00357     for(i = 0; i < msg->len; i++)
00358         msg->data[i] = _canHandle.pRxMsg->Data[i];
00359         
00360     return msg->len;
00361 }
00362 
00363 /**
00364  * @brief
00365  * @note
00366  * @param
00367  * @retval
00368  */
00369 int can_mode(CanMode mode) {
00370     switch(mode) {
00371     case MODE_RESET:
00372         return HAL_ERROR;
00373 
00374     case MODE_NORMAL:
00375         _canHandle.Init.Mode = CAN_MODE_NORMAL;
00376         break;
00377 
00378     case MODE_SILENT:
00379         _canHandle.Init.Mode = CAN_MODE_SILENT;
00380         break;
00381 
00382     case MODE_TEST_GLOBAL:
00383         _canHandle.Init.Mode = CAN_MODE_LOOPBACK;
00384         break;
00385 
00386     case MODE_TEST_LOCAL:
00387         _canHandle.Init.Mode = CAN_MODE_LOOPBACK;
00388         break;
00389 
00390     case MODE_TEST_SILENT:
00391         _canHandle.Init.Mode = CAN_MODE_SILENT_LOOPBACK;
00392         break;
00393     }
00394 
00395     return HAL_CAN_Init(&_canHandle);
00396 }
00397 
00398 /**
00399  * @brief
00400  * @note
00401  * @param
00402  * @retval
00403  */
00404 int can_filter(uint32_t id, uint32_t mask, CANFormat format /*=CANAny*/, int32_t handle /*=0*/ ) {
00405     CAN_FilterConfTypeDef   sFilterConfig;
00406 
00407     sFilterConfig.FilterNumber = handle;    // Specifies the filter number (must be a number between 0 and 13 at 32-bit filter scale)
00408     sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
00409     sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
00410     sFilterConfig.FilterIdHigh = (((id) >> 16) & 0xFFFF);
00411     sFilterConfig.FilterIdLow = ((id) & 0xFFFF);
00412     sFilterConfig.FilterMaskIdHigh = (((mask) >> 16) & 0xFFFF);
00413     sFilterConfig.FilterMaskIdLow = ((mask) & 0xFFFF);
00414     sFilterConfig.FilterFIFOAssignment = 0;
00415     sFilterConfig.FilterActivation = ENABLE;
00416     sFilterConfig.BankNumber = 0;           // Selects the start bank filter
00417     return HAL_CAN_ConfigFilter(&_canHandle, &sFilterConfig);
00418 }
00419 
00420 /**
00421  * @brief
00422  * @note
00423  * @param
00424  * @retval
00425  */
00426 void can_reset(void) {
00427     __HAL_CAN_RESET_HANDLE_STATE(&_canHandle);
00428 }
00429 
00430 /**
00431  * @brief
00432  * @note
00433  * @param
00434  * @retval
00435  */
00436 unsigned char can_rderror(void) {
00437     return HAL_CAN_GetError(&_canHandle);
00438 }
00439 
00440 /**
00441  * @brief
00442  * @note
00443  * @param
00444  * @retval
00445  */
00446 unsigned char can_tderror(void) {
00447     return HAL_CAN_GetError(&_canHandle);
00448 }
00449 
00450 /**
00451  * @brief
00452  * @note
00453  * @param
00454  * @retval
00455  */
00456 void can_monitor(int silent) {
00457 
00458     // not implemented
00459 }
00460 
00461 
00462 
00463 
00464 
00465 
00466 
00467