kinetis/dac: Implement basics DAC

Minimum working implementation for Kinetis' DAC.

Signed-off-by: Jiri Vlasak <jvlasak@elektroline.cz>
This commit is contained in:
Jiri Vlasak
2026-04-08 14:06:52 +02:00
committed by simbit18
parent 895a9423ee
commit 92b8bc14b8
5 changed files with 336 additions and 0 deletions
+6
View File
@@ -125,4 +125,10 @@ if(CONFIG_NET)
endif()
if(CONFIG_ANALOG)
if(CONFIG_DAC)
list(APPEND SRCS kinetis_dac.c)
endif()
endif()
target_sources(arch PRIVATE ${SRCS})
+4
View File
@@ -604,12 +604,16 @@ config KINETIS_I2S
config KINETIS_DAC0
bool "DAC0"
default n
select ANALOG
select DAC
---help---
Support DAC0
config KINETIS_DAC1
bool "DAC1"
default n
select ANALOG
select DAC
---help---
Support DAC1
+6
View File
@@ -114,3 +114,9 @@ endif
endif
endif
ifeq ($(CONFIG_ANALOG),y)
ifeq ($(CONFIG_DAC),y)
CHIP_CSRCS += kinetis_dac.c
endif
endif
+4
View File
@@ -779,5 +779,9 @@ int kinetis_netinitialize(int intf);
int kinetis_caninitialize(int intf);
#endif
#if defined(CONFIG_KINETIS_DAC0) || defined (CONFIG_KINETIS_DAC1)
struct dac_dev_s *kinetis_dac_initialize(int which);
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_SRC_KINETIS_KINETIS_H */
+316
View File
@@ -0,0 +1,316 @@
/****************************************************************************
* arch/arm/src/kinetis/kinetis_dac.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* 12-bit Digital-to-Analog Converter (DAC)
*
* From the Reference Manual:
*
* The 12-bit digital-to-analog converter (DAC) is a low-power,
* general-purpose DAC. The output of the DAC can be placed on an external
* pin or set as one of the inputs to the analog comparator, op-amps,
* or ADC.
*
* This file provides DAC driver for the Kinetis' 12-bit DAC.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <debug.h>
#include <nuttx/analog/dac.h>
#include "arm_internal.h" /* putreg... */
#include "hardware/kinetis_dac.h" /* KINETIS_DAC... */
#include "hardware/kinetis_sim.h" /* SIM_... */
#include "hardware/kinetis_vrefv1.h" /* VREF_... */
#if defined(CONFIG_KINETIS_DAC0) || defined(CONFIG_KINETIS_DAC1)
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static void dac_reset(struct dac_dev_s *dev);
static int dac_setup(struct dac_dev_s *dev);
static void dac_shutdown(struct dac_dev_s *dev);
static void dac_txint(struct dac_dev_s *dev, bool enable);
static int dac_send(struct dac_dev_s *dev, struct dac_msg_s *msg);
static int dac_ioctl(struct dac_dev_s *dev, int cmd, unsigned long arg);
/****************************************************************************
* Private Data
****************************************************************************/
static struct dac_ops_s const g_dacops =
{
.ao_reset = dac_reset,
.ao_setup = dac_setup,
.ao_shutdown = dac_shutdown,
.ao_txint = dac_txint,
.ao_send = dac_send,
.ao_ioctl = dac_ioctl,
};
#if defined(CONFIG_KINETIS_DAC0)
static struct dac_dev_s g_dac0_dev =
{
.ad_ops = &g_dacops,
.ad_priv = NULL,
};
#endif
#if defined(CONFIG_KINETIS_DAC1)
static struct dac_dev_s g_dac1_dev =
{
.ad_ops = &g_dacops,
.ad_priv = NULL,
};
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
static void dac_reset(struct dac_dev_s *dev)
{
uint8_t reg;
uint32_t addr;
dac_shutdown(dev);
dac_setup(dev);
#if defined(CONFIG_KINETIS_DAC0)
if (&g_dac0_dev == dev)
{
reg = 0x00;
addr = KINETIS_DAC0_DAT0L;
while (addr < KINETIS_DAC0_SR)
{
putreg8(reg, addr);
addr++;
}
putreg8(0x02, KINETIS_DAC0_SR);
putreg8(0x00, KINETIS_DAC0_C0);
putreg8(0x00, KINETIS_DAC0_C1);
putreg8(0x0f, KINETIS_DAC0_C2);
}
#endif /* defined(CONFIG_KINETIS_DAC0) */
#if defined(CONFIG_KINETIS_DAC1)
if (&g_dac1_dev == dev)
{
reg = 0x00;
addr = KINETIS_DAC1_DAT0L;
while (addr < KINETIS_DAC1_SR)
{
putreg8(reg, addr);
addr++;
}
putreg8(0x02, KINETIS_DAC1_SR);
putreg8(0x00, KINETIS_DAC1_C0);
putreg8(0x00, KINETIS_DAC1_C1);
putreg8(0x0f, KINETIS_DAC1_C2);
}
#endif /* defined(CONFIG_KINETIS_DAC1) */
}
static int dac_setup(struct dac_dev_s *dev)
{
uint32_t reg32;
uint8_t reg;
#if defined(CONFIG_KINETIS_DAC0)
if (&g_dac0_dev == dev)
{
/* Enable VREF (for DAC0) */
reg32 = getreg32(KINETIS_SIM_SCGC4);
reg32 |= SIM_SCGC4_VREF;
putreg32(reg32, KINETIS_SIM_SCGC4);
/* Configure VREF (for DAC0) */
reg = VREF_SC_VREFEN | VREF_SC_REGEN | VREF_SC_MODE_LV_LOWPWR;
putreg8(reg, KINETIS_VREF_SC);
/* Enable DAC0 */
reg32 = getreg32(KINETIS_SIM_SCGC2);
reg32 |= SIM_SCGC2_DAC0;
putreg32(reg32, KINETIS_SIM_SCGC2);
putreg8(DAC_C0_DACEN, KINETIS_DAC0_C0);
}
#endif /* defined(CONFIG_KINETIS_DAC0) */
#if defined(CONFIG_KINETIS_DAC1)
if (&g_dac1_dev == dev)
{
/* Enable VREF (for DAC1) */
reg32 = getreg32(KINETIS_SIM_SCGC4);
reg32 |= SIM_SCGC4_VREF;
putreg32(reg32, KINETIS_SIM_SCGC4);
/* Configure VREF (for DAC1) */
reg = VREF_SC_VREFEN | VREF_SC_REGEN | VREF_SC_MODE_LV_LOWPWR;
putreg8(reg, KINETIS_VREF_SC);
/* Enable DAC1 */
reg32 = getreg32(KINETIS_SIM_SCGC2);
reg32 |= SIM_SCGC2_DAC1;
putreg32(reg32, KINETIS_SIM_SCGC2);
putreg8(DAC_C0_DACEN, KINETIS_DAC1_C0);
}
#endif /* defined(CONFIG_KINETIS_DAC1) */
return OK;
}
static void dac_shutdown(struct dac_dev_s *dev)
{
uint32_t reg32;
#if defined(CONFIG_KINETIS_DAC0)
if (&g_dac0_dev == dev)
{
/* Is DAC0 module enabled? */
reg32 = getreg32(KINETIS_SIM_SCGC2);
if (reg32 & SIM_SCGC2_DAC0)
{
/* Disable DAC0 */
putreg8(DAC_C0_DACEN, KINETIS_DAC0_C0);
}
/* Disable DAC0 module */
reg32 &= ~SIM_SCGC2_DAC0;
putreg32(reg32, KINETIS_SIM_SCGC2);
/* Do not disable VREF (for DAC0) because someone else may use it. */
}
#endif /* defined(CONFIG_KINETIS_DAC0) */
#if defined(CONFIG_KINETIS_DAC1)
if (&g_dac1_dev == dev)
{
/* Is DAC1 module enabled? */
reg32 = getreg32(KINETIS_SIM_SCGC2);
if (reg32 & SIM_SCGC2_DAC1)
{
/* Disable DAC1 */
putreg8(DAC_C0_DACEN, KINETIS_DAC1_C0);
}
/* Disable DAC1 module */
reg32 &= ~SIM_SCGC2_DAC1;
putreg32(reg32, KINETIS_SIM_SCGC2);
/* Do not disable VREF (for DAC1) because someone else may use it. */
}
#endif /* defined(CONFIG_KINETIS_DAC1) */
}
static void dac_txint(struct dac_dev_s *dev, bool enable)
{
UNUSED(dev);
UNUSED(enable);
awarn("Interrupts not implemented for Kinetis' DAC");
}
static int dac_send(struct dac_dev_s *dev, struct dac_msg_s *msg)
{
#if defined(CONFIG_KINETIS_DAC0)
if (&g_dac0_dev == dev)
{
putreg8((uint8_t)((msg->am_data & 0x00ff) >> 0), KINETIS_DAC0_DAT0L);
putreg8((uint8_t)((msg->am_data & 0xff00) >> 8), KINETIS_DAC0_DAT0H);
}
#endif /* defined(CONFIG_KINETIS_DAC0) */
#if defined(CONFIG_KINETIS_DAC1)
if (&g_dac1_dev == dev)
{
putreg8((uint8_t)((msg->am_data & 0x00ff) >> 0), KINETIS_DAC1_DAT0L);
putreg8((uint8_t)((msg->am_data & 0xff00) >> 8), KINETIS_DAC1_DAT0H);
}
#endif /* defined(CONFIG_KINETIS_DAC1) */
dac_txdone(dev);
return OK;
}
static int dac_ioctl(struct dac_dev_s *dev, int cmd, unsigned long arg)
{
UNUSED(dev);
UNUSED(cmd);
UNUSED(arg);
return -ENOTTY;
}
/****************************************************************************
* Public Functions
****************************************************************************/
struct dac_dev_s *kinetis_dac_initialize(int which)
{
switch (which)
{
case 0:
#if defined(CONFIG_KINETIS_DAC0)
return &g_dac0_dev;
#else
awarn("CONFIG_KINETIS_DAC0 must be defined");
return NULL;
#endif
break;
case 1:
#if defined(CONFIG_KINETIS_DAC1)
return &g_dac1_dev;
#else
awarn("CONFIG_KINETIS_DAC1 must be defined");
return NULL;
#endif
break;
default:
awarn("Bad device specified, must be 0 <= %d <= 1", which);
}
return NULL;
}
#endif /* defined(CONFIG_KINETIS_DAC0) || defined(CONFIG_KINETIS_DAC1) */