From 3e7b2d617a019d8ed756fdde8135147268cfadcb Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 26 May 2016 14:56:10 -0600 Subject: [PATCH] All drivers that use SPI must call SPI_LOCK and SPI_UNLOCK. This is not optional. --- drivers/analog/ad5410.c | 108 +++++++++++++++++++++++++++++++------ drivers/analog/ads1242.c | 80 ++++++++++++++++++++------- drivers/sensors/max31855.c | 36 +++++++++++++ drivers/sensors/max6675.c | 36 +++++++++++++ 4 files changed, 226 insertions(+), 34 deletions(-) diff --git a/drivers/analog/ad5410.c b/drivers/analog/ad5410.c index 33da3c76615..58db6a7ceaf 100644 --- a/drivers/analog/ad5410.c +++ b/drivers/analog/ad5410.c @@ -1,9 +1,10 @@ /************************************************************************************ * arch/drivers/analog/ad5410.c * + * Copyright (C) 2010, 2016 Gregory Nutt. All rights reserved. * Copyright (C) 2011 Li Zhuoyi. All rights reserved. * Author: Li Zhuoyi - * History: 0.1 2011-08-05 initial version + * Gregory Nutt * * This file is a part of NuttX: * @@ -85,6 +86,9 @@ struct up_dev_s * ad_private Function Prototypes ****************************************************************************/ +static void dac_lock(FAR struct spi_dev_s *spi); +static void dac_unlock(FAR struct spi_dev_s *spi); + /* DAC methods */ static void dac_reset(FAR struct dac_dev_s *dev); @@ -121,64 +125,136 @@ static struct dac_dev_s g_dacdev = * ad_private Functions ****************************************************************************/ -/* Reset the DAC device. Called early to initialize the hardware. This - * is called, before ao_setup() and on error conditions. - */ +/**************************************************************************** + * Name: dac_lock + * + * Description: + * Lock and configure the SPI bus. + * + ****************************************************************************/ + +static void dac_lock(FAR struct spi_dev_s *spi) +{ + (void)SPI_LOCK(spi, true); + SPI_SETMODE(spi, SPIDEV_MODE0); + SPI_SETBITS(spi, 8); + (void)SPI_HWFEATURES(spi, 0); + SPI_SETFREQUENCY(spi, 400000); +} + +/**************************************************************************** + * Name: dac_unlock + * + * Description: + * Unlock the SPI bus. + * + ****************************************************************************/ + +static void dac_unlock(FAR struct spi_dev_s *spi) +{ + (void)SPI_LOCK(spi, false); +} + +/**************************************************************************** + * Name: dac_reset + * + * Description: + * Reset the DAC device. Called early to initialize the hardware. This + * is called, before ao_setup() and on error conditions. + * + ****************************************************************************/ static void dac_reset(FAR struct dac_dev_s *dev) { } -/* Configure the DAC. This method is called the first time that the DAC - * device is opened. This will occur when the port is first opened. - * This setup includes configuring and attaching DAC interrupts. Interrupts - * are all disabled upon return. - */ +/**************************************************************************** + * Name: dac_setup + * + * Description: + * Configure the DAC. This method is called the first time that the DAC + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching DAC interrupts. Interrupts + * are all disabled upon return. + * + ****************************************************************************/ static int dac_setup(FAR struct dac_dev_s *dev) { FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv; FAR struct spi_dev_s *spi = priv->spi; + dac_lock(spi); + SPI_SELECT(spi, priv->devno, true); SPI_SEND(spi, AD5410_REG_CMD); SPI_SEND(spi, (AD5410_CMD_OUTEN | AD5410_CMD_420MA) >> 8); SPI_SEND(spi, AD5410_CMD_OUTEN | AD5410_CMD_420MA); SPI_SELECT(spi, priv->devno, false); + + dac_unlock(spi); return OK; } -/* Disable the DAC. This method is called when the DAC device is closed. - * This method reverses the operation the setup method. - */ +/**************************************************************************** + * Name: dac_shutdown + * + * Description: + * Disable the DAC. This method is called when the DAC device is closed. + * This method reverses the operation the setup method. + * + ****************************************************************************/ static void dac_shutdown(FAR struct dac_dev_s *dev) { } -/* Call to enable or disable TX interrupts */ +/**************************************************************************** + * Name: dac_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ static void dac_txint(FAR struct dac_dev_s *dev, bool enable) { } -static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) +/**************************************************************************** + * Name: dac_send + * + * Description: + * + ****************************************************************************/ + +static int dac_send(FAR struct dac_dev_s *dev, FAR struct dac_msg_s *msg) { FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv; FAR struct spi_dev_s *spi = priv->spi; + dac_lock(spi); + SPI_SELECT(spi, priv->devno, true); SPI_SEND(spi, AD5410_REG_WR); SPI_SEND(spi, (uint8_t)(msg->am_data >> 24)); SPI_SEND(spi, (uint8_t)(msg->am_data >> 16)); SPI_SELECT(spi, priv->devno, false); + + dac_unlock(spi); dac_txdone(&g_dacdev); return 0; } -/* All ioctl calls will be routed through this method */ +/**************************************************************************** + * Name: dac_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ -static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) +static int dac_ioctl(FAR struct dac_dev_s *dev, int cmd, unsigned long arg) { dbg("Fix me:Not Implemented\n"); return 0; diff --git a/drivers/analog/ads1242.c b/drivers/analog/ads1242.c index 93b82942c2c..ccd9c0d18d0 100644 --- a/drivers/analog/ads1242.c +++ b/drivers/analog/ads1242.c @@ -2,8 +2,10 @@ * drivers/sensors/ads1242.c * Character driver for the MCP3426 Differential Input 16 Bit Delta/Sigma ADC * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. * Copyright (C) 2015 DS-Automotion GmbH. All rights reserved. * Author: Alexander Entinger + * Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -70,6 +72,8 @@ struct ads1242_dev_s /* SPI Helpers */ +static void ads1242_lock(FAR struct spi_dev_s *spi); +static void ads1242_unlock(FAR struct spi_dev_s *spi); static void ads1242_reset(FAR struct ads1242_dev_s *dev); static void ads1242_performSelfGainCalibration( FAR struct ads1242_dev_s *dev); @@ -128,19 +132,50 @@ static const struct file_operations g_ads1242_fops = * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: ads1242_lock + * + * Description: + * Lock and configure the SPI bus. + * + ****************************************************************************/ + +static void ads1242_lock(FAR struct spi_dev_s *spi) +{ + (void)SPI_LOCK(spi, true); + SPI_SETMODE(spi, ADS1242_SPI_MODE); + SPI_SETBITS(spi, 8); + (void)SPI_HWFEATURES(spi, 0); + SPI_SETFREQUENCY(spi, ADS1242_SPI_FREQUENCY); +} + +/**************************************************************************** + * Name: ads1242_unlock + * + * Description: + * Unlock the SPI bus. + * + ****************************************************************************/ + +static void ads1242_unlock(FAR struct spi_dev_s *spi) +{ + (void)SPI_LOCK(spi, false); +} + /**************************************************************************** * Name: ads1242_reset ****************************************************************************/ static void ads1242_reset(FAR struct ads1242_dev_s *dev) { + ads1242_lock(dev->spi); + SPI_SELECT(dev->spi, 0, true); /* Set nADC_SPI_CS to low which selects the ADS1242 */ - SPI_SEND(dev->spi, ADS1242_CMD_RESET);/* Issue reset command */ - SPI_SELECT(dev->spi, 0, false); /* Set nADC_SPI_CS to high which deselects the ADS1242 */ - up_mdelay(100); /* Wait a little so the device has time to perform a proper reset */ + + ads1242_unlock(dev->spi); } /**************************************************************************** @@ -149,11 +184,13 @@ static void ads1242_reset(FAR struct ads1242_dev_s *dev) static void ads1242_performSelfGainCalibration(FAR struct ads1242_dev_s *dev) { + ads1242_lock(dev->spi); + SPI_SELECT(dev->spi, 0, true); - SPI_SEND(dev->spi, ADS1242_CMD_SELF_GAIN_CALIB); - SPI_SELECT(dev->spi, 0, false); + + ads1242_unlock(dev->spi); } /**************************************************************************** @@ -162,11 +199,13 @@ static void ads1242_performSelfGainCalibration(FAR struct ads1242_dev_s *dev) static void ads1242_performSelfOffsetCalibration(FAR struct ads1242_dev_s *dev) { + ads1242_lock(dev->spi); + SPI_SELECT(dev->spi, 0, true); - SPI_SEND(dev->spi, ADS1242_CMD_SELF_OFFSET_CALIB); - SPI_SELECT(dev->spi, 0, false); + + ads1242_unlock(dev->spi); } /**************************************************************************** @@ -176,11 +215,13 @@ static void ads1242_performSelfOffsetCalibration(FAR struct ads1242_dev_s *dev) static void ads1242_performSystemOffsetCalibration(FAR struct ads1242_dev_s *dev) { + ads1242_lock(dev->spi); + SPI_SELECT(dev->spi, 0, true); - SPI_SEND(dev->spi, ADS1242_CMD_SYSTEM_OFFSET_CALIB); - SPI_SELECT(dev->spi, 0, false); + + ads1242_unlock(dev->spi); } /**************************************************************************** @@ -190,8 +231,9 @@ ads1242_performSystemOffsetCalibration(FAR struct ads1242_dev_s *dev) static void ads1242_read_conversion_result(FAR struct ads1242_dev_s *dev, FAR uint32_t *conversion_result) { - SPI_SELECT(dev->spi, 0, true); + ads1242_lock(dev->spi); + SPI_SELECT(dev->spi, 0, true); SPI_SEND(dev->spi, ADS1242_CMD_READ_DATA); /* Delay between last SCLK edge for DIN and first SCLK edge for DOUT: @@ -212,6 +254,8 @@ static void ads1242_read_conversion_result(FAR struct ads1242_dev_s *dev, *conversion_result |= ((uint32_t)(SPI_SEND(dev->spi, 0xFF))) << 0; SPI_SELECT(dev->spi, 0, false); + + ads1242_unlock(dev->spi); } /**************************************************************************** @@ -227,11 +271,15 @@ static void ads1242_read_conversion_result(FAR struct ads1242_dev_s *dev, static void ads1242_write_reg(FAR struct ads1242_dev_s *dev, uint8_t const reg_addr, uint8_t const reg_value) { + ads1242_lock(dev->spi); + SPI_SELECT(dev->spi, 0, true); SPI_SEND(dev->spi, ADS1242_CMD_WRITE_REGISTER | reg_addr); SPI_SEND(dev->spi, 0x00); /* Write 1 Byte */ SPI_SEND(dev->spi, reg_value); SPI_SELECT(dev->spi, 0, false); + + ads1242_unlock(dev->spi); } /**************************************************************************** @@ -248,6 +296,8 @@ static void ads1242_write_reg(FAR struct ads1242_dev_s *dev, static void ads1242_read_reg(FAR struct ads1242_dev_s *dev, uint8_t const reg_addr, FAR uint8_t *reg_value) { + ads1242_lock(dev->spi); + SPI_SELECT(dev->spi, 0, true); SPI_SEND(dev->spi, ADS1242_CMD_READ_REGISTER | reg_addr); SPI_SEND(dev->spi, 0x00); /* Read 1 Byte */ @@ -261,6 +311,8 @@ static void ads1242_read_reg(FAR struct ads1242_dev_s *dev, *reg_value = SPI_SEND(dev->spi, 0xFF); SPI_SELECT(dev->spi, 0, false); + + ads1242_unlock(dev->spi); } /**************************************************************************** @@ -562,14 +614,6 @@ int ads1242_register(FAR const char *devpath, FAR struct spi_dev_s *spi, kmm_free(priv); } - /* setup SPI frequency */ - - SPI_SETFREQUENCY(spi, ADS1242_SPI_FREQUENCY); - - /* Setup SPI mode */ - - SPI_SETMODE(spi, ADS1242_SPI_MODE); - return ret; } diff --git a/drivers/sensors/max31855.c b/drivers/sensors/max31855.c index c239d9688d8..d3e5b8e8f6e 100644 --- a/drivers/sensors/max31855.c +++ b/drivers/sensors/max31855.c @@ -83,6 +83,9 @@ struct max31855_dev_s * Private Function Prototypes ****************************************************************************/ +static void max31855_lock(FAR struct spi_dev_s *spi); +static void max31855_unlock(FAR struct spi_dev_s *spi); + /* Character driver methods */ static int max31855_open(FAR struct file *filep); @@ -112,6 +115,37 @@ static const struct file_operations g_max31855fops = /**************************************************************************** * Private Functions ****************************************************************************/ + +/**************************************************************************** + * Name: max31855_lock + * + * Description: + * Lock and configure the SPI bus. + * + ****************************************************************************/ + +static void max31855_lock(FAR struct spi_dev_s *spi) +{ + (void)SPI_LOCK(spi, true); + SPI_SETMODE(spi, SPIDEV_MODE0); + SPI_SETBITS(spi, 8); + (void)SPI_HWFEATURES(spi, 0); + SPI_SETFREQUENCY(spi, 400000); +} + +/**************************************************************************** + * Name: max31855_unlock + * + * Description: + * Unlock the SPI bus. + * + ****************************************************************************/ + +static void max31855_unlock(FAR struct spi_dev_s *spi) +{ + (void)SPI_LOCK(spi, false); +} + /**************************************************************************** * Name: max31855_open * @@ -167,6 +201,7 @@ static ssize_t max31855_read(FAR struct file *filep, FAR char *buffer, size_t bu /* Enable MAX31855's chip select */ + max31855_lock(priv->spi); SPI_SELECT(priv->spi, SPIDEV_TEMPERATURE, true); /* Read temperature */ @@ -176,6 +211,7 @@ static ssize_t max31855_read(FAR struct file *filep, FAR char *buffer, size_t bu /* Disable MAX31855's chip select */ SPI_SELECT(priv->spi, SPIDEV_TEMPERATURE, false); + max31855_unlock(priv->spi); regval = (regmsb & 0xFF000000) >> 24; regval |= (regmsb & 0xFF0000) >> 8; diff --git a/drivers/sensors/max6675.c b/drivers/sensors/max6675.c index 38aa6c18a7f..329f5185c5c 100644 --- a/drivers/sensors/max6675.c +++ b/drivers/sensors/max6675.c @@ -80,6 +80,9 @@ struct max6675_dev_s * Private Function Prototypes ****************************************************************************/ +static void max6675_lock(FAR struct spi_dev_s *spi) +static void max6675_unlock(FAR struct spi_dev_s *spi) + /* Character driver methods */ static int max6675_open(FAR struct file *filep); @@ -108,6 +111,37 @@ static const struct file_operations g_max6675fops = /**************************************************************************** * Private Functions ****************************************************************************/ + +/**************************************************************************** + * Name: max6675_lock + * + * Description: + * Lock and configure the SPI bus. + * + ****************************************************************************/ + +static void max6675_lock(FAR struct spi_dev_s *spi) +{ + (void)SPI_LOCK(spi, true); + SPI_SETMODE(spi, SPIDEV_MODE0); + SPI_SETBITS(spi, 8); + (void)SPI_HWFEATURES(spi, 0); + SPI_SETFREQUENCY(spi, 400000); +} + +/**************************************************************************** + * Name: max6675_unlock + * + * Description: + * Unlock the SPI bus. + * + ****************************************************************************/ + +static void max6675_unlock(FAR struct spi_dev_s *spi) +{ + (void)SPI_LOCK(spi, false); +} + /**************************************************************************** * Name: max6675_open * @@ -163,6 +197,7 @@ static ssize_t max6675_read(FAR struct file *filep, FAR char *buffer, size_t buf /* Enable MAX6675's chip select */ + max6675_lock(priv->spi); SPI_SELECT(priv->spi, SPIDEV_TEMPERATURE, true); /* Read temperature */ @@ -172,6 +207,7 @@ static ssize_t max6675_read(FAR struct file *filep, FAR char *buffer, size_t buf /* Disable MAX6675's chip select */ SPI_SELECT(priv->spi, SPIDEV_TEMPERATURE, false); + max6675_unlock(priv->spi); regval = (regmsb & 0xFF00) >> 8; regval |= (regmsb & 0xFF) << 8;