drv_pwm.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-03-12 wcx1024979076 first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include "drv_pwm.h"
  13. #ifdef BSP_USING_PWM
  14. #define DBG_LEVEL DBG_LOG
  15. #include <rtdbg.h>
  16. #define LOG_TAG "DRV.PWM"
  17. static rt_err_t _pwm_set(rt_uint8_t channel, struct rt_pwm_configuration *configuration)
  18. {
  19. struct bflb_device_s* pwm = bflb_device_get_by_name("pwm_v2_0");
  20. uint32_t period_hz = 1000000000 / configuration->period;
  21. struct bflb_pwm_v2_config_s pwm_config;
  22. pwm_config.clk_source = BFLB_SYSTEM_XCLK;
  23. pwm_config.clk_div = 40;
  24. pwm_config.period = 1000000 / period_hz;
  25. bflb_pwm_v2_init(pwm, &pwm_config);
  26. struct bflb_pwm_v2_channel_config_s pwm_ch_config = {
  27. .positive_polarity = PWM_POLARITY_ACTIVE_HIGH,
  28. .negative_polarity = PWM_POLARITY_ACTIVE_HIGH,
  29. .positive_stop_state = PWM_STATE_INACTIVE,
  30. .negative_stop_state = PWM_STATE_ACTIVE,
  31. .positive_brake_state = PWM_STATE_INACTIVE,
  32. .negative_brake_state = PWM_STATE_INACTIVE,
  33. .dead_time = 0,
  34. };
  35. bflb_pwm_v2_channel_init(pwm, channel, &pwm_ch_config);
  36. bflb_pwm_v2_channel_set_threshold(pwm, channel, 0, configuration->pulse);
  37. bflb_pwm_v2_channel_positive_stop(pwm, channel);
  38. bflb_pwm_v2_channel_negative_stop(pwm, channel);
  39. bflb_pwm_v2_stop(pwm);
  40. bflb_pwm_v2_channel_positive_start(pwm, channel);
  41. bflb_pwm_v2_channel_negative_start(pwm, channel);
  42. bflb_pwm_v2_start(pwm);
  43. return RT_EOK;
  44. }
  45. static rt_err_t _pwm_get(rt_uint8_t channel, struct rt_pwm_configuration *configuration)
  46. {
  47. uint32_t reg_base, regval, tmp;
  48. float period;
  49. reg_base = bflb_device_get_by_name("pwm_v2_0")->reg_base;
  50. regval = getreg32(reg_base + PWM_MC0_PERIOD_OFFSET);
  51. tmp = (regval & PWM_PERIOD_MASK) >> PWM_PERIOD_SHIFT;
  52. period = (float)tmp;
  53. uint32_t period_hz = 1000000 / period;
  54. regval = getreg32(reg_base + PWM_MC0_CH0_THRE_OFFSET + channel * 4);
  55. uint16_t high_threhold = regval >> 16;
  56. uint16_t low_threhold = regval;
  57. configuration->period = 1000000000 / period_hz;
  58. configuration->pulse = high_threhold;
  59. return RT_EOK;
  60. }
  61. static rt_err_t _pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
  62. {
  63. struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
  64. rt_uint32_t channel = 0;
  65. channel = configuration->channel;
  66. if (channel >= 4)
  67. return -RT_EINVAL;
  68. struct bflb_device_s* pwm = bflb_device_get_by_name("pwm_v2_0");
  69. switch (cmd)
  70. {
  71. case PWM_CMD_ENABLE:
  72. bflb_pwm_v2_channel_positive_start(pwm, channel);
  73. bflb_pwm_v2_channel_negative_start(pwm, channel);
  74. return RT_EOK;
  75. case PWM_CMD_DISABLE:
  76. bflb_pwm_v2_channel_positive_stop(pwm, channel);
  77. bflb_pwm_v2_channel_negative_stop(pwm, channel);
  78. return RT_EOK;
  79. case PWM_CMD_SET:
  80. return _pwm_set(channel, configuration);
  81. case PWM_CMD_GET:
  82. return _pwm_get(channel, configuration);
  83. default:
  84. return -RT_EINVAL;
  85. }
  86. }
  87. static struct rt_pwm_ops _pwm_ops =
  88. {
  89. _pwm_control
  90. };
  91. static struct rt_device_pwm pwm_device;
  92. int rt_hw_pwm_init(void)
  93. {
  94. int result = RT_EOK;
  95. struct bflb_device_s* gpio = bflb_device_get_by_name("gpio");
  96. bflb_gpio_init(gpio, GPIO_PIN_8, GPIO_FUNC_PWM0 | GPIO_ALTERNATE | GPIO_PULLDOWN | GPIO_SMT_EN | GPIO_DRV_1);
  97. struct bflb_device_s* pwm = bflb_device_get_by_name("pwm_v2_0");
  98. bflb_pwm_v2_start(pwm);
  99. result = rt_device_pwm_register(&pwm_device, "pwm", &_pwm_ops, 0);
  100. if(result != RT_EOK)
  101. {
  102. LOG_E("pwm device register fail.");
  103. }
  104. return result;
  105. }
  106. INIT_DEVICE_EXPORT(rt_hw_pwm_init);
  107. #endif /* BSP_USING_PWM */