ck_pwm.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /******************************************************************************
  17. * @file ck_pwm.c
  18. * @brief CSI Source File for PWM Driver
  19. * @version V1.0
  20. * @date 02. June 2017
  21. ******************************************************************************/
  22. #include "ck_pwm.h"
  23. #include "drv_pwm.h"
  24. #include "soc.h"
  25. #define ERR_PWM(errno) (CSI_DRV_ERRNO_PWM_BASE | errno)
  26. #define PWM_NULL_PARAM_CHK(para) \
  27. do { \
  28. if (para == NULL) { \
  29. return ERR_PWM(EDRV_PARAMETER); \
  30. } \
  31. } while (0)
  32. typedef struct {
  33. uint32_t base;
  34. uint32_t irq;
  35. uint32_t ch_num;
  36. } ck_pwm_priv_t;
  37. static ck_pwm_priv_t pwm_instance[CONFIG_PWM_NUM];
  38. int32_t __attribute__((weak)) target_pwm_init(pin_t pwm_pin, uint32_t *ch_num, uint32_t *base, uint32_t *irq)
  39. {
  40. return -1;
  41. }
  42. /**
  43. \brief Initialize PWM Interface. 1. Initializes the resources needed for the PWM interface 2.registers event callback function
  44. \param[in] pwm pin of gpio
  45. \return handle pwm handle to operate.
  46. */
  47. pwm_handle_t drv_pwm_initialize(pin_t pwm_pin)
  48. {
  49. uint32_t base = 0u;
  50. uint32_t irq = 0u;
  51. uint32_t ch_num = 0u;
  52. int32_t idx = target_pwm_init(pwm_pin, &ch_num, &base, &irq);
  53. if (idx < 0 || idx >= CONFIG_PWM_NUM) {
  54. return NULL;
  55. }
  56. ck_pwm_priv_t *pwm_priv = &pwm_instance[idx];
  57. pwm_priv->base = base;
  58. pwm_priv->irq = irq;
  59. pwm_priv->ch_num = ch_num;
  60. return pwm_priv;
  61. }
  62. /**
  63. \brief De-initialize PWM Interface. stops operation and releases the software resources used by the interface
  64. \param[in] handle pwm handle to operate.
  65. \return \ref execution_status
  66. */
  67. int32_t drv_pwm_uninitialize(pwm_handle_t handle)
  68. {
  69. PWM_NULL_PARAM_CHK(handle);
  70. return 0;
  71. }
  72. /**
  73. \brief config pwm mode.
  74. \param[in] handle pwm handle to operate.
  75. \param[in] sysclk configured system clock.
  76. \param[in] period_us the PWM period in us
  77. \param[in] duty the PMW duty. ( 0 - 10000 represents 0% - 100% ,other values are invalid)
  78. \return \ref execution_status
  79. */
  80. int32_t drv_pwm_config(pwm_handle_t handle, uint32_t sysclk, uint32_t period_us, uint32_t duty)
  81. {
  82. if (handle == NULL || duty > 10000) {
  83. return ERR_PWM(EDRV_PARAMETER);
  84. }
  85. ck_pwm_priv_t *pwm_priv = handle;
  86. uint32_t chn = pwm_priv->ch_num;
  87. uint32_t counter = (sysclk / 1000000 * period_us);
  88. if (counter >= 0xffff) {
  89. return ERR_PWM(EDRV_PARAMETER);
  90. }
  91. uint32_t data_width;
  92. data_width = (uint32_t)((counter * duty / 10000));
  93. ck_pwm_reg_t *addr = (ck_pwm_reg_t *)(pwm_priv->base);
  94. uint32_t ctl_tmp = addr->PWMCTL;
  95. uint32_t temp;
  96. if (chn == CKENUM_PWM_CH0 || chn == CKENUM_PWM_CH1) {
  97. ctl_tmp &= 0xfffffffe;
  98. addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP;
  99. temp = addr->PWM01LOAD;
  100. temp &= 0xffff0000;
  101. addr->PWM01LOAD = temp | counter;
  102. temp = addr->PWM0CMP;
  103. if (chn == CKENUM_PWM_CH0) {
  104. temp &= 0xffff0000;
  105. addr->PWM0CMP = temp | data_width;
  106. } else {
  107. temp &= 0x0000ffff;
  108. addr->PWM0CMP = temp | data_width << 16;
  109. }
  110. }
  111. if (chn == CKENUM_PWM_CH2 || chn == CKENUM_PWM_CH3) {
  112. ctl_tmp &= 0xfffffffd;
  113. addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 1;
  114. temp = addr->PWM01LOAD;
  115. temp &= 0x0000ffff;
  116. addr->PWM01LOAD = temp | counter << 16 ;
  117. temp = addr->PWM1CMP;
  118. if (chn == CKENUM_PWM_CH2) {
  119. temp &= 0xffff0000;
  120. addr->PWM1CMP = temp | data_width;
  121. } else {
  122. temp &= 0x0000ffff;
  123. addr->PWM1CMP = temp | data_width << 16;
  124. }
  125. }
  126. if (chn == CKENUM_PWM_CH4 || chn == CKENUM_PWM_CH5) {
  127. ctl_tmp &= 0xfffffffb;
  128. addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 2;
  129. temp = addr->PWM23LOAD;
  130. temp &= 0xffff0000;
  131. addr->PWM23LOAD = temp | counter;
  132. temp = addr->PWM2CMP;
  133. if (chn == CKENUM_PWM_CH4) {
  134. temp &= 0xffff0000;
  135. addr->PWM2CMP = temp | data_width;
  136. } else {
  137. temp &= 0x0000ffff;
  138. addr->PWM2CMP = temp | data_width << 16;
  139. }
  140. }
  141. if (chn == CKENUM_PWM_CH6 || chn == CKENUM_PWM_CH7) {
  142. ctl_tmp &= 0xfffffff7;
  143. addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 3;
  144. temp = addr->PWM23LOAD;
  145. temp &= 0x0000ffff;
  146. addr->PWM23LOAD = temp | counter << 16 ;
  147. temp = addr->PWM3CMP;
  148. if (chn == CKENUM_PWM_CH6) {
  149. temp &= 0xffff0000;
  150. addr->PWM3CMP = temp | data_width;
  151. } else {
  152. temp &= 0x0000ffff;
  153. addr->PWM3CMP = temp | data_width << 16;
  154. }
  155. }
  156. if (chn == CKENUM_PWM_CH8 || chn == CKENUM_PWM_CH9) {
  157. ctl_tmp &= 0xffffffef;
  158. addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 4;
  159. temp = addr->PWM45LOAD;
  160. temp &= 0xffff0000;
  161. addr->PWM45LOAD = temp | counter ;
  162. temp = addr->PWM4CMP;
  163. if (chn == CKENUM_PWM_CH8) {
  164. temp &= 0xffff0000;
  165. addr->PWM4CMP = temp | data_width;
  166. } else {
  167. temp &= 0x0000ffff;
  168. addr->PWM4CMP = temp | data_width << 16;
  169. }
  170. }
  171. if (chn == CKENUM_PWM_CH10 || chn == CKENUM_PWM_CH11) {
  172. ctl_tmp &= 0xffffffdf;
  173. addr->PWMCTL = ctl_tmp | (uint32_t)CKENUM_PWM_COUNT_UP << 5;
  174. temp = addr->PWM45LOAD;
  175. temp &= 0x0000ffff;
  176. addr->PWM45LOAD = temp | counter << 16 ;
  177. temp = addr->PWM5CMP;
  178. if (chn == CKENUM_PWM_CH10) {
  179. temp &= 0xffff0000;
  180. addr->PWM5CMP = temp | data_width;
  181. } else {
  182. temp &= 0x0000ffff;
  183. addr->PWM5CMP = temp | data_width << 16;
  184. }
  185. }
  186. return 0;
  187. }
  188. /**
  189. \brief start generate pwm signal.
  190. \param[in] handle pwm handle to operate.
  191. \param[in] pwm channel number.
  192. \return \ref execution_status
  193. */
  194. int32_t drv_pwm_start(pwm_handle_t handle)
  195. {
  196. PWM_NULL_PARAM_CHK(handle);
  197. ck_pwm_priv_t *pwm_priv = handle;
  198. ck_pwm_reg_t *addr = (ck_pwm_reg_t *)(pwm_priv->base);
  199. uint32_t chn = pwm_priv->ch_num;
  200. if (chn == CKENUM_PWM_CH0 || chn == CKENUM_PWM_CH1) {
  201. addr->PWMCFG |= 0x00000003; /* PWM0 output enable */
  202. }
  203. if (chn == CKENUM_PWM_CH2 || chn == CKENUM_PWM_CH3) {
  204. addr->PWMCFG |= 0x0000000C; /* PWM1 output enable */
  205. }
  206. if (chn == CKENUM_PWM_CH4 || chn == CKENUM_PWM_CH5) {
  207. addr->PWMCFG |= 0x00000030; /* PWM2 output enable */
  208. }
  209. if (chn == CKENUM_PWM_CH6 || chn == CKENUM_PWM_CH7) {
  210. addr->PWMCFG |= 0x000000C0; /* PWM3 output enable */
  211. }
  212. if (chn == CKENUM_PWM_CH8 || chn == CKENUM_PWM_CH9) {
  213. addr->PWMCFG |= 0x00000300; /* PWM4 output enable */
  214. }
  215. if (chn == CKENUM_PWM_CH10 || chn == CKENUM_PWM_CH11) {
  216. addr->PWMCFG |= 0x00000C00; /* PWM5 output enable */
  217. }
  218. return 0;
  219. }
  220. /**
  221. \brief Stop generate pwm signal.
  222. \param[in] handle pwm handle to operate.
  223. \return \ref execution_status
  224. */
  225. int32_t drv_pwm_stop(pwm_handle_t handle)
  226. {
  227. PWM_NULL_PARAM_CHK(handle);
  228. ck_pwm_priv_t *pwm_priv = handle;
  229. ck_pwm_reg_t *addr = (ck_pwm_reg_t *)(pwm_priv->base);
  230. uint32_t chn = pwm_priv->ch_num;
  231. if (chn == CKENUM_PWM_CH0 || chn == CKENUM_PWM_CH1) {
  232. addr->PWMCFG &= ~0x00000003; /* PWM0 output disable */
  233. }
  234. if (chn == CKENUM_PWM_CH2 || chn == CKENUM_PWM_CH3) {
  235. addr->PWMCFG &= ~0x0000000C; /* PWM1 output disable */
  236. }
  237. if (chn == CKENUM_PWM_CH4 || chn == CKENUM_PWM_CH5) {
  238. addr->PWMCFG &= ~0x00000030; /* PWM2 output disable */
  239. }
  240. if (chn == CKENUM_PWM_CH6 || chn == CKENUM_PWM_CH7) {
  241. addr->PWMCFG &= ~0x000000C0; /* PWM3 output disable */
  242. }
  243. if (chn == CKENUM_PWM_CH8 || chn == CKENUM_PWM_CH9) {
  244. addr->PWMCFG &= ~0x00000300; /* PWM4 output disable */
  245. }
  246. if (chn == CKENUM_PWM_CH10 || chn == CKENUM_PWM_CH11) {
  247. addr->PWMCFG &= ~0x00000C00; /* PWM5 output disable */
  248. }
  249. return 0;
  250. }