Working fork to test F0 application

Dependents:   ppCANOpen_Example

Fork of CANnucleo by Zoltan Hudak

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers can_api.c Source File

can_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@inbox.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 "can_api.h"
00029 #include "can_helper.h"
00030 #include "pinmap.h"
00031 
00032 extern void (*rxCompleteCallback) (void);
00033 extern CAN_HandleTypeDef    _canHandle;
00034 
00035 /**
00036  * @brief
00037  * @note
00038  * @param
00039  * @retval
00040  */
00041 void can_init(can_t* obj, PinName rd, PinName td, FunctionalState abom) {
00042     initCAN(obj, rd, td, abom);
00043     can_filter(obj, 0, 0, CANAny, 0);
00044 }
00045 
00046 /**
00047  * @brief
00048  * @note
00049  * @param
00050  * @retval
00051  */
00052 void can_free(can_t* obj) {
00053     HAL_CAN_MspDeInit(&_canHandle);
00054 }
00055 
00056 /**
00057  * @brief
00058  * @note
00059  * @param
00060  * @retval
00061  */
00062 int can_frequency(can_t* obj, int hz) {
00063     HAL_NVIC_DisableIRQ(CAN_IRQ);
00064     
00065 #if defined(TARGET_NUCLEO_F072RB) || \
00066     defined(TARGET_NUCLEO_F091RC)
00067     
00068         // APB1 peripheral clock = 48000000Hz
00069         
00070     switch(hz) {
00071     case 1000000:
00072         // 1000kbps bit rate
00073         _canHandle.Init.Prescaler = 4;      // number of time quanta = 48000000/4/1000000 = 12
00074         _canHandle.Init.SJW = CAN_SJW_1TQ;
00075         _canHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
00076         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00077         break;
00078  
00079     case 500000:
00080         // 500kbps bit rate
00081         _canHandle.Init.Prescaler = 8;      // number of time quanta = 48000000/8/500000 = 12
00082         _canHandle.Init.SJW = CAN_SJW_1TQ;
00083         _canHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
00084         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00085         break;
00086  
00087     case 250000:
00088         // 250kbps
00089         _canHandle.Init.Prescaler = 12;     // number of time quanta = 48000000/12/250000 = 16
00090         _canHandle.Init.SJW = CAN_SJW_1TQ;
00091         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00092         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00093         break;
00094  
00095     case 125000:
00096         // 125kbps
00097         _canHandle.Init.Prescaler = 24;     // number of time quanta = 48000000/24/125000 = 16
00098         _canHandle.Init.SJW = CAN_SJW_1TQ;
00099         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00100         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00101         break;
00102  
00103     default:
00104         // 125kbps (default)
00105         _canHandle.Init.Prescaler = 24;     // number of time quanta = 48000000/24/125000 = 16
00106         _canHandle.Init.SJW = CAN_SJW_1TQ;
00107         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00108         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00109     }
00110 
00111 #elif defined(TARGET_NUCLEO_F103RB) || \
00112     defined(TARGET_NUCLEO_F303RE) || \
00113     defined(TARGET_NUCLEO_F303K8) || \
00114     defined(TARGET_NUCLEO_F334R8) || \
00115     defined(TARGET_DISCO_F334C8)
00116     
00117     // APB1 peripheral clock = 36000000Hz
00118 
00119     switch(hz) {
00120     case 1000000:
00121         // 1000kbps bit rate
00122         _canHandle.Init.Prescaler = 3;      // number of time quanta = 36000000/3/1000000 = 12
00123         _canHandle.Init.SJW = CAN_SJW_1TQ;
00124         _canHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
00125         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00126         break;
00127 
00128     case 500000:
00129         // 500kbps bit rate
00130         _canHandle.Init.Prescaler = 6;      // number of time quanta = 36000000/6/500000 = 12
00131         _canHandle.Init.SJW = CAN_SJW_1TQ;
00132         _canHandle.Init.BS1 = CAN_BS1_8TQ;  // sample point at: (1 + 8) / 12 * 100 = 75%
00133         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00134         break;
00135 
00136     case 250000:
00137         // 250kbps
00138         _canHandle.Init.Prescaler = 9;      // number of time quanta = 36000000/9/250000 = 16
00139         _canHandle.Init.SJW = CAN_SJW_1TQ;
00140         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00141         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00142         break;
00143 
00144     case 125000:
00145         // 125kbps
00146         _canHandle.Init.Prescaler = 18;     // number of time quanta = 36000000/18/125000 = 16
00147         _canHandle.Init.SJW = CAN_SJW_1TQ;
00148         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00149         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00150         break;
00151 
00152     default:
00153         // 125kbps (default)
00154 #if DEBUG
00155         printf("Unknown frequency specified!\r\n");
00156         printf("Using default 125kbps\r\n");
00157 #endif
00158         _canHandle.Init.Prescaler = 18;     // number of time quanta = 36000000/18/125000 = 16
00159         _canHandle.Init.SJW = CAN_SJW_1TQ;
00160         _canHandle.Init.BS1 = CAN_BS1_11TQ; // sample point at: (1 + 11) / 16 * 100 = 75%
00161         _canHandle.Init.BS2 = CAN_BS2_4TQ;
00162     }
00163     
00164 #elif defined(TARGET_NUCLEO_F446RE)
00165     
00166     // APB1 peripheral clock = 45000000Hz
00167 
00168     switch(hz) {
00169     case 1000000:
00170         // 1000kbps bit rate
00171         _canHandle.Init.Prescaler = 5;      // number of time quanta = 45000000/5/1000000 = 9
00172         _canHandle.Init.SJW = CAN_SJW_1TQ;
00173         _canHandle.Init.BS1 = CAN_BS1_6TQ;  // sample point at: (1 + 6) / 9 * 100 = 77.78%
00174         _canHandle.Init.BS2 = CAN_BS2_2TQ;
00175         break;
00176 
00177     case 500000:
00178         // 500kbps bit rate
00179         _canHandle.Init.Prescaler = 10;      // number of time quanta = 45000000/10/500000 = 9
00180         _canHandle.Init.SJW = CAN_SJW_1TQ;
00181         _canHandle.Init.BS1 = CAN_BS1_6TQ;  // sample point at: (1 + 6) / 9 * 100 = 77.78%
00182         _canHandle.Init.BS2 = CAN_BS2_2TQ;
00183         break;
00184 
00185     case 250000:
00186         // 250kbps
00187         _canHandle.Init.Prescaler = 15;      // number of time quanta = 45000000/15/250000 = 12
00188         _canHandle.Init.SJW = CAN_SJW_1TQ;
00189         _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
00190         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00191         break;
00192 
00193     case 125000:
00194         // 125kbps
00195         _canHandle.Init.Prescaler = 30;     // number of time quanta = 45000000/30/125000 = 12
00196         _canHandle.Init.SJW = CAN_SJW_1TQ;
00197         _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
00198         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00199         break;
00200 
00201     default:
00202         // 125kbps (default)
00203 #if DEBUG
00204         printf("Unknown frequency specified!\r\n");
00205         printf("Using default 125kbps\r\n");
00206 #endif
00207         _canHandle.Init.Prescaler = 30;     // number of time quanta = 45000000/30/125000 = 12
00208         _canHandle.Init.SJW = CAN_SJW_1TQ;
00209         _canHandle.Init.BS1 = CAN_BS1_8TQ; // sample point at: (1 + 8) / 12 * 100 = 75%
00210         _canHandle.Init.BS2 = CAN_BS2_3TQ;
00211     }
00212     
00213 #endif
00214 
00215     HAL_CAN_Init(&_canHandle);
00216     HAL_NVIC_EnableIRQ(CAN_IRQ);
00217    
00218     return 1;
00219 }
00220 
00221 /**
00222  * @brief
00223  * @note
00224  * @param
00225  * @retval
00226  */
00227 void can_irq_init(can_t* obj, can_irq_handler handler, uint32_t id) {
00228     if(HAL_CAN_Receive_IT(&_canHandle, CAN_FIFO0) != HAL_OK) {
00229 #ifdef DEBUG
00230         printf("CAN reception initialization error\r\n");
00231 #endif
00232     }
00233 }
00234 
00235 /**
00236  * @brief
00237  * @note
00238  * @param
00239  * @retval
00240  */
00241 void can_irq_free(can_t* obj) {
00242     rxCompleteCallback = 0;
00243 }
00244 
00245 /**
00246  * @brief
00247  * @note
00248  * @param
00249  * @retval
00250  */
00251 void can_irq_set(void (*fptr) (void)) {
00252     rxCompleteCallback = fptr;
00253 }
00254 
00255 /**
00256  * @brief
00257  * @note
00258  * @param
00259  * @retval
00260  */
00261 int can_write(can_t* obj, CAN_Message msg, int cc) {
00262     int i = 0;
00263 
00264     if(msg.format == CANStandard) {
00265         _canHandle.pTxMsg->StdId = msg.id;
00266         _canHandle.pTxMsg->ExtId = 0x00;
00267     }
00268     else {
00269         _canHandle.pTxMsg->StdId = 0x00;
00270         _canHandle.pTxMsg->ExtId = msg.id;
00271     }
00272 
00273     _canHandle.pTxMsg->RTR = msg.type == CANData ? CAN_RTR_DATA : CAN_RTR_REMOTE;
00274     _canHandle.pTxMsg->IDE = msg.format == CANStandard ? CAN_ID_STD : CAN_ID_EXT;
00275     _canHandle.pTxMsg->DLC = msg.len;
00276 
00277     for(i = 0; i < msg.len; i++)
00278         _canHandle.pTxMsg->Data[i] = msg.data[i];
00279 
00280     if(HAL_CAN_Transmit(&_canHandle, 10) != HAL_OK) {
00281 #ifdef DEBUG
00282         printf("Transmission error\r\n");
00283 #endif
00284         return 0;
00285     }
00286     else
00287         return 1;
00288 }
00289 
00290 /**
00291  * @brief
00292  * @note
00293  * @param
00294  * @retval
00295  */
00296 int can_read(can_t* obj, CAN_Message* msg, int handle) {
00297     int i;
00298     msg->id = _canHandle.pRxMsg->IDE == CAN_ID_STD ? _canHandle.pRxMsg->StdId : _canHandle.pRxMsg->ExtId;
00299     msg->type = _canHandle.pRxMsg->RTR == CAN_RTR_DATA ? CANData : CANRemote;
00300     msg->format = _canHandle.pRxMsg->IDE == CAN_ID_STD ? CANStandard : CANExtended;
00301     msg->len = _canHandle.pRxMsg->DLC;
00302     for(i = 0; i < msg->len; i++)
00303         msg->data[i] = _canHandle.pRxMsg->Data[i];
00304         
00305     return msg->len;
00306 }
00307 
00308 /**
00309  * @brief
00310  * @note
00311  * @param
00312  * @retval
00313  */
00314 int can_mode(can_t* obj, CanMode mode) {
00315     switch(mode) {
00316     case MODE_RESET:
00317         return HAL_ERROR;
00318 
00319     case MODE_NORMAL:
00320         _canHandle.Init.Mode = CAN_MODE_NORMAL;
00321         break;
00322 
00323     case MODE_SILENT:
00324         _canHandle.Init.Mode = CAN_MODE_SILENT;
00325         break;
00326 
00327     case MODE_TEST_GLOBAL:
00328         _canHandle.Init.Mode = CAN_MODE_LOOPBACK;
00329         break;
00330 
00331     case MODE_TEST_LOCAL:
00332         _canHandle.Init.Mode = CAN_MODE_LOOPBACK;
00333         break;
00334 
00335     case MODE_TEST_SILENT:
00336         _canHandle.Init.Mode = CAN_MODE_SILENT_LOOPBACK;
00337         break;
00338     }
00339 
00340     return HAL_CAN_Init(&_canHandle);
00341 }
00342 
00343 /**
00344  * @brief
00345  * @note
00346  * @param
00347  * @retval
00348  */
00349 int can_filter(can_t* obj, uint32_t id, uint32_t mask, CANFormat format /*=CANAny*/, int32_t handle /*=0*/ ) {
00350     CAN_FilterConfTypeDef   sFilterConfig;
00351 
00352     sFilterConfig.FilterNumber = handle;    // Specifies the filter number (must be a number between 0 and 13 at 32-bit filter scale)
00353     sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
00354     sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
00355     sFilterConfig.FilterIdHigh = (((id) >> 16) & 0xFFFF);
00356     sFilterConfig.FilterIdLow = ((id) & 0xFFFF);
00357     sFilterConfig.FilterMaskIdHigh = (((mask) >> 16) & 0xFFFF);
00358     sFilterConfig.FilterMaskIdLow = ((mask) & 0xFFFF);
00359     sFilterConfig.FilterFIFOAssignment = 0;
00360     sFilterConfig.FilterActivation = ENABLE;
00361     sFilterConfig.BankNumber = 0;           // Selects the start bank filter
00362     return HAL_CAN_ConfigFilter(&_canHandle, &sFilterConfig);
00363 }
00364 
00365 /**
00366  * @brief
00367  * @note
00368  * @param
00369  * @retval
00370  */
00371 void can_reset(can_t* obj) {
00372     __HAL_CAN_RESET_HANDLE_STATE(&_canHandle);
00373 }
00374 
00375 /**
00376  * @brief
00377  * @note
00378  * @param
00379  * @retval
00380  */
00381 unsigned char can_rderror(can_t* obj) {
00382     return HAL_CAN_GetError(&_canHandle);
00383 }
00384 
00385 /**
00386  * @brief
00387  * @note
00388  * @param
00389  * @retval
00390  */
00391 unsigned char can_tderror(can_t* obj) {
00392     return HAL_CAN_GetError(&_canHandle);
00393 }
00394 
00395 /**
00396  * @brief
00397  * @note
00398  * @param
00399  * @retval
00400  */
00401 void can_monitor(can_t* obj, int silent) {
00402 
00403     // not implemented
00404 }
00405 
00406 
00407 
00408 
00409