@@ -45,16 +45,21 @@ struct pwm_sam0_config {
45
45
};
46
46
47
47
#define COUNTER_8BITS 8U
48
+ #define COUNTER_16BITS 16U
49
+ #define SYNC_WAIT_TIMEOUT 5U
50
+
48
51
49
52
/* Wait for the peripheral to finish all commands */
50
53
static void wait_synchronization (Tc * regs , uint8_t counter_size )
51
54
{
52
55
if (COUNTER_8BITS == counter_size ) {
53
56
while (regs -> COUNT8 .SYNCBUSY .reg != 0 ) {
54
57
}
55
- } else {
58
+ } else if ( COUNTER_16BITS == counter_size ) {
56
59
while (regs -> COUNT16 .SYNCBUSY .reg != 0 ) {
57
60
}
61
+ } else {
62
+ WAIT_FOR ((regs -> COUNT32 .SYNCBUSY .reg != 0 ), SYNC_WAIT_TIMEOUT , NULL );
58
63
}
59
64
}
60
65
@@ -78,15 +83,14 @@ static int pwm_sam0_set_cycles(const struct device *dev, uint32_t channel, uint3
78
83
const struct pwm_sam0_config * const cfg = dev -> config ;
79
84
Tc * regs = cfg -> regs ;
80
85
uint8_t counter_size = cfg -> counter_size ;
81
- uint32_t top = 1 << counter_size ;
86
+ uint64_t top = BIT64 ( counter_size ) ;
82
87
uint32_t invert_mask = 1 << channel ;
83
88
bool invert = ((flags & PWM_POLARITY_INVERTED ) != 0 );
84
89
bool inverted ;
85
-
86
90
if (channel >= cfg -> channels ) {
87
91
return - EINVAL ;
88
92
}
89
- if (period_cycles >= top || pulse_cycles >= top ) {
93
+ if (( uint64_t ) period_cycles >= top || pulse_cycles >= top ) {
90
94
return - EINVAL ;
91
95
}
92
96
@@ -108,7 +112,7 @@ static int pwm_sam0_set_cycles(const struct device *dev, uint32_t channel, uint3
108
112
regs -> COUNT8 .CTRLA .bit .ENABLE = 1 ;
109
113
wait_synchronization (regs , counter_size );
110
114
}
111
- } else {
115
+ } else if ( COUNTER_16BITS == counter_size ) {
112
116
inverted = ((regs -> COUNT16 .DRVCTRL .vec .INVEN & invert_mask ) != 0 );
113
117
regs -> COUNT16 .CCBUF [0 ].reg = TC_COUNT16_CCBUF_CCBUF (period_cycles );
114
118
regs -> COUNT16 .CCBUF [1 ].reg = TC_COUNT16_CCBUF_CCBUF (pulse_cycles );
@@ -122,6 +126,20 @@ static int pwm_sam0_set_cycles(const struct device *dev, uint32_t channel, uint3
122
126
regs -> COUNT16 .CTRLA .bit .ENABLE = 1 ;
123
127
wait_synchronization (regs , counter_size );
124
128
}
129
+ } else {
130
+ inverted = ((regs -> COUNT32 .DRVCTRL .vec .INVEN & invert_mask ) != 0 );
131
+ regs -> COUNT32 .CCBUF [0 ].reg = TC_COUNT32_CCBUF_CCBUF (period_cycles );
132
+ regs -> COUNT32 .CCBUF [1 ].reg = TC_COUNT32_CCBUF_CCBUF (pulse_cycles );
133
+ wait_synchronization (regs , counter_size );
134
+
135
+ if (invert != inverted ) {
136
+ regs -> COUNT32 .CTRLA .bit .ENABLE = 0 ;
137
+ wait_synchronization (regs , counter_size );
138
+
139
+ regs -> COUNT32 .DRVCTRL .vec .INVEN ^= invert_mask ;
140
+ regs -> COUNT32 .CTRLA .bit .ENABLE = 1 ;
141
+ wait_synchronization (regs , counter_size );
142
+ }
125
143
}
126
144
127
145
return 0 ;
@@ -161,7 +179,7 @@ static int pwm_sam0_init(const struct device *dev)
161
179
162
180
regs -> COUNT8 .CTRLA .bit .ENABLE = 1 ;
163
181
wait_synchronization (regs , counter_size );
164
- } else {
182
+ } else if ( COUNTER_16BITS == counter_size ) {
165
183
regs -> COUNT16 .CTRLA .bit .SWRST = 1 ;
166
184
wait_synchronization (regs , counter_size );
167
185
@@ -172,6 +190,16 @@ static int pwm_sam0_init(const struct device *dev)
172
190
173
191
regs -> COUNT16 .CTRLA .bit .ENABLE = 1 ;
174
192
wait_synchronization (regs , cfg -> counter_size );
193
+ } else {
194
+ regs -> COUNT32 .CTRLA .bit .SWRST = 1 ;
195
+ wait_synchronization (regs , counter_size );
196
+ regs -> COUNT32 .CTRLA .reg = cfg -> prescaler | TC_CTRLA_MODE_COUNT32 |
197
+ TC_CTRLA_PRESCSYNC_PRESC ;
198
+ regs -> COUNT32 .WAVE .reg = TC_WAVE_WAVEGEN_MPWM ;
199
+ regs -> COUNT32 .CC [0 ].reg = TC_COUNT32_CC_CC (1 );
200
+
201
+ regs -> COUNT32 .CTRLA .bit .ENABLE = 1 ;
202
+ wait_synchronization (regs , counter_size );
175
203
}
176
204
177
205
return 0 ;
0 commit comments