fcan.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. /*
  2. * Copyright : (C) 2022 Phytium Information Technology, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is OPEN SOURCE software: you can redistribute it and/or modify it
  6. * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
  7. * either version 1.0 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
  10. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. * See the Phytium Public License for more details.
  12. *
  13. *
  14. * FilePath: fcan.c
  15. * Date: 2021-04-29 10:21:53
  16. * LastEditTime: 2022-02-18 08:29:20
  17. * Description:  This files is for
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. */
  23. #include "string.h"
  24. #include <limits.h>
  25. #include <stdlib.h>
  26. #include "fkernel.h"
  27. #include "fcan.h"
  28. #include "fcan_hw.h"
  29. #include "fassert.h"
  30. #include "fdebug.h"
  31. #include "fswap.h"
  32. #include "fparameters.h"
  33. #include "fsleep.h"
  34. #define FT_CAN_DEBUG_TAG "FT_CAN"
  35. #define FCAN_DEBUG(format, ...) FT_DEBUG_PRINT_D(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
  36. #define FCAN_INFO(format, ...) FT_DEBUG_PRINT_I(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
  37. #define FCAN_WARN(format, ...) FT_DEBUG_PRINT_W(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
  38. #define FCAN_ERROR(format, ...) FT_DEBUG_PRINT_E(FT_CAN_DEBUG_TAG, format, ##__VA_ARGS__)
  39. typedef struct
  40. {
  41. u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */
  42. u32 tseg1_max;
  43. u32 tseg2_min; /* Time segement 2 = phase_seg2 */
  44. u32 tseg2_max;
  45. u32 sjw_max; /* Synchronisation jump width */
  46. u32 brp_min; /* Bit-rate prescaler */
  47. u32 brp_max;
  48. u32 brp_inc;
  49. } FCanBittimingConst;
  50. /* 仲裁段速率默认值 */
  51. static const FCanBittimingConst FCanArbBitConst =
  52. {
  53. .tseg1_min = FCAN_ARB_TSEG1_MIN, /* Time segement 1 = prop_seg + phase_seg1 */
  54. .tseg1_max = FCAN_ARB_TSEG1_MAX,
  55. .tseg2_min = FCAN_ARB_TSEG2_MIN, /* Time segement 2 = phase_seg2 */
  56. .tseg2_max = FCAN_ARB_TSEG2_MAX,
  57. .sjw_max = FCAN_ARB_SJW_MAX, /* Synchronisation jump width */
  58. .brp_min = FCAN_ARB_BRP_MIN, /* Bit-rate prescaler */
  59. .brp_max = FCAN_ARB_BRP_MAX,
  60. .brp_inc = FCAN_ARB_BRP_INC,
  61. };
  62. /* 数据段速率默认值 */
  63. static const FCanBittimingConst FCanDataBitConst =
  64. {
  65. .tseg1_min = FCAN_DATA_TSEG1_MIN, /* Time segement 1 = prop_seg + phase_seg1 */
  66. .tseg1_max = FCAN_DATA_TSEG1_MAX,
  67. .tseg2_min = FCAN_DATA_TSEG2_MIN, /* Time segement 2 = phase_seg2 */
  68. .tseg2_max = FCAN_DATA_TSEG2_MAX,
  69. .sjw_max = FCAN_DATA_SJW_MAX, /* Synchronisation jump width */
  70. .brp_min = FCAN_DATA_BRP_MIN, /* Bit-rate prescaler */
  71. .brp_max = FCAN_DATA_BRP_MAX,
  72. .brp_inc = FCAN_DATA_BRP_INC,
  73. };
  74. /* calculate the can sample point */
  75. static s32 FCanUpdateSamplePoint(const FCanBittimingConst *btc,
  76. u32 sample_point_nominal, u32 tseg,
  77. u32 *tseg1_ptr, u32 *tseg2_ptr,
  78. u32 *sample_point_error_ptr)
  79. {
  80. u32 sample_point_error, best_sample_point_error = UINT_MAX;
  81. u32 sample_point, best_sample_point = 0;
  82. u32 tseg1, tseg2;
  83. s32 i;
  84. for (i = 0; i <= 1; i++)
  85. {
  86. tseg2 = tseg + CAN_CALC_SYNC_SEG - (sample_point_nominal * (tseg + CAN_CALC_SYNC_SEG)) / 1000 - i;
  87. tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
  88. tseg1 = tseg - tseg2;
  89. if (tseg1 > btc->tseg1_max)
  90. {
  91. tseg1 = btc->tseg1_max;
  92. tseg2 = tseg - tseg1;
  93. }
  94. sample_point = 1000 * (tseg + CAN_CALC_SYNC_SEG - tseg2) / (tseg + CAN_CALC_SYNC_SEG);
  95. sample_point_error = abs(sample_point_nominal - sample_point);
  96. if ((sample_point <= sample_point_nominal) && (sample_point_error < best_sample_point_error))
  97. {
  98. best_sample_point = sample_point;
  99. best_sample_point_error = sample_point_error;
  100. *tseg1_ptr = tseg1;
  101. *tseg2_ptr = tseg2;
  102. }
  103. }
  104. if (sample_point_error_ptr)
  105. *sample_point_error_ptr = best_sample_point_error;
  106. return best_sample_point;
  107. }
  108. /**
  109. * @name: FCanCalcBittiming
  110. * @msg: This routine calculate Bit timing
  111. * @param {structFCanBittiming} *bt_p is is a structure that contains the CAN baud rate configuration parameter , The user needs to fill in the baudrate first
  112. * @param {u32} target_baudrate, parameters of target baudrate
  113. * @param {u32} target_sample_point, parameters of target sample point, 0 means the general configuration is used
  114. * @param {FCanSegmentType} target_segment, specifies which target is to be selected. followed by FCAN_ARB_SEGMENT or FCAN_DATA_SEGMENT
  115. * @return err code information, FCAN_SUCCESS indicates success,others indicates failed
  116. */
  117. static FError FCanCalcBittiming(FCanBaudrateConfig *bt_p, u32 target_baudrate, u32 target_sample_point, FCanSegmentType target_segment)
  118. {
  119. u32 baudrate; /* current baudrate */
  120. u32 baudrate_error; /* difference between current and nominal value */
  121. u32 best_baudrate_error = UINT_MAX;
  122. u32 sample_point_error; /* difference between current and nominal value */
  123. u32 best_sample_point_error = UINT_MAX;
  124. u32 sample_point_nominal; /* nominal sample point */
  125. u32 best_tseg = 0; /* current best value for tseg */
  126. u32 best_brp = 0; /* current best value for brp */
  127. u32 brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
  128. u64 v64;
  129. u32 reg_val;
  130. const FCanBittimingConst *btc;
  131. FCanBaudrateConfig *bt = bt_p;
  132. FASSERT(bt_p != NULL);
  133. FASSERT(target_segment < FCAN_SEGMENT_TYPE_NUM);
  134. if (target_segment == FCAN_DATA_SEGMENT)
  135. {
  136. btc = &FCanDataBitConst;
  137. }
  138. else
  139. {
  140. btc = &FCanArbBitConst;
  141. }
  142. if (target_sample_point)
  143. {
  144. sample_point_nominal = target_sample_point;
  145. }
  146. else
  147. {
  148. if (target_baudrate > 1000000)
  149. sample_point_nominal = 650;
  150. else if (target_baudrate > 800000)
  151. sample_point_nominal = 750;
  152. else if (target_baudrate > 500000)
  153. sample_point_nominal = 800;
  154. else
  155. sample_point_nominal = 875;
  156. }
  157. for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
  158. tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--)
  159. {
  160. tsegall = CAN_CALC_SYNC_SEG + tseg / 2;
  161. /* Compute all possible tseg choices (tseg=tseg1+tseg2) */
  162. brp = FCAN_REF_CLOCK / (tsegall * target_baudrate) + tseg % 2;
  163. /* choose brp step which is possible in system */
  164. brp = (brp / btc->brp_inc) * btc->brp_inc;
  165. if ((brp < btc->brp_min) || (brp > btc->brp_max))
  166. continue;
  167. baudrate = FCAN_REF_CLOCK / (brp * tsegall);
  168. baudrate_error = abs(target_baudrate - baudrate);
  169. /* tseg brp biterror */
  170. if (baudrate_error > best_baudrate_error)
  171. continue;
  172. /* reset sample point error if we have a better baudrate */
  173. if (baudrate_error < best_baudrate_error)
  174. best_sample_point_error = UINT_MAX;
  175. FCanUpdateSamplePoint(btc, sample_point_nominal, tseg / 2, &tseg1, &tseg2, &sample_point_error);
  176. FCAN_DEBUG("target_segment=%d, brp=%d, tseg=%d, tseg1=%d, tseg2=%d, sample_point_nominal=%d",
  177. target_segment, brp, tseg, tseg1, tseg2, sample_point_nominal);
  178. u32 prop_seg = tseg1 / 2;
  179. u32 phase_seg1 = tseg1 - prop_seg;
  180. u32 phase_seg2 = tseg2;
  181. u32 sjw = 1;
  182. /* Setting Baud Rate prescalar value in BRPR Register */
  183. reg_val = (brp - 1) << 16;
  184. reg_val |= (prop_seg - 1) << 2;
  185. reg_val |= (phase_seg1 - 1) << 5;
  186. reg_val |= (phase_seg2 - 1) << 8;
  187. reg_val |= (sjw - 1);
  188. FCAN_DEBUG("reg_val=%#x\n", reg_val);
  189. if (sample_point_error > best_sample_point_error)
  190. continue;
  191. best_sample_point_error = sample_point_error;
  192. best_baudrate_error = baudrate_error;
  193. best_tseg = tseg / 2;
  194. best_brp = brp;
  195. if (baudrate_error == 0 && sample_point_error == 0)
  196. break;
  197. }
  198. if (best_baudrate_error)
  199. {
  200. /* Error in one-tenth of a percent */
  201. v64 = (u64)best_baudrate_error * 1000;
  202. do_div(v64, target_baudrate);
  203. baudrate_error = (u32)v64;
  204. if (baudrate_error > CAN_CALC_MAX_ERROR)
  205. {
  206. FCAN_ERROR("baudrate error");
  207. return FCAN_FAILURE;
  208. }
  209. }
  210. /* real sample point */
  211. FCanUpdateSamplePoint(btc, sample_point_nominal, best_tseg,
  212. &tseg1, &tseg2, NULL);
  213. FCAN_DEBUG("tseg1=%d, tseg2=%d, sample_point_nominal=%d", tseg1, tseg2, sample_point_nominal);
  214. bt->prop_seg = tseg1 / 2;
  215. bt->phase_seg1 = tseg1 - bt->prop_seg;
  216. bt->phase_seg2 = tseg2;
  217. /* check for sjw user settings */
  218. if (!bt->sjw || !btc->sjw_max)
  219. {
  220. bt->sjw = 1;
  221. }
  222. else
  223. {
  224. /* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
  225. if (bt->sjw > btc->sjw_max)
  226. bt->sjw = btc->sjw_max;
  227. /* bt->sjw must not be higher than tseg2 */
  228. if (tseg2 < bt->sjw)
  229. bt->sjw = tseg2;
  230. }
  231. bt->brp = best_brp;
  232. /* real baudrate */
  233. if (target_baudrate != FCAN_REF_CLOCK / (bt->brp * (CAN_CALC_SYNC_SEG + tseg1 + tseg2)))
  234. {
  235. FCAN_ERROR("target baudrate calculate timing failed");
  236. return FCAN_FAILURE;
  237. }
  238. FCAN_DEBUG("bt->prop_seg=%d, bt->phase_seg1=%d, bt->phase_seg2=%d, bt->sjw=%d, bt->brp=%d",
  239. bt->prop_seg, bt->phase_seg1, bt->phase_seg2, bt->sjw, bt->brp);
  240. return FCAN_SUCCESS;
  241. }
  242. static u32 FCanGetDlcLen(u32 dlc)
  243. {
  244. u32 dlc_len = 0;
  245. if (dlc == 0)
  246. {
  247. dlc_len = 8;
  248. }
  249. switch (dlc)
  250. {
  251. case 1:
  252. dlc_len = 1;
  253. break;
  254. case 2:
  255. dlc_len = 2;
  256. break;
  257. case 3:
  258. dlc_len = 3;
  259. break;
  260. case 4:
  261. dlc_len = 4;
  262. break;
  263. case 5:
  264. dlc_len = 5;
  265. break;
  266. case 6:
  267. dlc_len = 6;
  268. break;
  269. case 7:
  270. dlc_len = 7;
  271. break;
  272. case 8:
  273. dlc_len = 8;
  274. break;
  275. case 9:
  276. dlc_len = 12;
  277. break;
  278. case 10:
  279. dlc_len = 16;
  280. break;
  281. case 11:
  282. dlc_len = 20;
  283. break;
  284. case 12:
  285. dlc_len = 24;
  286. break;
  287. case 13:
  288. dlc_len = 32;
  289. break;
  290. case 14:
  291. dlc_len = 48;
  292. break;
  293. case 15:
  294. dlc_len = 64;
  295. break;
  296. default :
  297. dlc_len = 0;
  298. break;
  299. }
  300. return dlc_len;
  301. }
  302. static u32 FCanSetDlcLen(u32 len)
  303. {
  304. if (len <= 8)
  305. {
  306. return len;
  307. }
  308. else if (len <= 12)
  309. {
  310. return 9;
  311. }
  312. else if (len <= 16)
  313. {
  314. return 10;
  315. }
  316. else if (len <= 20)
  317. {
  318. return 11;
  319. }
  320. else if (len <= 24)
  321. {
  322. return 12;
  323. }
  324. else if (len <= 32)
  325. {
  326. return 13;
  327. }
  328. else if (len <= 48)
  329. {
  330. return 14;
  331. }
  332. else if (len <= 64)
  333. {
  334. return 15;
  335. }
  336. else
  337. {
  338. return 0;
  339. }
  340. }
  341. /**
  342. * @name: FCanReset
  343. * @msg: reset a specific can instance
  344. * @param {FCanCtrl} *pctrl, instance of FCan controller
  345. * @return {*}
  346. */
  347. void FCanReset(FCanCtrl *instance_p)
  348. {
  349. u32 reg_value;
  350. FCanConfig *config_p;
  351. FASSERT(instance_p != NULL);
  352. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  353. config_p = &instance_p->config;
  354. FCAN_WRITE_REG32(config_p->base_address, FCAN_CTRL_OFFSET, 0);
  355. reg_value = FCAN_READ_REG32(config_p->base_address, FCAN_CTRL_OFFSET);
  356. if (reg_value & FCAN_CTRL_XFER_MASK)
  357. {
  358. FCAN_ERROR("FT can is not in configration mode\n");
  359. return;
  360. }
  361. /* reset can */
  362. FCAN_WRITE_REG32(config_p->base_address, FCAN_CTRL_OFFSET, FCAN_CTRL_RST_MASK);
  363. }
  364. /**
  365. * @name: FCanDeInitialize
  366. * @msg: Deinitializes a specific can instance
  367. * @param {FCanCtrl} *pctrl, instance of FCan controller
  368. * @return {*}
  369. */
  370. void FCanDeInitialize(FCanCtrl *instance_p)
  371. {
  372. FASSERT(instance_p);
  373. instance_p->is_ready = 0;
  374. memset(instance_p, 0, sizeof(*instance_p));
  375. return;
  376. }
  377. /**
  378. * @name: FCanCfgInitialize
  379. * @msg: Initializes a specific instance such that it is ready to be used.
  380. * @param {FCanCtrl} *instance_p, instance of FCanCtrl controller
  381. * @param {FCanConfig} *input_config_p, configuration parameters of FCanCtrl
  382. * @return err code information, FCAN_SUCCESS indicates success,others indicates failed
  383. */
  384. FError FCanCfgInitialize(FCanCtrl *instance_p, const FCanConfig *input_config_p)
  385. {
  386. FASSERT(instance_p != NULL);
  387. FASSERT(input_config_p != NULL);
  388. FError ret = FCAN_SUCCESS;
  389. /*
  390. * If the device is started, disallow the initialize and return a Status
  391. * indicating it is started. This allows the user to de-initialize the device
  392. * and reinitialize, but prevents a user from inadvertently
  393. * initializing.
  394. */
  395. if (FT_COMPONENT_IS_READY == instance_p->is_ready)
  396. {
  397. FCAN_WARN("device is already initialized!!!");
  398. }
  399. /*Set default values and configuration data */
  400. FCanDeInitialize(instance_p);
  401. instance_p->config = *input_config_p;
  402. instance_p->is_ready = FT_COMPONENT_IS_READY;
  403. FCanReset(instance_p);
  404. return ret;
  405. }
  406. /**
  407. * @name: FCanStatusGet
  408. * @msg: read can status, include transfer status, error and fifo count.
  409. * @param {FCanCtrl} *instance_p, pointer to a FCanCtrl structure that contains
  410. * the configuration information for the specified can module.
  411. * @param {FCanStatus} *status_p, pointer to can status, include send and receive, error and fifo count .
  412. * @return err code information, FCAN_SUCCESS indicates success,others indicates failed.
  413. */
  414. FError FCanStatusGet(FCanCtrl *instance_p, FCanStatus *status_p)
  415. {
  416. FASSERT(instance_p != NULL);
  417. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  418. FASSERT(status_p != NULL);
  419. uintptr base_address = instance_p->config.base_address;
  420. u32 reg_val = 0;
  421. reg_val = FCAN_READ_REG32(base_address, FCAN_XFER_STS_OFFSET);
  422. status_p->xfer_status.xfers = FCAN_XFER_STS_XFERS_GET(reg_val);
  423. status_p->xfer_status.rs = FCAN_XFER_STS_RS_GET(reg_val);
  424. status_p->xfer_status.ts = FCAN_XFER_STS_TS_GET(reg_val);
  425. status_p->xfer_status.fies = FCAN_XFER_STS_FIES_GET(reg_val);
  426. status_p->xfer_status.fras = FCAN_XFER_STS_FRAS_GET(reg_val);
  427. reg_val = FCAN_READ_REG32(base_address, FCAN_ERR_CNT_OFFSET);
  428. status_p->rx_err_cnt = FCAN_ERR_CNT_RFN_GET(reg_val);
  429. status_p->tx_err_cnt = FCAN_ERR_CNT_TFN_GET(reg_val);
  430. reg_val = FCAN_READ_REG32(base_address, FCAN_FIFO_CNT_OFFSET);
  431. status_p->tx_fifo_cnt = FCAN_FIFO_CNT_TFN_GET(reg_val);
  432. status_p->rx_fifo_cnt = FCAN_FIFO_CNT_RFN_GET(reg_val);
  433. return FCAN_SUCCESS;
  434. }
  435. /**
  436. * @name: FCanRecv
  437. * @msg: receive can message by specific can instance.
  438. * @param {FCanCtrl} *instance_p, pointer to a FCanCtrl structure that contains
  439. * the configuration information for the specific can module.
  440. * @param {FCanFrame} *frame_p, can message receive struct.
  441. * @return err code information, FCAN_SUCCESS indicates success,others indicates failed.
  442. */
  443. FError FCanRecv(FCanCtrl *instance_p, FCanFrame *frame_p)
  444. {
  445. u32 canid;
  446. u32 dlc;
  447. int i = 0, j = 0;
  448. FASSERT(instance_p != NULL);
  449. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  450. FASSERT(frame_p != NULL);
  451. uintptr base_address = instance_p->config.base_address;
  452. memset(frame_p, 0, sizeof(FCanFrame));
  453. /* Read a frame from Phytium CAN */
  454. canid = FCAN_READ_REG32(base_address, FCAN_RX_FIFO_OFFSET);
  455. /* if canid is big-endian ,use swap change to little-endian */
  456. canid = be32_to_cpu(canid);
  457. FCAN_DEBUG("FCanRecv canid = %#x\n", canid);
  458. /* identifier extension */
  459. if (canid & FCAN_IDR_IDE_MASK)
  460. {
  461. dlc = FCAN_READ_REG32(base_address, FCAN_RX_FIFO_OFFSET);
  462. dlc = be32_to_cpu(dlc);
  463. FCAN_DEBUG("FCanRecv dlc = %#x\n", dlc);
  464. if (dlc & FTCANFD_ID2_FDL_MASK)
  465. {
  466. if (dlc & FTCANFD_ID2_BRS_MASK)
  467. {
  468. frame_p->flags |= CANFD_BRS;
  469. }
  470. if (dlc & FTCANFD_ID2_ESI_MASK)
  471. {
  472. frame_p->flags |= CANFD_ESI;
  473. }
  474. dlc = FTCANFD_ID2_EDLC_GET(dlc);
  475. }
  476. else
  477. {
  478. dlc = FCAN_IDR_EDLC_GET(dlc);
  479. }
  480. frame_p->canid = FCAN_IDR_ID1_GET(canid) << FCAN_ACC_IDN_SHIFT;
  481. frame_p->canid |= FCAN_IDR_ID2_GET(canid);
  482. frame_p->canid |= CAN_EFF_FLAG;
  483. if (canid & FCAN_IDR_RTR_MASK)
  484. {
  485. frame_p->canid |= CAN_RTR_FLAG;
  486. }
  487. }
  488. else
  489. {
  490. if (canid & FTCANFD_ID1_FDL_MASK)
  491. {
  492. if (canid & FTCANFD_ID1_BRS_MASK)
  493. {
  494. frame_p->flags |= CANFD_BRS;
  495. }
  496. if (canid & FTCANFD_ID1_ESI_MASK)
  497. {
  498. frame_p->flags |= CANFD_ESI;
  499. }
  500. dlc = FTCANFD_ID1_SDLC_GET(canid);
  501. }
  502. else
  503. {
  504. dlc = FCAN_IDR_DLC_GET(canid);
  505. }
  506. /* The received frame is a standard format frame */
  507. frame_p->canid = FCAN_IDR_ID1_GET(canid);
  508. if (canid & FCAN_IDR_SRR_MASK)
  509. {
  510. frame_p->canid |= CAN_RTR_FLAG;
  511. }
  512. }
  513. frame_p->candlc = FCanGetDlcLen(dlc);
  514. FCAN_DEBUG("FCanRecv frame_p->candlc = %d\n", frame_p->candlc);
  515. if (!(frame_p->canid & CAN_RTR_FLAG))
  516. {
  517. j = 0;
  518. for (i = frame_p->candlc; i > 0; i -= 4)
  519. {
  520. *(u32 *)(frame_p->data + j) = FCAN_READ_REG32(base_address, FCAN_RX_FIFO_OFFSET);
  521. j += 4;
  522. }
  523. if (i > 0)
  524. {
  525. *(u32 *)(frame_p->data + j) = FCAN_READ_REG32(base_address, FCAN_RX_FIFO_OFFSET);
  526. }
  527. }
  528. return FCAN_SUCCESS;
  529. }
  530. /**
  531. * @name: FCanSend
  532. * @msg: send can message by specific can instance.
  533. * @param {FCanCtrl} *instance_p, pointer to a FCanCtrl structure that contains
  534. * the configuration information for the specific can module.
  535. * @param {FCanFrame} *frame_p, can message send struct.
  536. * @return err code information, FCAN_SUCCESS indicates success,others indicates failed.
  537. */
  538. FError FCanSend(FCanCtrl *instance_p, FCanFrame *frame_p)
  539. {
  540. u32 id, dlc;
  541. int i = 0, j = 0;
  542. FASSERT(instance_p != NULL);
  543. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  544. uintptr base_address = instance_p->config.base_address;
  545. while (FCAN_TX_FIFO_FULL(instance_p));
  546. u32 can_send_dlc = FCanSetDlcLen(frame_p->candlc);
  547. if (frame_p->canid & CAN_EFF_FLAG)
  548. {
  549. /* Extended CAN id format */
  550. id = FCAN_IDR_ID2_GET(frame_p->canid & CAN_EFF_MASK);
  551. id |= FCAN_IDR_ID1_GET((frame_p->canid & CAN_EFF_MASK) >>
  552. (CAN_EFF_ID_BITS - CAN_SFF_ID_BITS));
  553. /* The substibute remote TX request bit should be "1"
  554. * for extended frames as in the Phytium CAN datasheet
  555. */
  556. id |= FCAN_IDR_IDE_MASK | FCAN_IDR_SRR_MASK;
  557. if (frame_p->canid & CAN_RTR_FLAG)
  558. {
  559. id |= FCAN_IDR_RTR_MASK;
  560. }
  561. if (instance_p->use_canfd == TRUE)
  562. {
  563. dlc = can_send_dlc << FCANFD_IDR_EDLC_SHIFT;
  564. dlc |= FTCANFD_ID2_FDL_MASK;
  565. /* enable brs-Bit Rate Switch */
  566. frame_p->flags |= CANFD_BRS;
  567. if (frame_p->flags & CANFD_BRS)
  568. {
  569. dlc |= FTCANFD_ID2_BRS_MASK;
  570. }
  571. if (frame_p->flags & CANFD_ESI)
  572. {
  573. dlc |= FTCANFD_ID2_ESI_MASK;
  574. }
  575. }
  576. else
  577. {
  578. dlc = can_send_dlc << FCAN_IDR_EDLC_SHIFT;
  579. }
  580. FCAN_DEBUG("FCanSend id = %#x\n", id);
  581. FCAN_DEBUG("FCanSend dlc = %#x\n", dlc);
  582. FCAN_WRITE_REG32(base_address, FCAN_TX_FIFO_OFFSET, be32_to_cpu(id));
  583. FCAN_WRITE_REG32(base_address, FCAN_TX_FIFO_OFFSET, be32_to_cpu(dlc));
  584. }
  585. else
  586. {
  587. /* Standard CAN id format */
  588. id = FCAN_IDR_ID1_GET(frame_p->canid & CAN_SFF_MASK);
  589. if (frame_p->canid & CAN_RTR_FLAG)
  590. id |= FCAN_IDR_SRR_MASK;
  591. FCAN_DEBUG("instance_p->use_canfd = %d, can_send_dlc = %d \n",
  592. instance_p->use_canfd, can_send_dlc);
  593. if (instance_p->use_canfd == TRUE)
  594. {
  595. dlc = ((can_send_dlc << FCANFD_IDR1_SDLC_SHIFT) | FTCANFD_IDR_PAD_MASK);
  596. dlc |= FTCANFD_ID1_FDL_MASK;
  597. /* enable brs-Bit Rate Switch */
  598. frame_p->flags |= CANFD_BRS;
  599. if (frame_p->flags & CANFD_BRS)
  600. {
  601. dlc |= FTCANFD_ID1_BRS_MASK;
  602. }
  603. if (frame_p->flags & CANFD_ESI)
  604. {
  605. dlc |= FTCANFD_ID1_ESI_MASK;
  606. }
  607. }
  608. else
  609. {
  610. dlc = ((can_send_dlc << FCAN_IDR_SDLC_SHIFT) | FCAN_IDR_PAD_MASK);
  611. }
  612. id |= dlc;
  613. FCAN_DEBUG("can_send id = %#x\n", id);
  614. FCAN_WRITE_REG32(base_address, FCAN_TX_FIFO_OFFSET, be32_to_cpu(id));
  615. }
  616. if (!(frame_p->canid & CAN_RTR_FLAG))
  617. {
  618. j = 0;
  619. FCAN_DEBUG("frame_p->canid=%#x, frame_p->candlc = %d\n", frame_p->canid, frame_p->candlc);
  620. for (i = frame_p->candlc; i > 0; i -= 4)
  621. {
  622. FCAN_WRITE_REG32(base_address, FCAN_TX_FIFO_OFFSET, *(u32 *)(frame_p->data + j));
  623. j += 4;
  624. }
  625. if (i > 0)
  626. {
  627. FCAN_WRITE_REG32(base_address, FCAN_TX_FIFO_OFFSET, *(u32 *)(frame_p->data + j));
  628. }
  629. }
  630. /* triggers tranmission */
  631. FCAN_CLEARBIT(base_address, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
  632. FCAN_SETBIT(base_address, FCAN_CTRL_OFFSET, FCAN_CTRL_TXREQ_MASK | FCAN_CTRL_XFER_MASK);
  633. return FCAN_SUCCESS;
  634. }
  635. /**
  636. * @name: FCan_SetTiming
  637. * @msg: This routine sets Bit time
  638. * @param {FCanCtrl} *instance_p is a pointer to the FCanCtrl instance.
  639. * @param {FCanBaudrateConfig} *bittiming_p, parameters of arbitration or data segment baudrate
  640. * @param {FCanSegmentType} target_segment, specifies which target is to be selected. followed by FCAN_ARB_SEGMENT or FCAN_DATA_SEGMENT
  641. * @out param:
  642. * @return {*}
  643. */
  644. static FError FCanSetTiming(FCanCtrl *instance_p, FCanBaudrateConfig *bittiming_p, FCanSegmentType target_segment)
  645. {
  646. u32 reg_val = 0;
  647. u32 transfer_enable;
  648. FASSERT(instance_p != NULL);
  649. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  650. FASSERT(target_segment < FCAN_SEGMENT_TYPE_NUM);
  651. uintptr base_address = instance_p->config.base_address;
  652. FASSERT(bittiming_p->brp != 0);
  653. FASSERT(bittiming_p->prop_seg != 0);
  654. FASSERT(bittiming_p->phase_seg1 != 0);
  655. FASSERT(bittiming_p->phase_seg2 != 0);
  656. FCAN_DEBUG("brp=%d, prop_seg=%d, phase_seg1=%d, phase_seg2=%d, sjw=%d",
  657. bittiming_p->brp, bittiming_p->prop_seg, bittiming_p->phase_seg1,
  658. bittiming_p->phase_seg2, bittiming_p->sjw);
  659. /* Setting Baud Rate prescalar value in BRPR Register */
  660. reg_val = (bittiming_p->brp - 1) << 16;
  661. reg_val |= (bittiming_p->prop_seg - 1) << 2;
  662. reg_val |= (bittiming_p->phase_seg1 - 1) << 5;
  663. reg_val |= (bittiming_p->phase_seg2 - 1) << 8;
  664. reg_val |= (bittiming_p->sjw - 1);
  665. transfer_enable = (FCAN_READ_REG32(base_address, FCAN_CTRL_OFFSET) & FCAN_CTRL_XFER_MASK);
  666. if (transfer_enable)
  667. {
  668. FCAN_CLEARBIT(base_address, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
  669. }
  670. if (reg_val)
  671. {
  672. if (target_segment == FCAN_DATA_SEGMENT)
  673. FCAN_WRITE_REG32(base_address, FCAN_DAT_RATE_CTRL_OFFSET, reg_val);
  674. else
  675. FCAN_WRITE_REG32(base_address, FCAN_ARB_RATE_CTRL_OFFSET, reg_val);
  676. }
  677. else
  678. {
  679. FCAN_ERROR("FCanSetTiming reg_val failed");
  680. return FCAN_FAILURE;
  681. }
  682. return FCAN_SUCCESS;
  683. }
  684. /**
  685. * @name: FCanBaudrateSet
  686. * @msg: Set the fcan baudrate by FCanBaudrateConfig parameters.
  687. * @param {FCanCtrl} *instance_p, instance of FCanCtrl controller
  688. * @param {FCanBaudrateConfig} *baudrate_p, parameters of arbitration or data segment baudrate
  689. * include baudrate, parameters of target baudrate
  690. * include sample_point, parameters of target sample point, 0 means the general configuration is used.
  691. * The value is the percentage of sampling points multiplied by 1000.
  692. * For example, if sample point is 0.75, set target_sample_point = 750.
  693. * Or manual config baudrate parameters.
  694. * @param {FCanSegmentType} segment, specifies data segment or arbitration segment is selected. followed by FCAN_ARB_SEGMENT or FCAN_DATA_SEGMENT
  695. * @return err code information, FQSPI_SUCCESS indicates success,others indicates failed
  696. * @note this function is to set arb and data segment baudrate, according to the prop_seg,
  697. * phase_seg1, phase_seg2 ,brp and sjw parameters, users can use this function to set can baudrate.
  698. * A formula to calculate baudrate is:
  699. * baudrate = FCAN_REF_CLOCK/(brp*(sjw+prop_seg+phase_seg1++phase_seg2))
  700. * sample point = (sjw+prop_seg+phase_seg1)/(sjw+prop_seg+phase_seg1++phase_seg2)
  701. * Recommended sample point :
  702. * 75.0% : baudrate > 800000
  703. * 80.0% : baudrate > 500000
  704. * 87.5% : baudrate <= 500000
  705. */
  706. FError FCanBaudrateSet(FCanCtrl *instance_p, FCanBaudrateConfig *baudrate_p)
  707. {
  708. FASSERT(instance_p != NULL);
  709. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  710. FCanSegmentType segment = baudrate_p->segment;
  711. FASSERT(segment < FCAN_SEGMENT_TYPE_NUM);
  712. u32 baudrate = baudrate_p->baudrate;
  713. u32 sample_point = baudrate_p->sample_point;
  714. if (baudrate_p->auto_calc == TRUE)
  715. {
  716. #if defined(CONFIG_TARGET_F2000_4) || defined(CONFIG_TARGET_D2000)
  717. if ((segment == FCAN_ARB_SEGMENT) && ((baudrate > FCAN_BAUDRATE_1000K) || (baudrate < FCAN_BAUDRATE_50K)))
  718. {
  719. FCAN_ERROR("FCanBaudrateSet FCAN_ARB_SEGMENT baudrate = %d invalid", baudrate);
  720. return FCAN_INVAL_PARAM;
  721. }
  722. if ((segment == FCAN_DATA_SEGMENT) && ((baudrate > FCAN_BAUDRATE_1000K) || (baudrate < FCAN_BAUDRATE_50K)))
  723. {
  724. FCAN_ERROR("FCanBaudrateSet FCAN_DATA_SEGMENT baudrate = %d invalid", baudrate);
  725. return FCAN_INVAL_PARAM;
  726. }
  727. #elif defined(CONFIG_TARGET_E2000)
  728. if ((segment == FCAN_ARB_SEGMENT) && ((baudrate > FCAN_BAUDRATE_1000K) || (baudrate < FCAN_BAUDRATE_10K)))
  729. {
  730. FCAN_ERROR("FCanBaudrateSet FCAN_ARB_SEGMENT baudrate = %d invalid", baudrate);
  731. return FCAN_INVAL_PARAM;
  732. }
  733. if ((segment == FCAN_DATA_SEGMENT) && ((baudrate > FCAN_BAUDRATE_5000K) || (baudrate < FCAN_BAUDRATE_10K)))
  734. {
  735. FCAN_ERROR("FCanBaudrateSet FCAN_DATA_SEGMENT baudrate = %d invalid", baudrate);
  736. return FCAN_INVAL_PARAM;
  737. }
  738. #endif
  739. }
  740. FError ret = FCAN_SUCCESS;
  741. FCanBaudrateConfig timing_config;
  742. memset(&timing_config, 0, sizeof(timing_config));
  743. /* Automatically calculate parameters based on baudrate and sample point */
  744. if (baudrate_p->auto_calc == TRUE)
  745. {
  746. ret = FCanCalcBittiming(&timing_config, baudrate, sample_point, segment);
  747. if (ret != FCAN_SUCCESS)
  748. {
  749. FCAN_ERROR("FCanCalcBittiming %d failed", segment);
  750. return FCAN_FAILURE;
  751. }
  752. ret = FCanSetTiming(instance_p, &timing_config, segment);
  753. if (ret != FCAN_SUCCESS)
  754. {
  755. FCAN_ERROR("FCanSetTiming %d failed", segment);
  756. return FCAN_FAILURE;
  757. }
  758. }
  759. else
  760. {
  761. ret = FCanSetTiming(instance_p, baudrate_p, segment);
  762. if (ret != FCAN_SUCCESS)
  763. {
  764. FCAN_ERROR("FCanSetTiming failed");
  765. return FCAN_FAILURE;
  766. }
  767. }
  768. return ret;
  769. }
  770. /**
  771. * @name: FCanFdEnable
  772. * @msg: Enable or disable can.
  773. * @param {FCanCtrl} *instance_p, instance of FCanCtrl controller
  774. * @param {boolean} enable, TRUE-enable canfd, FALSE-disable canfd.
  775. * @return err code information, FCAN_SUCCESS indicates success,others indicates failed
  776. */
  777. FError FCanEnable(FCanCtrl *instance_p, boolean enable)
  778. {
  779. FASSERT(instance_p);
  780. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  781. uintptr base_addr = instance_p->config.base_address;
  782. if (enable == TRUE)
  783. {
  784. FCAN_SETBIT(base_addr, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
  785. }
  786. else
  787. {
  788. FCAN_CLEARBIT(base_addr, FCAN_CTRL_OFFSET, FCAN_CTRL_XFER_MASK);
  789. }
  790. return FCAN_SUCCESS;
  791. }
  792. /**
  793. * @name: FCanIdMaskFilterSet
  794. * @msg: Set the can mask and umask id.
  795. * @param {FCanCtrl} *instance_p, instance of FCanCtrl controller
  796. * @param {FCanIdMaskConfig} *id_mask_p, include filter register index, umask id and mask id
  797. * id indicates a specific ID can receive
  798. * mask indicates mask the corresponding bit of the id
  799. * @return err code information, FCAN_SUCCESS indicates success,others indicates failed
  800. */
  801. FError FCanIdMaskFilterSet(FCanCtrl *instance_p, FCanIdMaskConfig *id_mask_p)
  802. {
  803. FASSERT(instance_p);
  804. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  805. FASSERT(id_mask_p);
  806. u32 filter_index = id_mask_p->filter_index;
  807. FASSERT(filter_index < FCAN_ACC_ID_REG_NUM);
  808. uintptr base_address = instance_p->config.base_address;
  809. u32 id_reg_offset = 0;
  810. u32 mask_reg_offset = 0;
  811. u32 id = 0;
  812. u32 mask = 0;
  813. switch (filter_index)
  814. {
  815. case 0:
  816. id_reg_offset = FCAN_ACC_ID0_OFFSET;
  817. mask_reg_offset = FCAN_ACC_ID0_MASK_OFFSET;
  818. break;
  819. case 1:
  820. id_reg_offset = FCAN_ACC_ID1_OFFSET;
  821. mask_reg_offset = FCAN_ACC_ID1_MASK_OFFSET;
  822. break;
  823. case 2:
  824. id_reg_offset = FCAN_ACC_ID2_OFFSET;
  825. mask_reg_offset = FCAN_ACC_ID2_MASK_OFFSET;
  826. break;
  827. case 3:
  828. id_reg_offset = FCAN_ACC_ID3_OFFSET;
  829. mask_reg_offset = FCAN_ACC_ID3_MASK_OFFSET;
  830. break;
  831. default:
  832. return FCAN_FAILURE;
  833. }
  834. if (id_mask_p->type == FCAN_STANDARD_FRAME)
  835. {
  836. id = id_mask_p->id << FCAN_ACC_IDN_SHIFT;
  837. mask = id_mask_p->mask << FCAN_ACC_IDN_SHIFT;
  838. }
  839. FCAN_WRITE_REG32(base_address, id_reg_offset, id);
  840. FCAN_WRITE_REG32(base_address, mask_reg_offset, mask);
  841. return FCAN_SUCCESS;
  842. }
  843. /**
  844. * @name: FCanIdMaskFilterEnable
  845. * @msg: Set the can id mask filter enable.
  846. * @param {FCanCtrl} *instance_p, instance of FCanCtrl controller
  847. * @return {*}
  848. */
  849. void FCanIdMaskFilterEnable(FCanCtrl *instance_p)
  850. {
  851. FCanConfig *config_p;
  852. FASSERT(instance_p != NULL);
  853. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  854. config_p = &instance_p->config;
  855. FCAN_SETBIT(config_p->base_address, FCAN_CTRL_OFFSET, FCAN_CTRL_AIME_MASK);
  856. }
  857. /**
  858. * @name: FCanIdMaskFilterDisable
  859. * @msg: Set the can id mask filter disable.
  860. * @param {FCanCtrl} *instance_p, instance of FCanCtrl controller
  861. * @return {*}
  862. */
  863. void FCanIdMaskFilterDisable(FCanCtrl *instance_p)
  864. {
  865. FCanConfig *config_p;
  866. FASSERT(instance_p != NULL);
  867. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  868. config_p = &instance_p->config;
  869. FCAN_CLEARBIT(config_p->base_address, FCAN_CTRL_OFFSET, FCAN_CTRL_AIME_MASK);
  870. }
  871. /**
  872. * @name: FCanInterruptEnable
  873. * @msg: Enable can interrupt.
  874. * @param {FCanCtrl} *instance_p, instance of FCanCtrl controller
  875. * @param {FCanIntrEventType} event_type, interrupt event type
  876. * @return err code information, FCAN_SUCCESS indicates success,others indicates failed
  877. */
  878. FError FCanInterruptEnable(FCanCtrl *instance_p, FCanIntrEventType event_type)
  879. {
  880. FASSERT(instance_p != NULL);
  881. FASSERT(FT_COMPONENT_IS_READY == instance_p->is_ready);
  882. uintptr base_addr = instance_p->config.base_address;
  883. u32 reg_val = 0;
  884. reg_val = FCAN_READ_REG32(base_addr, FCAN_INTR_OFFSET);
  885. switch (event_type)
  886. {
  887. case FCAN_INTR_EVENT_SEND:
  888. reg_val |= FCAN_INTR_TEIE_MASK;
  889. break;
  890. case FCAN_INTR_EVENT_RECV:
  891. reg_val |= FCAN_INTR_REIE_MASK;
  892. break;
  893. case FCAN_INTR_EVENT_ERROR:
  894. reg_val |= FCAN_INTR_EIE_MASK;
  895. break;
  896. default:
  897. break;
  898. }
  899. FCAN_WRITE_REG32(base_addr, FCAN_INTR_OFFSET, reg_val);
  900. return FCAN_SUCCESS;
  901. }
  902. /**
  903. * @name: FCanFdEnable
  904. * @msg: Enable or disable can fd.
  905. * @param {FCanCtrl} *instance_p, instance of FCanCtrl controller
  906. * @param {boolean} enable, TRUE-enable canfd, FALSE-disable canfd.
  907. * @return err code information, FCAN_SUCCESS indicates success,others indicates failed
  908. */
  909. FError FCanFdEnable(FCanCtrl *instance_p, boolean enable)
  910. {
  911. FASSERT(instance_p != NULL);
  912. FASSERT(FT_COMPONENT_IS_READY == instance_p->is_ready);
  913. uintptr base_addr = instance_p->config.base_address;
  914. if (enable == TRUE)
  915. {
  916. instance_p->use_canfd = TRUE;
  917. FCAN_SETBIT(base_addr, FCAN_CTRL_OFFSET, FCAN_CTRL_FDCRC_MASK | FCAN_CTRL_IOF_MASK);
  918. }
  919. else
  920. {
  921. instance_p->use_canfd = FALSE;
  922. FCAN_SETBIT(base_addr, FCAN_CTRL_OFFSET, FCAN_CTRL_IOF_MASK);
  923. FCAN_CLEARBIT(base_addr, FCAN_CTRL_OFFSET, FCAN_CTRL_FDCRC_MASK);
  924. }
  925. return FCAN_SUCCESS;
  926. }