From ae17e6bcf06ce8ff7af5885eac2bd091b53bd70a Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 30 May 2017 12:04:48 -0600 Subject: [PATCH 01/22] Cosmetic --- drivers/usbdev/usbmsc.h | 2 +- include/nuttx/usb/usbmsc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usbdev/usbmsc.h b/drivers/usbdev/usbmsc.h index 2da7b762f2a..4fa8405248c 100644 --- a/drivers/usbdev/usbmsc.h +++ b/drivers/usbdev/usbmsc.h @@ -592,7 +592,7 @@ struct usb_strdesc_s; int usbmsc_mkstrdesc(uint8_t id, struct usb_strdesc_s *strdesc); /************************************************************************************ - * Name: usbmsc_getepdesc + * Name: usbmsc_getdevdesc * * Description: * Return a pointer to the raw device descriptor diff --git a/include/nuttx/usb/usbmsc.h b/include/nuttx/usb/usbmsc.h index 270fac0da3e..701fc958370 100644 --- a/include/nuttx/usb/usbmsc.h +++ b/include/nuttx/usb/usbmsc.h @@ -60,7 +60,7 @@ * Public Types ************************************************************************************/ - /************************************************************************************ +/************************************************************************************ * Public Data ************************************************************************************/ From 830ad9370a13e7aeec4c7017ff0a282b5413b994 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 31 May 2017 06:19:05 -0600 Subject: [PATCH 02/22] Update README file --- README.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.txt b/README.txt index 9a4775c77b7..c5e0b9c69e6 100644 --- a/README.txt +++ b/README.txt @@ -186,6 +186,13 @@ Ubuntu Bash under Windows 10 With these differences (perhaps a few other Windows quirks) the Ubuntu install works just like Ubuntu running natively on your PC. + A good tip for file sharing is to use symbolic links within your Ubuntu + home directory. For example, suppose you have your "projects" directory + at C:\Documents\projects. Then you can set up a link to the projects/ + directory in your Ubuntu directory like: + + $ ln -s /mnt/c/Documents/projects projects + Accessing Ubuntu Files From Windows ----------------------------------- In Ubuntu Userspace for Windows, the Ubuntu file system root directory is @@ -205,6 +212,8 @@ Ubuntu Bash under Windows 10 able to use Windows tools outside of the Ubuntu sandbox with versions of NuttX built within the sandbox using that path. + Executing Windows Tools from Ubuntu + ----------------------------------- You can also execute Windows tools from within the Ubuntu sandbox: $ /mnt/c/Program\ Files\ \(x86\)/Microchip/xc32/v1.43/bin/xc32-gcc.exe --version @@ -217,7 +226,7 @@ Ubuntu Bash under Windows 10 POSIX paths. I think you would have to use Linux tools only from within the Ubuntu sandbox. - Install Linux Software. + Install Ubuntu Software ----------------------- Use "sudo apt-get install ". As examples, this is how you would get GIT: From b8b9309d2bd97ffeb13786e486edd884db3a96d1 Mon Sep 17 00:00:00 2001 From: Harri Luhtala Date: Wed, 31 May 2017 06:20:18 -0600 Subject: [PATCH 03/22] vfs: fdopen: add missing file stream flags clearing. Clear file stream structure regardless of config options. Structure clearing is needed as previous use of stream list entry might leave fs_flags set. --- fs/vfs/fs_fdopen.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/vfs/fs_fdopen.c b/fs/vfs/fs_fdopen.c index 43e00f184af..ebacc4c5ff9 100644 --- a/fs/vfs/fs_fdopen.c +++ b/fs/vfs/fs_fdopen.c @@ -221,11 +221,7 @@ FAR struct file_struct *fs_fdopen(int fd, int oflags, FAR struct tcb_s *tcb) { /* Zero the structure */ -#ifndef CONFIG_STDIO_DISABLE_BUFFERING memset(stream, 0, sizeof(FILE)); -#elif CONFIG_NUNGET_CHARS > 0 - stream->fs_nungotten = 0; -#endif #ifndef CONFIG_STDIO_DISABLE_BUFFERING /* Initialize the semaphore the manages access to the buffer */ From 80cc19d6b0ee6c4a70a367881dcdc45231ac41ce Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Wed, 31 May 2017 06:31:53 -0600 Subject: [PATCH 04/22] drivers/input: add Cypress MBR3108 CapSense touch button driver --- drivers/input/Kconfig | 24 + drivers/input/Make.defs | 4 + drivers/input/cypress_mbr3108.c | 1157 +++++++++++++++++++++++++ include/nuttx/input/cypress_mbr3108.h | 139 +++ 4 files changed, 1324 insertions(+) create mode 100644 drivers/input/cypress_mbr3108.c create mode 100644 include/nuttx/input/cypress_mbr3108.h diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 0fc96d6c918..69d77e62d2f 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -322,6 +322,30 @@ config STMPE811_REGDEBUG endif # INPUT_STMPE811 +config INPUT_CYPRESS_MBR3108 + bool "Enable Cypress MBR3108 CapSense driver" + default n + ---help--- + Enable support for Cypress MBR3108 CapSense touch button & proximity + input sensor. + +if INPUT_CYPRESS_MBR3108 + +config INPUT_CYPRESS_MBR3108_DEBUG + bool "Enable debug support for Cypress sensor" + default n + depends on DEBUG_FEATURES + ---help--- + Enable debugging traces for MBR3108 driver + +config INPUT_CYPRESS_MBR3108_NPOLLWAITERS + int "Number of waiters to poll" + default 1 + ---help--- + Maximum number of threads that can be waiting on poll() + +endif # INPUT_CYPRESS_MBR3108 + config BUTTONS bool "Button Inputs" default n diff --git a/drivers/input/Make.defs b/drivers/input/Make.defs index 8285bfda0f7..af98782596b 100644 --- a/drivers/input/Make.defs +++ b/drivers/input/Make.defs @@ -71,6 +71,10 @@ ifneq ($(CONFIG_INPUT_STMPE811_TEMP_DISABLE),y) endif endif +ifeq ($(CONFIG_INPUT_CYPRESS_MBR3108),y) + CSRCS += cypress_mbr3108.c +endif + ifeq ($(CONFIG_BUTTONS),y) CSRCS += button_upper.c ifeq ($(CONFIG_BUTTONS_LOWER),y) diff --git a/drivers/input/cypress_mbr3108.c b/drivers/input/cypress_mbr3108.c new file mode 100644 index 00000000000..d1b29f672c2 --- /dev/null +++ b/drivers/input/cypress_mbr3108.c @@ -0,0 +1,1157 @@ +/**************************************************************************** + * drivers/input/cypress_mbr3108.c + * + * Copyright (C) 2014 Haltian Ltd. All rights reserved. + * Author: Jussi Kivilinna + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-Processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_INPUT_CYPRESS_MBR3108_DEBUG +# define mbr3108_dbg(x, ...) _info(x, ##__VA_ARGS__) +#else +# define mbr3108_dbg(x, ...) iinfo(x, ##__VA_ARGS__) +#endif + +/* Register macros */ + +#define MBR3108_SENSOR_EN 0x0 +#define MBR3108_FSS_EN 0x02 +#define MBR3108_TOGGLE_EN 0x04 +#define MBR3108_LED_ON_EN 0x06 +#define MBR3108_SENSITIVITY0 0x08 +#define MBR3108_SENSITIVITY1 0x09 +#define MBR3108_BASE_THRESHOLD0 0x0c +#define MBR3108_BASE_THRESHOLD1 0x0d +#define MBR3108_FINGER_THRESHOLD2 0x0e +#define MBR3108_FINGER_THRESHOLD3 0x0f +#define MBR3108_FINGER_THRESHOLD4 0x10 +#define MBR3108_FINGER_THRESHOLD5 0x11 +#define MBR3108_FINGER_THRESHOLD6 0x12 +#define MBR3108_FINGER_THRESHOLD7 0x13 +#define MBR3108_SENSOR_DEBOUNCE 0x1c +#define MBR3108_BUTTON_HYS 0x1d +#define MBR3108_BUTTON_LBR 0x1f +#define MBR3108_BUTTON_NNT 0x20 +#define MBR3108_BUTTON_NT 0x21 +#define MBR3108_PROX_EN 0x26 +#define MBR3108_PROX_CFG 0x27 +#define MBR3108_PROX_CFG2 0x28 +#define MBR3108_PROX_TOUCH_TH0 0x2a +#define MBR3108_PROX_TOUCH_TH1 0x2c +#define MBR3108_PROX_RESOLUTION0 0x2e +#define MBR3108_PROX_RESOLUTION1 0x2f +#define MBR3108_PROX_HYS 0x30 +#define MBR3108_PROX_LBR 0x32 +#define MBR3108_PROX_NNT 0x33 +#define MBR3108_PROX_NT 0x34 +#define MBR3108_PROX_POSITIVE_TH0 0x35 +#define MBR3108_PROX_POSITIVE_TH1 0x36 +#define MBR3108_PROX_NEGATIVE_TH0 0x39 +#define MBR3108_PROX_NEGATIVE_TH1 0x3a +#define MBR3108_LED_ON_TIME 0x3d +#define MBR3108_BUZZER_CFG 0x3e +#define MBR3108_BUZZER_ON_TIME 0x3f +#define MBR3108_GPO_CFG 0x40 +#define MBR3108_PWM_DUTYCYCLE_CFG0 0x41 +#define MBR3108_PWM_DUTYCYCLE_CFG1 0x42 +#define MBR3108_PWM_DUTYCYCLE_CFG2 0x43 +#define MBR3108_PWM_DUTYCYCLE_CFG3 0x44 +#define MBR3108_SPO_CFG 0x4c +#define MBR3108_DEVICE_CFG0 0x4d +#define MBR3108_DEVICE_CFG1 0x4e +#define MBR3108_DEVICE_CFG2 0x4f +#define MBR3108_DEVICE_CFG3 0x50 +#define MBR3108_I2C_ADDR 0x51 +#define MBR3108_REFRESH_CTRL 0x52 +#define MBR3108_STATE_TIMEOUT 0x55 +#define MBR3108_CONFIG_CRC 0x7e +#define MBR3108_GPO_OUTPUT_STATE 0x80 +#define MBR3108_SENSOR_ID 0x82 +#define MBR3108_CTRL_CMD 0x86 +#define MBR3108_CTRL_CMD_STATUS 0x88 +#define MBR3108_CTRL_CMD_ERR 0x89 +#define MBR3108_SYSTEM_STATUS 0x8a +#define MBR3108_PREV_CTRL_CMD_CODE 0x8c +#define MBR3108_FAMILY_ID 0x8f +#define MBR3108_DEVICE_ID 0x90 +#define MBR3108_DEVICE_REV 0x92 +#define MBR3108_CALC_CRC 0x94 +#define MBR3108_TOTAL_WORKING_SNS 0x97 +#define MBR3108_SNS_CP_HIGH 0x98 +#define MBR3108_SNS_VDD_SHORT 0x9a +#define MBR3108_SNS_GND_SHORT 0x9c +#define MBR3108_SNS_SNS_SHORT 0x9e +#define MBR3108_CMOD_SHIELD_TEST 0xa0 +#define MBR3108_BUTTON_STAT 0xaa +#define MBR3108_LATCHED_BUTTON_STAT 0xac +#define MBR3108_PROX_STAT 0xae +#define MBR3108_LATCHED_PROX_STAT 0xaf +#define MBR3108_SYNC_COUNTER0 0xb9 +#define MBR3108_DIFFERENCE_COUNT_SENSOR0 0xba +#define MBR3108_DIFFERENCE_COUNT_SENSOR1 0xbc +#define MBR3108_DIFFERENCE_COUNT_SENSOR2 0xbe +#define MBR3108_DIFFERENCE_COUNT_SENSOR3 0xc0 +#define MBR3108_DIFFERENCE_COUNT_SENSOR4 0xc2 +#define MBR3108_DIFFERENCE_COUNT_SENSOR5 0xc4 +#define MBR3108_DIFFERENCE_COUNT_SENSOR6 0xc6 +#define MBR3108_DIFFERENCE_COUNT_SENSOR7 0xc8 +#define MBR3108_GPO_DATA 0xda +#define MBR3108_SYNC_COUNTER1 0xdb +#define MBR3108_DEBUG_SENSOR_ID 0xdc +#define MBR3108_DEBUG_CP 0xdd +#define MBR3108_DEBUG_DIFFERENCE_COUNT0 0xde +#define MBR3108_DEBUG_BASELINE0 0xe0 +#define MBR3108_DEBUG_RAW_COUNT0 0xe2 +#define MBR3108_DEBUG_AVG_RAW_COUNT0 0xe4 +#define MBR3108_SYNC_COUNTER2 0xe7 + +/* Device commands for MBR3108_CTRL_CMD */ + +#define MBR3108_CMD_COMPLETED 0 +#define MBR3108_CMD_CHECK_CONFIG_CRC 2 +#define MBR3108_CMD_SET_CONFIG_CRC 3 +#define MBR3108_CMD_ENTER_LOW_POWER_MODE 7 +#define MBR3108_CMD_CLEAR_LATCHED 8 +#define MBR3108_CMD_RESET_ADV_LOWPASS_FILTER_PROX_SENS_0 9 +#define MBR3108_CMD_RESET_ADV_LOWPASS_FILTER_PROX_SENS_1 10 +#define MBR3108_CMD_SOFTWARE_RESET 255 + +#define MBR3108_CMD_STATUS_SUCCESS 0 +#define MBR3108_CMD_STATUS_ERROR 1 +#define MBR3108_CMD_STATUS_MASK 1 + +/* Completion times for device commands */ + +#define MBR3108_CMD_MSECS_CHECK_CONFIG_CRC 280 /* >220 (typ.) */ +#define MBR3108_CMD_MSECS_SOFTWARE_RESET 50 +#define MBR3108_CMD_MSECS_CLEAR_LATCHED 50 + +/* Other macros */ + +#define MBR3108_I2C_RETRIES 10 +#define MBR3108_NUM_SENSORS 8 +#define MBR3108_EXPECTED_FAMILY_ID 0x9a +#define MBR3108_EXPECTED_DEVICE_ID 0x0a03 +#define MBR3108_EXPECTED_DEVICE_REV 1 +#define MBR3108_SYNC_RETRIES 10 + +#ifndef CONFIG_MBR3108_I2C_FREQUENCY +# define CONFIG_MBR3108_I2C_FREQUENCY 400000 +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct mbr3108_dev_s +{ + /* I2C bus and address for device. */ + + struct i2c_master_s *i2c; + uint8_t addr; + + /* Configuration for device. */ + + struct mbr3108_board_s *board; + const struct mbr3108_sensor_conf_s *sensor_conf; + sem_t devsem; + uint8_t cref; + struct mbr3108_debug_conf_s debug_conf; + bool int_pending; + +#ifndef CONFIG_DISABLE_POLL + struct pollfd *fds[CONFIG_INPUT_CYPRESS_MBR3108_NPOLLWAITERS]; +#endif +}; + +/**************************************************************************** +* Private Function Prototypes +*****************************************************************************/ + +static int mbr3108_open(FAR struct file *filep); +static int mbr3108_close(FAR struct file *filep); +static ssize_t mbr3108_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t mbr3108_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +#ifndef CONFIG_DISABLE_POLL +static int mbr3108_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup); +#endif + +/**************************************************************************** +* Private Data +****************************************************************************/ + +static const struct file_operations g_mbr3108_fileops = +{ + mbr3108_open, /* open */ + mbr3108_close, /* close */ + mbr3108_read, /* read */ + mbr3108_write, /* write */ + 0, /* seek */ + 0 /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , mbr3108_poll /* poll */ +#endif +}; + +/**************************************************************************** +* Private Functions +****************************************************************************/ + +static int mbr3108_i2c_write(FAR struct mbr3108_dev_s *dev, uint8_t reg, + const uint8_t *buf, size_t buflen) +{ + struct i2c_msg_s msgv[2] = + { + { + .frequency = CONFIG_MBR3108_I2C_FREQUENCY, + .addr = dev->addr, + .flags = 0, + .buffer = ®, + .length = 1 + }, + { + .frequency = CONFIG_MBR3108_I2C_FREQUENCY, + .addr = dev->addr, + .flags = I2C_M_NORESTART, + .buffer = (void *)buf, + .length = buflen + } + }; + int ret = -EIO; + int retries; + + /* MBR3108 will respond with NACK to address when in low-power mode. Host + * needs to retry address selection multiple times to get MBR3108 to wake-up. + */ + + for (retries = 0; retries < MBR3108_I2C_RETRIES; retries++) + { + ret = I2C_TRANSFER(dev->i2c, msgv, 2); + if (ret == -ENXIO) + { + /* -ENXIO is returned when getting NACK from response. + * Keep trying. + */ + + continue; + } + + if (ret >= 0) + { + /* Success! */ + + return 0; + } + } + + /* Failed to read sensor. */ + + return ret; +} + +static int mbr3108_i2c_read(FAR struct mbr3108_dev_s *dev, uint8_t reg, + uint8_t *buf, size_t buflen) +{ + struct i2c_msg_s msgv[2] = + { + { + .frequency = CONFIG_MBR3108_I2C_FREQUENCY, + .addr = dev->addr, + .flags = 0, + .buffer = ®, + .length = 1 + }, + { + .frequency = CONFIG_MBR3108_I2C_FREQUENCY, + .addr = dev->addr, + .flags = I2C_M_READ, + .buffer = buf, + .length = buflen + } + }; + int ret = -EIO; + int retries; + + /* MBR3108 will respond with NACK to address when in low-power mode. Host + * needs to retry address selection multiple times to get MBR3108 to wake-up. + */ + + for (retries = 0; retries < MBR3108_I2C_RETRIES; retries++) + { + ret = I2C_TRANSFER(dev->i2c, msgv, 2); + if (ret == -ENXIO) + { + /* -ENXIO is returned when getting NACK from response. + * Keep trying. + */ + + continue; + } + else if (ret >= 0) + { + /* Success! */ + + return 0; + } + else + { + /* Some other error. Try to reset I2C bus and keep trying. */ + +#ifdef CONFIG_I2C_RESET + if (retries == MBR3108_I2C_RETRIES - 1) + { + break; + } + + ret = I2C_RESET(dev->i2c); + if (ret < 0) + { + mbr3108_dbg("I2C_RESET failed: %d\n", ret); + return ret; + } +#endif + } + } + + /* Failed to read sensor. */ + + return ret; +} + +static int mbr3108_check_cmd_status(FAR struct mbr3108_dev_s *dev) +{ + const uint8_t start_reg = MBR3108_CTRL_CMD; + const uint8_t last_reg = MBR3108_CTRL_CMD_ERR; + uint8_t readbuf[MBR3108_CTRL_CMD_ERR - MBR3108_CTRL_CMD + 1]; + uint8_t cmd, cmd_status, cmd_err; + int ret; + + DEBUGASSERT(last_reg - start_reg + 1 == sizeof(readbuf)); + + /* Multi-byte read to get command status. */ + + ret = mbr3108_i2c_read(dev, start_reg, readbuf, sizeof(readbuf)); + if (ret < 0) + { + mbr3108_dbg("cmd status get failed. ret=%d\n", ret); + return ret; + } + + cmd = readbuf[MBR3108_CTRL_CMD - MBR3108_CTRL_CMD]; + cmd_status = readbuf[MBR3108_CTRL_CMD_STATUS - MBR3108_CTRL_CMD]; + cmd_err = readbuf[MBR3108_CTRL_CMD_ERR - MBR3108_CTRL_CMD]; + + mbr3108_dbg("cmd: %d, status: %d, err: %d\n", cmd, cmd_status, cmd_err); + + if (cmd != MBR3108_CMD_COMPLETED) + { + return -EBUSY; + } + + if ((cmd_status & MBR3108_CMD_STATUS_MASK) == MBR3108_CMD_STATUS_SUCCESS) + { + /* Success. */ + + return 0; + } + + return cmd_err; +} + +static int mbr3108_save_check_crc(FAR struct mbr3108_dev_s *dev) +{ + uint8_t reg = MBR3108_CTRL_CMD; + uint8_t cmd = MBR3108_CMD_CHECK_CONFIG_CRC; + int ret; + + ret = mbr3108_i2c_write(dev, reg, &cmd, 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108_CTRL_CMD:CHECK_CONFIG_CRC write failed.\n"); + return ret; + } + + usleep(MBR3108_CMD_MSECS_CHECK_CONFIG_CRC * 1000); + + ret = mbr3108_check_cmd_status(dev); + if (ret != 0) + { + return ret < 0 ? ret : -EIO; + } + + return 0; +} + +static int mbr3108_software_reset(FAR struct mbr3108_dev_s *dev) +{ + uint8_t reg = MBR3108_CTRL_CMD; + uint8_t cmd = MBR3108_CMD_SOFTWARE_RESET; + int ret; + + ret = mbr3108_i2c_write(dev, reg, &cmd, 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108_CTRL_CMD:SOFTWARE_RESET write failed.\n"); + return ret; + } + + usleep(MBR3108_CMD_MSECS_SOFTWARE_RESET * 1000); + + ret = mbr3108_check_cmd_status(dev); + if (ret != 0) + { + return ret < 0 ? ret : -EIO; + } + + return 0; +} + +static int mbr3108_enter_low_power_mode(FAR struct mbr3108_dev_s *dev) +{ + uint8_t reg = MBR3108_CTRL_CMD; + uint8_t cmd = MBR3108_CMD_ENTER_LOW_POWER_MODE; + int ret; + + ret = mbr3108_i2c_write(dev, reg, &cmd, 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108_CTRL_CMD:SOFTWARE_RESET write failed.\n"); + return ret; + } + + /* Device is now in low-power mode and not scanning. Further communication + * will cause wake-up and make chip resume scanning operations. + */ + + return 0; +} + +static int mbr3108_clear_latched(FAR struct mbr3108_dev_s *dev) +{ + uint8_t reg = MBR3108_CTRL_CMD; + uint8_t cmd = MBR3108_CMD_CLEAR_LATCHED; + int ret; + + ret = mbr3108_i2c_write(dev, reg, &cmd, 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108_CTRL_CMD:MBR3108_CMD_CLEAR_LATCHED write failed.\n"); + return ret; + } + + usleep(MBR3108_CMD_MSECS_CLEAR_LATCHED * 1000); + + ret = mbr3108_check_cmd_status(dev); + if (ret != 0) + { + return ret < 0 ? ret : -EIO; + } + + return 0; +} + +static int mbr3108_debug_setup(FAR struct mbr3108_dev_s *dev, + FAR const struct mbr3108_debug_conf_s *conf) +{ + uint8_t reg = MBR3108_SENSOR_ID; + int ret; + + /* Store new debug configuration. */ + + dev->debug_conf = *conf; + + if (!conf->debug_mode) + { + return 0; + } + + /* Setup debug sensor id. */ + + ret = mbr3108_i2c_write(dev, reg, &conf->debug_sensor_id, 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108_SENSOR_ID write failed.\n"); + + dev->debug_conf.debug_mode = false; + } + + return ret; +} + +static int mbr3108_device_configuration(FAR struct mbr3108_dev_s *dev, + FAR const struct mbr3108_sensor_conf_s *conf) +{ + const uint8_t start_reg = MBR3108_SENSOR_EN; + const uint8_t last_reg = MBR3108_CONFIG_CRC + 1; + uint8_t value; + int ret = 0; + + DEBUGASSERT(sizeof(conf->conf_data) == last_reg - start_reg + 1); + + ret = mbr3108_i2c_read(dev, MBR3108_CTRL_CMD, &value, 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108_CTRL_CMD read failed.\n"); + return ret; + } + + if (value != MBR3108_CMD_COMPLETED) + { + /* Device is busy processing previous command. */ + + return -EBUSY; + } + + ret = mbr3108_i2c_write(dev, start_reg, conf->conf_data, + last_reg - start_reg + 1); + if (ret < 0) + { + mbr3108_dbg("MBR3108 configuration write failed.\n"); + return ret; + } + + ret = mbr3108_save_check_crc(dev); + if (ret < 0) + { + mbr3108_dbg("MBR3108 save check CRC failed. ret=%d\n", ret); + return ret; + } + + ret = mbr3108_software_reset(dev); + if (ret < 0) + { + mbr3108_dbg("MBR3108 software reset failed.\n"); + return ret; + } + + dev->board->irq_enable(dev->board, true); + + return 0; +} + +static int mbr3108_get_sensor_status(FAR struct mbr3108_dev_s *dev, + FAR void *buf) +{ + struct mbr3108_sensor_status_s status = {}; + const uint8_t start_reg = MBR3108_BUTTON_STAT; + const uint8_t last_reg = MBR3108_LATCHED_PROX_STAT; + uint8_t readbuf[MBR3108_LATCHED_PROX_STAT - MBR3108_BUTTON_STAT + 1]; + int ret; + + DEBUGASSERT(last_reg - start_reg + 1 == sizeof(readbuf)); + + /* Attempt to sensor status registers.*/ + + ret = mbr3108_i2c_read(dev, start_reg, readbuf, sizeof(readbuf)); + if (ret < 0) + { + mbr3108_dbg("Sensor status read failed.\n"); + + return ret; + } + + status.button = (readbuf[MBR3108_BUTTON_STAT + 0 - start_reg]) | + (readbuf[MBR3108_BUTTON_STAT + 1 - start_reg] << 8); + status.proximity = readbuf[MBR3108_PROX_STAT - start_reg]; + + status.latched_button = + (readbuf[MBR3108_LATCHED_BUTTON_STAT + 0 - start_reg]) | + (readbuf[MBR3108_LATCHED_BUTTON_STAT + 1 - start_reg] << 8); + status.latched_proximity = readbuf[MBR3108_LATCHED_PROX_STAT - start_reg]; + + memcpy(buf, &status, sizeof(status)); + + mbr3108_dbg("but: %x, prox: %x; latched[btn: %x, prox: %x]\n", + status.button, status.proximity, status.latched_button, + status.latched_button); + + return 0; +} + +static int mbr3108_get_sensor_debug_data(FAR struct mbr3108_dev_s *dev, + FAR void *buf) +{ + struct mbr3108_sensor_debug_s data = {}; + const uint8_t start_reg = MBR3108_SYNC_COUNTER1; + const uint8_t last_reg = MBR3108_SYNC_COUNTER2; + uint8_t readbuf[MBR3108_SYNC_COUNTER2 - MBR3108_SYNC_COUNTER1 + 1]; + int ret; + int retries; + uint8_t sync1, sync2; + + DEBUGASSERT(last_reg - start_reg + 1 == sizeof(readbuf)); + + for (retries = MBR3108_SYNC_RETRIES; retries > 0; retries--) + { + ret = mbr3108_i2c_read(dev, start_reg, readbuf, sizeof(readbuf)); + if (ret < 0) + { + mbr3108_dbg("Sensor debug data read failed.\n"); + + return ret; + } + + /* Sync counters need to match. */ + + sync1 = readbuf[MBR3108_SYNC_COUNTER1 - start_reg]; + sync2 = readbuf[MBR3108_SYNC_COUNTER2 - start_reg]; + + if (sync1 == sync2) + { + break; + } + } + + if (retries == 0) + { + return -EIO; + } + + data.sensor_average_counts = + (readbuf[MBR3108_DEBUG_AVG_RAW_COUNT0 + 0 - start_reg]) | + (readbuf[MBR3108_DEBUG_AVG_RAW_COUNT0 + 1 - start_reg] << 8); + data.sensor_baseline = + (readbuf[MBR3108_DEBUG_BASELINE0 + 0 - start_reg]) | + (readbuf[MBR3108_DEBUG_BASELINE0 + 1 - start_reg] << 8); + data.sensor_diff_counts = + (readbuf[MBR3108_DEBUG_DIFFERENCE_COUNT0 + 0 - start_reg]) | + (readbuf[MBR3108_DEBUG_DIFFERENCE_COUNT0 + 1 - start_reg] << 8); + data.sensor_raw_counts = + (readbuf[MBR3108_DEBUG_RAW_COUNT0 + 0 - start_reg]) | + (readbuf[MBR3108_DEBUG_RAW_COUNT0 + 1 - start_reg] << 8); + data.sensor_total_capacitance = readbuf[MBR3108_DEBUG_CP - start_reg]; + + memcpy(buf, &data, sizeof(data)); + + mbr3108_dbg("avg_cnt: %d, baseline: %d, diff_cnt: %d, raw_cnt: %d, " + "total_cp: %d\n", + data.sensor_average_counts, data.sensor_baseline, + data.sensor_diff_counts, data.sensor_raw_counts, + data.sensor_total_capacitance); + + return 0; +} + +static int mbr3108_probe_device(FAR struct mbr3108_dev_s *dev) +{ + const uint8_t start_reg = MBR3108_FAMILY_ID; + const uint8_t last_reg = MBR3108_DEVICE_REV; + uint8_t readbuf[MBR3108_DEVICE_REV - MBR3108_FAMILY_ID + 1]; + uint8_t fam_id; + uint16_t dev_id; + uint8_t dev_rev; + int ret; + + DEBUGASSERT(last_reg - start_reg + 1 == sizeof(readbuf)); + + /* Attempt to read device identification registers with multi-byte read.*/ + + ret = mbr3108_i2c_read(dev, start_reg, readbuf, sizeof(readbuf)); + if (ret < 0) + { + /* Failed to read registers from device. */ + + mbr3108_dbg("Probe failed.\n"); + + return ret; + } + + /* Check result. */ + + fam_id = readbuf[MBR3108_FAMILY_ID - start_reg]; + dev_id = (readbuf[MBR3108_DEVICE_ID + 0 - start_reg]) | + (readbuf[MBR3108_DEVICE_ID + 1 - start_reg] << 8); + dev_rev = readbuf[MBR3108_DEVICE_REV - start_reg]; + + mbr3108_dbg("family_id: 0x%02x, device_id: 0x%04x, device_rev: %d\n", + fam_id, dev_id, dev_rev); + + if (fam_id != MBR3108_EXPECTED_FAMILY_ID || + dev_id != MBR3108_EXPECTED_DEVICE_ID || + dev_rev != MBR3108_EXPECTED_DEVICE_REV) + { + mbr3108_dbg("Probe failed, dev-id mismatch!\n"); + mbr3108_dbg( + " Expected: family_id: 0x%02x, device_id: 0x%04x, device_rev: %d\n", + MBR3108_EXPECTED_FAMILY_ID, + MBR3108_EXPECTED_DEVICE_ID, + MBR3108_EXPECTED_DEVICE_REV); + + return -ENXIO; + } + + return 0; +} + +static ssize_t mbr3108_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct inode *inode; + FAR struct mbr3108_dev_s *priv; + size_t outlen; + irqstate_t flags; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = inode->i_private; + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + ret = -EINVAL; + + if (priv->debug_conf.debug_mode) + { + outlen = sizeof(struct mbr3108_sensor_debug_s); + if (buflen >= outlen) + { + ret = mbr3108_get_sensor_debug_data(priv, buffer); + } + } + else + { + outlen = sizeof(struct mbr3108_sensor_status_s); + if (buflen >= outlen) + { + ret = mbr3108_get_sensor_status(priv, buffer); + } + } + + flags = enter_critical_section(); + priv->int_pending = false; + leave_critical_section(flags); + + sem_post(&priv->devsem); + return ret < 0 ? ret : outlen; +} + +static ssize_t mbr3108_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + FAR struct inode *inode; + FAR struct mbr3108_dev_s *priv; + enum mbr3108_cmd_e type; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = inode->i_private; + + if (buflen < sizeof(enum mbr3108_cmd_e)) + { + return -EINVAL; + } + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + type = *(FAR const enum mbr3108_cmd_e *)buffer; + + switch (type) + { + case CYPRESS_MBR3108_CMD_SENSOR_CONF: + { + FAR const struct mbr3108_cmd_sensor_conf_s *conf = + (FAR const struct mbr3108_cmd_sensor_conf_s *)buffer; + + if (buflen != sizeof(*conf)) + { + ret = -EINVAL; + goto out; + } + + ret = mbr3108_device_configuration(priv, &conf->conf); + break; + } + + case CYPRESS_MBR3108_CMD_DEBUG_CONF: + { + FAR const struct mbr3108_cmd_debug_conf_s *conf = + (FAR const struct mbr3108_cmd_debug_conf_s *)buffer; + + if (buflen != sizeof(*conf)) + { + ret = -EINVAL; + goto out; + } + + ret = mbr3108_debug_setup(priv, &conf->conf); + break; + } + + case CYPRESS_MBR3108_CMD_CLEAR_LATCHED: + { + if (buflen != sizeof(type)) + { + ret = -EINVAL; + goto out; + } + + ret = mbr3108_clear_latched(priv); + break; + } + + default: + ret = -EINVAL; + break; + } + +out: + sem_post(&priv->devsem); + + return ret < 0 ? ret : buflen; +} + +static int mbr3108_open(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct mbr3108_dev_s *priv; + unsigned int use_count; + int ret; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = inode->i_private; + + while (sem_wait(&priv->devsem) != 0) + { + assert(errno == EINTR); + } + + use_count = priv->cref + 1; + if (use_count == 1) + { + /* First user, do power on. */ + + ret = priv->board->set_power(priv->board, true); + if (ret < 0) + { + goto out_sem; + } + + /* Let chip to power up before probing */ + + usleep(100 * 1000); + + /* Check that device exists on I2C. */ + + ret = mbr3108_probe_device(priv); + if (ret < 0) + { + /* No such device. Power off the switch. */ + + (void)priv->board->set_power(priv->board, false); + goto out_sem; + } + + if (priv->sensor_conf) + { + /* Do configuration. */ + + ret = mbr3108_device_configuration(priv, priv->sensor_conf); + if (ret < 0) + { + /* Configuration failed. Power off the switch. */ + + (void)priv->board->set_power(priv->board, false); + goto out_sem; + } + } + + priv->cref = use_count; + } + else + { + DEBUGASSERT(use_count < UINT8_MAX && use_count > priv->cref); + + priv->cref = use_count; + ret = 0; + } + +out_sem: + sem_post(&priv->devsem); + return ret; +} + +static int mbr3108_close(FAR struct file *filep) +{ + FAR struct inode *inode; + FAR struct mbr3108_dev_s *priv; + int use_count; + + DEBUGASSERT(filep); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = inode->i_private; + + while (sem_wait(&priv->devsem) != 0) + { + assert(errno == EINTR); + } + + use_count = priv->cref - 1; + if (use_count == 0) + { + /* Disable interrupt */ + + priv->board->irq_enable(priv->board, false); + + /* Set chip in low-power mode. */ + + (void)mbr3108_enter_low_power_mode(priv); + + /* Last user, do power off. */ + + (void)priv->board->set_power(priv->board, false); + + priv->debug_conf.debug_mode = false; + priv->cref = use_count; + } + else + { + DEBUGASSERT(use_count > 0); + + priv->cref = use_count; + } + + sem_post(&priv->devsem); + + return 0; +} + +#ifndef CONFIG_DISABLE_POLL + +static void mbr3108_poll_notify(FAR struct mbr3108_dev_s *priv) +{ + int i; + + DEBUGASSERT(priv != NULL); + + for (i = 0; i < CONFIG_INPUT_CYPRESS_MBR3108_NPOLLWAITERS; i++) + { + struct pollfd *fds = priv->fds[i]; + if (fds) + { + mbr3108_dbg("Report events: %02x\n", fds->revents); + + fds->revents |= POLLIN; + sem_post(fds->sem); + } + } +} + +static int mbr3108_poll(FAR struct file *filep, FAR struct pollfd *fds, + bool setup) +{ + FAR struct mbr3108_dev_s *priv; + FAR struct inode *inode; + bool pending; + int ret = 0; + int i; + + DEBUGASSERT(filep && fds); + inode = filep->f_inode; + + DEBUGASSERT(inode && inode->i_private); + priv = (FAR struct mbr3108_dev_s *)inode->i_private; + + ret = sem_wait(&priv->devsem); + if (ret < 0) + { + return ret; + } + + if (setup) + { + /* Ignore waits that do not include POLLIN */ + + if ((fds->events & POLLIN) == 0) + { + ret = -EDEADLK; + goto out; + } + + /* This is a request to set up the poll. Find an available slot for the + * poll structure reference. + */ + + for (i = 0; i < CONFIG_INPUT_CYPRESS_MBR3108_NPOLLWAITERS; i++) + { + /* Find an available slot */ + + if (!priv->fds[i]) + { + /* Bind the poll structure and this slot */ + + priv->fds[i] = fds; + fds->priv = &priv->fds[i]; + break; + } + } + + if (i >= CONFIG_INPUT_CYPRESS_MBR3108_NPOLLWAITERS) + { + fds->priv = NULL; + ret = -EBUSY; + } + else + { + pending = priv->int_pending; + if (pending) + { + mbr3108_poll_notify(priv); + } + } + } + else if (fds->priv) + { + /* This is a request to tear down the poll. */ + + FAR struct pollfd **slot = (FAR struct pollfd **)fds->priv; + DEBUGASSERT(slot != NULL); + + /* Remove all memory of the poll setup */ + + *slot = NULL; + fds->priv = NULL; + } + +out: + sem_post(&priv->devsem); + return ret; +} + +#endif /* !CONFIG_DISABLE_POLL */ + +static int mbr3108_isr_handler(int irq, FAR void *context, FAR void *arg) +{ + FAR struct mbr3108_dev_s *priv = (FAR struct mbr3108_dev_s *)arg; + irqstate_t flags; + + DEBUGASSERT(priv != NULL); + + flags = enter_critical_section(); + priv->int_pending = true; + leave_critical_section(flags); + +#ifndef CONFIG_DISABLE_POLL + mbr3108_poll_notify(priv); +#endif + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int cypress_mbr3108_register(FAR const char *devpath, + FAR struct i2c_master_s *i2c_dev, + uint8_t i2c_devaddr, + struct mbr3108_board_s *board_config, + const struct mbr3108_sensor_conf_s *sensor_conf) +{ + struct mbr3108_dev_s *priv; + int ret = 0; + + /* Allocate device private structure. */ + + priv = kmm_zalloc(sizeof(struct mbr3108_dev_s)); + if (!priv) + { + mbr3108_dbg("Memory cannot be allocated for mbr3108 sensor\n"); + return -ENOMEM; + } + + /* Setup device structure. */ + + priv->addr = i2c_devaddr; + priv->i2c = i2c_dev; + priv->board = board_config; + priv->sensor_conf = sensor_conf; + + sem_init(&priv->devsem, 0, 1); + + ret = register_driver(devpath, &g_mbr3108_fileops, 0666, priv); + if (ret < 0) + { + kmm_free(priv); + mbr3108_dbg("Error occurred during the driver registering\n"); + return ret; + } + + mbr3108_dbg("Registered with %d\n", ret); + + /* Prepare interrupt line and handler. */ + + priv->board->irq_attach(priv->board, mbr3108_isr_handler, priv); + priv->board->irq_enable(priv->board, false); + + return 0; +} diff --git a/include/nuttx/input/cypress_mbr3108.h b/include/nuttx/input/cypress_mbr3108.h new file mode 100644 index 00000000000..941de91cc02 --- /dev/null +++ b/include/nuttx/input/cypress_mbr3108.h @@ -0,0 +1,139 @@ +/**************************************************************************** + * include/nuttx/input/cypress_mbr3108.c + * + * Copyright (C) 2014 Haltian Ltd. All rights reserved. + * Author: Jussi Kivilinna + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_INPUT_CYPRESS_MBR3108_H_ +#define __INCLUDE_NUTTX_INPUT_CYPRESS_MBR3108_H_ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Sensor configuration for Cypress MBR3108 device */ + +begin_packed_struct struct mbr3108_sensor_conf_s +{ + uint8_t conf_data[128]; /* Sensor configuration, generated with EZ-Click. */ +} end_packed_struct; + +/* Debug configuration */ + +begin_packed_struct struct mbr3108_debug_conf_s +{ + bool debug_mode; /* Configure to debug mode if 'true'. */ + uint8_t debug_sensor_id; /* Sensor to read in debug mode. */ +} end_packed_struct; + +/* Write commands to MBR3108 driver. */ + +begin_packed_struct enum mbr3108_cmd_e +{ + CYPRESS_MBR3108_CMD_SENSOR_CONF = -3, + CYPRESS_MBR3108_CMD_DEBUG_CONF, + CYPRESS_MBR3108_CMD_CLEAR_LATCHED, +} end_packed_struct; + +/* CYPRESS_MBR3108_CMD_SENSOR_CONF command structure. Used to reconfigure + * chip with new configuration generated using EZ-Click tool. */ + +begin_packed_struct struct mbr3108_cmd_sensor_conf_s +{ + enum mbr3108_cmd_e id; + struct mbr3108_sensor_conf_s conf; +} end_packed_struct; + +/* CYPRESS_MBR3108_CMD_DEBUG_CONF command structure. Use to enable debug + * output from chip/sensor, see 'struct mbr3108_sensor_data_s'. */ + +begin_packed_struct struct mbr3108_cmd_debug_conf_s +{ + enum mbr3108_cmd_e id; + struct mbr3108_debug_conf_s conf; +} end_packed_struct; + +/* Sensor status output */ + +begin_packed_struct struct mbr3108_sensor_status_s +{ + unsigned int button:8; /* MBR3108 has maximum of 8 button sensors + * configurable. + * Each bit in this field indicate if + * corresponding button is pressed. */ + unsigned int latched_button:8; + unsigned int proximity:2; /* MBR3108 has maximum of 2 proximity + * sensors configurable. */ + unsigned int latched_proximity:2; +} end_packed_struct; + +/* Sensor debug data output */ + +begin_packed_struct struct mbr3108_sensor_debug_s +{ + uint8_t sensor_total_capacitance; + uint16_t sensor_diff_counts; + uint16_t sensor_baseline; + uint16_t sensor_raw_counts; + uint16_t sensor_average_counts; +} end_packed_struct; + +/* Board configuration */ + +struct mbr3108_board_s +{ + int (*irq_attach) (FAR struct mbr3108_board_s *state, xcpt_t isr, FAR void *arg); + void (*irq_enable) (FAR struct mbr3108_board_s *state, bool enable); + int (*set_power) (FAR struct mbr3108_board_s *state, bool on); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Device registration */ + +int cypress_mbr3108_register(FAR const char *devpath, + FAR struct i2c_master_s *dev, + uint8_t i2c_devaddr, + struct mbr3108_board_s *board_config, + const struct mbr3108_sensor_conf_s *sensor_conf); + +#endif /* __INCLUDE_NUTTX_INPUT_CYPRESS_MBR3108_H_ */ From 14c233a2f5ee5ce4e8261f52311090d3e1a3417c Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Wed, 31 May 2017 06:34:14 -0600 Subject: [PATCH 05/22] STM32L4: gpio: put back EXTI line source selection --- arch/arm/src/stm32l4/stm32l4_gpio.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/arch/arm/src/stm32l4/stm32l4_gpio.c b/arch/arm/src/stm32l4/stm32l4_gpio.c index 049c40fd2cf..f46f341662c 100644 --- a/arch/arm/src/stm32l4/stm32l4_gpio.c +++ b/arch/arm/src/stm32l4/stm32l4_gpio.c @@ -309,17 +309,15 @@ int stm32l4_configgpio(uint32_t cfgset) /* Otherwise, it is an input pin. Should it configured as an EXTI interrupt? */ - if ((cfgset & GPIO_EXTI) != 0) + if (pinmode != GPIO_MODER_OUTPUT && (cfgset & GPIO_EXTI) != 0) { -#if 0 - /* "In STM32 F1 the selection of the EXTI line source is performed through - * the EXTIx bits in the AFIO_EXTICRx registers, while in F2 series this - * selection is done through the EXTIx bits in the SYSCFG_EXTICRx registers. + /* The selection of the EXTI line source is performed through the EXTIx + * bits in the SYSCFG_EXTICRx registers. * - * "Only the mapping of the EXTICRx registers has been changed, without any - * changes to the meaning of the EXTIx bits. However, the range of EXTI - * bits values has been extended to 0b1000 to support the two ports added - * in F2, port H and I (in F1 series the maximum value is 0b0110)." + * The range of EXTI bit values in STM32L4x6 goes to 0b1000 to support the + * ports up to PI in STM32L496xx devices. For STM32L4x3 the EXTI bit values + * end at 0b111 (for PH0, PH1 and PH3 only) and values for non-existent + * ports F and G are reserved. */ uint32_t regaddr; @@ -334,7 +332,6 @@ int stm32l4_configgpio(uint32_t cfgset) regval |= (((uint32_t)port) << shift); putreg32(regval, regaddr); -#endif } leave_critical_section(flags); From c7fcdf968d797488f9aae8ed8255a66a1ec2b74d Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Wed, 31 May 2017 09:07:25 -0600 Subject: [PATCH 06/22] mtd/smart: Fix use of uninitialized variable --- drivers/mtd/smart.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/smart.c b/drivers/mtd/smart.c index c5c6e80a3e9..e483bc99d3f 100644 --- a/drivers/mtd/smart.c +++ b/drivers/mtd/smart.c @@ -1368,7 +1368,8 @@ static int smart_add_sector_to_cache(FAR struct smart_struct_s *dev, index = 1; if (dev->cache_entries < CONFIG_MTD_SMART_SECTOR_CACHE_SIZE) { - index = dev->cache_entries++; + oldest = 0; + index = dev->cache_entries++; } else { @@ -1387,7 +1388,7 @@ static int smart_add_sector_to_cache(FAR struct smart_struct_s *dev, if (dev->sCache[x].birth < oldest) { oldest = dev->sCache[x].birth; - index = x; + index = x; } } } From 8b006e705e9a81c94793aa3fb79c330d91382523 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Wed, 31 May 2017 09:09:24 -0600 Subject: [PATCH 07/22] drivers/mtd/w25.c: erase sector only if it is not in erased state --- drivers/mtd/w25.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/drivers/mtd/w25.c b/drivers/mtd/w25.c index 79ac0a5a66b..fb292217a7e 100644 --- a/drivers/mtd/w25.c +++ b/drivers/mtd/w25.c @@ -247,6 +247,7 @@ static void w25_unprotect(FAR struct w25_dev_s *priv); static uint8_t w25_waitwritecomplete(FAR struct w25_dev_s *priv); static inline void w25_wren(FAR struct w25_dev_s *priv); static inline void w25_wrdi(FAR struct w25_dev_s *priv); +static bool w25_is_erased(struct w25_dev_s *priv, off_t address, off_t size); static void w25_sectorerase(FAR struct w25_dev_s *priv, off_t offset); static inline int w25_chiperase(FAR struct w25_dev_s *priv); static void w25_byteread(FAR struct w25_dev_s *priv, FAR uint8_t *buffer, @@ -549,6 +550,55 @@ static inline void w25_wrdi(struct w25_dev_s *priv) SPI_SELECT(priv->spi, SPIDEV_FLASH(0), false); } +/************************************************************************************ + * Name: w25_is_erased + ************************************************************************************/ + +static bool w25_is_erased(struct w25_dev_s *priv, off_t address, off_t size) +{ + size_t npages = size >> W25_PAGE_SHIFT; + uint32_t erased_32; + unsigned int i; + uint32_t *buf; + + DEBUGASSERT((address % W25_PAGE_SIZE) == 0); + DEBUGASSERT((size % W25_PAGE_SIZE) == 0); + + buf = kmm_malloc(W25_PAGE_SIZE); + if (!buf) + { + return false; + } + + memset(&erased_32, W25_ERASED_STATE, sizeof(erased_32)); + + /* Walk all pages in given area. */ + + while (npages) + { + /* Check if all bytes of page is in erased state. */ + + w25_byteread(priv, (unsigned char *)buf, address, W25_PAGE_SIZE); + + for (i = 0; i < W25_PAGE_SIZE / sizeof(uint32_t); i++) + { + if (buf[i] != erased_32) + { + /* Page not in erased state! */ + + kmm_free(buf); + return false; + } + } + + address += W25_PAGE_SIZE; + npages--; + } + + kmm_free(buf); + return true; +} + /************************************************************************************ * Name: w25_sectorerase ************************************************************************************/ @@ -559,6 +609,15 @@ static void w25_sectorerase(struct w25_dev_s *priv, off_t sector) finfo("sector: %08lx\n", (long)sector); + /* Check if sector is already erased. */ + + if (w25_is_erased(priv, address, W25_SECTOR_SIZE)) + { + /* Sector already in erased state, so skip erase. */ + + return; + } + /* Wait for any preceding write or erase operation to complete. */ (void)w25_waitwritecomplete(priv); From 369b72f65a44dc067bab40a6d7c0482a0ef5f176 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Wed, 31 May 2017 09:13:20 -0600 Subject: [PATCH 08/22] stm32f7: Add SPI DMA support --- arch/arm/src/stm32f7/stm32_spi.c | 70 ++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/arch/arm/src/stm32f7/stm32_spi.c b/arch/arm/src/stm32f7/stm32_spi.c index c00e717a09a..d6b4cb9e9c3 100644 --- a/arch/arm/src/stm32f7/stm32_spi.c +++ b/arch/arm/src/stm32f7/stm32_spi.c @@ -80,6 +80,7 @@ #include "up_internal.h" #include "up_arch.h" +#include "cache.h" #include "chip.h" #include "stm32_gpio.h" #include "stm32_dma.h" @@ -110,12 +111,10 @@ #ifdef CONFIG_STM32F7_SPI_DMA -# error "SPI DMA not yet supported" - # if defined(CONFIG_SPI_DMAPRIO) # define SPI_DMA_PRIO CONFIG_SPI_DMAPRIO # elif defined(DMA_SCR_PRIMED) -# define SPI_DMA_PRIO DMA_SCR_PRIMED +# define SPI_DMA_PRIO DMA_SCR_PRILO # else # error "Unknown STM32 DMA" # endif @@ -264,8 +263,8 @@ static struct stm32_spidev_s g_spi1dev = .spiirq = STM32_IRQ_SPI1, #endif #ifdef CONFIG_STM32F7_SPI_DMA - .rxch = DMACHAN_SPI1_RX, - .txch = DMACHAN_SPI1_TX, + .rxch = DMAMAP_SPI1_RX, + .txch = DMAMAP_SPI1_TX, #endif }; #endif @@ -308,8 +307,8 @@ static struct stm32_spidev_s g_spi2dev = .spiirq = STM32_IRQ_SPI2, #endif #ifdef CONFIG_STM32F7_SPI_DMA - .rxch = DMACHAN_SPI2_RX, - .txch = DMACHAN_SPI2_TX, + .rxch = DMAMAP_SPI2_RX, + .txch = DMAMAP_SPI2_TX, #endif }; #endif @@ -352,8 +351,8 @@ static struct stm32_spidev_s g_spi3dev = .spiirq = STM32_IRQ_SPI3, #endif #ifdef CONFIG_STM32F7_SPI_DMA - .rxch = DMACHAN_SPI3_RX, - .txch = DMACHAN_SPI3_TX, + .rxch = DMAMAP_SPI3_RX, + .txch = DMAMAP_SPI3_TX, #endif }; #endif @@ -396,8 +395,8 @@ static struct stm32_spidev_s g_spi4dev = .spiirq = STM32_IRQ_SPI4, #endif #ifdef CONFIG_STM32F7_SPI_DMA - .rxch = DMACHAN_SPI4_RX, - .txch = DMACHAN_SPI4_TX, + .rxch = DMAMAP_SPI4_RX, + .txch = DMAMAP_SPI4_TX, #endif }; #endif @@ -440,8 +439,8 @@ static struct stm32_spidev_s g_spi5dev = .spiirq = STM32_IRQ_SPI5, #endif #ifdef CONFIG_STM32F7_SPI_DMA - .rxch = DMACHAN_SPI5_RX, - .txch = DMACHAN_SPI5_TX, + .rxch = DMAMAP_SPI5_RX, + .txch = DMAMAP_SPI5_TX, #endif }; #endif @@ -484,8 +483,8 @@ static struct stm32_spidev_s g_spi6dev = .spiirq = STM32_IRQ_SPI6, #endif #ifdef CONFIG_STM32F7_SPI_DMA - .rxch = DMACHAN_SPI6_RX, - .txch = DMACHAN_SPI6_TX, + .rxch = DMAMAP_SPI6_RX, + .txch = DMAMAP_SPI6_TX, #endif }; #endif @@ -927,7 +926,7 @@ static void spi_dmatxsetup(FAR struct stm32_spidev_s *priv, FAR const void *txbu ************************************************************************************/ #ifdef CONFIG_STM32F7_SPI_DMA -static inline void spi_dmarxstart(FAR struct stm32_spidev_s *priv) +static void spi_dmarxstart(FAR struct stm32_spidev_s *priv) { priv->rxresult = 0; stm32_dmastart(priv->rxdma, spi_dmarxcallback, priv, false); @@ -943,7 +942,7 @@ static inline void spi_dmarxstart(FAR struct stm32_spidev_s *priv) ************************************************************************************/ #ifdef CONFIG_STM32F7_SPI_DMA -static inline void spi_dmatxstart(FAR struct stm32_spidev_s *priv) +static void spi_dmatxstart(FAR struct stm32_spidev_s *priv) { priv->txresult = 0; stm32_dmastart(priv->txdma, spi_dmatxcallback, priv, false); @@ -1528,6 +1527,8 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, { FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; + DEBUGASSERT(priv != NULL); + #ifdef CONFIG_STM32F7_DMACAPABLE if ((txbuffer && !stm32_dmacapable((uint32_t)txbuffer, nwords, priv->txccr)) || (rxbuffer && !stm32_dmacapable((uint32_t)rxbuffer, nwords, priv->rxccr))) @@ -1539,17 +1540,31 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, else #endif { - static uint16_t rxdummy = 0xffff; + static uint8_t rxdummy[ARMV7M_DCACHE_LINESIZE] + __attribute__((aligned(ARMV7M_DCACHE_LINESIZE))); static const uint16_t txdummy = 0xffff; + size_t buflen = nwords; + + if (spi_9to16bitmode(priv)) + { + buflen = nwords * sizeof(uint16_t); + } spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords); - DEBUGASSERT(priv && priv->spibase); + DEBUGASSERT(priv->spibase != 0); /* Setup DMAs */ - spi_dmarxsetup(priv, rxbuffer, &rxdummy, nwords); + spi_dmarxsetup(priv, rxbuffer, (uint16_t *)rxdummy, nwords); spi_dmatxsetup(priv, txbuffer, &txdummy, nwords); + /* Flush cache to physical memory */ + + if (txbuffer) + { + arch_flush_dcache((uintptr_t)txbuffer, (uintptr_t)txbuffer + buflen); + } + /* Start the DMAs */ spi_dmarxstart(priv); @@ -1559,6 +1574,19 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, spi_dmarxwait(priv); spi_dmatxwait(priv); + + /* Force RAM re-read */ + + if (rxbuffer) + { + arch_invalidate_dcache((uintptr_t)rxbuffer, + (uintptr_t)rxbuffer + buflen); + } + else + { + arch_invalidate_dcache((uintptr_t)rxdummy, + (uintptr_t)rxdummy + sizeof(rxdummy)); + } } } #endif /* CONFIG_STM32F7_SPI_DMA */ @@ -1694,7 +1722,7 @@ static void spi_bus_initialize(FAR struct stm32_spidev_s *priv) priv->txdma = stm32_dmachannel(priv->txch); DEBUGASSERT(priv->rxdma && priv->txdma); - spi_putreg(priv, STM32_SPI_CR2_OFFSET, SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN); + spi_modifycr2(priv, SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN, 0); #endif /* Enable spi */ From 7af5cbb833146b9bd7fec18f54fa054dd59ab87f Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Wed, 31 May 2017 09:17:58 -0600 Subject: [PATCH 09/22] drivers/mtd/w25.c: Enable short delay after sector/chip erase --- drivers/mtd/w25.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/w25.c b/drivers/mtd/w25.c index fb292217a7e..458c85e092b 100644 --- a/drivers/mtd/w25.c +++ b/drivers/mtd/w25.c @@ -224,6 +224,7 @@ struct w25_dev_s struct mtd_dev_s mtd; /* MTD interface */ FAR struct spi_dev_s *spi; /* Saved SPI interface instance */ uint16_t nsectors; /* Number of erase sectors */ + uint8_t prev_instr; /* Previous instruction given to W25 device */ #if defined(CONFIG_W25_SECTOR512) && !defined(CONFIG_W25_READONLY) uint8_t flags; /* Buffered sector flags */ @@ -495,17 +496,17 @@ static uint8_t w25_waitwritecomplete(struct w25_dev_s *priv) /* Given that writing could take up to few tens of milliseconds, and erasing * could take more. The following short delay in the "busy" case will allow - * other peripherals to access the SPI bus. + * other peripherals to access the SPI bus. Delay would slow down writing + * too much, so go to sleep only if previous operation was not a page program + * operation. */ -#if 0 /* Makes writes too slow */ - if ((status & W25_SR_BUSY) != 0) + if (priv->prev_instr != W25_PP && (status & W25_SR_BUSY) != 0) { w25_unlock(priv->spi); usleep(1000); w25_lock(priv->spi); } -#endif } while ((status & W25_SR_BUSY) != 0); @@ -633,6 +634,7 @@ static void w25_sectorerase(struct w25_dev_s *priv, off_t sector) /* Send the "Sector Erase (SE)" instruction */ (void)SPI_SEND(priv->spi, W25_SE); + priv->prev_instr = W25_SE; /* Send the sector address high byte first. Only the most significant bits (those * corresponding to the sector) have any meaning. @@ -670,6 +672,7 @@ static inline int w25_chiperase(struct w25_dev_s *priv) /* Send the "Chip Erase (CE)" instruction */ (void)SPI_SEND(priv->spi, W25_CE); + priv->prev_instr = W25_CE; /* Deselect the FLASH */ @@ -706,8 +709,10 @@ static void w25_byteread(FAR struct w25_dev_s *priv, FAR uint8_t *buffer, #ifdef CONFIG_W25_SLOWREAD (void)SPI_SEND(priv->spi, W25_RDDATA); + priv->prev_instr = W25_RDDATA; #else (void)SPI_SEND(priv->spi, W25_FRD); + priv->prev_instr = W25_FRD; #endif /* Send the address high byte first. */ @@ -763,6 +768,7 @@ static void w25_pagewrite(struct w25_dev_s *priv, FAR const uint8_t *buffer, /* Send the "Page Program (W25_PP)" Command */ SPI_SEND(priv->spi, W25_PP); + priv->prev_instr = W25_PP; /* Send the address high byte first. */ @@ -819,6 +825,7 @@ static inline void w25_bytewrite(struct w25_dev_s *priv, FAR const uint8_t *buff /* Send "Page Program (PP)" command */ (void)SPI_SEND(priv->spi, W25_PP); + priv->prev_instr = W25_PP; /* Send the page offset high byte first. */ From 05e5841000e6df79349ee5cc7cdfa312b4daabed Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Wed, 31 May 2017 09:20:14 -0600 Subject: [PATCH 10/22] include/nuttx/spi/spi/h: Use of argument to SPI_SEND should be within parentheses. --- include/nuttx/spi/spi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nuttx/spi/spi.h b/include/nuttx/spi/spi.h index c4757bb9754..08b28e26255 100644 --- a/include/nuttx/spi/spi.h +++ b/include/nuttx/spi/spi.h @@ -320,7 +320,7 @@ * ****************************************************************************/ -#define SPI_SEND(d,wd) ((d)->ops->send(d,(uint16_t)wd)) +#define SPI_SEND(d,wd) ((d)->ops->send(d,(uint16_t)(wd))) /**************************************************************************** * Name: SPI_SNDBLOCK From 1cc842794d45a4902e1cd670b08f3b9a747b72a4 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Wed, 31 May 2017 09:28:20 -0600 Subject: [PATCH 11/22] drivers/rwbuffer.c: Fix compiler warnings --- drivers/rwbuffer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/rwbuffer.c b/drivers/rwbuffer.c index a7db82e156d..3871454e402 100644 --- a/drivers/rwbuffer.c +++ b/drivers/rwbuffer.c @@ -406,7 +406,9 @@ static int rwb_rhreload(struct rwbuffer_s *rwb, off_t startblock) int rwb_invalidate_writebuffer(FAR struct rwbuffer_s *rwb, off_t startblock, size_t blockcount) { - int ret; + int ret = OK; + + /* Is there a write buffer? Is data saved in the write buffer? */ if (rwb->wrmaxblocks > 0 && rwb->wrnblocks > 0) { @@ -909,7 +911,7 @@ ssize_t rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock, */ } else -#else +#endif /* CONFIG_DRVR_WRITEBUFFER */ { /* No write buffer.. just pass the write operation through via the * flush callback. @@ -917,7 +919,6 @@ ssize_t rwb_write(FAR struct rwbuffer_s *rwb, off_t startblock, ret = rwb->wrflush(rwb->dev, wrbuffer, startblock, nblocks); } -#endif return (ssize_t)ret; } From 705185be1e32cda88cf6a5cf63bc997928a1df18 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Wed, 31 May 2017 09:33:44 -0600 Subject: [PATCH 12/22] libc/string/lib_vikmemcpy.c: fix 'casting pointer to integer of different size' compiler warnings --- libc/string/lib_vikmemcpy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libc/string/lib_vikmemcpy.c b/libc/string/lib_vikmemcpy.c index 41ab3ecf371..598672aac1c 100644 --- a/libc/string/lib_vikmemcpy.c +++ b/libc/string/lib_vikmemcpy.c @@ -240,9 +240,9 @@ #define COPY_SHIFT(shift) \ { \ - UIntN* dstN = (UIntN*)((((UIntN)dst8) PRE_LOOP_ADJUST) & \ + UIntN* dstN = (UIntN*)((((uintptr_t)dst8) PRE_LOOP_ADJUST) & \ ~(TYPE_WIDTH - 1)); \ - UIntN* srcN = (UIntN*)((((UIntN)src8) PRE_LOOP_ADJUST) & \ + UIntN* srcN = (UIntN*)((((uintptr_t)src8) PRE_LOOP_ADJUST) & \ ~(TYPE_WIDTH - 1)); \ size_t length = count / TYPE_WIDTH; \ UIntN srcWord = INC_VAL(srcN); \ @@ -324,13 +324,13 @@ FAR void *memcpy(FAR void *dest, FAR const void *src, size_t count) START_VAL(dst8); START_VAL(src8); - while (((UIntN)dst8 & (TYPE_WIDTH - 1)) != WHILE_DEST_BREAK) + while (((uintptr_t)dst8 & (TYPE_WIDTH - 1)) != WHILE_DEST_BREAK) { INC_VAL(dst8) = INC_VAL(src8); count--; } - switch ((((UIntN)src8) PRE_SWITCH_ADJUST) & (TYPE_WIDTH - 1)) + switch ((((uintptr_t)src8) PRE_SWITCH_ADJUST) & (TYPE_WIDTH - 1)) { case 0: COPY_NO_SHIFT(); break; case 1: COPY_SHIFT(1); break; From 90dda9357ecbcc1aa53ee207a650d07a4192ac2f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 31 May 2017 10:55:37 -0600 Subject: [PATCH 13/22] pthread robust mutexes: Fix memmory trashing problem: the main task may also use mutexes; need to check thread type before accessing pthread-specific mutex data structures. Problem noted by Jussi Kivilinna. --- configs/sim/ostest/defconfig | 30 +++++++- sched/pthread/pthread_mutex.c | 133 +++++++++++++++++++++++----------- 2 files changed, 117 insertions(+), 46 deletions(-) diff --git a/configs/sim/ostest/defconfig b/configs/sim/ostest/defconfig index d13dc5b9911..374b538fc48 100644 --- a/configs/sim/ostest/defconfig +++ b/configs/sim/ostest/defconfig @@ -28,6 +28,7 @@ CONFIG_BUILD_FLAT=y # CONFIG_MOTOROLA_SREC is not set # CONFIG_RAW_BINARY is not set # CONFIG_UBOOT_UIMAGE is not set +# CONFIG_DFU_BINARY is not set # # Customize Header Files @@ -77,11 +78,11 @@ CONFIG_HOST_X86_64=y CONFIG_SIM_X8664_SYSTEMV=y # CONFIG_SIM_X8664_MICROSOFT is not set # CONFIG_SIM_WALLTIME is not set -CONFIG_SIM_NET_HOST_ROUTE=y -# CONFIG_SIM_NET_BRIDGE is not set # CONFIG_SIM_FRAMEBUFFER is not set # CONFIG_SIM_SPIFLASH is not set # CONFIG_SIM_QSPIFLASH is not set +# CONFIG_ARCH_TOOLCHAIN_IAR is not set +# CONFIG_ARCH_TOOLCHAIN_GNU is not set # # Architecture Options @@ -102,6 +103,7 @@ CONFIG_ARCH_HAVE_MULTICPU=y # CONFIG_ARCH_HAVE_EXTCLK is not set CONFIG_ARCH_HAVE_POWEROFF=y # CONFIG_ARCH_HAVE_RESET is not set +# CONFIG_ARCH_HAVE_RTC_SUBSECONDS is not set # CONFIG_ARCH_STACKDUMP is not set # CONFIG_ENDIAN_BIG is not set # CONFIG_ARCH_IDLE_CUSTOM is not set @@ -204,6 +206,8 @@ CONFIG_SCHED_WAITPID=y # CONFIG_PTHREAD_MUTEX_TYPES=y CONFIG_PTHREAD_MUTEX_ROBUST=y +# CONFIG_PTHREAD_MUTEX_UNSAFE is not set +# CONFIG_PTHREAD_MUTEX_BOTH is not set CONFIG_NPTHREAD_KEYS=4 # CONFIG_PTHREAD_CLEANUP is not set # CONFIG_CANCELLATION_POINTS is not set @@ -368,6 +372,7 @@ CONFIG_SERIAL_CONSOLE=y # CONFIG_PSEUDOTERM is not set # CONFIG_USBDEV is not set # CONFIG_USBHOST is not set +# CONFIG_USBMISC is not set # CONFIG_HAVE_USBTRACE is not set # CONFIG_DRIVERS_WIRELESS is not set # CONFIG_DRIVERS_CONTACTLESS is not set @@ -376,7 +381,9 @@ CONFIG_SERIAL_CONSOLE=y # System Logging # # CONFIG_ARCH_SYSLOG is not set +CONFIG_SYSLOG_WRITE=y # CONFIG_RAMLOG is not set +# CONFIG_SYSLOG_BUFFER is not set # CONFIG_SYSLOG_INTBUFFER is not set # CONFIG_SYSLOG_TIMESTAMP is not set CONFIG_SYSLOG_SERIAL_CONSOLE=y @@ -437,6 +444,11 @@ CONFIG_MM_REGIONS=1 # CONFIG_ARCH_HAVE_HEAP2 is not set # CONFIG_GRAN is not set +# +# Common I/O Buffer Support +# +# CONFIG_MM_IOB is not set + # # Audio Support # @@ -445,6 +457,7 @@ CONFIG_MM_REGIONS=1 # # Wireless Support # +# CONFIG_WIRELESS is not set # # Binary Loader @@ -594,7 +607,6 @@ CONFIG_LIB_SENDFILE_BUFSIZE=512 # CONFIG_EXAMPLES_MM is not set # CONFIG_EXAMPLES_MODBUS is not set # CONFIG_EXAMPLES_MOUNT is not set -# CONFIG_EXAMPLES_NRF24L01TERM is not set # CONFIG_EXAMPLES_NSH is not set # CONFIG_EXAMPLES_NULL is not set # CONFIG_EXAMPLES_NX is not set @@ -630,6 +642,7 @@ CONFIG_EXAMPLES_OSTEST_WAITRESULT=y # CONFIG_EXAMPLES_TOUCHSCREEN is not set # CONFIG_EXAMPLES_WATCHDOG is not set # CONFIG_EXAMPLES_WEBSERVER is not set +# CONFIG_EXAMPLES_XBC_TEST is not set # # File System Utilities @@ -700,3 +713,14 @@ CONFIG_EXAMPLES_OSTEST_WAITRESULT=y # CONFIG_SYSTEM_UBLOXMODEM is not set # CONFIG_SYSTEM_VI is not set # CONFIG_SYSTEM_ZMODEM is not set + +# +# Wireless Libraries and NSH Add-Ons +# + +# +# IEEE 802.15.4 applications +# +# CONFIG_IEEE802154_LIBMAC is not set +# CONFIG_IEEE802154_LIBUTILS is not set +# CONFIG_IEEE802154_I8SAK is not set diff --git a/sched/pthread/pthread_mutex.c b/sched/pthread/pthread_mutex.c index 13dde1a53d1..8b6566b8a28 100644 --- a/sched/pthread/pthread_mutex.c +++ b/sched/pthread/pthread_mutex.c @@ -58,7 +58,7 @@ * Name: pthread_mutex_add * * Description: - * Add the mutex to the list of mutexes held by this thread. + * Add the mutex to the list of mutexes held by this pthread. * * Parameters: * mutex - The mux to be locked @@ -70,17 +70,91 @@ static void pthread_mutex_add(FAR struct pthread_mutex_s *mutex) { - FAR struct pthread_tcb_s *rtcb = (FAR struct pthread_tcb_s *)this_task(); - irqstate_t flags; + FAR struct tcb_s *rtcb = this_task(); DEBUGASSERT(mutex->flink == NULL); - /* Add the mutex to the list of mutexes held by this task */ + /* Check if this is a pthread. The main thread may also lock and unlock + * mutexes. The main thread, however, does not participate in the mutex + * consistency logic. Presumably, when the main thread exits, all of the + * child pthreads will also terminate. + * + * REVISIT: NuttX does not support that behavior at present; child pthreads + * will persist after the main thread exits. + */ - flags = enter_critical_section(); - mutex->flink = rtcb->mhead; - rtcb->mhead = mutex; - leave_critical_section(flags); + if ((rtcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD) + { + FAR struct pthread_tcb_s *ptcb = (FAR struct pthread_tcb_s *)rtcb; + irqstate_t flags; + + /* Add the mutex to the list of mutexes held by this pthread */ + + flags = enter_critical_section(); + mutex->flink = ptcb->mhead; + ptcb->mhead = mutex; + leave_critical_section(flags); + } +} + +/**************************************************************************** + * Name: pthread_mutex_remove + * + * Description: + * Remove the mutex to the list of mutexes held by this pthread. + * + * Parameters: + * mutex - The mux to be locked + * + * Return Value: + * None + * + ****************************************************************************/ + +static void pthread_mutex_remove(FAR struct pthread_mutex_s *mutex) +{ + FAR struct tcb_s *rtcb = this_task(); + + DEBUGASSERT(mutex->flink == NULL); + + /* Check if this is a pthread. The main thread may also lock and unlock + * mutexes. The main thread, however, does not participate in the mutex + * consistency logic. + */ + + if ((rtcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD) + { + FAR struct pthread_tcb_s *ptcb = (FAR struct pthread_tcb_s *)rtcb; + FAR struct pthread_mutex_s *curr; + FAR struct pthread_mutex_s *prev; + irqstate_t flags; + + flags = enter_critical_section(); + + /* Remove the mutex from the list of mutexes held by this task */ + + for (prev = NULL, curr = ptcb->mhead; + curr != NULL && curr != mutex; + prev = curr, curr = curr->flink); + + DEBUGASSERT(curr == mutex); + + /* Remove the mutex from the list. prev == NULL means that the mutex + * to be removed is at the head of the list. + */ + + if (prev == NULL) + { + ptcb->mhead = mutex->flink; + } + else + { + prev->flink = mutex->flink; + } + + mutex->flink = NULL; + leave_critical_section(flags); + } } /**************************************************************************** @@ -233,8 +307,6 @@ int pthread_mutex_trytake(FAR struct pthread_mutex_s *mutex) int pthread_mutex_give(FAR struct pthread_mutex_s *mutex) { - FAR struct pthread_mutex_s *curr; - FAR struct pthread_mutex_s *prev; int ret = EINVAL; /* Verify input parameters */ @@ -242,34 +314,9 @@ int pthread_mutex_give(FAR struct pthread_mutex_s *mutex) DEBUGASSERT(mutex != NULL); if (mutex != NULL) { - FAR struct pthread_tcb_s *rtcb = (FAR struct pthread_tcb_s *)this_task(); - irqstate_t flags; - - flags = enter_critical_section(); - /* Remove the mutex from the list of mutexes held by this task */ - for (prev = NULL, curr = rtcb->mhead; - curr != NULL && curr != mutex; - prev = curr, curr = curr->flink); - - DEBUGASSERT(curr == mutex); - - /* Remove the mutex from the list. prev == NULL means that the mutex - * to be removed is at the head of the list. - */ - - if (prev == NULL) - { - rtcb->mhead = mutex->flink; - } - else - { - prev->flink = mutex->flink; - } - - mutex->flink = NULL; - leave_critical_section(flags); + pthread_mutex_remove(mutex); /* Now release the underlying semaphore */ @@ -300,7 +347,7 @@ int pthread_mutex_give(FAR struct pthread_mutex_s *mutex) #ifdef CONFIG_CANCELLATION_POINTS uint16_t pthread_disable_cancel(void) { - FAR struct pthread_tcb_s *tcb = (FAR struct pthread_tcb_s *)this_task(); + FAR struct tcb_s *tcb = this_task(); irqstate_t flags; uint16_t old; @@ -309,15 +356,15 @@ uint16_t pthread_disable_cancel(void) */ flags = enter_critical_section(); - old = tcb->cmn.flags & (TCB_FLAG_CANCEL_PENDING | TCB_FLAG_NONCANCELABLE); - tcb->cmn.flags &= ~(TCB_FLAG_CANCEL_PENDING | TCB_FLAG_NONCANCELABLE); + old = tcb->flags & (TCB_FLAG_CANCEL_PENDING | TCB_FLAG_NONCANCELABLE); + tcb->flags &= ~(TCB_FLAG_CANCEL_PENDING | TCB_FLAG_NONCANCELABLE); leave_critical_section(flags); return old; } void pthread_enable_cancel(uint16_t cancelflags) { - FAR struct pthread_tcb_s *tcb = (FAR struct pthread_tcb_s *)this_task(); + FAR struct tcb_s *tcb = this_task(); irqstate_t flags; /* We need perform the following operations from within a critical section @@ -325,7 +372,7 @@ void pthread_enable_cancel(uint16_t cancelflags) */ flags = enter_critical_section(); - tcb->cmn.flags |= cancelflags; + tcb->flags |= cancelflags; /* What should we do if there is a pending cancellation? * @@ -337,8 +384,8 @@ void pthread_enable_cancel(uint16_t cancelflags) * then we need to terminate now by simply calling pthread_exit(). */ - if ((tcb->cmn.flags & TCB_FLAG_CANCEL_DEFERRED) == 0 && - (tcb->cmn.flags & TCB_FLAG_CANCEL_PENDING) != 0) + if ((tcb->flags & TCB_FLAG_CANCEL_DEFERRED) == 0 && + (tcb->flags & TCB_FLAG_CANCEL_PENDING) != 0) { pthread_exit(NULL); } From e4b145b9a9b9c2803267f4af3102ed7c11081f37 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 31 May 2017 11:17:11 -0600 Subject: [PATCH 14/22] Upate TODO list --- TODO | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/TODO b/TODO index 2cf4fdcaaae..64c98a8c860 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ -NuttX TODO List (Last updated May 18, 2017) +NuttX TODO List (Last updated May 31, 2017) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with @@ -45,6 +45,13 @@ o Task/Scheduler (sched/) terminated? Status: Closed. No, this behavior will not be implemented. Priority: Medium, required for good emulation of process/pthread model. + The current behavior allows for the main thread of a task to + exit() and any child pthreads will perist. That does raise + some issues: The main thread is treated much like just-another- + pthread but must follow the semantics of a task or a process. + That results in some inconsistencies (for example, with robust + mutexes, what should happen if the main thread exits while + holding a mutex?) Title: pause() NON-COMPLIANCE Description: In the POSIX description of this function the pause() function From bb02c0c92d08624e4b9660c3984199eed51ebf48 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 31 May 2017 15:17:28 -0600 Subject: [PATCH 15/22] Makefiles.*: It should be possible to run 'make menuconfig' with no .config and no Make.defs file. This change removes the dependency on Make.defs, but does not solve the problem of the missing .config file. Without a .config file, it is not currently possible for the Makefile.* to correctly setup up the symbolic links to directories. --- Makefile.unix | 4 +++- Makefile.win | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile.unix b/Makefile.unix index b7bf86b8056..806b9af1fb8 100644 --- a/Makefile.unix +++ b/Makefile.unix @@ -280,7 +280,9 @@ tools/cnvwindeps$(HOSTEXEEXT): # Directories links. Most of establishing the NuttX configuration involves # setting up symbolic links with 'generic' directory names to specific, # configured directories. -# + +Make.defs: + # Link the arch//include directory to include/arch include/arch: Make.defs diff --git a/Makefile.win b/Makefile.win index e1d9bc1278c..9829c913417 100644 --- a/Makefile.win +++ b/Makefile.win @@ -275,7 +275,9 @@ tools\mkdeps$(HOSTEXEEXT): # Directories links. Most of establishing the NuttX configuration involves # setting up symbolic links with 'generic' directory names to specific, # configured directories. -# + +Make.defs: + # Link the arch\\include directory to include\arch include\arch: Make.defs From f5e6afe9cdab2feba74036be4896857e8f09239e Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 31 May 2017 15:39:18 -0600 Subject: [PATCH 16/22] Makefile.*: Create a Make.defs file if one does not exist --- Makefile.unix | 2 ++ Makefile.win | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Makefile.unix b/Makefile.unix index 806b9af1fb8..811b0551e36 100644 --- a/Makefile.unix +++ b/Makefile.unix @@ -282,6 +282,8 @@ tools/cnvwindeps$(HOSTEXEEXT): # configured directories. Make.defs: + echo "include $(TOPDIR)$(DELIM).config" > Make.defs + echo "include $(TOPDIR)$(DELIM)tools$(DELIM)Config.mk" >> Make.defs # Link the arch//include directory to include/arch diff --git a/Makefile.win b/Makefile.win index 9829c913417..32d42772c62 100644 --- a/Makefile.win +++ b/Makefile.win @@ -277,6 +277,8 @@ tools\mkdeps$(HOSTEXEEXT): # configured directories. Make.defs: + echo "include $(TOPDIR)$(DELIM).config" > Make.defs + echo "include $(TOPDIR)$(DELIM)tools$(DELIM)Config.mk" >> Make.defs # Link the arch\\include directory to include\arch From ad6515563b1da0b5103a1bd1487921045f37321f Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Thu, 1 Jun 2017 06:15:28 -0600 Subject: [PATCH 17/22] STM32L4 RTC: store RTC MAGIC to backup reg, not to address zero --- arch/arm/src/stm32l4/stm32l4_rcc.c | 2 +- arch/arm/src/stm32l4/stm32l4_rtc.h | 10 +++++----- arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c | 2 +- arch/arm/src/stm32l4/stm32l4_rtcc.c | 19 +++++++++++-------- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/arch/arm/src/stm32l4/stm32l4_rcc.c b/arch/arm/src/stm32l4/stm32l4_rcc.c index ffe1c4d2dc7..c2f3cfa198d 100644 --- a/arch/arm/src/stm32l4/stm32l4_rcc.c +++ b/arch/arm/src/stm32l4/stm32l4_rcc.c @@ -114,7 +114,7 @@ static inline void rcc_resetbkp(void) /* Check if the RTC is already configured */ - init_stat = rtc_is_inits(); + init_stat = stm32l4_rtc_is_initialized(); if(!init_stat) { /* Enable write access to the backup domain (RTC registers, RTC diff --git a/arch/arm/src/stm32l4/stm32l4_rtc.h b/arch/arm/src/stm32l4/stm32l4_rtc.h index 18e7f6031be..3e0a5a21307 100644 --- a/arch/arm/src/stm32l4/stm32l4_rtc.h +++ b/arch/arm/src/stm32l4/stm32l4_rtc.h @@ -76,7 +76,7 @@ enum alm_id_e RTC_ALARM_LAST }; -/* Structure used to pass parmaters to set an alarm */ +/* Structure used to pass parameters to set an alarm */ struct alm_setalarm_s { @@ -106,7 +106,7 @@ extern "C" ****************************************************************************/ /************************************************************************************ - * Name: rtc_is_inits + * Name: stm32l4_rtc_is_initialized * * Description: * Returns 'true' if the RTC has been initialized (according to the RTC itself). @@ -120,10 +120,10 @@ extern "C" * bool -- true if the INITS flag is set in the ISR. * ************************************************************************************/ -#ifdef CONFIG_RTC_DRIVER -bool rtc_is_inits(void); -#endif +#ifdef CONFIG_RTC_DRIVER +bool stm32l4_rtc_is_initialized(void); +#endif /**************************************************************************** * Name: stm32l4_rtc_getdatetime_with_subseconds diff --git a/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c b/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c index 5ab212dd86f..f3415af305d 100644 --- a/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c +++ b/arch/arm/src/stm32l4/stm32l4_rtc_lowerhalf.c @@ -176,7 +176,7 @@ static void stm32l4_alarm_callback(FAR void *arg, unsigned int alarmid) rtc_alarm_callback_t cb; FAR void *priv; - DEBUGASSERT(priv != NULL); + DEBUGASSERT(arg != NULL); DEBUGASSERT(alarmid == RTC_ALARMA || alarmid == RTC_ALARMB); lower = (struct stm32l4_lowerhalf_s *)arg; diff --git a/arch/arm/src/stm32l4/stm32l4_rtcc.c b/arch/arm/src/stm32l4/stm32l4_rtcc.c index f36d4d040c4..d053ee99293 100644 --- a/arch/arm/src/stm32l4/stm32l4_rtcc.c +++ b/arch/arm/src/stm32l4/stm32l4_rtcc.c @@ -95,6 +95,10 @@ # define CONFIG_RTC_MAGIC_REG (0) #endif +#define RTC_MAGIC CONFIG_RTC_MAGIC +#define RTC_MAGIC_TIME_SET CONFIG_RTC_MAGIC_TIME_SET +#define RTC_MAGIC_REG STM32L4_RTC_BKR(CONFIG_RTC_MAGIC_REG) + /* Constants ************************************************************************/ #define SYNCHRO_TIMEOUT (0x00020000) @@ -816,7 +820,7 @@ static inline void rtc_enable_alarm(void) ************************************************************************************/ /************************************************************************************ - * Name: rtc_is_inits + * Name: stm32l4_rtc_is_initialized * * Description: * Returns 'true' if the RTC has been initialized (according to the RTC itself). @@ -831,7 +835,7 @@ static inline void rtc_enable_alarm(void) * ************************************************************************************/ -bool rtc_is_inits(void) +bool stm32l4_rtc_is_initialized(void) { uint32_t regval; @@ -867,8 +871,7 @@ int up_rtc_initialize(void) * backed, we don't need or want to re-initialize on each reset. */ - init_stat = rtc_is_inits(); - + init_stat = stm32l4_rtc_is_initialized(); if (!init_stat) { /* Enable write access to the backup domain (RTC registers, RTC @@ -1164,7 +1167,7 @@ int stm32l4_rtc_setdatetime(FAR const struct tm *tp) /* Then write the broken out values to the RTC */ - /* Convert the struct tm format to RTC time register fields. All of the STM32 + /* Convert the struct tm format to RTC time register fields. * All of the ranges of values correspond between struct tm and the time * register. */ @@ -1216,10 +1219,10 @@ int stm32l4_rtc_setdatetime(FAR const struct tm *tp) /* Remember that the RTC is initialized and had its time set. */ - if (getreg32(CONFIG_RTC_MAGIC_REG) != CONFIG_RTC_MAGIC_TIME_SET) + if (getreg32(RTC_MAGIC_REG) != RTC_MAGIC_TIME_SET) { stm32l4_pwr_enablebkp(true); - putreg32(CONFIG_RTC_MAGIC_TIME_SET, CONFIG_RTC_MAGIC_REG); + putreg32(RTC_MAGIC_TIME_SET, RTC_MAGIC_REG); stm32l4_pwr_enablebkp(false); } @@ -1243,7 +1246,7 @@ int stm32l4_rtc_setdatetime(FAR const struct tm *tp) bool stm32l4_rtc_havesettime(void) { - return getreg32(CONFIG_RTC_MAGIC_REG) == CONFIG_RTC_MAGIC_TIME_SET; + return getreg32(RTC_MAGIC_REG) == RTC_MAGIC_TIME_SET; } /************************************************************************************ From 32610b53f450aa2b426b0eaf4eccd97969463298 Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Thu, 1 Jun 2017 06:19:54 -0600 Subject: [PATCH 18/22] drivers/{sensors,usbmisc}: Fix uninitialized I2C frequency --- drivers/sensors/Kconfig | 15 +++++++++++++++ drivers/sensors/hts221.c | 40 +++++++++++++++++++++++---------------- drivers/sensors/lis2dh.c | 22 +++++++++++++-------- drivers/sensors/lps25h.c | 40 +++++++++++++++++++++++---------------- drivers/usbmisc/Kconfig | 5 +++++ drivers/usbmisc/fusb301.c | 31 ++++++++++++++++++------------ 6 files changed, 101 insertions(+), 52 deletions(-) diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index 03911022b57..43c82293f1e 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -41,6 +41,11 @@ config HTS221 if HTS221 +config HTS221_I2C_FREQUENCY + int "HTS221 I2C frequency" + default 400000 + range 1 400000 + config DEBUG_HTS221 bool "Debug support for the HTS221" default n @@ -84,6 +89,11 @@ config LIS2DH if LIS2DH +config LIS2DH_I2C_FREQUENCY + int "LIS2DH I2C frequency" + default 400000 + range 1 400000 + config DEBUG_LIS2DH bool "Debug support for the LIS2DH" default n @@ -144,6 +154,11 @@ config LPS25H if LPS25H +config LPS25H_I2C_FREQUENCY + int "LPS25H I2C frequency" + default 400000 + range 1 400000 + config DEBUG_LPS25H bool "Debug support for the LPS25H" default n diff --git a/drivers/sensors/hts221.c b/drivers/sensors/hts221.c index 9f3138bddf6..9b85cf7e93f 100644 --- a/drivers/sensors/hts221.c +++ b/drivers/sensors/hts221.c @@ -61,6 +61,10 @@ # define hts221_dbg(x, ...) sninfo(x, ##__VA_ARGS__) #endif +#ifndef CONFIG_HTS221_I2C_FREQUENCY +# define CONFIG_HTS221_I2C_FREQUENCY 400000 +#endif + #define HTS221_WHO_AM_I 0x0f #define HTS221_AV_CONF 0x10 #define HTS221_CTRL_REG1 0x20 @@ -221,16 +225,18 @@ static int32_t hts221_write_reg8(FAR struct hts221_dev_s *priv, struct i2c_msg_s msgv[2] = { { - .addr = priv->addr, - .flags = 0, - .buffer = (FAR void *)&command[0], - .length = 1 + .frequency = CONFIG_HTS221_I2C_FREQUENCY, + .addr = priv->addr, + .flags = 0, + .buffer = (FAR void *)&command[0], + .length = 1 }, { - .addr = priv->addr, - .flags = I2C_M_NORESTART, - .buffer = (FAR void *)&command[1], - .length = 1 + .frequency = CONFIG_HTS221_I2C_FREQUENCY, + .addr = priv->addr, + .flags = I2C_M_NORESTART, + .buffer = (FAR void *)&command[1], + .length = 1 } }; @@ -243,16 +249,18 @@ static int hts221_read_reg(FAR struct hts221_dev_s *priv, struct i2c_msg_s msgv[2] = { { - .addr = priv->addr, - .flags = 0, - .buffer = (FAR void *)command, - .length = 1 + .frequency = CONFIG_HTS221_I2C_FREQUENCY, + .addr = priv->addr, + .flags = 0, + .buffer = (FAR void *)command, + .length = 1 }, { - .addr = priv->addr, - .flags = I2C_M_READ, - .buffer = value, - .length = 1 + .frequency = CONFIG_HTS221_I2C_FREQUENCY, + .addr = priv->addr, + .flags = I2C_M_READ, + .buffer = value, + .length = 1 } }; diff --git a/drivers/sensors/lis2dh.c b/drivers/sensors/lis2dh.c index f7a982f1518..67e0bf1185f 100644 --- a/drivers/sensors/lis2dh.c +++ b/drivers/sensors/lis2dh.c @@ -65,6 +65,10 @@ # define lis2dh_dbg(x, ...) sninfo(x, ##__VA_ARGS__) #endif +#ifndef CONFIG_LIS2DH_I2C_FREQUENCY +# define CONFIG_LIS2DH_I2C_FREQUENCY 400000 +#endif + #ifdef CONFIG_LIS2DH_DRIVER_SELFTEST # define LSB_AT_10BIT_RESOLUTION 4 # define LSB_AT_12BIT_RESOLUTION 1 @@ -1594,16 +1598,18 @@ static int lis2dh_access(FAR struct lis2dh_dev_s *dev, uint8_t subaddr, struct i2c_msg_s msgv[2] = { { - .addr = dev->addr, - .flags = 0, - .buffer = &subaddr, - .length = 1 + .frequency = CONFIG_LIS2DH_I2C_FREQUENCY, + .addr = dev->addr, + .flags = 0, + .buffer = &subaddr, + .length = 1 }, { - .addr = dev->addr, - .flags = flags, - .buffer = buf, - .length = length + .frequency = CONFIG_LIS2DH_I2C_FREQUENCY, + .addr = dev->addr, + .flags = flags, + .buffer = buf, + .length = length } }; diff --git a/drivers/sensors/lps25h.c b/drivers/sensors/lps25h.c index bd35f38043a..1eb762af0a7 100644 --- a/drivers/sensors/lps25h.c +++ b/drivers/sensors/lps25h.c @@ -58,6 +58,10 @@ # define lps25h_dbg(x, ...) sninfo(x, ##__VA_ARGS__) #endif +#ifndef CONFIG_LPS25H_I2C_FREQUENCY +# define CONFIG_LPS25H_I2C_FREQUENCY 400000 +#endif + #define LPS25H_PRESSURE_INTERNAL_DIVIDER 4096 /* 'AN4450 - Hardware and software guidelines for use of LPS25H pressure @@ -277,16 +281,18 @@ static int lps25h_write_reg8(struct lps25h_dev_s *dev, uint8_t reg_addr, struct i2c_msg_s msgv[2] = { { - .addr = dev->addr, - .flags = 0, - .buffer = ®_addr, - .length = 1 + .frequency = CONFIG_LPS25H_I2C_FREQUENCY, + .addr = dev->addr, + .flags = 0, + .buffer = ®_addr, + .length = 1 }, { - .addr = dev->addr, - .flags = I2C_M_NORESTART, - .buffer = (void *)&value, - .length = 1 + .frequency = CONFIG_LPS25H_I2C_FREQUENCY, + .addr = dev->addr, + .flags = I2C_M_NORESTART, + .buffer = (void *)&value, + .length = 1 } }; @@ -300,16 +306,18 @@ static int lps25h_read_reg8(FAR struct lps25h_dev_s *dev, struct i2c_msg_s msgv[2] = { { - .addr = dev->addr, - .flags = 0, - .buffer = reg_addr, - .length = 1 + .frequency = CONFIG_LPS25H_I2C_FREQUENCY, + .addr = dev->addr, + .flags = 0, + .buffer = reg_addr, + .length = 1 }, { - .addr = dev->addr, - .flags = I2C_M_READ, - .buffer = value, - .length = 1 + .frequency = CONFIG_LPS25H_I2C_FREQUENCY, + .addr = dev->addr, + .flags = I2C_M_READ, + .buffer = value, + .length = 1 } }; diff --git a/drivers/usbmisc/Kconfig b/drivers/usbmisc/Kconfig index 68bd619ee3a..66690612833 100644 --- a/drivers/usbmisc/Kconfig +++ b/drivers/usbmisc/Kconfig @@ -14,6 +14,11 @@ config FUSB301 if FUSB301 +config FUSB301_I2C_FREQUENCY + int "FUSB301 I2C frequency" + default 400000 + range 1 400000 + config DEBUG_FUSB301 bool "Enable debug support for the FUSB301" default n diff --git a/drivers/usbmisc/fusb301.c b/drivers/usbmisc/fusb301.c index f24ae785582..d57d8a95ecc 100644 --- a/drivers/usbmisc/fusb301.c +++ b/drivers/usbmisc/fusb301.c @@ -63,6 +63,10 @@ # define fusb301_info(x, ...) uinfo(x, ##__VA_ARGS__) #endif +#ifndef CONFIG_FUSB301_I2C_FREQUENCY +# define CONFIG_FUSB301_I2C_FREQUENCY 400000 +#endif + /* Other macros */ #define FUSB301_I2C_RETRIES 10 @@ -146,15 +150,17 @@ static int fusb301_getreg(FAR struct fusb301_dev_s *priv, uint8_t reg) DEBUGASSERT(priv); - msg[0].addr = priv->addr; - msg[0].flags = 0; - msg[0].buffer = ® - msg[0].length = 1; + msg[0].frequency = CONFIG_FUSB301_I2C_FREQUENCY; + msg[0].addr = priv->addr; + msg[0].flags = 0; + msg[0].buffer = ® + msg[0].length = 1; - msg[1].addr = priv->addr; - msg[1].flags = I2C_M_READ; - msg[1].buffer = ®val; - msg[1].length = 1; + msg[1].frequency = CONFIG_FUSB301_I2C_FREQUENCY; + msg[1].addr = priv->addr; + msg[1].flags = I2C_M_READ; + msg[1].buffer = ®val; + msg[1].length = 1; /* Perform the transfer */ @@ -220,10 +226,11 @@ static int fusb301_putreg(FAR struct fusb301_dev_s *priv, uint8_t regaddr, /* Setup 8-bit FUSB301 address write message */ - msg.addr = priv->addr; - msg.flags = 0; - msg.buffer = txbuffer; - msg.length = 2; + msg.frequency = CONFIG_FUSB301_I2C_FREQUENCY; + msg.addr = priv->addr; + msg.flags = 0; + msg.buffer = txbuffer; + msg.length = 2; /* Perform the transfer */ From 06edfae1339272081c7c061f7d7df8c2add0b8d2 Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Thu, 1 Jun 2017 06:22:27 -0600 Subject: [PATCH 19/22] mtd/config: Add some error checks for I/O errors --- drivers/mtd/mtd_config.c | 34 +++++++++++++++++++++++++++++++--- drivers/mtd/mtd_partition.c | 2 +- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/mtd_config.c b/drivers/mtd/mtd_config.c index 69ac00237d0..2566efedc85 100644 --- a/drivers/mtd/mtd_config.c +++ b/drivers/mtd/mtd_config.c @@ -352,7 +352,14 @@ static int mtdconfig_findfirstentry(FAR struct mtdconfig_struct_s *dev, off_t bytes_left_in_block; uint16_t endblock; - mtdconfig_readbytes(dev, 0, sig, sizeof(sig)); /* Read the signature bytes */ + /* Read the signature bytes */ + + ret = mtdconfig_readbytes(dev, 0, sig, sizeof(sig)); + if (ret != OK) + { + return 0; + } + if (sig[0] != 'C' || sig[1] != 'D' || sig[2] != CONFIGDATA_FORMAT_VERSION) { /* Config Data partition not formatted. */ @@ -788,7 +795,14 @@ static off_t mtdconfig_consolidate(FAR struct mtdconfig_struct_s *dev) /* Scan all headers and move them to the src_offset */ retry_relocate: - MTD_READ(dev->mtd, src_offset, sizeof(hdr), (uint8_t *) &hdr); + bytes = MTD_READ(dev->mtd, src_offset, sizeof(hdr), (uint8_t *) &hdr); + if (bytes != sizeof(hdr)) + { + /* I/O Error! */ + + goto errout; + } + if (hdr.flags == MTD_ERASED_FLAGS) { /* Test if the source entry is active or if we are at the end @@ -967,6 +981,11 @@ static ssize_t mtdconfig_read(FAR struct file *filep, FAR char *buffer, /* Read data from the file */ bytes = MTD_READ(dev->mtd, dev->readoff, len, (uint8_t *) buffer); + if (bytes != len) + { + return -EIO; + } + dev->readoff += bytes; return bytes; } @@ -981,6 +1000,7 @@ static int mtdconfig_findentry(FAR struct mtdconfig_struct_s *dev, FAR struct mtdconfig_header_s *phdr) { uint16_t endblock; + int ret; #ifdef CONFIG_MTD_CONFIG_RAM_CONSOLIDATE endblock = dev->neraseblocks; @@ -1013,7 +1033,15 @@ static int mtdconfig_findentry(FAR struct mtdconfig_struct_s *dev, /* Read the 1st header from the next block */ - mtdconfig_readbytes(dev, offset, (uint8_t *) phdr, sizeof(*phdr)); + ret = mtdconfig_readbytes(dev, offset, (uint8_t *) phdr, sizeof(*phdr)); + if (ret != OK) + { + /* Error reading the data */ + + offset = 0; + break; + } + if (phdr->flags == MTD_ERASED_FLAGS) { continue; diff --git a/drivers/mtd/mtd_partition.c b/drivers/mtd/mtd_partition.c index 655fe368261..f8438cdd976 100644 --- a/drivers/mtd/mtd_partition.c +++ b/drivers/mtd/mtd_partition.c @@ -157,7 +157,7 @@ static int part_procfs_stat(FAR const char *relpath, ****************************************************************************/ #if defined(CONFIG_FS_PROCFS) && !defined(CONFIG_PROCFS_EXCLUDE_PARTITIONS) -struct mtd_partition_s *g_pfirstpartition = NULL; +static struct mtd_partition_s *g_pfirstpartition = NULL; const struct procfs_operations part_procfsoperations = { From 0fe9c2f3f9b30ec967f27630b5aeaab327976318 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 1 Jun 2017 06:28:23 -0600 Subject: [PATCH 20/22] pthread mutex: Remove bogus DEBUGASSERT. Problem noted by Jussi Kivilinna --- sched/pthread/pthread_mutex.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sched/pthread/pthread_mutex.c b/sched/pthread/pthread_mutex.c index 8b6566b8a28..5a75481a51f 100644 --- a/sched/pthread/pthread_mutex.c +++ b/sched/pthread/pthread_mutex.c @@ -115,8 +115,6 @@ static void pthread_mutex_remove(FAR struct pthread_mutex_s *mutex) { FAR struct tcb_s *rtcb = this_task(); - DEBUGASSERT(mutex->flink == NULL); - /* Check if this is a pthread. The main thread may also lock and unlock * mutexes. The main thread, however, does not participate in the mutex * consistency logic. From 4d46979a6fa86a595db2158737a797987839d356 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 1 Jun 2017 06:38:47 -0600 Subject: [PATCH 21/22] Tiva SSI: Resolves issue 52 'Copy-Paste error in tiva_ssibus_initialize()' submitted by Aleksandr Kazantsev. --- arch/arm/src/tiva/tiva_ssi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/src/tiva/tiva_ssi.c b/arch/arm/src/tiva/tiva_ssi.c index 709850e01a8..9930c6184f5 100644 --- a/arch/arm/src/tiva/tiva_ssi.c +++ b/arch/arm/src/tiva/tiva_ssi.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/tiva/tiva_ssi.c * - * Copyright (C) 2009-2010, 2014, 2016 Gregory Nutt. All rights reserved. + * Copyright (C) 2009-2010, 2014, 2016-2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -1616,8 +1616,8 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port) * to the SSI3 peripheral, bringing it a fully functional state. */ - tiva_ssi1_enablepwr(); - tiva_ssi1_enableclk(); + tiva_ssi3_enablepwr(); + tiva_ssi3_enableclk(); /* Configure SSI3 GPIOs */ @@ -1626,7 +1626,7 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port) tiva_configgpio(GPIO_SSI3_RX); /* PE2: SSI3 receive (SSI3Rx) */ tiva_configgpio(GPIO_SSI3_TX); /* PE3: SSI3 transmit (SSI3Tx) */ break; -#endif /* CONFIG_TIVA_SSI1 */ +#endif /* CONFIG_TIVA_SSI3 */ default: leave_critical_section(flags); From ff2b54a5e0b969748f132ef83bff710446e86ce9 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 1 Jun 2017 06:44:24 -0600 Subject: [PATCH 22/22] nucleo-f4x1re User LEDS: Issue #51 reports compilation problems with stm32_userled.c. Reported by Gappi92. --- configs/nucleo-f4x1re/src/stm32_userleds.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/configs/nucleo-f4x1re/src/stm32_userleds.c b/configs/nucleo-f4x1re/src/stm32_userleds.c index dd775007118..dcfaa895100 100644 --- a/configs/nucleo-f4x1re/src/stm32_userleds.c +++ b/configs/nucleo-f4x1re/src/stm32_userleds.c @@ -183,7 +183,7 @@ void board_userled(int led, bool ledon) { if (led == 1) { - stm32_gpiowrite(GPIO_LD2, ldeon); + stm32_gpiowrite(GPIO_LD2, ledon); } } @@ -193,10 +193,7 @@ void board_userled(int led, bool ledon) void board_userled_all(uint8_t ledset) { - if (led == 1) - { - stm32_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0); - } + stm32_gpiowrite(GPIO_LD2, (ledset & BOARD_LD2_BIT) != 0); } /****************************************************************************