stm32_dac_driver.c 7.94 KB
Newer Older
Clément Foucher's avatar
Clément Foucher committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/*
 * Copyright (c) 2021 LAAS-CNRS
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published by
 *   the Free Software Foundation, either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: LGLPV2.1
 */

/**
 * @author  Clément Foucher <clement.foucher@laas.fr>
 */


// Zephyr
#include <zephyr.h>

// STM32 LL
#include <stm32_ll_dac.h>
#include <stm32_ll_gpio.h>
#include <stm32_ll_bus.h>

// Current file header
#include "stm32_dac_driver.h"


/////
// Init function

static int dac_stm32_init(const struct device* dev)
{
	DAC_TypeDef* dac_dev = ((struct stm32_dac_driver_data*)dev->data)->dac_struct;

	if (dac_dev == DAC1)
	{
		LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_DAC1);
	}
	else if (dac_dev == DAC2)
	{
		LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_DAC2);
	}
	else if (dac_dev == DAC3)
	{
		LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_DAC3);
	}

	return 0;
}


/////
// API

static const struct dac_driver_api dac_funcs =
{
	.setconstvalue = dac_stm32_set_const_value,
	.setfunction   = dac_stm32_set_function,
Clément Foucher's avatar
Clément Foucher committed
68
69
	.fn_upd_reset  = dac_stm32_function_update_reset,
	.fn_upd_step   = dac_stm32_function_update_step,
Clément Foucher's avatar
Clément Foucher committed
70
71
72
73
74
75
76
77
78
79
80
81
	.pinconfigure  = dac_stm32_pin_configure,
	.start         = dac_stm32_start,
	.stop          = dac_stm32_stop
};

static void dac_stm32_set_const_value(const struct device* dev, uint8_t channel, uint32_t value)
{
	struct stm32_dac_driver_data* data = (struct stm32_dac_driver_data*)dev->data;
	DAC_TypeDef* dac_dev = data->dac_struct;

	uint8_t dac_channel = __LL_DAC_DECIMAL_NB_TO_CHANNEL(channel);

Clément Foucher's avatar
Clément Foucher committed
82
	if (data->dac_mode[channel-1] != dac_mode_constant)
Clément Foucher's avatar
Clément Foucher committed
83
	{
Clément Foucher's avatar
Clément Foucher committed
84
85
		data->dac_mode[channel-1] = dac_mode_constant;
		data->dac_config->constant_value = value;
Clément Foucher's avatar
Clément Foucher committed
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

		LL_DAC_SetSignedFormat(dac_dev, dac_channel, LL_DAC_SIGNED_FORMAT_DISABLE);

		LL_DAC_SetWaveAutoGeneration(dac_dev, dac_channel, LL_DAC_WAVE_AUTO_GENERATION_NONE);

		LL_DAC_DisableTrigger(dac_dev, dac_channel);
		LL_DAC_DisableDMADoubleDataMode(dac_dev, dac_channel);
	}

	LL_DAC_ConvertData12RightAligned(dac_dev, dac_channel, value);
}

static void dac_stm32_set_function(const struct device* dev, uint8_t channel, const dac_function_config_t* function_config)
{
	struct stm32_dac_driver_data* data = (struct stm32_dac_driver_data*)dev->data;
	DAC_TypeDef* dac_dev = data->dac_struct;

	uint8_t dac_channel = __LL_DAC_DECIMAL_NB_TO_CHANNEL(channel);

Clément Foucher's avatar
Clément Foucher committed
105
	data->dac_mode[channel-1] = dac_mode_function;
Clément Foucher's avatar
Clément Foucher committed
106
107
108

	if (function_config->dac_function == dac_function_sawtooth)
	{
Clément Foucher's avatar
Clément Foucher committed
109
110
		data->dac_config->function_config = *function_config;

Clément Foucher's avatar
Clément Foucher committed
111
112
113
114
115
116
117
118
119
120
121
122
123
124
		LL_DAC_SetSignedFormat(dac_dev, dac_channel, LL_DAC_SIGNED_FORMAT_DISABLE);

		LL_DAC_SetWaveAutoGeneration(dac_dev, dac_channel, LL_DAC_WAVE_AUTO_GENERATION_SAWTOOTH);
		LL_DAC_SetWaveSawtoothResetTriggerSource(dac_dev, dac_channel, function_config->trigger_source);
		LL_DAC_SetWaveSawtoothStepTriggerSource(dac_dev, dac_channel, function_config->step_trigger_source);
		LL_DAC_SetWaveSawtoothPolarity(dac_dev, dac_channel, function_config->polarity);
		LL_DAC_SetWaveSawtoothResetData(dac_dev, dac_channel, function_config->reset_data);
		LL_DAC_SetWaveSawtoothStepData(dac_dev, dac_channel, function_config->step_data);

		LL_DAC_EnableTrigger(dac_dev, dac_channel);
		LL_DAC_DisableDMADoubleDataMode(dac_dev, dac_channel);
	}
}

Clément Foucher's avatar
Clément Foucher committed
125
126
127
static void dac_stm32_function_update_reset(const struct device* dev, uint8_t channel, uint32_t reset_data)
{
	struct stm32_dac_driver_data* data = (struct stm32_dac_driver_data*)dev->data;
128
129
130
	DAC_TypeDef* dac_dev = data->dac_struct;

	uint8_t dac_channel = __LL_DAC_DECIMAL_NB_TO_CHANNEL(channel);
Clément Foucher's avatar
Clément Foucher committed
131
132
133

	if (data->dac_mode[channel-1] == dac_mode_function)
	{
134
135
136
137
138
139
		data->dac_config->function_config.reset_data = reset_data;

		if (data->started[channel-1] == 1)
		{
			LL_DAC_Disable(dac_dev, dac_channel);
		}
Clément Foucher's avatar
Clément Foucher committed
140

141
142
143
144
145
146
147
148
149
150
151
		LL_DAC_SetWaveSawtoothResetData(dac_dev, dac_channel, reset_data);

		if (data->started[channel-1] == 1)
		{
			LL_DAC_Enable(dac_dev, dac_channel);

			while (LL_DAC_IsReady(dac_dev, dac_channel) == 0)
			{
				// Wait
			}
		}
Clément Foucher's avatar
Clément Foucher committed
152
153
154
155
156
157
	}
}

static void dac_stm32_function_update_step(const struct device* dev, uint8_t channel, uint32_t step_data)
{
	struct stm32_dac_driver_data* data = (struct stm32_dac_driver_data*)dev->data;
158
159
160
	DAC_TypeDef* dac_dev = data->dac_struct;

	uint8_t dac_channel = __LL_DAC_DECIMAL_NB_TO_CHANNEL(channel);
Clément Foucher's avatar
Clément Foucher committed
161
162
163

	if (data->dac_mode[channel-1] == dac_mode_function)
	{
164
165
166
167
168
169
170
171
172
173
174
175
		data->dac_config->function_config.step_data = step_data;

		if (data->started[channel-1] == 1)
		{
			LL_DAC_Disable(dac_dev, dac_channel);
		}

		LL_DAC_SetWaveSawtoothStepData(dac_dev, dac_channel, step_data);

		if (data->started[channel-1] == 1)
		{
			LL_DAC_Enable(dac_dev, dac_channel);
Clément Foucher's avatar
Clément Foucher committed
176

177
178
179
180
181
			while (LL_DAC_IsReady(dac_dev, dac_channel) == 0)
			{
				// Wait
			}
		}
Clément Foucher's avatar
Clément Foucher committed
182
183
184
	}
}

Clément Foucher's avatar
Clément Foucher committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
static void dac_stm32_pin_configure(const struct device* dev, uint8_t channel, const dac_pin_config_t* pin_config)
{
	struct stm32_dac_driver_data* data = (struct stm32_dac_driver_data*)dev->data;
	DAC_TypeDef* dac_dev = data->dac_struct;

	uint8_t dac_channel = __LL_DAC_DECIMAL_NB_TO_CHANNEL(channel);

	LL_DAC_ConfigOutput(dac_dev, dac_channel, LL_DAC_OUTPUT_MODE_NORMAL, pin_config->pin_buffer_enable, pin_config->pin_connect);
}

static void dac_stm32_start(const struct device* dev, uint8_t channel)
{
	struct stm32_dac_driver_data* data = (struct stm32_dac_driver_data*)dev->data;
	DAC_TypeDef* dac_dev = data->dac_struct;

	uint8_t dac_channel = __LL_DAC_DECIMAL_NB_TO_CHANNEL(channel);

202
	if ( (data->dac_mode[channel-1] != dac_mode_unset) && (data->started[channel-1] == 0) )
Clément Foucher's avatar
Clément Foucher committed
203
	{
Clément Foucher's avatar
Clément Foucher committed
204
205
206
207
208
209
		LL_DAC_Enable(dac_dev, dac_channel);

		while (LL_DAC_IsReady(dac_dev, dac_channel) == 0)
		{
			// Wait
		}
210
211

		data->started[channel-1] = 1;
Clément Foucher's avatar
Clément Foucher committed
212
213
214
215
216
217
218
219
220
221
	}
}

static void dac_stm32_stop(const struct device* dev, uint8_t channel)
{
	struct stm32_dac_driver_data* data = (struct stm32_dac_driver_data*)dev->data;
	DAC_TypeDef* dac_dev = data->dac_struct;

	uint8_t dac_channel = __LL_DAC_DECIMAL_NB_TO_CHANNEL(channel);

222
223
224
225
226
227
	if (data->started[channel-1] == 1)
	{
		LL_DAC_Disable(dac_dev, dac_channel);

		data->started[channel-1] = 0;
	}
Clément Foucher's avatar
Clément Foucher committed
228
229
230
231
232
233
234
235
236
237
238
239
}


/////
// Device definitions

// DAC 1
#if DT_NODE_HAS_STATUS(DAC1_NODELABEL, okay)

struct stm32_dac_driver_data dac1_data =
{
	.dac_struct = DAC1,
240
241
	.dac_mode   = {dac_mode_unset, dac_mode_unset},
	.started    = {0, 0}
Clément Foucher's avatar
Clément Foucher committed
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
};

DEVICE_DT_DEFINE(DAC1_NODELABEL,
                 dac_stm32_init,
                 device_pm_control_nop,
                 &dac1_data,
                 NULL,
                 PRE_KERNEL_1,
                 CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
                 &dac_funcs
                );

#endif // DAC 1

// DAC 2
#if DT_NODE_HAS_STATUS(DAC2_NODELABEL, okay)

struct stm32_dac_driver_data dac2_data =
{
	.dac_struct = DAC2,
262
263
	.dac_mode   = {dac_mode_unset, dac_mode_unset},
	.started    = {0, 0}
Clément Foucher's avatar
Clément Foucher committed
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
};

DEVICE_DT_DEFINE(DAC2_NODELABEL,
                 dac_stm32_init,
                 device_pm_control_nop,
                 &dac2_data,
                 NULL,
                 PRE_KERNEL_1,
                 CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
                 &dac_funcs
                );

#endif // DAC 2

// DAC 3
#if DT_NODE_HAS_STATUS(DAC3_NODELABEL, okay)

struct stm32_dac_driver_data dac3_data =
{
	.dac_struct = DAC3,
284
285
	.dac_mode   = {dac_mode_unset, dac_mode_unset},
	.started    = {0, 0}
Clément Foucher's avatar
Clément Foucher committed
286
287
288
289
290
291
292
293
294
295
296
297
298
};

DEVICE_DT_DEFINE(DAC3_NODELABEL,
                 dac_stm32_init,
                 device_pm_control_nop,
                 &dac3_data,
                 NULL,
                 PRE_KERNEL_1,
                 CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
                 &dac_funcs
                );

#endif // DAC 3