BLE5.2 1.0
开发文档说明
xc_drv_dma.c
浏览该文件的文档.
1
25/*-----------------------------------------------------------------------------------
26 INCLUDE HEADE FILES
27 ------------------------------------------------------------------------------------*/
28#include "xc_drv_dma.h"
29
30/*------------------------------------------------------------------------------------
31 Global Variables
32 -------------------------------------------------------------------------------------*/
34
35/*------------------------------------------------------------------------------------
36 Functions
37 -------------------------------------------------------------------------------------*/
48__RAM_CODE void xc_dma_set_test_mode(uint8_t mode)
49{
50 dma_test_reg_set(mode);
51}
52
65{
66 uint8_t priority[DMA_MAX_CHANNELS];
67 uint8_t i, ch_priority, order;
68
69 for (i = 0; i < DMA_MAX_CHANNELS; i++) {
70 priority[i] = 0;
71 inst->Ch_Order[i] = i;
72 }
73
74 for (uint8_t ch_num = 0; ch_num < DMA_MAX_CHANNELS; ch_num++) {
75 // read the priority of the current channel
76 ch_priority = dma_cfg_l__ch_prior__getf(ch_num);
77
78 // Check the channel order array to see what position
79 // this channel comes in the priority list.
80 for (i = 0; i <= DMA_MAX_CHANNELS; i++) {
81 if (A_MAXEQ_B(ch_priority, priority[i]) || i == DMA_MAX_CHANNELS) {
82 order = i;
83 break;
84 }
85 }
86
87 // Now we know the order for this channel insert in the correct
88 // array position and shift current priority ordering to suite.
89 for (i = ch_num; i > order; i--) {
90 priority[i] = priority[i - 1];
91 inst->Ch_Order[i] = inst->Ch_Order[i - 1];
92 }
93 priority[order] = ch_priority;
94 inst->Ch_Order[order] = ch_num;
95 }
96}
97
110{
111 for (uint8_t i = 0; i < DMA_MAX_CHANNELS; i++) {
112 switch (i) {
113 case 0:
114 inst->Ch[i].ch_num = DMA_CHANNEL0;
115 break;
116 case 1:
117 inst->Ch[i].ch_num = DMA_CHANNEL1;
118 break;
119 // case 2:
120 // inst->Ch[i].ch_num = DMA_CHANNEL2;
121 // break;
122 // case 3:
123 // inst->Ch[i].ch_num = DMA_CHANNEL3;
124 // break;
125 }
126
127 inst->Ch[i].userCallback = NULL;
128 inst->Ch[i].userListener = NULL;
129 }
130
131 // Set the channel priority order
133}
134
146__RAM_CODE uint8_t xc_dma_check_channel_range(eDMA_Ch_Num ch_num)
147{
148 uint8_t errorCode = DMA_OK;
149
150 if (ch_num == DMA_NO_CHANNEL || ch_num > DMA_ALL_CHANNELS) {
151 errorCode = DMA_ECHRNG;
152 }
153
154 return errorCode;
155}
156
168__RAM_CODE uint8_t xc_dma_check_channel_busy(eDMA_Ch_Num ch_num)
169{
170 uint8_t errorCode = DMA_OK;
171
172 if (ch_num == DMA_NO_CHANNEL || ch_num & (~DMA_ALL_CHANNELS)) {
173 errorCode = DMA_ECHRNG;
174 } else {
175 if (((uint16_t)dma_ch_en_reg_get( )) & ch_num) {
176 errorCode = DMA_EBUSY;
177 }
178 }
179
180 return errorCode;
181}
182
194__RAM_CODE uint8_t xc_dma_get_channel_index(eDMA_Ch_Num ch_num)
195{
196 uint8_t ch_enum = 1;
197 uint8_t ch_index = 0;
198
199 ch_num &= (DMA_ALL_CHANNELS >> 8);
200 while (ch_index < DMA_MAX_CHANNELS) {
201 if (ch_enum == ch_num) {
202 break;
203 }
204 ch_enum *= 2;
205 ch_index++;
206 }
207
208 return ch_index;
209}
210
222__RAM_CODE void xc_dma_enable(void) { dma_cfg_reg_set(ENABLE); }
223
235__RAM_CODE uint8_t xc_dma_disable(void)
236{
237 uint8_t errorCode = 0;
238 uint8_t dma_en = dma_cfg_reg__dma_en__getf( );
239
240 if (dma_en != 0) {
241 dma_cfg_reg_set(DISABLE);
242
243 // Ensure that the DMA was disabled
244 // May not disable due to split response on one
245 // of the DMA channels
246 if (dma_cfg_reg_get( )) {
247 errorCode = DMA_EBUSY;
248 }
249 }
250
251 return errorCode;
252}
253
266{
267 bool ret;
268
269 ret = (bool)dma_cfg_reg__dma_en__getf( );
270
271 return ret;
272}
273
285__RAM_CODE uint8_t xc_dma_enable_channel(eDMA_Ch_Num ch_num)
286{
287 uint8_t errorCode = 0;
288
289 // Check for valid channel number and not busy
290 errorCode = xc_dma_check_channel_busy(ch_num);
291 if (errorCode == 0) {
292 // The dw_dmac_channel_number enum is declared such that
293 // the enumerated value maps exactly to the value that
294 // needs to be written into the ChEnReg for enabling.
295 dma_ch_en_reg_set(ch_num);
296 }
297
298 return errorCode;
299}
300
312__RAM_CODE uint8_t xc_dma_disable_channel(eDMA_Ch_Num ch_num)
313{
314 uint8_t errorCode = 0;
315 uint32_t enabled_ch;
316
317 // Check for valid channel number
318 errorCode = xc_dma_check_channel_range(ch_num);
319
320 if (errorCode == 0) {
321 enabled_ch = (dma_ch_en_reg_get( ) & ch_num);
322 if (enabled_ch != 0) {
323 dma_ch_en_reg_set((ch_num & (DMA_ALL_CHANNELS << 8)));
324
325 // Ensure that the channel(s) was disabled.
326 // Channel may not disable due to a split response.
327 if (dma_ch_en_reg_get( ) & ch_num) {
328 errorCode = DMA_EBUSY;
329 }
330 }
331 }
332
333 return errorCode;
334}
335
348{
349 uint8_t ch_index;
350 bool ret;
351
352 ch_index = xc_dma_get_channel_index(ch_num);
353
354 // Allow only ONE channel to be specified
355 if (ch_index == DMA_MAX_CHANNELS)
356 return false;
357
358 // Check that the specified channel is in range
359 if (ch_num & (~DMA_ALL_CHANNELS))
360 return false;
361
362 ret = (bool)REG_BIT_VAL_GET(dma_ch_en_reg__ch_en__getf( ), 1 << ch_index, ch_index);
363
364 return ret;
365}
366
378__RAM_CODE uint8_t xc_dma_enable_channel_irq(eDMA_Ch_Num ch_num)
379{
380 uint8_t errorCode = DMA_OK;
381
382 // Check for valid channel number and not busy
383 errorCode = xc_dma_check_channel_busy(ch_num);
384
385 if (errorCode == 0) {
386 // Loop through each channel in turn and disable
387 // the channel Irq for the selected channels.
388 for (uint8_t x = 0; x < DMA_MAX_CHANNELS; x++) {
389 if (ch_num & (1 << x)) {
390 if (dma_ctl_l__int_en__getf(x) != 0x1) {
391 dma_ctl_l__int_en__setf(x, ENABLE);
392 }
393 }
394 }
395 }
396
397 return errorCode;
398}
399
411__RAM_CODE uint8_t xc_dma_disable_channel_irq(eDMA_Ch_Num ch_num)
412{
413 uint8_t errorCode = DMA_OK;
414
415 // Check for valid channel number and not busy
416 errorCode = xc_dma_check_channel_busy(ch_num);
417
418 if (errorCode == 0) {
419 // Loop through each channel in turn and disable
420 // the channel Irq for the selected channels.
421 for (uint8_t x = 0; x < DMA_MAX_CHANNELS; x++) {
422 if (ch_num & (1 << x)) {
423 if (dma_ctl_l__int_en__getf(x) != 0x0) {
424 dma_ctl_l__int_en__setf(x, DISABLE);
425 }
426 }
427 }
428 }
429
430 return errorCode;
431}
432
444__RAM_CODE uint8_t xc_dma_mask_irq(eDMA_Ch_Num ch_num, eDMA_Irq ch_irq)
445{
446 uint8_t errorCode = DMA_OK;
447 uint16_t reg;
448
449 // Check for valid channel number
450 errorCode = xc_dma_check_channel_range(ch_num);
451 if (errorCode == 0) {
452 // Loop through and clear the selected channel Irq
453 // for the targeted channels.
454 reg = (ch_num & (DMA_ALL_CHANNELS << 8));
455 for (uint8_t x = 0; x < DMA_MAX_INTERRUPTS; x++) {
456 if (ch_irq & (1 << x)) {
457 switch (x) {
458 case 0:
459 dma_mask_tfr_set(reg);
460 break;
461 case 1:
462 dma_mask_block_set(reg);
463 break;
464 case 2:
465 dma_mask_src_tran_set(reg);
466 break;
467 case 3:
468 dma_mask_dst_tran_set(reg);
469 break;
470 case 4:
471 dma_mask_err_set(reg);
472 break;
473 }
474 }
475 }
476 }
477
478 return errorCode;
479}
480
493{
494 uint8_t errorCode = DMA_OK;
495 uint16_t reg;
496
497 // Check for valid channel number
498 errorCode = xc_dma_check_channel_range(ch_num);
499 if (errorCode == 0) {
500 // Loop through and clear the selected channel Irq
501 // for the targeted channels.
502 reg = ch_num;
503 for (uint8_t x = 0; x < DMA_MAX_INTERRUPTS; x++) {
504 if (ch_irq & (1 << x)) {
505 switch (x) {
506 case 0:
507 dma_mask_tfr_set(reg);
508 break;
509 case 1:
510 dma_mask_block_set(reg);
511 break;
512 case 2:
513 dma_mask_src_tran_set(reg);
514 break;
515 case 3:
516 dma_mask_dst_tran_set(reg);
517 break;
518 case 4:
519 dma_mask_err_set(reg);
520 break;
521 }
522 }
523 }
524 }
525
526 return errorCode;
527}
528
540__RAM_CODE uint8_t xc_dma_clear_irq(eDMA_Ch_Num ch_num, eDMA_Irq ch_irq)
541{
542 uint8_t errorCode = DMA_OK;
543 uint16_t reg;
544
545 // Check for valid channel number
546 errorCode = xc_dma_check_channel_range(ch_num);
547 if (errorCode == 0) {
548 // Loop through and clear the selected channel Irq
549 // for the targeted channels.
550 reg = (ch_num & (DMA_ALL_CHANNELS >> 8));
551 for (uint8_t x = 0; x < DMA_MAX_INTERRUPTS; x++) {
552 if (ch_irq & (1 << x)) {
553 switch (x) {
554 case 0:
555 dma_clear_tfr_set(reg);
556 break;
557 case 1:
558 dma_clear_block_set(reg);
559 break;
560 case 2:
561 dma_clear_src_tran_set(reg);
562 break;
563 case 3:
564 dma_clear_dst_tran_set(reg);
565 break;
566 case 4:
567 dma_clear_err_set(reg);
568 break;
569 }
570 }
571 }
572 }
573
574 return errorCode;
575}
576
588__RAM_CODE uint8_t xc_dma_init(void)
589{
590 // Remove from test mode
591 xc_dma_set_test_mode(DISABLE);
592 // Reset the DMA instance structure
594 // Disable the DMA controller
595 uint8_t errorCode = xc_dma_disable( );
596 if (errorCode == 0) {
597 // Disable all DMA channels
599 }
600
601 if (errorCode == 0) {
602 // Disable all channel interrupts
604 }
605
606 if (errorCode == 0) {
607 // Mask all channel interrupts
609 }
610
611 if (errorCode == 0) {
612 // Clear any pending interrupts
614 }
615
616 return errorCode;
617}
618
630__RAM_CODE uint8_t xc_dma_set_channel_config(eDMA_Ch_Num ch_num,
631 DMA_Chx_Cfg_t *ch)
632{
633 uint8_t errorCode;
634 uint8_t ch_index;
635
636 ch_index = xc_dma_get_channel_index(ch_num);
637
638 // Check for valid channel number and not busy
639 errorCode = xc_dma_check_channel_busy(ch_num);
640 if (errorCode == 0) {
641 // Set the control register
642 dma_ctl_l_pack(ch_index, ch->ctl_tt_fc, ch->ctl_src_msize, ch->ctl_dst_msize,
644 0);
645
646 dma_ctl_h__block_ts__setf(ch_index, ch->ctl_block_ts);
647
648 // Set the config register
649 dma_cfg_l__hs_sel_src__setf(ch_index, ch->cfg_hs_sel_src);
650 dma_cfg_l__hs_sel_dst__setf(ch_index, ch->cfg_hs_sel_dst);
651
652 dma_cfg_h_pack(ch_index, (ch->cfg_dst_per & 0xf), (ch->cfg_src_per & 0xf), (ch->cfg_fifo_mode & 0x1));
653
654 // set the SAR/DAR registers
655 dma_sar_set(ch_index, ch->sar);
656 dma_dar_set(ch_index, ch->dar);
657 };
658
659 return errorCode;
660}
661
673__RAM_CODE bool xc_dma_set_listener(eDMA_Ch_Num ch_num,
674 DMA_Callback userFunction)
675{
676 uint8_t ch_index;
678
679 ch_index = xc_dma_get_channel_index(ch_num);
680
681 // Allow only ONE channel to be specified
682 if (ch_index == DMA_MAX_CHANNELS)
683 return false;
684
685 // Check that the specified channel is in range
686 if (ch_num & (~DMA_ALL_CHANNELS))
687 return false;
688
689 inst->Ch[ch_index].userListener = userFunction;
690
691 return true;
692}
693
705__RAM_CODE uint8_t xc_dma_start_transfer(eDMA_Ch_Num ch_num, DMA_Callback cb_func)
706{
707 uint8_t errorCode;
708 uint8_t ch_index;
709
711 // Update the channel instance
712 ch_index = xc_dma_get_channel_index(ch_num);
713
714 // Allow only ONE channel to be specified
715 if (ch_index == DMA_MAX_CHANNELS) {
716 errorCode = DMA_ECHRNG;
717 } else {
718 // Check for valid channel number and not busy
719 errorCode = xc_dma_check_channel_busy(ch_num);
720 }
721
722 if (errorCode == 0) {
723 // Disable the channels interrupts
724 errorCode = xc_dma_disable_channel_irq(ch_num);
725 }
726
727 if (errorCode == 0) {
728 // set the call back function, the number of blocks
729 // in the transfer and the source and destination states.
730 inst->Ch[ch_index].userCallback = cb_func;
731
732 // always want to unmask the tfr, block and err interrupts
735
736 // Enable the channel interrupts for the type of transfer
737 errorCode = xc_dma_enable_channel_irq(ch_num);
738
739 if (errorCode == 0) {
740 // Enable the DMA channel
741 errorCode = xc_dma_enable_channel(ch_num);
742 }
743 }
744
745 return errorCode;
746}
747
759__RAM_CODE bool dma_irq_handler(DMA_Instance_t *inst)
760{
761 bool retval;
762 uint8_t i, ch_index, callbackArg;
763 uint32_t reg, mask;
764 DMA_Callback userCallback;
765
766 // Assume an interrupt will be processed. The return value will be
767 // set to false if an active interrupt is not found.
768 retval = true;
769
770 // ERR INTERRUPT
771 if (dma_status_int__err__getf( )) {
772 reg = dma_status_err_get( );
773
774 // Loop through the channels until we find
775 // active interrupt. We start at the highest priority
776 // channel and work down to the lowest priority.
777 for (i = 0; i < DMA_MAX_CHANNELS; i++) {
778 mask = 1 << inst->Ch_Order[i];
779 if (reg & mask) {
780 ch_index = inst->Ch_Order[i];
781 break;
782 }
783 }
784
785 // run the listener function
786 if (inst->Ch[ch_index].userListener != NULL) {
787 userCallback = inst->Ch[ch_index].userListener;
788 callbackArg = DMA_IRQ_ERR;
789 userCallback(callbackArg);
790 }
791
792 // clear the interrupt
793 dma_clear_err_set(mask);
794 }
795 // TFR INTERRUPT
796 else if (dma_status_int__tfr__getf( )) {
797 reg = dma_status_tfr_get( );
798
799 // Loop through the channels until we find
800 // active interrupt. We start at the highest priority
801 // channel and work down to the lowest priority.
802 for (i = 0; i < DMA_MAX_CHANNELS; i++) {
803 mask = 1 << inst->Ch_Order[i];
804 if (reg & mask) {
805 ch_index = inst->Ch_Order[i];
806 break;
807 }
808 }
809
810 // Disable all channel interrupts
811 xc_dma_disable_channel_irq(inst->Ch[ch_index].ch_num);
812
813 // clear any pending block/srcTran/dstTran interrupts
814 dma_clear_block_set(mask);
815 dma_clear_src_tran_set(mask);
816 dma_clear_dst_tran_set(mask);
817 xc_dma_clear_irq(inst->Ch[ch_index].ch_num, DMA_IRQ_TRF);
818
819 // Mask all channel interrupts
820 xc_dma_mask_irq(inst->Ch[ch_index].ch_num, DMA_IRQ_ALL);
821
822 // run the callback function
823 if (inst->Ch[ch_index].userCallback != NULL) {
824 userCallback = inst->Ch[ch_index].userCallback;
825 callbackArg = 0;
826 userCallback(callbackArg);
827 }
828
829 } else {
830 // If we've reached this point, either the enabling and
831 // disabling of DW_ahb_dmac interrupts is not being handled
832 // properly or this function is being called unnecessarily.
833 retval = false;
834 }
835
836 return retval;
837}
838
839__RAM_CODE void DMA_Handler(void) { dma_irq_handler(&DMA_Instance); }
uint8_t Ch_Order[DMA_MAX_CHANNELS]
Definition xc_drv_dma.h:252
DMA_Callback userListener
Definition xc_drv_dma.h:250
struct dma_instance_s::@0 Ch[DMA_MAX_CHANNELS]
eDMA_Ch_Num ch_num
Definition xc_drv_dma.h:248
DMA_Callback userCallback
Definition xc_drv_dma.h:249
eDMA_Burst_Trans_Len ctl_dst_msize
Definition xc_drv_dma.h:218
eDMA_Fifo_Mode cfg_fifo_mode
Definition xc_drv_dma.h:227
eDMA_Trans_Width ctl_src_tr_width
Definition xc_drv_dma.h:221
eDMA_SW_HW_HS_Select cfg_hs_sel_src
Definition xc_drv_dma.h:228
eDMA_SW_HW_HS_Select cfg_hs_sel_dst
Definition xc_drv_dma.h:229
eDMA_Burst_Trans_Len ctl_src_msize
Definition xc_drv_dma.h:217
eDMA_Trans_Flow ctl_tt_fc
Definition xc_drv_dma.h:226
eDMA_Trans_Width ctl_dst_tr_width
Definition xc_drv_dma.h:222
eDMA_HS_Interface cfg_dst_per
Definition xc_drv_dma.h:223
eDMA_Addr_Increment ctl_dinc
Definition xc_drv_dma.h:220
eDMA_HS_Interface cfg_src_per
Definition xc_drv_dma.h:224
eDMA_Addr_Increment ctl_sinc
Definition xc_drv_dma.h:219
__RAM_CODE uint8_t xc_dma_enable_channel_irq(eDMA_Ch_Num ch_num)
xc_dma_enable_channel_irq
Definition xc_drv_dma.c:378
__RAM_CODE uint8_t xc_dma_check_channel_range(eDMA_Ch_Num ch_num)
xc_dma_check_channel_range
Definition xc_drv_dma.c:146
__RAM_CODE uint8_t xc_dma_disable(void)
xc_dma_disable
Definition xc_drv_dma.c:235
__RAM_CODE uint8_t xc_dma_check_channel_busy(eDMA_Ch_Num ch_num)
xc_dma_check_channel_busy
Definition xc_drv_dma.c:168
__RAM_CODE uint8_t xc_dma_disable_channel(eDMA_Ch_Num ch_num)
xc_dma_disable_channel
Definition xc_drv_dma.c:312
__RAM_CODE void xc_dma_set_channel_priority_order(DMA_Instance_t *inst)
xc_dma_set_channel_priority_order
Definition xc_drv_dma.c:64
__RAM_CODE uint8_t xc_dma_set_channel_config(eDMA_Ch_Num ch_num, DMA_Chx_Cfg_t *ch)
xc_dma_set_channel_config
Definition xc_drv_dma.c:630
__RAM_CODE bool xc_dma_set_listener(eDMA_Ch_Num ch_num, DMA_Callback userFunction)
xc_dma_set_listener
Definition xc_drv_dma.c:673
__RAM_CODE uint8_t xc_dma_clear_irq(eDMA_Ch_Num ch_num, eDMA_Irq ch_irq)
xc_dma_clear_irq
Definition xc_drv_dma.c:540
__RAM_CODE uint8_t xc_dma_init(void)
xc_dma_init
Definition xc_drv_dma.c:588
uint8_t xc_dma_unmask_irq(eDMA_Ch_Num ch_num, eDMA_Irq ch_irq)
xc_dma_unmask_irq
Definition xc_drv_dma.c:492
__RAM_CODE uint8_t xc_dma_enable_channel(eDMA_Ch_Num ch_num)
xc_dma_enable_channel
Definition xc_drv_dma.c:285
__RAM_CODE uint8_t xc_dma_disable_channel_irq(eDMA_Ch_Num ch_num)
xc_dma_disable_channel_irq
Definition xc_drv_dma.c:411
__RAM_CODE void xc_dma_enable(void)
xc_dma_enable
Definition xc_drv_dma.c:222
__RAM_CODE void xc_dma_reset_instance(DMA_Instance_t *inst)
xc_dma_reset_instance
Definition xc_drv_dma.c:109
__RAM_CODE void xc_dma_set_test_mode(uint8_t mode)
xc_dma_set_test_mode
Definition xc_drv_dma.c:48
bool xc_dma_is_channel_enabled(eDMA_Ch_Num ch_num)
xc_dma_is_channel_enabled
Definition xc_drv_dma.c:347
__RAM_CODE void DMA_Handler(void)
Definition xc_drv_dma.c:839
__RAM_CODE uint8_t xc_dma_mask_irq(eDMA_Ch_Num ch_num, eDMA_Irq ch_irq)
xc_dma_mask_irq
Definition xc_drv_dma.c:444
__RAM_CODE uint8_t xc_dma_start_transfer(eDMA_Ch_Num ch_num, DMA_Callback cb_func)
xc_dma_start_transfer
Definition xc_drv_dma.c:705
bool xc_dma_is_enable(void)
xc_dma_is_enable
Definition xc_drv_dma.c:265
__RAM_CODE uint8_t xc_dma_get_channel_index(eDMA_Ch_Num ch_num)
xc_dma_get_channel_index
Definition xc_drv_dma.c:194
DMA_Instance_t DMA_Instance
Definition xc_drv_dma.c:33
__RAM_CODE bool dma_irq_handler(DMA_Instance_t *inst)
dma_irq_handler
Definition xc_drv_dma.c:759
The header of xc_drv_dma.c
@ DMA_IRQ_TRF
Definition xc_drv_dma.h:120
@ DMA_IRQ_ERR
Definition xc_drv_dma.h:124
@ DMA_IRQ_ALL
Definition xc_drv_dma.h:125
enum dw_dmac_irq eDMA_Irq
enum dmac_channel_number eDMA_Ch_Num
@ DMA_ALL_CHANNELS
Definition xc_drv_dma.h:73
@ DMA_CHANNEL1
Definition xc_drv_dma.h:72
@ DMA_CHANNEL0
Definition xc_drv_dma.h:71
@ DMA_NO_CHANNEL
Definition xc_drv_dma.h:70
void(* DMA_Callback)(uint8_t eCode)
Definition xc_drv_dma.h:65