1 
2 /* Copyright Canaan Inc.
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 #include <rtthread.h>
18 #include "dmalock.h"
19 
20 struct dmac_host
21 {
22     struct rt_semaphore sem;
23     struct rt_mutex mutex;
24     uint8_t channel_used[DMAC_CHANNEL_COUNT];
25     char *channel_name[DMAC_CHANNEL_COUNT];
26 };
27 
28 static struct dmac_host _dmac_host;
29 
dmalock_init(void)30 void dmalock_init(void)
31 {
32     rt_sem_init(&_dmac_host.sem, "dma_sem", DMAC_CHANNEL_COUNT, RT_IPC_FLAG_FIFO);
33     rt_mutex_init(&_dmac_host.mutex, "dma_mutex", RT_IPC_FLAG_PRIO);
34     for (int i = 0; i < DMAC_CHANNEL_COUNT; i++)
35     {
36         _dmac_host.channel_used[i] = 0;
37         _dmac_host.channel_name[i] = NULL;
38     }
39 }
40 
_dmalock_sync_take(dmac_channel_number_t * chn,int timeout_ms,const char * name)41 int _dmalock_sync_take(dmac_channel_number_t *chn, int timeout_ms, const char *name)
42 {
43     rt_err_t result;
44 
45     *chn = DMAC_CHANNEL_MAX;
46     result = rt_sem_take(&_dmac_host.sem, timeout_ms);
47     if (result == RT_EOK)
48     {
49         rt_mutex_take(&_dmac_host.mutex, RT_WAITING_FOREVER);
50         for (int i = 0; i < DMAC_CHANNEL_COUNT; i++)
51         {
52             if (_dmac_host.channel_used[i] == 0)
53             {
54                 _dmac_host.channel_used[i] = 1;
55                 _dmac_host.channel_name[i] = name;
56                 *chn = i;
57                 break;
58             }
59         }
60         rt_mutex_release(&_dmac_host.mutex);
61     }
62     return result;
63 }
64 
dmalock_release(dmac_channel_number_t chn)65 void dmalock_release(dmac_channel_number_t chn)
66 {
67     if (chn >= DMAC_CHANNEL_MAX)
68         return;
69     _dmac_host.channel_name[chn] = NULL;
70     _dmac_host.channel_used[chn] = 0;
71     rt_sem_release(&_dmac_host.sem);
72 }
73 
dma_ch_info(int argc,char ** argv)74 static void dma_ch_info(int argc, char **argv)
75 {
76     uint32_t cnt = 0;
77 
78     for (int i = 0; i < DMAC_CHANNEL_COUNT; i++)
79     {
80         if (_dmac_host.channel_used[i] != 0)
81         {
82             rt_kprintf("dma_ch%d is using by func [%s]\n", i, _dmac_host.channel_name[i]);
83             cnt++;
84         }
85     }
86 
87     if(cnt == 0)
88         rt_kprintf(" no dma_ch is using.\n");
89 }
90 MSH_CMD_EXPORT(dma_ch_info, list dma channel informationn.);
91