twai_hal.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stddef.h>
  7. #include "sdkconfig.h"
  8. #include "hal/twai_hal.h"
  9. #include "hal/efuse_hal.h"
  10. #include "soc/soc_caps.h"
  11. //Default values written to various registers on initialization
  12. #define TWAI_HAL_INIT_TEC 0
  13. #define TWAI_HAL_INIT_REC 0
  14. #define TWAI_HAL_INIT_EWL 96
  15. /* ---------------------------- Init and Config ----------------------------- */
  16. bool twai_hal_init(twai_hal_context_t *hal_ctx, const twai_hal_config_t *config)
  17. {
  18. //Initialize HAL context
  19. hal_ctx->dev = TWAI_LL_GET_HW(config->controller_id);
  20. hal_ctx->state_flags = 0;
  21. hal_ctx->clock_source_hz = config->clock_source_hz;
  22. //Initialize TWAI controller, and set default values to registers
  23. twai_ll_enter_reset_mode(hal_ctx->dev);
  24. if (!twai_ll_is_in_reset_mode(hal_ctx->dev)) { //Must enter reset mode to write to config registers
  25. return false;
  26. }
  27. #if SOC_TWAI_SUPPORT_MULTI_ADDRESS_LAYOUT
  28. twai_ll_enable_extended_reg_layout(hal_ctx->dev); //Changes the address layout of the registers
  29. #endif
  30. twai_ll_set_mode(hal_ctx->dev, TWAI_MODE_LISTEN_ONLY); //Freeze REC by changing to LOM mode
  31. //Both TEC and REC should start at 0
  32. twai_ll_set_tec(hal_ctx->dev, TWAI_HAL_INIT_TEC);
  33. twai_ll_set_rec(hal_ctx->dev, TWAI_HAL_INIT_REC);
  34. twai_ll_set_err_warn_lim(hal_ctx->dev, TWAI_HAL_INIT_EWL); //Set default value of for EWL
  35. return true;
  36. }
  37. void twai_hal_deinit(twai_hal_context_t *hal_ctx)
  38. {
  39. //Clear any pending registers
  40. (void) twai_ll_get_and_clear_intrs(hal_ctx->dev);
  41. twai_ll_set_enabled_intrs(hal_ctx->dev, 0);
  42. twai_ll_clear_arb_lost_cap(hal_ctx->dev);
  43. twai_ll_clear_err_code_cap(hal_ctx->dev);
  44. hal_ctx->dev = NULL;
  45. }
  46. void twai_hal_configure(twai_hal_context_t *hal_ctx, const twai_timing_config_t *t_config, const twai_filter_config_t *f_config, uint32_t intr_mask, uint32_t clkout_divider)
  47. {
  48. uint32_t brp = t_config->brp;
  49. // both quanta_resolution_hz and brp can affect the baud rate
  50. // but a non-zero quanta_resolution_hz takes higher priority
  51. if (t_config->quanta_resolution_hz) {
  52. brp = hal_ctx->clock_source_hz / t_config->quanta_resolution_hz;
  53. }
  54. //Configure bus timing, acceptance filter, CLKOUT, and interrupts
  55. twai_ll_set_bus_timing(hal_ctx->dev, brp, t_config->sjw, t_config->tseg_1, t_config->tseg_2, t_config->triple_sampling);
  56. twai_ll_set_acc_filter(hal_ctx->dev, f_config->acceptance_code, f_config->acceptance_mask, f_config->single_filter);
  57. twai_ll_set_clkout(hal_ctx->dev, clkout_divider);
  58. twai_ll_set_enabled_intrs(hal_ctx->dev, intr_mask);
  59. (void) twai_ll_get_and_clear_intrs(hal_ctx->dev); //Clear any latched interrupts
  60. }
  61. /* -------------------------------- Actions --------------------------------- */
  62. void twai_hal_start(twai_hal_context_t *hal_ctx, twai_mode_t mode)
  63. {
  64. twai_ll_set_mode(hal_ctx->dev, mode); //Set operating mode
  65. //Clear the TEC and REC
  66. twai_ll_set_tec(hal_ctx->dev, 0);
  67. #ifdef CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM
  68. /*
  69. Errata workaround: Prevent transmission of dominant error frame while in listen only mode by setting REC to 128
  70. before exiting reset mode. This forces the controller to be error passive (thus only transmits recessive bits).
  71. The TEC/REC remain frozen in listen only mode thus ensuring we remain error passive.
  72. */
  73. if (mode == TWAI_MODE_LISTEN_ONLY) {
  74. twai_ll_set_rec(hal_ctx->dev, 128);
  75. } else
  76. #endif
  77. {
  78. twai_ll_set_rec(hal_ctx->dev, 0);
  79. }
  80. (void) twai_ll_get_and_clear_intrs(hal_ctx->dev); //Clear any latched interrupts
  81. TWAI_HAL_SET_BITS(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_RUNNING);
  82. twai_ll_exit_reset_mode(hal_ctx->dev);
  83. }
  84. void twai_hal_stop(twai_hal_context_t *hal_ctx)
  85. {
  86. twai_ll_enter_reset_mode(hal_ctx->dev);
  87. (void) twai_ll_get_and_clear_intrs(hal_ctx->dev);
  88. twai_ll_set_mode(hal_ctx->dev, TWAI_MODE_LISTEN_ONLY); //Freeze REC by changing to LOM mode
  89. //Any TX is immediately halted on entering reset mode
  90. TWAI_HAL_CLEAR_BITS(hal_ctx->state_flags, TWAI_HAL_STATE_FLAG_TX_BUFF_OCCUPIED | TWAI_HAL_STATE_FLAG_RUNNING);
  91. }