1
1
/*
2
- * Copyright (c) 2017-2019 Thomas Roell. All rights reserved.
2
+ * Copyright (c) 2017-2020 Thomas Roell. All rights reserved.
3
3
*
4
4
* Permission is hereby granted, free of charge, to any person obtaining a copy
5
5
* of this software and associated documentation files (the "Software"), to
30
30
#include "stm32l0_dma.h"
31
31
#include "stm32l0_system.h"
32
32
33
+ #define STM32L0_DMA_CHANNEL_LOCKED 0x8000
34
+
33
35
extern void DMA1_Channel1_IRQHandler (void );
34
36
extern void DMA1_Channel2_3_IRQHandler (void );
35
37
extern void DMA1_Channel4_5_6_7_IRQHandler (void );
@@ -45,7 +47,7 @@ static DMA_Channel_TypeDef * const stm32l0_dma_xlate_DMA[7] = {
45
47
};
46
48
47
49
typedef struct _stm32l0_dma_t {
48
- uint8_t channel ;
50
+ volatile uint16_t channel ;
49
51
uint16_t size ;
50
52
stm32l0_dma_callback_t callback ;
51
53
void * context ;
@@ -56,8 +58,7 @@ typedef struct _stm32l0_dma_device_t {
56
58
uint8_t priority_1 ;
57
59
uint8_t priority_2_3 ;
58
60
uint8_t priority_4_5_6_7 ;
59
- volatile uint16_t dma ;
60
- volatile uint16_t lock ;
61
+ volatile uint8_t dma ;
61
62
} stm32l0_dma_device_t ;
62
63
63
64
static stm32l0_dma_device_t stm32l0_dma_device ;
@@ -109,81 +110,48 @@ unsigned int stm32l0_dma_priority(unsigned int channel)
109
110
110
111
unsigned int stm32l0_dma_channel (unsigned int channel )
111
112
{
112
- return ((stm32l0_dma_device .dma & (1ul << (channel & 7 ))) ? stm32l0_dma_device .channels [channel & 7 ].channel : STM32L0_DMA_CHANNEL_UNDEFINED );
113
+ uint32_t index , mask ;
114
+
115
+ index = channel & 7 ;
116
+ mask = 1ul << index ;
117
+
118
+ return ((stm32l0_dma_device .dma & mask ) ? (stm32l0_dma_device .channels [index ].channel & STM32L0_DMA_CHANNEL_MASK ): STM32L0_DMA_CHANNEL_UNDEFINED );
113
119
}
114
120
115
121
bool stm32l0_dma_lock (unsigned int channel )
116
122
{
117
123
stm32l0_dma_t * dma = & stm32l0_dma_device .channels [channel & 7 ];
118
- uint32_t primask , mask ;
119
-
120
- mask = 1ul << (channel & 7 );
121
-
122
- primask = __get_PRIMASK ();
123
-
124
- __disable_irq ();
125
-
126
- if (stm32l0_dma_device .lock & mask )
127
- {
128
- __set_PRIMASK (primask );
129
124
130
- return false;
131
- }
132
-
133
- dma -> channel = channel ;
134
-
135
- stm32l0_dma_device .lock |= mask ;
136
-
137
- __set_PRIMASK (primask );
138
-
139
- return true;
125
+ return (armv6m_atomic_cash (& dma -> channel , STM32L0_DMA_CHANNEL_NONE , channel ) == STM32L0_DMA_CHANNEL_NONE );
140
126
}
141
127
142
128
void stm32l0_dma_unlock (unsigned int channel )
143
129
{
144
- uint32_t primask , mask ;
145
-
146
- mask = 1ul << (channel & 7 );
147
-
148
- primask = __get_PRIMASK ();
149
-
150
- __disable_irq ();
151
-
152
- stm32l0_dma_device .lock &= ~mask ;
130
+ stm32l0_dma_t * dma = & stm32l0_dma_device .channels [channel & 7 ];
153
131
154
- __set_PRIMASK ( primask ) ;
132
+ dma -> channel = STM32L0_DMA_CHANNEL_NONE ;
155
133
}
156
134
157
135
bool stm32l0_dma_enable (unsigned int channel , stm32l0_dma_callback_t callback , void * context )
158
136
{
159
137
stm32l0_dma_t * dma = & stm32l0_dma_device .channels [channel & 7 ];
160
138
unsigned int shift ;
161
- uint32_t primask , mask ;
139
+ uint32_t primask , mask , o_channel ;
140
+
141
+ o_channel = armv6m_atomic_cash (& dma -> channel , STM32L0_DMA_CHANNEL_NONE , channel );
162
142
143
+ if ((o_channel != STM32L0_DMA_CHANNEL_NONE ) && (o_channel != (STM32L0_DMA_CHANNEL_LOCKED | channel )))
144
+ {
145
+ return false;
146
+ }
147
+
163
148
shift = (channel & 7 ) << 2 ;
164
149
mask = 1ul << (channel & 7 );
165
150
166
151
primask = __get_PRIMASK ();
167
152
168
153
__disable_irq ();
169
154
170
- if (stm32l0_dma_device .dma & mask )
171
- {
172
- __set_PRIMASK (primask );
173
-
174
- return false;
175
- }
176
-
177
- if (stm32l0_dma_device .lock & mask )
178
- {
179
- if (dma -> channel != channel )
180
- {
181
- __set_PRIMASK (primask );
182
-
183
- return false;
184
- }
185
- }
186
-
187
155
if (!stm32l0_dma_device .dma )
188
156
{
189
157
RCC -> AHBENR |= RCC_AHBENR_DMAEN ;
@@ -192,10 +160,10 @@ bool stm32l0_dma_enable(unsigned int channel, stm32l0_dma_callback_t callback, v
192
160
193
161
stm32l0_dma_device .dma |= mask ;
194
162
195
- DMA1_CSELR -> CSELR = (DMA1_CSELR -> CSELR & ~(15 << shift )) | ((channel >> 4 ) << shift );
196
-
197
163
__set_PRIMASK (primask );
198
164
165
+ armv6m_atomic_modify (& DMA1_CSELR -> CSELR , (15 << shift ), ((channel >> 4 ) << shift ));
166
+
199
167
dma -> channel = channel ;
200
168
dma -> callback = callback ;
201
169
dma -> context = context ;
@@ -205,6 +173,7 @@ bool stm32l0_dma_enable(unsigned int channel, stm32l0_dma_callback_t callback, v
205
173
206
174
void stm32l0_dma_disable (unsigned int channel )
207
175
{
176
+ stm32l0_dma_t * dma = & stm32l0_dma_device .channels [channel & 7 ];
208
177
uint32_t primask , mask ;
209
178
210
179
mask = 1ul << (channel & 7 );
@@ -222,6 +191,11 @@ void stm32l0_dma_disable(unsigned int channel)
222
191
}
223
192
224
193
__set_PRIMASK (primask );
194
+
195
+ if (!(dma -> channel & STM32L0_DMA_CHANNEL_LOCKED ))
196
+ {
197
+ dma -> channel = STM32L0_DMA_CHANNEL_NONE ;
198
+ }
225
199
}
226
200
227
201
void stm32l0_dma_start (unsigned int channel , uint32_t tx_data , uint32_t rx_data , uint16_t xf_count , uint32_t option )
0 commit comments