From 89c81f6c08ddd37cd2126e33ce35c4d66dab373e Mon Sep 17 00:00:00 2001 From: Sebastien Lorquet Date: Mon, 3 Aug 2015 09:14:15 -0600 Subject: [PATCH 01/35] FIX typo in DEBUASSERTion --- arch | 2 +- sched/semaphore/sem_tickwait.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch b/arch index d99e8ced384..52f459de149 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit d99e8ced38440ef61bebfd1507269b9072aba355 +Subproject commit 52f459de149c45a4cd7a7758b350167a400375f3 diff --git a/sched/semaphore/sem_tickwait.c b/sched/semaphore/sem_tickwait.c index 74de8f054de..57e36d1f0cb 100644 --- a/sched/semaphore/sem_tickwait.c +++ b/sched/semaphore/sem_tickwait.c @@ -87,7 +87,7 @@ int sem_tickwait(FAR sem_t *sem, uint32_t start, uint32_t delay) uint32_t elapsed; int ret; - DEBUGASSERT(sem |= NULL && up_interrupt_context() == false && + DEBUGASSERT(sem != NULL && up_interrupt_context() == false && rtcb->waitdog == NULL); /* Create a watchdog. We will not actually need this watchdog From 991adde6ae74b6164edbfd9edeac353c8cc06c6a Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 3 Aug 2015 10:46:36 -0600 Subject: [PATCH 02/35] Add definition of SCHED_MAX_REPL --- include/sched.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/include/sched.h b/include/sched.h index cb89b056640..60b32522cac 100644 --- a/include/sched.h +++ b/include/sched.h @@ -53,10 +53,14 @@ /* POSIX-like scheduling policies */ -#define SCHED_FIFO 1 /* FIFO per priority scheduling policy */ -#define SCHED_RR 2 /* Round robin scheduling policy */ -#define SCHED_SPORADIC 3 /* Sporadic scheduling policy */ -#define SCHED_OTHER 4 /* Not supported */ +#define SCHED_FIFO 1 /* FIFO per priority scheduling policy */ +#define SCHED_RR 2 /* Round robin scheduling policy */ +#define SCHED_SPORADIC 3 /* Sporadic scheduling policy */ +#define SCHED_OTHER 4 /* Not supported */ + +/* Maximum number of SCHED_SPORADIC replenishments */ + +#define SS_REPL_MAX CONFIG_SCHED_SPORADIC_MAXREPL /* Pthread definitions **********************************************************/ From 9cbac41e78a99cbcedafa4b6acd2c950aef00ebf Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Mon, 3 Aug 2015 11:01:41 -0600 Subject: [PATCH 03/35] Clean-up/standardize a few header files --- include/errno.h | 4 ++-- include/mqueue.h | 2 +- include/pthread.h | 7 +++---- include/queue.h | 4 ++-- include/sched.h | 2 +- include/signal.h | 7 +++---- include/stdlib.h | 19 +++++++------------ include/string.h | 2 +- include/unistd.h | 8 ++++---- 9 files changed, 24 insertions(+), 31 deletions(-) diff --git a/include/errno.h b/include/errno.h index 08f76e4d321..f215269c731 100644 --- a/include/errno.h +++ b/include/errno.h @@ -379,11 +379,11 @@ #define ECANCELED_STR "Operation cancelled" /************************************************************************ - * Type Declarations + * Public Type Definitions ************************************************************************/ /************************************************************************ - * Global Function Prototypes + * Public Function Prototypes ************************************************************************/ #undef EXTERN diff --git a/include/mqueue.h b/include/mqueue.h index 6719cbd42f8..b1f2abaea38 100644 --- a/include/mqueue.h +++ b/include/mqueue.h @@ -51,7 +51,7 @@ #define MQ_NONBLOCK O_NONBLOCK /******************************************************************************** - * Global Type Declarations + * Public Type Declarations ********************************************************************************/ /* Message queue attributes */ diff --git a/include/pthread.h b/include/pthread.h index d65f6d50804..4de07d62a22 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -148,7 +148,7 @@ prctl((int)PR_GET_NAME, (char*)name, (int)thread) /******************************************************************************** - * Global Type Declarations + * Public Type Definitions ********************************************************************************/ #ifdef __cplusplus @@ -241,11 +241,11 @@ typedef bool pthread_once_t; struct sched_param; /* Defined in sched.h */ /******************************************************************************** - * Global Variables + * Public Data ********************************************************************************/ /******************************************************************************** - * Global Function Prototypes + * Public Function Prototypes ********************************************************************************/ /* Initializes a thread attributes object (attr) with default values for all of @@ -414,4 +414,3 @@ int pthread_sigmask(int how, FAR const sigset_t *set, FAR sigset_t *oset); #endif #endif /* __INCLUDE_PTHREAD_H */ - diff --git a/include/queue.h b/include/queue.h index 7d10e86e1d2..56c87469a77 100644 --- a/include/queue.h +++ b/include/queue.h @@ -60,7 +60,7 @@ #define dq_peek(q) ((q)->head) /**************************************************************************** - * Global Type Declarations + * Public Type Definitions ****************************************************************************/ struct sq_entry_s @@ -91,7 +91,7 @@ struct dq_queue_s typedef struct dq_queue_s dq_queue_t; /**************************************************************************** - * Global Function Prototypes + * Public Function Prototypes ****************************************************************************/ #ifdef __cplusplus diff --git a/include/sched.h b/include/sched.h index 60b32522cac..4fe16542d60 100644 --- a/include/sched.h +++ b/include/sched.h @@ -53,7 +53,7 @@ /* POSIX-like scheduling policies */ -#define SCHED_FIFO 1 /* FIFO per priority scheduling policy */ +#define SCHED_FIFO 1 /* FIFO priority scheduling policy */ #define SCHED_RR 2 /* Round robin scheduling policy */ #define SCHED_SPORADIC 3 /* Sporadic scheduling policy */ #define SCHED_OTHER 4 /* Not supported */ diff --git a/include/signal.h b/include/signal.h index 492ce416c08..30f97ef687d 100644 --- a/include/signal.h +++ b/include/signal.h @@ -183,7 +183,7 @@ #endif /******************************************************************************** - * Global Type Declarations + * Public Type Definitions ********************************************************************************/ /* This defines a set of 32 signals (numbered 0 through 31). */ @@ -251,11 +251,11 @@ struct sigaction #define sa_sigaction sa_u._sa_sigaction /******************************************************************************** - * Global Variables + * Public Data ********************************************************************************/ /******************************************************************************** - * Global Function Prototypes + * Public Function Prototypes ********************************************************************************/ #ifdef __cplusplus @@ -297,4 +297,3 @@ int sigqueue(int pid, int signo, FAR void *sival_ptr); #endif #endif /* __INCLUDE_SIGNAL_H */ - diff --git a/include/stdlib.h b/include/stdlib.h index 14b06f88aee..70e9f707e75 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -49,9 +49,9 @@ * Pre-processor Definitions ****************************************************************************/ -/* The C standard specifies two constants, EXIT_SUCCESS and - * EXIT_FAILURE, that may be passed to exit() to indicate - * successful or unsucessful termination, respectively. +/* The C standard specifies two constants, EXIT_SUCCESS and EXIT_FAILURE, + * that may be passed to exit() to indicate successful or unsuccessful + * termination, respectively. */ #define EXIT_SUCCESS 0 @@ -71,9 +71,8 @@ #define MB_CUR_MAX 1 -/* The environ variable, normally 'extern char **environ;' is - * not implemented as a function call. However, get_environ_ptr() - * can be used in its place. +/* The environ variable, normally 'char **environ;' is not implemented as a + * function call. However, get_environ_ptr() can be used in its place. */ #ifndef CONFIG_DISABLE_ENVIRON @@ -81,7 +80,7 @@ #endif /**************************************************************************** - * Global Type Definitions + * Public Type Definitions ****************************************************************************/ struct mallinfo @@ -97,11 +96,7 @@ struct mallinfo }; /**************************************************************************** - * Global Function Prototypes - ****************************************************************************/ - -/**************************************************************************** - * Global Function Prototypes + * Public Function Prototypes ****************************************************************************/ #undef EXTERN diff --git a/include/string.h b/include/string.h index 79849e4a96f..396f440872c 100644 --- a/include/string.h +++ b/include/string.h @@ -56,7 +56,7 @@ #define bcopy(b1,b2,len) (void)memmove(b2,b1,len) /**************************************************************************** - * Global Function Prototypes + * Public Function Prototypes ****************************************************************************/ #undef EXTERN diff --git a/include/unistd.h b/include/unistd.h index 7816fb36c38..e482109f5c1 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -113,7 +113,7 @@ #define HOST_NAME_MAX 32 /**************************************************************************** - * Global Variables + * Public Data ****************************************************************************/ #undef EXTERN @@ -133,7 +133,7 @@ extern "C" #ifndef __NXFLAT__ EXTERN FAR char *optarg; /* Optional argument following option */ EXTERN int optind; /* Index into argv */ -EXTERN int optopt; /* unrecognized option character */ +EXTERN int optopt; /* Unrecognized option character */ #else # define optarg (*(getoptargp())) # define optind (*(getoptindp())) @@ -141,7 +141,7 @@ EXTERN int optopt; /* unrecognized option character */ #endif /**************************************************************************** - * Global Function Prototypes + * Public Function Prototypes ****************************************************************************/ /* Task Control Interfaces */ @@ -205,7 +205,7 @@ int getopt(int argc, FAR char *const argv[], FAR const char *optstring); FAR char **getoptargp(void); /* Optional argument following option */ int *getoptindp(void); /* Index into argv */ -int *getoptoptp(void); /* unrecognized option character */ +int *getoptoptp(void); /* Unrecognized option character */ #ifdef CONFIG_NET int gethostname(FAR char *name, size_t size); From e3decca82c554616d781e3cb100ace1fde108ea4 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 5 Aug 2015 08:07:58 -0600 Subject: [PATCH 04/35] Cosmetic update to some comments --- arch | 2 +- configs | 2 +- drivers/can.c | 10 +++++++++- include/nuttx/can.h | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/arch b/arch index 52f459de149..393a1dcf68b 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 52f459de149c45a4cd7a7758b350167a400375f3 +Subproject commit 393a1dcf68b3571f39a28f9b9e87843eedb77df8 diff --git a/configs b/configs index bba0b5c9b5e..86d7dde23be 160000 --- a/configs +++ b/configs @@ -1 +1 @@ -Subproject commit bba0b5c9b5e62c8d1f8d69cdd96c960e042bf82c +Subproject commit 86d7dde23be4b04331c58cc12c13ce381151ab9e diff --git a/drivers/can.c b/drivers/can.c index 4f2e5f95440..f52ccae555c 100644 --- a/drivers/can.c +++ b/drivers/can.c @@ -811,7 +811,15 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr, if (nexttail != fifo->rx_head) { - /* Add the new, decoded CAN message at the tail of the FIFO */ + /* Add the new, decoded CAN message at the tail of the FIFO. + * + * REVISIT: In the CAN FD format, the coding of the DLC differs from + * the standard CAN format. The DLC codes 0 to 8 have the same coding + * as in standard CAN, the codes 9 to 15, which in standard CAN all + * code a data field of 8 bytes, are encoded: + * + * 9->12, 10->16, 11->20, 12->24, 13->32, 14->48, 15->64 + */ memcpy(&fifo->rx_buffer[fifo->rx_tail].cm_hdr, hdr, sizeof(struct can_hdr_s)); for (i = 0, dest = fifo->rx_buffer[fifo->rx_tail].cm_data; i < hdr->ch_dlc; i++) diff --git a/include/nuttx/can.h b/include/nuttx/can.h index 98ce0e416cd..d22a2b8bc30 100644 --- a/include/nuttx/can.h +++ b/include/nuttx/can.h @@ -167,7 +167,7 @@ struct can_hdr_s #else struct can_hdr_s { - uint16_t ch_dlc : 4; /* 4-bit DLC */ + uint16_t ch_dlc : 4; /* 4-bit DLC. May be encoded in CAN_FD mode. */ uint16_t ch_rtr : 1; /* RTR indication */ uint16_t ch_id : 11; /* 11-bit standard ID */ } packed_struct; From a17d6e26a1c3363e388e7de6bd29694d6f2c86a4 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 5 Aug 2015 08:22:26 -0600 Subject: [PATCH 05/35] Update submodules --- arch | 2 +- configs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch b/arch index 393a1dcf68b..ce2c57026d7 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 393a1dcf68b3571f39a28f9b9e87843eedb77df8 +Subproject commit ce2c57026d76f3c5f3a5f9378f5f7b44fb0dd034 diff --git a/configs b/configs index 86d7dde23be..d76826b2205 160000 --- a/configs +++ b/configs @@ -1 +1 @@ -Subproject commit 86d7dde23be4b04331c58cc12c13ce381151ab9e +Subproject commit d76826b2205bef1ac39b27ad4ebd7adce881a619 From 9a347f135a370498322be8c368bba432c0fd1410 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 5 Aug 2015 09:17:27 -0600 Subject: [PATCH 06/35] Update submodules --- arch | 2 +- configs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch b/arch index ce2c57026d7..5faba88c51c 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit ce2c57026d76f3c5f3a5f9378f5f7b44fb0dd034 +Subproject commit 5faba88c51c916a2ce8a465cf1be3d9ebd83dc62 diff --git a/configs b/configs index d76826b2205..639546480f1 160000 --- a/configs +++ b/configs @@ -1 +1 @@ -Subproject commit d76826b2205bef1ac39b27ad4ebd7adce881a619 +Subproject commit 639546480f11f4438ab84aef4a51a82ab937c716 From 36d4559ee8c9558f7a8a86d0c012bde5ca6be7b8 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 5 Aug 2015 13:00:31 -0600 Subject: [PATCH 07/35] CAN: Define IOCTL commands that manage filters --- arch | 2 +- drivers/can.c | 14 ++++---- include/nuttx/can.h | 69 +++++++++++++++++++++++++++++++++++----- include/nuttx/fs/ioctl.h | 9 +++++- 4 files changed, 77 insertions(+), 17 deletions(-) diff --git a/arch b/arch index 5faba88c51c..478948e2fd0 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 5faba88c51c916a2ce8a465cf1be3d9ebd83dc62 +Subproject commit 478948e2fd0c1621bce15195c6f207df4156fbe6 diff --git a/drivers/can.c b/drivers/can.c index f52ccae555c..def854e1384 100644 --- a/drivers/can.c +++ b/drivers/can.c @@ -97,7 +97,7 @@ static int can_xmit(FAR struct can_dev_s *dev); static ssize_t can_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); static inline ssize_t can_rtrread(FAR struct can_dev_s *dev, - FAR struct canioctl_rtr_s *rtr); + FAR struct canioc_rtr_s *rtr); static int can_ioctl(FAR struct file *filep, int cmd, unsigned long arg); @@ -604,7 +604,7 @@ return_with_irqdisabled: ****************************************************************************/ static inline ssize_t can_rtrread(FAR struct can_dev_s *dev, - FAR struct canioctl_rtr_s *rtr) + FAR struct canioc_rtr_s *rtr) { FAR struct can_rtrwait_s *wait = NULL; irqstate_t flags; @@ -663,19 +663,19 @@ static int can_ioctl(FAR struct file *filep, int cmd, unsigned long arg) switch (cmd) { - /* CANIOCTL_RTR: Send the remote transmission request and wait for the - * response. Argument is a reference to struct canioctl_rtr_s + /* CANIOC_RTR: Send the remote transmission request and wait for the + * response. Argument is a reference to struct canioc_rtr_s * (casting to uintptr_t first eliminates complaints on some * architectures where the sizeof long is different from the size of * a pointer). */ - case CANIOCTL_RTR: - ret = can_rtrread(dev, (struct canioctl_rtr_s*)((uintptr_t)arg)); + case CANIOC_RTR: + ret = can_rtrread(dev, (struct canioc_rtr_s*)((uintptr_t)arg)); break; /* Not a "built-in" ioctl command.. perhaps it is unique to this - * device driver. + * lower-half, device driver. */ default: diff --git a/include/nuttx/can.h b/include/nuttx/can.h index d22a2b8bc30..25594814ef7 100644 --- a/include/nuttx/can.h +++ b/include/nuttx/can.h @@ -1,7 +1,7 @@ /************************************************************************************ * include/nuttx/can.h * - * Copyright (C) 2008, 2009, 2011-2012 Gregory Nutt. All rights reserved. + * Copyright (C) 2008, 2009, 2011-2012, 2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -49,6 +49,7 @@ #include #include +#include #ifdef CONFIG_CAN @@ -109,18 +110,56 @@ #define CAN_MSGLEN(nbytes) (sizeof(struct can_msg_s) - CAN_MAXDATALEN + (nbytes)) -/* Built-in ioctl commands +/* Built-in ioctl commands support by the upper half driver. * - * CANIOCTL_RTR: Send the remote transmission request and wait for the response. + * CANIOC_RTR: + * Description: Send the remote transmission request and wait for the response. + * Argument: A reference to struct canioc_rtr_s + * + * Ioctl commands that may or may not be supported by the lower half driver. + * + * CANIOC_ADD_STDFILTER: + * Description: Add an address filter for a standard 11 bit address. + * Argument: A reference to struct canioc_stdfilter_s + * Returned Value: A non-negative filter ID is returned on success. + * Otherwise -1 (ERROR) is returned with the errno + * variable set to indicate the nature of the error. + * + * CANIOC_ADD_EXTFILTER: + * Description: Add an address filter for a extended 28 bit address. + * Argument: A reference to struct canioc_extfilter_s + * Returned Value: A non-negative filter ID is returned on success. + * Otherwise -1 (ERROR) is returned with the errno + * variable set to indicate the nature of the error. + * + * CANIOC_DEL_STDFILTER: + * Description: Remove an address filter for a standard 11 bit address. + * Argument: The filter index previously returned by the + * CANIOC_ADD_STDFILTER command + * Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR) + * is returned with the errno variable set to indicate the + * nature of the error. + * + * CANIOC_DEL_EXTFILTER: + * Description: Remove an address filter for a standard 28 bit address. + * Argument: The filter index previously returned by the + * CANIOC_ADD_EXTFILTER command + * Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR) + * is returned with the errno variable set to indicate the + * nature of the error. */ -#define CANIOCTL_RTR 1 /* Argument is a reference to struct canioctl_rtr_s */ +#define CANIOC_RTR _CANIOC(1) +#define CANIOC_ADD_STDFILTER _CANIOC(2) +#define CANIOC_ADD_EXTFILTER _CANIOC(3) +#define CANIOC_DEL_STDFILTER _CANIOC(4) +#define CANIOC_DEL_EXTFILTER _CANIOC(5) -/* CANIOCTL_USER: Device specific ioctl calls can be supported with cmds greater +/* CANIOC_USER: Device specific ioctl calls can be supported with cmds greater * than this value */ -#define CANIOCTL_USER 2 +#define CANIOC_USER _CANIOC(6) /************************************************************************************ * Public Types @@ -158,7 +197,7 @@ #ifdef CONFIG_CAN_EXTID struct can_hdr_s { - uint32_t ch_id; /* 11- or 29-bit ID (3-bits unsed) */ + uint32_t ch_id; /* 11- or 29-bit ID (3-bits unused) */ uint8_t ch_dlc : 4; /* 4-bit DLC */ uint8_t ch_rtr : 1; /* RTR indication */ uint8_t ch_extid : 1; /* Extended ID indication */ @@ -296,12 +335,26 @@ struct can_dev_s /* Structures used with ioctl calls */ -struct canioctl_rtr_s +struct canioc_rtr_s { uint16_t ci_id; /* The 11-bit ID to use in the RTR message */ FAR struct can_msg_s *ci_msg; /* The location to return the RTR response */ }; +#ifdef CONFIG_CAN_EXTID +struct canioc_extfilter_s +{ + uint32_t xf_id; /* 28-bit ID (4-bits unused) */ + uint32_t xf_mask; /* 28-bit address mask (4-bits unused) */ +}; +#else +struct canioc_stdfilter_s +{ + uint16_t sf_id; /* 11-bit ID (5-bits unused) */ + uint16_t sf_mask; /* 11-bit address mask (5-bits unused) */ +}; +#endif + /************************************************************************************ * Public Data ************************************************************************************/ diff --git a/include/nuttx/fs/ioctl.h b/include/nuttx/fs/ioctl.h index 65bc85b45bd..f047d389068 100644 --- a/include/nuttx/fs/ioctl.h +++ b/include/nuttx/fs/ioctl.h @@ -76,7 +76,8 @@ #define _PIPEBASE (0x1700) /* FIFO/pipe ioctl commands */ #define _RTCBASE (0x1800) /* RTC ioctl commands */ #define _RELAYBASE (0x1900) /* Relay devices ioctl commands */ -#define _BOARDBASE (0x1a00) /* boardctl commands */ +#define _CANBASE (0x1a00) /* CAN ioctl commands */ +#define _BOARDBASE (0x1b00) /* boardctl ioctl commands */ /* Macros used to manage ioctl commands */ @@ -348,6 +349,12 @@ #define _RELAYIOCVALID(c) (_IOC_TYPE(c)==_RELAYBASE) #define _RELAYIOC(nr) _IOC(_RELAYBASE,nr) +/* CAN driver ioctl definitions *********************************************/ +/* (see nuttx/can.h */ + +#define _CANIOCVALID(c) (_IOC_TYPE(c)==_CANBASE) +#define _CANIOC(nr) _IOC(_CANBASE,nr) + /* boardctl() command definitions *******************************************/ #define _BOARDIOCVALID(c) (_IOC_TYPE(c)==_BOARDBASE) From 4b589903626299ab104df8b94991fd9222b942ba Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 5 Aug 2015 13:56:48 -0600 Subject: [PATCH 08/35] CAN: Add CAN FD mode as a configuration option --- arch | 2 +- drivers/Kconfig | 9 +++- drivers/can.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 118 insertions(+), 4 deletions(-) diff --git a/arch b/arch index 478948e2fd0..b331b89caf5 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 478948e2fd0c1621bce15195c6f207df4156fbe6 +Subproject commit b331b89caf5aa68bc8b8e585b35e10777f469e1c diff --git a/drivers/Kconfig b/drivers/Kconfig index b94ad60f990..263001d9cca 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -99,13 +99,20 @@ menuconfig CAN See include/nuttx/can.h for further CAN driver information. if CAN + config CAN_EXTID bool "CAN extended IDs" default n ---help--- - Enables support for the 29-bit extended ID. Default Standard 11-bit + Enables support for the 28-bit extended ID. Default Standard 11-bit IDs. +config CAN_FD + bool "CAN FD" + default n + ---help--- + Enables support for the CAN_FD mode. + config CAN_FIFOSIZE int "CAN driver I/O buffer size" default 8 diff --git a/drivers/can.c b/drivers/can.c index def854e1384..f11e7d66eb3 100644 --- a/drivers/can.c +++ b/drivers/can.c @@ -89,6 +89,15 @@ * Private Function Prototypes ****************************************************************************/ +/* CAN helpers */ + +static uint8_t can_dlc2bytes(uint8_t dlc); +#if 0 /* Not used */ +static uint8_t can_bytes2dlc(uint8_t nbytes); +#endif + +/* Character driver methods */ + static int can_open(FAR struct file *filep); static int can_close(FAR struct file *filep); static ssize_t can_read(FAR struct file *filep, FAR char *buffer, @@ -125,6 +134,101 @@ static const struct file_operations g_canops = * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: can_dlc2bytes and can_bytes2dlc + * + * Description: + * In the CAN FD format, the coding of the DLC differs from the standard + * CAN format. The DLC codes 0 to 8 have the same coding as in standard + * CAN. But the codes 9 to 15 all imply a data field of 8 bytes with + * standard CAN. In CAN FD mode, the values 9 to 15 are encoded to values + * in the range 12 to 64. + * + * Input Parameter: + * dlc - the DLC to convert to a byte count, OR + * nbytes - the byte count to convert to a DLC + * + * Returned Value: + * The converted value + * + ****************************************************************************/ + +static uint8_t can_dlc2bytes(uint8_t dlc) +{ + if (dlc > 8) + { +#ifdef CONFIG_CAN_FD + switch (dlc) + { + case 9: + return 12; + case 10: + return 16; + case 11: + return 20; + case 12: + return 24; + case 13: + return 32; + case 14: + return 48; + default: + case 15: + return 64; + } +#else + return 8; +#endif + } + + return dlc; +} + +#if 0 /* Not used */ +static uint8_t can_bytes2dlc(FAR struct sam_can_s *priv, uint8_t nbytes) +{ + if (nbytes <= 8) + { + return nbytes; + } +#ifdef CONFIG_CAN_FD + else if (nbytes <= 12) + { + return 9; + } + else if (nbytes <= 16) + { + return 10; + } + else if (nbytes <= 20) + { + return 11; + } + else if (nbytes <= 24) + { + return 12; + } + else if (nbytes <= 32) + { + return 13; + } + else if (nbytes <= 48) + { + return 14; + } + else /* if (nbytes <= 64) */ + { + return 15; + } +#else + else + { + return 8; + } +#endif +} +#endif + /**************************************************************************** * Name: can_open * @@ -351,7 +455,8 @@ static ssize_t can_read(FAR struct file *filep, FAR char *buffer, /* Will the next message in the FIFO fit into the user buffer? */ FAR struct can_msg_s *msg = &dev->cd_recv.rx_buffer[dev->cd_recv.rx_head]; - int msglen = CAN_MSGLEN(msg->cm_hdr.ch_dlc); + int nbytes = can_dlc2bytes(msg->cm_hdr.ch_dlc); + int msglen = CAN_MSGLEN(nbytes); if (nread + msglen > buflen) { @@ -472,6 +577,7 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer, ssize_t nsent = 0; irqstate_t flags; int nexttail; + int nbytes; int msglen; int ret = 0; @@ -562,7 +668,8 @@ static ssize_t can_write(FAR struct file *filep, FAR const char *buffer, */ msg = (FAR struct can_msg_s *)&buffer[nsent]; - msglen = CAN_MSGLEN(msg->cm_hdr.ch_dlc); + nbytes = can_dlc2bytes(msg->cm_hdr.ch_dlc); + msglen = CAN_MSGLEN(nbytes); memcpy(&fifo->tx_buffer[fifo->tx_tail], msg, msglen); /* Increment the tail of the circular buffer */ From 007e258c2b4efd25f89fa00b617427be196384e6 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 5 Aug 2015 16:22:40 -0600 Subject: [PATCH 09/35] Update some function headers --- ChangeLog | 5 +++++ arch | 2 +- drivers/can.c | 25 +++++++++++++++++++++---- include/nuttx/can.h | 10 ++++++++-- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 08f1df472d2..3dec204a8fb 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10780,3 +10780,8 @@ OS. It is a non-standard but more efficient version of sem_timedwait() for use in higher performance device drivers (2015-08-01). * drivers/net/slip.c: Fix another compilation error (2015-08-02). + * drivers/can.c include/nuttx/can.h, and fs/fs.h: Add CAN IOCTL command + definitions to manage CAN message filtering (2015-08-05) + * drivers/Kconfig and can.c: Add configuration to support DLC to byte + conversions needed for CAN FD mode (2015-08-05). + diff --git a/arch b/arch index b331b89caf5..37ea27a989e 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit b331b89caf5aa68bc8b8e585b35e10777f469e1c +Subproject commit 37ea27a989e81fcbba814431b389ffe05286b0db diff --git a/drivers/can.c b/drivers/can.c index f11e7d66eb3..f1eb4d195a8 100644 --- a/drivers/can.c +++ b/drivers/can.c @@ -135,7 +135,7 @@ static const struct file_operations g_canops = ****************************************************************************/ /**************************************************************************** - * Name: can_dlc2bytes and can_bytes2dlc + * Name: can_dlc2bytes * * Description: * In the CAN FD format, the coding of the DLC differs from the standard @@ -145,11 +145,10 @@ static const struct file_operations g_canops = * in the range 12 to 64. * * Input Parameter: - * dlc - the DLC to convert to a byte count, OR - * nbytes - the byte count to convert to a DLC + * dlc - the DLC value to convert to a byte count * * Returned Value: - * The converted value + * The number of bytes corresponding to the DLC value. * ****************************************************************************/ @@ -184,6 +183,24 @@ static uint8_t can_dlc2bytes(uint8_t dlc) return dlc; } +/**************************************************************************** + * Name: can_bytes2dlc + * + * Description: + * In the CAN FD format, the coding of the DLC differs from the standard + * CAN format. The DLC codes 0 to 8 have the same coding as in standard + * CAN. But the codes 9 to 15 all imply a data field of 8 bytes with + * standard CAN. In CAN FD mode, the values 9 to 15 are encoded to values + * in the range 12 to 64. + * + * Input Parameter: + * nbytes - the byte count to convert to a DLC value + * + * Returned Value: + * The encoded DLC value corresponding to at least that number of bytes. + * + ****************************************************************************/ + #if 0 /* Not used */ static uint8_t can_bytes2dlc(FAR struct sam_can_s *priv, uint8_t nbytes) { diff --git a/include/nuttx/can.h b/include/nuttx/can.h index 25594814ef7..69313024da7 100644 --- a/include/nuttx/can.h +++ b/include/nuttx/can.h @@ -61,6 +61,8 @@ * CONFIG_STM32_CAN2 must also be defined) * CONFIG_CAN_EXTID - Enables support for the 29-bit extended ID. Default * Standard 11-bit IDs. + * CONFIG_CAN_FD - Enable support for CAN FD mode. For the upper half driver, this + * just means handling encoded DLC values (for values of DLC > 9). * CONFIG_CAN_FIFOSIZE - The size of the circular buffer of CAN messages. * Default: 8 * CONFIG_CAN_NPENDINGRTR - The size of the list of pending RTR requests. @@ -110,13 +112,13 @@ #define CAN_MSGLEN(nbytes) (sizeof(struct can_msg_s) - CAN_MAXDATALEN + (nbytes)) -/* Built-in ioctl commands support by the upper half driver. +/* Ioctl commands supported by the upper half CAN driver. * * CANIOC_RTR: * Description: Send the remote transmission request and wait for the response. * Argument: A reference to struct canioc_rtr_s * - * Ioctl commands that may or may not be supported by the lower half driver. + * Ioctl commands that may or may not be supported by the lower half CAN driver. * * CANIOC_ADD_STDFILTER: * Description: Add an address filter for a standard 11 bit address. @@ -124,6 +126,7 @@ * Returned Value: A non-negative filter ID is returned on success. * Otherwise -1 (ERROR) is returned with the errno * variable set to indicate the nature of the error. + * Dependencies: Requires CONFIG_CAN_EXID *not* defined * * CANIOC_ADD_EXTFILTER: * Description: Add an address filter for a extended 28 bit address. @@ -131,6 +134,7 @@ * Returned Value: A non-negative filter ID is returned on success. * Otherwise -1 (ERROR) is returned with the errno * variable set to indicate the nature of the error. + * Dependencies: Requires CONFIG_CAN_EXID=y * * CANIOC_DEL_STDFILTER: * Description: Remove an address filter for a standard 11 bit address. @@ -139,6 +143,7 @@ * Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR) * is returned with the errno variable set to indicate the * nature of the error. + * Dependencies: Requires CONFIG_CAN_EXID *not* defined * * CANIOC_DEL_EXTFILTER: * Description: Remove an address filter for a standard 28 bit address. @@ -147,6 +152,7 @@ * Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR) * is returned with the errno variable set to indicate the * nature of the error. + * Dependencies: Requires CONFIG_CAN_EXID=y */ #define CANIOC_RTR _CANIOC(1) From 36db0725c5a0d1f503b8c20f7f2e6eacd26657e0 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 6 Aug 2015 10:28:34 -0600 Subject: [PATCH 10/35] Update TODO list --- TODO | 13 +++++++++++-- arch | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/TODO b/TODO index 66ae1cedbe6..b63ea6f6464 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,4 @@ -NuttX TODO List (Last updated July 26, 2015) +NuttX TODO List (Last updated August 6, 2015) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This file summarizes known NuttX bugs, limitations, inconsistencies with @@ -20,7 +20,7 @@ nuttx/ (4) USB (drivers/usbdev, drivers/usbhost) (12) Libraries (libc/, libm/) (11) File system/Generic drivers (fs/, drivers/) - (7) Graphics subsystem (graphics/) + (8) Graphics subsystem (graphics/) (1) Pascal add-on (pcode/) (2) Build system / Toolchains (3) Linux/Cywgin simulation (arch/sim) @@ -1536,6 +1536,15 @@ o Graphics subsystem (graphics/) Status: Open Priority: Low, of mostly strategic value. + Title: VERTICAL ANTI-ALIASING + Description: Anti-aliasing is implemented along the horizontal raster line + with fractional pixels at the ends of each line. There is no + accounting for fractional pixels in the vertical direction. + As a result lines closer to vertical receive better anti- + aliasing than lines closer to horizontal. + Status: Open + Priority: Low, not a serious issue but worth noting. There is no plan + to change this behavior. o Pascal Add-On (pcode/) ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/arch b/arch index 37ea27a989e..084d00887dc 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 37ea27a989e81fcbba814431b389ffe05286b0db +Subproject commit 084d00887dc6443c060be6103a6757563f00f7ce From f4d9c3e33d66b46cef8345bfcb53ab24298a2dc0 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 6 Aug 2015 11:51:13 -0600 Subject: [PATCH 11/35] CAN extended IDs are 29, not 28 bits --- arch | 2 +- include/nuttx/can.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch b/arch index 084d00887dc..6ca16388ea8 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 084d00887dc6443c060be6103a6757563f00f7ce +Subproject commit 6ca16388ea8de09d99befabc27def2ee5e665a72 diff --git a/include/nuttx/can.h b/include/nuttx/can.h index 69313024da7..2787750acec 100644 --- a/include/nuttx/can.h +++ b/include/nuttx/can.h @@ -129,7 +129,7 @@ * Dependencies: Requires CONFIG_CAN_EXID *not* defined * * CANIOC_ADD_EXTFILTER: - * Description: Add an address filter for a extended 28 bit address. + * Description: Add an address filter for a extended 29 bit address. * Argument: A reference to struct canioc_extfilter_s * Returned Value: A non-negative filter ID is returned on success. * Otherwise -1 (ERROR) is returned with the errno @@ -146,7 +146,7 @@ * Dependencies: Requires CONFIG_CAN_EXID *not* defined * * CANIOC_DEL_EXTFILTER: - * Description: Remove an address filter for a standard 28 bit address. + * Description: Remove an address filter for a standard 29 bit address. * Argument: The filter index previously returned by the * CANIOC_ADD_EXTFILTER command * Returned Value: Zero (OK) is returned on success. Otherwise -1 (ERROR) @@ -350,8 +350,8 @@ struct canioc_rtr_s #ifdef CONFIG_CAN_EXTID struct canioc_extfilter_s { - uint32_t xf_id; /* 28-bit ID (4-bits unused) */ - uint32_t xf_mask; /* 28-bit address mask (4-bits unused) */ + uint32_t xf_id; /* 29-bit ID (3-bits unused) */ + uint32_t xf_mask; /* 29-bit address mask (3-bits unused) */ }; #else struct canioc_stdfilter_s From e1c902d468b4bd1a2405cad714637253722ab972 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 6 Aug 2015 14:06:43 -0600 Subject: [PATCH 12/35] Remove some incorrect comments --- arch | 2 +- drivers/net/slip.c | 3 +-- include/nuttx/net/slip.h | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/arch b/arch index 6ca16388ea8..5102f815891 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 6ca16388ea8de09d99befabc27def2ee5e665a72 +Subproject commit 5102f815891b899f87a718ab85d3913015a015ea diff --git a/drivers/net/slip.c b/drivers/net/slip.c index a8e50343bbf..8333017ae81 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -939,8 +939,7 @@ static int slip_rmmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) * * Parameters: * intf - In the case where there are multiple SLIP interfaces, this value - * identifies which is to be initialized. The network name will be, - * for example, "/dev/slip5" for intf == 5 + * identifies which is to be initialized. * * Returned Value: * OK on success; Negated errno on failure. diff --git a/include/nuttx/net/slip.h b/include/nuttx/net/slip.h index 020f8e302f1..9baf7a6b3da 100644 --- a/include/nuttx/net/slip.h +++ b/include/nuttx/net/slip.h @@ -75,8 +75,7 @@ extern "C" * * Parameters: * intf - In the case where there are multiple SLIP interfaces, this value - * identifies which is to be initialized. The network name will be, - * for example, "/dev/slip5" for intf == 5 + * identifies which is to be initialized. * * Returned Value: * OK on success; Negated errno on failure. From 1ff1cd6c0c8be7aa2f9786a725ab0e739543fe97 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 6 Aug 2015 14:07:59 -0600 Subject: [PATCH 13/35] Update ChangeLog --- ChangeLog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ChangeLog b/ChangeLog index 3dec204a8fb..d344d1e241d 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10784,4 +10784,7 @@ definitions to manage CAN message filtering (2015-08-05) * drivers/Kconfig and can.c: Add configuration to support DLC to byte conversions needed for CAN FD mode (2015-08-05). + * arch/arm/src/samv7: Add an MCAN driver for the SAMV7 platform + (2015-08-06). + From 86769101a1c96709b45a800e8b136b53de16d6b6 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 6 Aug 2015 14:32:12 -0600 Subject: [PATCH 14/35] SLIP: Review code, update comments, add missing configuration items --- drivers/net/Kconfig | 59 ++++++++++++++++++++++++++++++++++------ drivers/net/slip.c | 55 +++++++++++++++++++------------------ include/nuttx/net/slip.h | 41 +++++++++++++++++++++++++--- 3 files changed, 116 insertions(+), 39 deletions(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index dc9890ee64f..f76a228380c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -52,7 +52,7 @@ config NET_DUMPPACKET comment "External Ethernet MAC Device Support" -config NET_DM90x0 +menuconfig NET_DM90x0 bool "Davicom dm9000/dm9010 support" default n ---help--- @@ -132,7 +132,7 @@ config NET_CS89x0 ---help--- Under construction -- do not use -config ENC28J60 +menuconfig ENC28J60 bool "Microchip ENC28J60 support" default n select SPI @@ -142,6 +142,7 @@ config ENC28J60 DS39662C, 2008 Microchip Technology Inc. if ENC28J60 + config ENC28J60_NINTERFACES int "Number of physical ENC28J60" default 1 @@ -192,9 +193,9 @@ config ENC28J60_REGDEBUG ---help--- Enable very low-level register access debug. Depends on DEBUG and DEBUG_NET. -endif +endif # ENC28J60 -config ENCX24J600 +menuconfig ENCX24J600 bool "Microchip ENCX24J600 support" default n select SPI @@ -205,6 +206,7 @@ config ENCX24J600 with SPI or Parallel Interface DS39935B, 2009 Microchip Technology Inc. if ENCX24J600 + config ENC28J60_NINTERFACES int "Number of physical ENCX24J600" default 1 @@ -258,9 +260,9 @@ config ENCX24J600_REGDEBUG ---help--- Enable very low-level register access debug. Depends on DEBUG and DEBUG_NET. -endif +endif # ENCX24J600 -config NET_E1000 +menuconfig NET_E1000 bool "E1000 support" default n @@ -280,13 +282,52 @@ config E1000_BUFF_SIZE endif # NET_E1000 -config NET_SLIP +menuconfig NET_SLIP bool "SLIP (serial line) support" default n ---help--- Reference: RFC 1055 -config NET_FTMAC100 +if NET_SLIP + +config NET_SLIP_STACKSIZE + int "Daemon stack size" + default 2048 + ---help--- + Provides the stack size for SLIP RX and TX. + +config NET_SLIP_DEFPRIO + int "Daemon priority" + default 128 + ---help--- + Provides the priority for SLIP RX and TX threads. + +config NET_SLIP_MTU + int "Packet size (MTU)" + default 296 + ---help--- + Provides the size of the SLIP packet buffers. + + The Linux slip module hard-codes its MTU size to 296 (40 bytes for + the IP+TPC headers plus 256 bytes of data). So you might as well + set CONFIG_NET_SLIP_MTU to 296 as well. + + There may be an issue with this setting, however. I see that Linux + uses a MTU of 296 and window of 256, but actually only sends 168 + bytes of data: 40 + 128. I believe that is to allow for the 2x + worst cast packet expansion. Ideally we would like to advertise the + 256 MSS, but restrict transfers to 128 bytes (possibly by modifying + the tcp_mss() macro). + +config SLIP_NINTERFACES + int "Number of SLIP interfaces" + default 1 + ---help--- + Determines the number of physical interfaces that will be supported. + +endif + +menuconfig NET_FTMAC100 bool "Faraday 10/100 Ethernet" default n ---help--- @@ -316,7 +357,7 @@ config FTMAC100_MAC0_ENV_ADDR endif # NET_FTMAC100 -config NET_VNET +menuconfig NET_VNET bool "VNET support" default n diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 8333017ae81..4b02475b831 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -83,12 +83,12 @@ # warning "CONFIG_NET_MULTIBUFFER must be set" #endif -#ifndef CONFIG_SLIP_STACKSIZE -# define CONFIG_SLIP_STACKSIZE 2048 +#ifndef CONFIG_NET_SLIP_STACKSIZE +# define CONFIG_NET_SLIP_STACKSIZE 2048 #endif -#ifndef CONFIG_SLIP_DEFPRIO -# define CONFIG_SLIP_DEFPRIO 128 +#ifndef CONFIG_NET_SLIP_DEFPRIO +# define CONFIG_NET_SLIP_DEFPRIO 128 #endif /* The Linux slip module hard-codes its MTU size to 296 (40 bytes for the @@ -99,7 +99,7 @@ * a MTU of 296 and window of 256, but actually only sends 168 bytes of data: * 40 + 128. I believe that is to allow for the 2x worst cast packet * expansion. Ideally we would like to advertise the 256 MSS, but restrict - * uIP to 128 bytes (possibly by modifying the tcp_mss() macro). + * transfers to 128 bytes (possibly by modifying the tcp_mss() macro). */ #if CONFIG_NET_SLIP_MTU < 296 @@ -250,7 +250,7 @@ static void slip_semtake(FAR struct slip_driver_s *priv) * Description: * Just an inline wrapper around fwrite with error checking. * - * Parameters: + * Input Parameters: * priv - Reference to the driver state structure * buffer - Buffer data to send * len - Buffer length in bytes @@ -274,7 +274,7 @@ static inline void slip_write(FAR struct slip_driver_s *priv, * Description: * Just an inline wrapper around putc with error checking. * - * Parameters: + * Input Parameters: * priv - Reference to the driver state structure * ch - The character to send * @@ -293,7 +293,7 @@ static inline void slip_putc(FAR struct slip_driver_s *priv, int ch) * Start hardware transmission. Called either from the txdone interrupt * handling or from watchdog based polling. * - * Parameters: + * Input Parameters: * priv - Reference to the driver state structure * * Returned Value: @@ -407,7 +407,7 @@ static int slip_transmit(FAR struct slip_driver_s *priv) * 1. When the preceding TX packet send is complete, or * 2. During normal periodic polling * - * Parameters: + * Input Parameters: * dev - Reference to the NuttX driver state structure * * Returned Value: @@ -444,7 +444,7 @@ static int slip_txpoll(FAR struct net_driver_s *dev) * Description: * Polling and transmission is performed on tx thread. * - * Parameters: + * Input Parameters: * arg - Reference to the NuttX driver state structure * * Returned Value: @@ -535,7 +535,7 @@ static void slip_txtask(int argc, FAR char *argv[]) * Description: * Get one byte from the serial input. * - * Parameters: + * Input Parameters: * priv - Reference to the driver state structure * * Returned Value: @@ -561,7 +561,7 @@ static inline int slip_getc(FAR struct slip_driver_s *priv) * Description: * Read a packet from the serial input * - * Parameters: + * Input Parameters: * priv - Reference to the driver state structure * * Returned Value: @@ -666,7 +666,7 @@ static inline void slip_receive(FAR struct slip_driver_s *priv) * Description: * Wait for incoming data. * - * Parameters: + * Input Parameters: * argc * argv * @@ -786,7 +786,7 @@ static int slip_rxtask(int argc, FAR char *argv[]) * NuttX Callback: Bring up the Ethernet interface when an IP address is * provided * - * Parameters: + * Input Parameters: * dev - Reference to the NuttX driver state structure * * Returned Value: @@ -816,7 +816,7 @@ static int slip_ifup(FAR struct net_driver_s *dev) * Description: * NuttX Callback: Stop the interface. * - * Parameters: + * Input Parameters: * dev - Reference to the NuttX driver state structure * * Returned Value: @@ -844,7 +844,7 @@ static int slip_ifdown(FAR struct net_driver_s *dev) * stimulus perform an out-of-cycle poll and, thereby, reduce the TX * latency. * - * Parameters: + * Input Parameters: * dev - Reference to the NuttX driver state structure * * Returned Value: @@ -876,7 +876,7 @@ static int slip_txavail(FAR struct net_driver_s *dev) * NuttX Callback: Add the specified MAC address to the hardware multicast * address filtering * - * Parameters: + * Input Parameters: * dev - Reference to the NuttX driver state structure * mac - The MAC address to be added * @@ -905,7 +905,7 @@ static int slip_addmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) * NuttX Callback: Remove the specified MAC address from the hardware multicast * address filtering * - * Parameters: + * Input Parameters: * dev - Reference to the NuttX driver state structure * mac - The MAC address to be removed * @@ -937,9 +937,12 @@ static int slip_rmmac(FAR struct net_driver_s *dev, FAR const uint8_t *mac) * Description: * Instantiate a SLIP network interface. * - * Parameters: - * intf - In the case where there are multiple SLIP interfaces, this value - * identifies which is to be initialized. + * Input Parameters: + * intf - In the case where there are multiple SLIP interfaces, this + * value identifies which is to be initialized. The number of + * possible SLIP interfaces is determined by + * devname - This is the path to the serial device that will support SLIP. + * For example, this might be "/dev/ttyS1" * * Returned Value: * OK on success; Negated errno on failure. @@ -996,9 +999,9 @@ int slip_initialize(int intf, FAR const char *devname) argv[0] = buffer; argv[1] = NULL; - priv->rxpid = task_create("rxslip", CONFIG_SLIP_DEFPRIO, - CONFIG_SLIP_STACKSIZE, (main_t)slip_rxtask, - (FAR char * const *)argv); + priv->rxpid = task_create("rxslip", CONFIG_NET_SLIP_DEFPRIO, + CONFIG_NET_SLIP_STACKSIZE, (main_t)slip_rxtask, + (FAR char * const *)argv); if (priv->rxpid < 0) { ndbg("ERROR: Failed to start receiver task\n"); @@ -1011,8 +1014,8 @@ int slip_initialize(int intf, FAR const char *devname) /* Start the SLIP transmitter task */ - priv->txpid = task_create("txslip", CONFIG_SLIP_DEFPRIO, - CONFIG_SLIP_STACKSIZE, (main_t)slip_txtask, + priv->txpid = task_create("txslip", CONFIG_NET_SLIP_DEFPRIO, + CONFIG_NET_SLIP_STACKSIZE, (main_t)slip_txtask, (FAR char * const *)argv); if (priv->txpid < 0) { diff --git a/include/nuttx/net/slip.h b/include/nuttx/net/slip.h index 9baf7a6b3da..cfd1a3c8ad5 100644 --- a/include/nuttx/net/slip.h +++ b/include/nuttx/net/slip.h @@ -48,8 +48,38 @@ #ifdef CONFIG_NET_SLIP /**************************************************************************** - * Public Type Definitions + * Pre-processor Definitions ****************************************************************************/ +/* Configuration ***********************************************************/ +/* Dependencies: + * + * CONFIG_NET_NOINTS - Required. + * CONFIG_NET_MULTIBUFFER - Required. + * + * SLIP Configuration: + * + * CONFIG_NET_SLIP - Enables building of the SLIP driver + * CONFIG_SLIP_STACKSIZE - Provides the stack size for SLIP RX and TX + * threads. Default: 2048 + * CONFIG_SLIP_DEFPRIO - Provides the priority for SLIP RX and TX threads. + * Default 128. + * CONFIG_NET_SLIP_MTU - Provides the size of the SLIP packet buffers. + * Default 296 + * + * The Linux slip module hard-codes its MTU size to 296 (40 bytes for the + * IP+TPC headers plus 256 bytes of data). So you might as well set + * CONFIG_NET_SLIP_MTU to 296 as well. + * + * There may be an issue with this setting, however. I see that Linux + * uses a MTU of 296 and window of 256, but actually only sends 168 bytes + * of data: 40 + 128. I believe that is to allow for the 2x worst cast + * packet expansion. Ideally we would like to advertise the 256 MSS, + * but restrict transfers to 128 bytes (possibly by modifying the tcp_mss() + * macro). + * + * CONFIG_SLIP_NINTERFACES determines the number of physical interfaces + * that will be supported. + */ /**************************************************************************** * Public Data @@ -73,9 +103,12 @@ extern "C" * Description: * Instantiate a SLIP network interface. * - * Parameters: - * intf - In the case where there are multiple SLIP interfaces, this value - * identifies which is to be initialized. + * Input Parameters: + * intf - In the case where there are multiple SLIP interfaces, this + * value identifies which is to be initialized. The number of + * possible SLIP interfaces is determined by + * devname - This is the path to the serial device that will support SLIP. + * For example, this might be "/dev/ttyS1" * * Returned Value: * OK on success; Negated errno on failure. From 0dd273935acce9c1d18f252a51b917c9a35671bb Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 6 Aug 2015 15:08:15 -0600 Subject: [PATCH 15/35] Standardize naming of all SLIP configuration options --- configs | 2 +- drivers/net/Kconfig | 2 +- drivers/net/slip.c | 16 ++++++++-------- include/nuttx/net/slip.h | 14 +++++++------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/configs b/configs index 639546480f1..abab21dfa55 160000 --- a/configs +++ b/configs @@ -1 +1 @@ -Subproject commit 639546480f11f4438ab84aef4a51a82ab937c716 +Subproject commit abab21dfa553656a0ce40423931a2af2c61f3466 diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index f76a228380c..32c87c7e0c7 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -319,7 +319,7 @@ config NET_SLIP_MTU 256 MSS, but restrict transfers to 128 bytes (possibly by modifying the tcp_mss() macro). -config SLIP_NINTERFACES +config NET_SLIP_NINTERFACES int "Number of SLIP interfaces" default 1 ---help--- diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 4b02475b831..bbabc1527e8 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -108,12 +108,12 @@ # warning "CONFIG_NET_SLIP_MTU == 296 is optimal" #endif -/* CONFIG_SLIP_NINTERFACES determines the number of physical interfaces +/* CONFIG_NET_SLIP_NINTERFACES determines the number of physical interfaces * that will be supported. */ -#ifndef CONFIG_SLIP_NINTERFACES -# define CONFIG_SLIP_NINTERFACES 1 +#ifndef CONFIG_NET_SLIP_NINTERFACES +# define CONFIG_NET_SLIP_NINTERFACES 1 #endif /* SLIP special character codes *******************************************/ @@ -183,11 +183,11 @@ struct slip_driver_s * Private Data ****************************************************************************/ - /* We really should get rid of CONFIG_SLIP_NINTERFACES and, instead, + /* We really should get rid of CONFIG_NET_SLIP_NINTERFACES and, instead, * kmm_malloc() new interface instances as needed. */ -static struct slip_driver_s g_slip[CONFIG_SLIP_NINTERFACES]; +static struct slip_driver_s g_slip[CONFIG_NET_SLIP_NINTERFACES]; /**************************************************************************** * Private Function Prototypes @@ -462,7 +462,7 @@ static void slip_txtask(int argc, FAR char *argv[]) unsigned int hsec; ndbg("index: %d\n", index); - DEBUGASSERT(index < CONFIG_SLIP_NINTERFACES); + DEBUGASSERT(index < CONFIG_NET_SLIP_NINTERFACES); /* Get our private data structure instance and wake up the waiting * initialization logic. @@ -685,7 +685,7 @@ static int slip_rxtask(int argc, FAR char *argv[]) int ch; ndbg("index: %d\n", index); - DEBUGASSERT(index < CONFIG_SLIP_NINTERFACES); + DEBUGASSERT(index < CONFIG_NET_SLIP_NINTERFACES); /* Get our private data structure instance and wake up the waiting * initialization logic. @@ -959,7 +959,7 @@ int slip_initialize(int intf, FAR const char *devname) /* Get the interface structure associated with this interface number. */ - DEBUGASSERT(intf < CONFIG_SLIP_NINTERFACES); + DEBUGASSERT(intf < CONFIG_NET_SLIP_NINTERFACES); priv = &g_slip[intf]; /* Initialize the driver structure */ diff --git a/include/nuttx/net/slip.h b/include/nuttx/net/slip.h index cfd1a3c8ad5..1fb2e46514c 100644 --- a/include/nuttx/net/slip.h +++ b/include/nuttx/net/slip.h @@ -59,11 +59,11 @@ * SLIP Configuration: * * CONFIG_NET_SLIP - Enables building of the SLIP driver - * CONFIG_SLIP_STACKSIZE - Provides the stack size for SLIP RX and TX + * CONFIG_NET_SLIP_STACKSIZE - Provides the stack size for SLIP RX and TX * threads. Default: 2048 - * CONFIG_SLIP_DEFPRIO - Provides the priority for SLIP RX and TX threads. - * Default 128. - * CONFIG_NET_SLIP_MTU - Provides the size of the SLIP packet buffers. + * CONFIG_NET_SLIP_DEFPRIO - Provides the priority for SLIP RX and TX + * threads. Default 128. + * CONFIG_NET_NET_SLIP_MTU - Provides the size of the SLIP packet buffers. * Default 296 * * The Linux slip module hard-codes its MTU size to 296 (40 bytes for the @@ -74,10 +74,10 @@ * uses a MTU of 296 and window of 256, but actually only sends 168 bytes * of data: 40 + 128. I believe that is to allow for the 2x worst cast * packet expansion. Ideally we would like to advertise the 256 MSS, - * but restrict transfers to 128 bytes (possibly by modifying the tcp_mss() - * macro). + * but restrict transfers to 128 bytes (possibly by modifying the + * tcp_mss() macro). * - * CONFIG_SLIP_NINTERFACES determines the number of physical interfaces + * CONFIG_NET_SLIP_NINTERFACES determines the number of physical interfaces * that will be supported. */ From 282c4f5347b1ae15ffab947accfc0029f0d8d999 Mon Sep 17 00:00:00 2001 From: "Paul A. Patience" Date: Thu, 6 Aug 2015 13:07:33 -0400 Subject: [PATCH 16/35] Added LM92 temperature sensor. --- drivers/sensors/Kconfig | 7 + drivers/sensors/Make.defs | 4 + drivers/sensors/lm92.c | 622 +++++++++++++++++++++++++++++++++++ include/nuttx/sensors/lm92.h | 150 +++++++++ 4 files changed, 783 insertions(+) create mode 100644 drivers/sensors/lm92.c create mode 100644 include/nuttx/sensors/lm92.h diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index c7137c3c124..66c25c770bd 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -79,6 +79,13 @@ config LM75 This should also work with compatible temperature sensors such as the TI TMP100/101. +config LM92 + bool "TI LM92 Temperature Sensor support" + default n + select I2C + ---help--- + Enable driver support for the TI LM92 Temperature Sensor. + config QENCODER bool "Qencoder" default n diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs index ce887cdd1b0..1f369e801c8 100644 --- a/drivers/sensors/Make.defs +++ b/drivers/sensors/Make.defs @@ -60,6 +60,10 @@ endif ifeq ($(CONFIG_I2C_LM75),y) CSRCS += lm75.c endif + +ifeq ($(CONFIG_LM92),y) + CSRCS += lm92.c +endif endif # CONFIG_I2C # These drivers depend on SPI support diff --git a/drivers/sensors/lm92.c b/drivers/sensors/lm92.c new file mode 100644 index 00000000000..8d75e017713 --- /dev/null +++ b/drivers/sensors/lm92.c @@ -0,0 +1,622 @@ +/**************************************************************************** + * drivers/sensors/lm92.c + * Character driver for the TI LM92 Temperature Sensor + * + * Copyright (C) 2011, 2013 Gregory Nutt. All rights reserved. + * Copyright (C) 2015 Alexandru Duru. All rights reserved. + * Author: Gregory Nutt + * Alexandru Duru + * + * 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 + +#if defined(CONFIG_I2C) && defined(CONFIG_LM92) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Centigrade to Fahrenheit conversion: F = 9*C/5 + 32 */ + +#define B16_9DIV5 (9 * 65536 / 5) +#define B16_32 (32 * 65536) + +/**************************************************************************** + * Private + ****************************************************************************/ + +struct lm92_dev_s +{ + FAR struct i2c_dev_s *i2c; /* I2C interface */ + uint8_t addr; /* I2C address */ + bool fahrenheit; /* true: temperature will be reported in Fahrenheit */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* I2C Helpers */ + +static int lm92_readb16(FAR struct lm92_dev_s *priv, uint8_t regaddr, + FAR b16_t *regvalue); +static int lm92_writeb16(FAR struct lm92_dev_s *priv, uint8_t regaddr, + b16_t regval); +static int lm92_readtemp(FAR struct lm92_dev_s *priv, FAR b16_t *temp); +static int lm92_readconf(FAR struct lm92_dev_s *priv, FAR uint8_t *conf); +static int lm92_writeconf(FAR struct lm92_dev_s *priv, uint8_t conf); + +/* Character driver methods */ + +static int lm92_open(FAR struct file *filep); +static int lm92_close(FAR struct file *filep); +static ssize_t lm92_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t lm92_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +static int lm92_ioctl(FAR struct file *filep, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_lm92fops = +{ + lm92_open, + lm92_close, + lm92_read, + lm92_write, + 0, + lm92_ioctl +#ifndef CONFIG_DISABLE_POLL + , 0 +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: lm92_readb16 + * + * Description: + * Read a 16-bit register (LM92_TEMP_REG, LM92_THYS_REG, LM92_TCRIT_REG, + * LM92_TLOW_REG, LM92_THIGH_REG, or LM92_ID_REG) + * + ****************************************************************************/ + +static int lm92_readb16(FAR struct lm92_dev_s *priv, uint8_t regaddr, + FAR b16_t *regvalue) +{ + uint8_t buffer[2]; + int ret; + + /* Write the register address */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + ret = I2C_WRITE(priv->i2c, ®addr, 1); + if (ret < 0) + { + sndbg("I2C_WRITE failed: %d\n", ret); + return ret; + } + + /* Restart and read 16 bits from the register (discarding 3) */ + + ret = I2C_READ(priv->i2c, buffer, 2); + if (ret < 0) + { + sndbg("I2C_READ failed: %d\n", ret); + return ret; + } + + /* Data format is: TTTTTTTT TTTTTxxx where TTTTTTTTTTTTT is a thirteen-bit, + * signed temperature value with LSB = 0.0625 degrees Centigrade. + */ + + *regvalue = (b16_t)((uint32_t)(buffer[0] & (1 << 7)) << 24 | + (uint32_t)(buffer[0] & ~(1 << 7)) << 17 | + (uint32_t)(buffer[1] & ~7) << 9); + sndbg("addr: %02x value: %08x ret: %d\n", regaddr, *regvalue, ret); + return OK; +} + +/**************************************************************************** + * Name: lm92_writeb16 + * + * Description: + * Write to a 16-bit register (LM92_TEMP_REG, LM92_THYS_REG, LM92_TCRIT_REG, + * LM92_TLOW_REG, LM92_THIGH_REG, or LM92_ID_REG) + * + ****************************************************************************/ + +static int lm92_writeb16(FAR struct lm92_dev_s *priv, uint8_t regaddr, + b16_t regval) +{ + uint8_t buffer[3]; + + sndbg("addr: %02x value: %08x\n", regaddr, regval); + + /* Set up a 3-byte message to send */ + + buffer[0] = regaddr; + buffer[1] = (uint8_t)(((uint32_t)regval & (1 << 31)) >> 24 | + ((uint32_t)regval & ~(1 << 31)) >> 17); + buffer[2] = (uint8_t)(((uint32_t)regval & ~(1 << 31)) >> 9); + + /* Write the register address followed by the data (no RESTART) */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + return I2C_WRITE(priv->i2c, buffer, 3); +} + +/**************************************************************************** + * Name: lm92_readtemp + * + * Description: + * Read the temperature register with special scaling (LM92_TEMP_REG) + * + ****************************************************************************/ + +static int lm92_readtemp(FAR struct lm92_dev_s *priv, FAR b16_t *temp) +{ + b16_t temp16; + int ret; + + /* Read the raw temperature data (b16_t) */ + + ret = lm92_readb16(priv, LM92_TEMP_REG, &temp16); + if (ret < 0) + { + sndbg("lm92_readb16 failed: %d\n", ret); + return ret; + } + + sndbg("Centigrade: %08x\n", temp16); + + /* Was Fahrenheit requested? */ + + if (priv->fahrenheit) + { + /* Centigrade to Fahrenheit conversion: F = 9*C/5 + 32 */ + + temp16 = b16mulb16(temp16, B16_9DIV5) + B16_32; + sndbg("Fahrenheit: %08x\n", temp16); + } + + *temp = temp16; + return OK; +} + +/**************************************************************************** + * Name: lm92_readconf + * + * Description: + * Read the 8-bit LM92 configuration register + * + ****************************************************************************/ + +static int lm92_readconf(FAR struct lm92_dev_s *priv, FAR uint8_t *conf) +{ + uint8_t buffer; + int ret; + + /* Write the configuration register address */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + + buffer = LM92_CONF_REG; + ret = I2C_WRITE(priv->i2c, &buffer, 1); + if (ret < 0) + { + sndbg("I2C_WRITE failed: %d\n", ret); + return ret; + } + + /* Restart and read 8 bits from the register */ + + ret = I2C_READ(priv->i2c, conf, 1); + sndbg("conf: %02x ret: %d\n", *conf, ret); + return ret; +} + +/**************************************************************************** + * Name: lm92_writeconf + * + * Description: + * Write to a 8-bit LM92 configuration register. + * + ****************************************************************************/ + +static int lm92_writeconf(FAR struct lm92_dev_s *priv, uint8_t conf) +{ + uint8_t buffer[2]; + + sndbg("conf: %02x\n", conf); + + /* Set up a 2-byte message to send */ + + buffer[0] = LM92_CONF_REG; + buffer[1] = conf; + + /* Write the register address followed by the data (no RESTART) */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + return I2C_WRITE(priv->i2c, buffer, 2); +} + +/**************************************************************************** + * Name: lm92_readid + * + * Description: + * Read the 16-bit LM92 identification register + * + ****************************************************************************/ + +static int lm92_readid(FAR struct lm92_dev_s *priv, FAR uint16_t *id) +{ + uint8_t buffer[2]; + uint8_t regaddr; + int ret; + + /* Write the identification register address */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + + regaddr = LM92_ID_REG; + ret = I2C_WRITE(priv->i2c, ®addr, 1); + if (ret < 0) + { + sndbg("I2C_WRITE failed: %d\n", ret); + return ret; + } + + /* Restart and read 16 bits from the register */ + + ret = I2C_READ(priv->i2c, buffer, 2); + if (ret < 0) + { + sndbg("I2C_READ failed: %d\n", ret); + return ret; + } + + *id = (uint16_t)buffer[0] << 8 | (uint16_t)buffer[1]; + sndbg("id: %04x ret: %d\n", *id, ret); + return OK; +} + +/**************************************************************************** + * Name: lm92_open + * + * Description: + * This function is called whenever the LM92 device is opened. + * + ****************************************************************************/ + +static int lm92_open(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: lm92_close + * + * Description: + * This function is called whenever the LM92 device is closed. + * + ****************************************************************************/ + +static int lm92_close(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: lm92_read + ****************************************************************************/ + +static ssize_t lm92_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct lm92_dev_s *priv = inode->i_private; + FAR b16_t *ptr; + ssize_t nsamples; + int i; + int ret; + + /* How many samples were requested to get? */ + + nsamples = buflen / sizeof(b16_t); + ptr = (FAR b16_t *)buffer; + + sndbg("buflen: %d nsamples: %d\n", buflen, nsamples); + + /* Get the requested number of samples */ + + for (i = 0; i < nsamples; i++) + { + b16_t temp = 0; + + /* Read the next b16_t temperature value */ + + ret = lm92_readtemp(priv, &temp); + if (ret < 0) + { + sndbg("lm92_readtemp failed: %d\n",ret); + return (ssize_t)ret; + } + + /* Save the temperature value in the user buffer */ + + *ptr++ = temp; + } + + return nsamples * sizeof(b16_t); +} + +/**************************************************************************** + * Name: lm92_write + ****************************************************************************/ + +static ssize_t lm92_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + return -ENOSYS; +} + +/**************************************************************************** + * Name: lm92_ioctl + ****************************************************************************/ + +static int lm92_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct lm92_dev_s *priv = inode->i_private; + int ret = OK; + + switch (cmd) + { + /* Read from the configuration register. Arg: uint8_t* pointer */ + + case SNIOC_READCONF: + { + FAR uint8_t *ptr = (FAR uint8_t *)((uintptr_t)arg); + ret = lm92_readconf(priv, ptr); + sndbg("conf: %02x ret: %d\n", *ptr, ret); + } + break; + + /* Write to the configuration register. Arg: uint8_t value */ + + case SNIOC_WRITECONF: + ret = lm92_writeconf(priv, (uint8_t)arg); + sndbg("conf: %02x ret: %d\n", *(uint8_t *)arg, ret); + break; + + /* Shutdown the LM92. Arg: None */ + + case SNIOC_SHUTDOWN: + { + uint8_t conf; + ret = lm92_readconf(priv, &conf); + if (ret == OK) + { + ret = lm92_writeconf(priv, conf | LM92_CONF_SHUTDOWN); + } + + sndbg("conf: %02x ret: %d\n", conf | LM92_CONF_SHUTDOWN, ret); + } + break; + + /* Powerup the LM92. Arg: None */ + + case SNIOC_POWERUP: + { + uint8_t conf; + ret = lm92_readconf(priv, &conf); + if (ret == OK) + { + ret = lm92_writeconf(priv, conf & ~LM92_CONF_SHUTDOWN); + } + + sndbg("conf: %02x ret: %d\n", conf & ~LM92_CONF_SHUTDOWN, ret); + } + break; + + /* Report samples in Fahrenheit. Arg: None */ + + case SNIOC_FAHRENHEIT: + priv->fahrenheit = true; + sndbg("Fahrenheit\n"); + break; + + /* Report samples in Centigrade. Arg: None */ + + case SNIOC_CENTIGRADE: + priv->fahrenheit = false; + sndbg("Centigrade\n"); + break; + + /* Read THYS temperature register. Arg: b16_t* pointer */ + + case SNIOC_READTHYS: + { + FAR b16_t *ptr = (FAR b16_t *)((uintptr_t)arg); + ret = lm92_readb16(priv, LM92_THYS_REG, ptr); + sndbg("THYS: %08x ret: %d\n", *ptr, ret); + } + break; + + /* Write THYS temperature register. Arg: b16_t value */ + + case SNIOC_WRITETHYS: + ret = lm92_writeb16(priv, LM92_THYS_REG, (b16_t)arg); + sndbg("THYS: %08x ret: %d\n", (b16_t)arg, ret); + break; + + /* Read TCRIT temperature register. Arg: b16_t* pointer */ + + case SNIOC_READTCRIT: + { + FAR b16_t *ptr = (FAR b16_t *)((uintptr_t)arg); + ret = lm92_readb16(priv, LM92_TCRIT_REG, ptr); + sndbg("TCRIT: %08x ret: %d\n", *ptr, ret); + } + break; + + /* Write TCRIT temperature register. Arg: b16_t value */ + + case SNIOC_WRITETCRIT: + ret = lm92_writeb16(priv, LM92_TCRIT_REG, (b16_t)arg); + sndbg("TCRIT: %08x ret: %d\n", (b16_t)arg, ret); + break; + + /* Read TLOW temperature register. Arg: b16_t* pointer */ + + case SNIOC_READTLOW: + { + FAR b16_t *ptr = (FAR b16_t *)((uintptr_t)arg); + ret = lm92_readb16(priv, LM92_TLOW_REG, ptr); + sndbg("TLOW: %08x ret: %d\n", *ptr, ret); + } + break; + + /* Write TLOW temperature register. Arg: b16_t value */ + + case SNIOC_WRITETLOW: + ret = lm92_writeb16(priv, LM92_TLOW_REG, (b16_t)arg); + sndbg("TLOW: %08x ret: %d\n", (b16_t)arg, ret); + break; + + /* Read THIGH temperature register. Arg: b16_t* pointer */ + + case SNIOC_READTHIGH: + { + FAR b16_t *ptr = (FAR b16_t *)((uintptr_t)arg); + ret = lm92_readb16(priv, LM92_THIGH_REG, ptr); + sndbg("THIGH: %08x ret: %d\n", *ptr, ret); + } + break; + + /* Write THIGH temperature register. Arg: b16_t value */ + + case SNIOC_WRITETHIGH: + ret = lm92_writeb16(priv, LM92_THIGH_REG, (b16_t)arg); + sndbg("THIGH: %08x ret: %d\n", (b16_t)arg, ret); + break; + + /* Read from the identification register. Arg: uint16_t* pointer */ + + case SNIOC_READID: + { + FAR uint16_t *ptr = (FAR uint16_t *)((uintptr_t)arg); + ret = lm92_readid(priv, ptr); + sndbg("id: %04x ret: %d\n", *ptr, ret); + } + break; + + default: + sndbg("Unrecognized cmd: %d\n", cmd); + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lm92_register + * + * Description: + * Register the LM92 character device as 'devpath' + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/temp0". + * i2c - An instance of the I2C interface to use to communicate + * with the LM92. + * addr - The I2C address of the LM92. The base I2C address of the LM92 + * is 0x48. Bits 0-2 can be controlled to get 4 unique addresses + * from 0x48 through 0x4b. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int lm92_register(FAR const char *devpath, FAR struct i2c_dev_s *i2c, + uint8_t addr) +{ + FAR struct lm92_dev_s *priv; + int ret; + + /* Initialize the LM92 device structure */ + + priv = (FAR struct lm92_dev_s *)kmm_malloc(sizeof(struct lm92_dev_s)); + if (!priv) + { + sndbg("Failed to allocate instance\n"); + return -ENOMEM; + } + + priv->i2c = i2c; + priv->addr = addr; + priv->fahrenheit = false; + + /* Register the character driver */ + + ret = register_driver(devpath, &g_lm92fops, 0666, priv); + if (ret < 0) + { + sndbg("Failed to register driver: %d\n", ret); + kmm_free(priv); + } + + return ret; +} +#endif /* CONFIG_I2C && CONFIG_LM92 */ diff --git a/include/nuttx/sensors/lm92.h b/include/nuttx/sensors/lm92.h new file mode 100644 index 00000000000..7db294dfdf0 --- /dev/null +++ b/include/nuttx/sensors/lm92.h @@ -0,0 +1,150 @@ +/**************************************************************************** + * include/nuttx/sensors/lm92.h + * + * Copyright (C) 2011-2012, 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2015 Alexandru Duru. All rights reserved. + * Author: Gregory Nutt + * Alexandru Duru + * + * 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_SENSORS_LM92_H +#define __INCLUDE_NUTTX_SENSORS_LM92_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************ + * CONFIG_I2C - Enables support for I2C drivers + * CONFIG_LM92 - Enables support for the LM92 driver + */ + +#define CONFIG_LM92_BASEADDR 0x48 +#define CONFIG_LM92_ADDR0 (CONFIG_LM92_BASEADDR + 0) +#define CONFIG_LM92_ADDR1 (CONFIG_LM92_BASEADDR + 1) +#define CONFIG_LM92_ADDR2 (CONFIG_LM92_BASEADDR + 2) +#define CONFIG_LM92_ADDR3 (CONFIG_LM92_BASEADDR + 3) + +/* IOCTL Commands ***********************************************************/ + +#define SNIOC_READCONF _SNIOC(0x0001) /* Arg: uint8_t* pointer */ +#define SNIOC_WRITECONF _SNIOC(0x0002) /* Arg: uint8_t value */ +#define SNIOC_SHUTDOWN _SNIOC(0x0003) /* Arg: None */ +#define SNIOC_POWERUP _SNIOC(0x0004) /* Arg: None */ +#define SNIOC_FAHRENHEIT _SNIOC(0x0005) /* Arg: None */ +#define SNIOC_CENTIGRADE _SNIOC(0x0006) /* Arg: None */ +#define SNIOC_READTHYS _SNIOC(0x0007) /* Arg: b16_t* pointer */ +#define SNIOC_WRITETHYS _SNIOC(0x0008) /* Arg: b16_t value */ +#define SNIOC_READTCRIT _SNIOC(0x0009) /* Arg: b16_t* pointer */ +#define SNIOC_WRITETCRIT _SNIOC(0x000a) /* Arg: b16_t value */ +#define SNIOC_READTLOW _SNIOC(0x000b) /* Arg: b16_t* pointer */ +#define SNIOC_WRITETLOW _SNIOC(0x000c) /* Arg: b16_t value */ +#define SNIOC_READTHIGH _SNIOC(0x000d) /* Arg: b16_t* pointer */ +#define SNIOC_WRITETHIGH _SNIOC(0x000e) /* Arg: b16_t value */ +#define SNIOC_READID _SNIOC(0x000f) /* Arg: uint16_t* pointer */ + +/* LM92 Register Definitions ***********************************************/ +/* LM92 Register Addresses */ + +#define LM92_TEMP_REG 0x00 /* Temperature Register */ +#define LM92_CONF_REG 0x01 /* Configuration Register */ +#define LM92_THYS_REG 0x02 /* Temperature Register */ +#define LM92_TCRIT_REG 0x03 /* Critical Temperature Register */ +#define LM92_TLOW_REG 0x04 /* Low Temperature Register */ +#define LM92_THIGH_REG 0x05 /* High Temperature Register */ +#define LM92_ID_REG 0x07 /* Manufacturer's Identification Register */ + +/* Configuration Register Bit Definitions */ + +#define LM92_CONF_SHUTDOWN (1 << 0) /* Bit 0: Put LM92 goes in low power shutdown mode */ +#define LM92_CONF_INTMODE (1 << 1) /* Bit 1: 0=Comparator 1=Interrupt mode */ +#define LM92_CONF_TCRITPOLARITY (1 << 2) /* Bit 2: 0=Active low 1=Active high */ +#define LM92_CONF_INTPOLARITY (1 << 3) /* Bit 3: 0=Active low 1=Active high */ +#define LM92_CONF_FAULTQ (1 << 4) /* Bit 4: 0=Disabled 1=Enabled */ + +/* NOTE: When temperature values are read, they are returned as b16_t, fixed + * precision integer values (see include/fixedmath.h). + */ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: lm92_register + * + * Description: + * Register the LM92 character device as 'devpath' + * + * Input Parameters: + * devpath - The full path to the driver to register. E.g., "/dev/temp0". + * i2c - An instance of the I2C interface to use to communicate + * with the LM92. + * addr - The I2C address of the LM92. The base I2C address of the LM92 + * is 0x48. Bits 0-2 can be controlled to get 4 unique addresses + * from 0x48 through 0x4b. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int lm92_register(FAR const char *devpath, FAR struct i2c_dev_s *i2c, + uint8_t addr); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_SENSORS_LM92_H */ From 6d59603610f6632b55f849d27b233cb09b5b1141 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 6 Aug 2015 16:33:02 -0600 Subject: [PATCH 17/35] Trivial updates from review of LM92 driver; Update ChangeLog --- ChangeLog | 5 +++-- drivers/sensors/Kconfig | 10 +++++----- drivers/sensors/Make.defs | 1 + 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index d344d1e241d..8893499c999 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10786,5 +10786,6 @@ conversions needed for CAN FD mode (2015-08-05). * arch/arm/src/samv7: Add an MCAN driver for the SAMV7 platform (2015-08-06). - - + * drivers/sensors/lm92.c and include/nuttx/sensors/lm92.h: Add a driver + for the LM92 temperature sensor. Contributed by Paul Patience + (2015-08-06). diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index 66c25c770bd..98de706814a 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -80,11 +80,11 @@ config LM75 the TI TMP100/101. config LM92 - bool "TI LM92 Temperature Sensor support" - default n - select I2C - ---help--- - Enable driver support for the TI LM92 Temperature Sensor. + bool "TI LM92 Temperature Sensor support" + default n + select I2C + ---help--- + Enable driver support for the TI LM92 Temperature Sensor. config QENCODER bool "Qencoder" diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs index 1f369e801c8..1b34e93f613 100644 --- a/drivers/sensors/Make.defs +++ b/drivers/sensors/Make.defs @@ -64,6 +64,7 @@ endif ifeq ($(CONFIG_LM92),y) CSRCS += lm92.c endif + endif # CONFIG_I2C # These drivers depend on SPI support From 2591b2b1984e0753ab72cb1757c13e4c9d944542 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 7 Aug 2015 08:24:12 -0600 Subject: [PATCH 18/35] CAN: Extend new filter IOCTLs to support message prioritization and additional filter modes --- arch | 2 +- include/nuttx/can.h | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/arch b/arch index 5102f815891..6734df2a2a8 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 5102f815891b899f87a718ab85d3913015a015ea +Subproject commit 6734df2a2a8460bed878a7a060134e7849a66055 diff --git a/include/nuttx/can.h b/include/nuttx/can.h index 2787750acec..1a1f20feb0f 100644 --- a/include/nuttx/can.h +++ b/include/nuttx/can.h @@ -106,7 +106,12 @@ /* CAN message support */ -#define CAN_MAXDATALEN 8 +#ifdef CONFIG_CAN_FD +# define CAN_MAXDATALEN 64 +#else +# define CAN_MAXDATALEN 8 +#endif + #define CAN_MAX_MSGID 0x07ff #define CAN_MAX_EXTMSGID 0x1fffffff @@ -167,6 +172,20 @@ #define CANIOC_USER _CANIOC(6) +/* Some CAN hardware supports a notion of prioritizing messages that match filters. + * Only two priority levels are currently supported and are encoded as defined + * below: + */ + +#define CAN_MSGPRIO_LOW 0 +#define CAN_MSGPRIO_HIGH 1 + +/* Filter type */ + +#define CAN_FILTER_DUAL 0 /* Dual address match */ +#define CAN_FILTER_MASK 1 /* Address match under a mask */ +#define CAN_FILTER_RANGE 2 /* Match a range of addresses */ + /************************************************************************************ * Public Types ************************************************************************************/ @@ -350,14 +369,22 @@ struct canioc_rtr_s #ifdef CONFIG_CAN_EXTID struct canioc_extfilter_s { - uint32_t xf_id; /* 29-bit ID (3-bits unused) */ - uint32_t xf_mask; /* 29-bit address mask (3-bits unused) */ + uint32_t xf_id1; /* 29-bit ID. For dual match or for the + * lower address in a range of addresses */ + uint32_t xf_id2; /* 29-bit ID. For dual match, address mask + * or for upper address in address range */ + uint8_t xf_type; /* See CAN_FILTER_* definitions */ + uint8_t xf_prio; /* See CAN_MSGPRIO_* definitions */ }; #else struct canioc_stdfilter_s { - uint16_t sf_id; /* 11-bit ID (5-bits unused) */ - uint16_t sf_mask; /* 11-bit address mask (5-bits unused) */ + uint16_t sf_id1; /* 11-bit ID. For dual match or for the + * lower address in a range of addresses */ + uint16_t sf_id2; /* 11-bit ID. For dual match, address mask + * or for upper address in address range */ + uint8_t sf_type; /* See CAN_FILTER_* definitions */ + uint8_t sf_prio; /* See CAN_MSGPRIO_* definitions */ }; #endif From f7b64b1bfc0b1826c5d7b2baedf197351b0017d4 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 7 Aug 2015 09:02:12 -0600 Subject: [PATCH 19/35] can.h: Mostly cosmetic cleanup --- arch | 2 +- include/nuttx/can.h | 68 +++++++++++++++++++++++---------------------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/arch b/arch index 6734df2a2a8..7cf7436760f 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 6734df2a2a8460bed878a7a060134e7849a66055 +Subproject commit 7cf7436760f09d9ee5f76e049d07ced4f940884f diff --git a/include/nuttx/can.h b/include/nuttx/can.h index 1a1f20feb0f..3235b9de544 100644 --- a/include/nuttx/can.h +++ b/include/nuttx/can.h @@ -91,32 +91,7 @@ # define CONFIG_CAN_NPENDINGRTR 255 #endif -/* Convenience macros */ - -#define dev_reset(dev) dev->cd_ops->co_reset(dev) -#define dev_setup(dev) dev->cd_ops->co_setup(dev) -#define dev_shutdown(dev) dev->cd_ops->co_shutdown(dev) -#define dev_txint(dev,enable) dev->cd_ops->co_txint(dev,enable) -#define dev_rxint(dev,enable) dev->cd_ops->co_rxint(dev,enable) -#define dev_ioctl(dev,cmd,arg) dev->cd_ops->co_ioctl(dev,cmd,arg) -#define dev_remoterequest(dev,id) dev->cd_ops->co_remoterequest(dev,id) -#define dev_send(dev,m) dev->cd_ops->co_send(dev,m) -#define dev_txready(dev) dev->cd_ops->co_txready(dev) -#define dev_txempty(dev) dev->cd_ops->co_txempty(dev) - -/* CAN message support */ - -#ifdef CONFIG_CAN_FD -# define CAN_MAXDATALEN 64 -#else -# define CAN_MAXDATALEN 8 -#endif - -#define CAN_MAX_MSGID 0x07ff -#define CAN_MAX_EXTMSGID 0x1fffffff - -#define CAN_MSGLEN(nbytes) (sizeof(struct can_msg_s) - CAN_MAXDATALEN + (nbytes)) - +/* Ioctl Commands *******************************************************************/ /* Ioctl commands supported by the upper half CAN driver. * * CANIOC_RTR: @@ -172,6 +147,33 @@ #define CANIOC_USER _CANIOC(6) +/* Convenience macros ***************************************************************/ + +#define dev_reset(dev) dev->cd_ops->co_reset(dev) +#define dev_setup(dev) dev->cd_ops->co_setup(dev) +#define dev_shutdown(dev) dev->cd_ops->co_shutdown(dev) +#define dev_txint(dev,enable) dev->cd_ops->co_txint(dev,enable) +#define dev_rxint(dev,enable) dev->cd_ops->co_rxint(dev,enable) +#define dev_ioctl(dev,cmd,arg) dev->cd_ops->co_ioctl(dev,cmd,arg) +#define dev_remoterequest(dev,id) dev->cd_ops->co_remoterequest(dev,id) +#define dev_send(dev,m) dev->cd_ops->co_send(dev,m) +#define dev_txready(dev) dev->cd_ops->co_txready(dev) +#define dev_txempty(dev) dev->cd_ops->co_txempty(dev) + +/* CAN message support **************************************************************/ + +#ifdef CONFIG_CAN_FD +# define CAN_MAXDATALEN 64 +#else +# define CAN_MAXDATALEN 8 +#endif + +#define CAN_MAX_STDMSGID 0x07ff +#define CAN_MAX_EXTMSGID 0x1fffffff + +#define CAN_MSGLEN(nbytes) (sizeof(struct can_msg_s) - CAN_MAXDATALEN + (nbytes)) + +/* CAN filter support ***************************************************************/ /* Some CAN hardware supports a notion of prioritizing messages that match filters. * Only two priority levels are currently supported and are encoded as defined * below: @@ -180,35 +182,35 @@ #define CAN_MSGPRIO_LOW 0 #define CAN_MSGPRIO_HIGH 1 -/* Filter type */ +/* Filter type. Not all CAN hardware will support all filter types. */ -#define CAN_FILTER_DUAL 0 /* Dual address match */ -#define CAN_FILTER_MASK 1 /* Address match under a mask */ +#define CAN_FILTER_MASK 0 /* Address match under a mask */ +#define CAN_FILTER_DUAL 1 /* Dual address match */ #define CAN_FILTER_RANGE 2 /* Match a range of addresses */ /************************************************************************************ * Public Types ************************************************************************************/ -/* CAN-message Format (without Extended ID suppport) +/* CAN-message Format (without Extended ID support) * * One based CAN-message is represented with a maximum of 10 bytes. A message is * composed of at least the first 2 bytes (when there are no data bytes present). * * Bytes 0-1: Hold a 16-bit value in host byte order * Bits 0-3: Data Length Code (DLC) - * Bit 4: Remote Tranmission Request (RTR) + * Bit 4: Remote Transmission Request (RTR) * Bits 5-15: The 11-bit CAN identifier * * Bytes 2-9: CAN data * - * CAN-message Format (with Extended ID suppport) + * CAN-message Format (with Extended ID support) * * One CAN-message consists of a maximum of 13 bytes. A message is composed of at * least the first 5 bytes (when there are no data bytes). * * Bytes 0-3: Hold 11- or 29-bit CAN ID in host byte order * Byte 4: Bits 0-3: Data Length Code (DLC) - * Bit 4: Remote Tranmission Request (RTR) + * Bit 4: Remote Transmission Request (RTR) * Bit 5: Extended ID indication * Bits 6-7: Unused * Bytes 5-12: CAN data From 834e01ea7c0bb786cb43366458121573db1d632c Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 7 Aug 2015 11:41:31 -0600 Subject: [PATCH 20/35] can.c: Fix a couple of missed DLC conversions --- drivers/can.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/can.c b/drivers/can.c index f1eb4d195a8..f37557205bd 100644 --- a/drivers/can.c +++ b/drivers/can.c @@ -911,10 +911,14 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr, if (msg && hdr->ch_id == rtr->cr_id) { + int nbytes; + /* We have the response... copy the data to the user's buffer */ memcpy(&msg->cm_hdr, hdr, sizeof(struct can_hdr_s)); - for (i = 0, dest = msg->cm_data; i < hdr->ch_dlc; i++) + + nbytes = can_dlc2bytes(hdr->ch_dlc); + for (i = 0, dest = msg->cm_data; i < nbytes; i++) { *dest++ = *data++; } @@ -935,6 +939,8 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr, if (nexttail != fifo->rx_head) { + int nbytes; + /* Add the new, decoded CAN message at the tail of the FIFO. * * REVISIT: In the CAN FD format, the coding of the DLC differs from @@ -946,7 +952,9 @@ int can_receive(FAR struct can_dev_s *dev, FAR struct can_hdr_s *hdr, */ memcpy(&fifo->rx_buffer[fifo->rx_tail].cm_hdr, hdr, sizeof(struct can_hdr_s)); - for (i = 0, dest = fifo->rx_buffer[fifo->rx_tail].cm_data; i < hdr->ch_dlc; i++) + + nbytes = can_dlc2bytes(hdr->ch_dlc); + for (i = 0, dest = fifo->rx_buffer[fifo->rx_tail].cm_data; i < nbytes; i++) { *dest++ = *data++; } From 0dacef7562e1b61e780424316dd1874e87fbb3be Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 7 Aug 2015 12:31:33 -0600 Subject: [PATCH 21/35] Update submodules --- arch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch b/arch index 7cf7436760f..451478b9366 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 7cf7436760f09d9ee5f76e049d07ced4f940884f +Subproject commit 451478b9366f065d65e08489fa554668c65c2d47 From b7e0fc34c5343464f5d76e58b5dd425b70f7dd8c Mon Sep 17 00:00:00 2001 From: "Paul A. Patience" Date: Fri, 7 Aug 2015 10:24:29 -0400 Subject: [PATCH 22/35] Added AS5048B magnetic rotary encoder. --- drivers/sensors/Kconfig | 7 + drivers/sensors/Make.defs | 4 + drivers/sensors/as5048b.c | 616 ++++++++++++++++++++++++++++++++ include/nuttx/sensors/as5048b.h | 136 +++++++ 4 files changed, 763 insertions(+) create mode 100644 drivers/sensors/as5048b.c create mode 100644 include/nuttx/sensors/as5048b.h diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig index 98de706814a..19bdedae26d 100644 --- a/drivers/sensors/Kconfig +++ b/drivers/sensors/Kconfig @@ -3,6 +3,13 @@ # see the file kconfig-language.txt in the NuttX tools repository. # +config AS5048B + bool "AMS AS5048B Magnetic Rotary Encoder support" + default n + select I2C + ---help--- + Enable driver support for the AMS AS5048B magnetic rotary encoder. + config BMP180 bool "Bosch BMP180 Barometer Sensor support" default n diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs index 1b34e93f613..0d86e8e9f7a 100644 --- a/drivers/sensors/Make.defs +++ b/drivers/sensors/Make.defs @@ -45,6 +45,10 @@ endif ifeq ($(CONFIG_I2C),y) +ifeq ($(CONFIG_AS5048B),y) + CSRCS += as5048b.c +endif + ifeq ($(CONFIG_LIS331DL),y) CSRCS += lis331dl.c endif diff --git a/drivers/sensors/as5048b.c b/drivers/sensors/as5048b.c new file mode 100644 index 00000000000..ffa96a47f21 --- /dev/null +++ b/drivers/sensors/as5048b.c @@ -0,0 +1,616 @@ +/**************************************************************************** + * drivers/sensors/as5048b.c + * Character driver for the AMS AS5048B Magnetic Rotary Encoder + * + * Copyright (C) 2015 Alexandru Duru. All rights reserved. + * Author: Alexandru Duru + * + * 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 + +#if defined(CONFIG_I2C) && defined(CONFIG_AS5048B) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct as5048b_dev_s +{ + FAR struct i2c_dev_s *i2c; /* I2C interface */ + uint8_t addr; /* I2C address */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ +/* I2C Helpers */ + +static int as5048b_readb8(FAR struct as5048b_dev_s *priv, uint8_t regaddr, + FAR uint8_t *regval); +static int as5048b_readb16(FAR struct as5048b_dev_s *priv, uint8_t regaddrhi, + uint8_t regaddrlo, FAR uint16_t *regval); +static int as5048b_writeb8(FAR struct as5048b_dev_s *priv, uint8_t regaddr, + uint8_t regval); +static int as5048b_writeb16(FAR struct as5048b_dev_s *priv, uint8_t regaddrhi, + uint8_t regaddrlo, uint16_t regval); +static int as5048b_readzero(FAR struct as5048b_dev_s *priv, + FAR uint16_t *zero); +static int as5048b_writezero(FAR struct as5048b_dev_s *priv, uint16_t zero); +static int as5048b_readagc(FAR struct as5048b_dev_s *priv, FAR uint8_t *agc); +static int as5048b_readdiag(FAR struct as5048b_dev_s *priv, + FAR uint8_t *diag); +static int as5048b_readmag(FAR struct as5048b_dev_s *priv, FAR uint16_t *mag); +static int as5048b_readang(FAR struct as5048b_dev_s *priv, FAR uint16_t *ang); + +/* Character Driver Methods */ + +static int as5048b_open(FAR struct file *filep); +static int as5048b_close(FAR struct file *filep); +static ssize_t as5048b_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t as5048b_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +static int as5048b_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_as5048bfops = +{ + as5048b_open, + as5048b_close, + as5048b_read, + as5048b_write, + NULL, + as5048b_ioctl +#ifndef CONFIG_DISABLE_POLL + , NULL +#endif +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: as5048b_readb8 + * + * Description: + * Read from an 8-bit register + * + ****************************************************************************/ + +static int as5048b_readb8(FAR struct as5048b_dev_s *priv, uint8_t regaddr, + FAR uint8_t *regval) +{ + uint8_t buffer; + int ret; + + /* Write the register address */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + ret = I2C_WRITE(priv->i2c, ®addr, sizeof(regaddr)); + if (ret < 0) + { + sndbg("I2C_WRITE failed: %d\n", ret); + return ret; + } + + /* Restart and read 8 bits from the register */ + + ret = I2C_READ(priv->i2c, &buffer, sizeof(buffer)); + if (ret < 0) + { + sndbg("I2C_READ failed: %d\n", ret); + return ret; + } + + *regval = buffer; + sndbg("addr: %02x value: %02x ret: %d\n", regaddr, *regval, ret); + return ret; +} + +/**************************************************************************** + * Name: as5048b_readb16 + * + * Description: + * Read from two 8-bit registers + * + ****************************************************************************/ + +static int as5048b_readb16(FAR struct as5048b_dev_s *priv, uint8_t regaddrhi, + uint8_t regaddrlo, FAR uint16_t *regval) +{ + uint8_t hi, lo; + int ret; + + /* Read the high 8 bits of the 13-bit value */ + + ret = as5048b_readb8(priv, regaddrhi, &hi); + if (ret < 0) + { + sndbg("as5048b_readb8 failed: %d\n", ret); + return ret; + } + + /* Read the low 5 bits of the 13-bit value */ + + ret = as5048b_readb8(priv, regaddrlo, &lo); + if (ret < 0) + { + sndbg("as5048b_readb8 failed: %d\n", ret); + return ret; + } + + *regval = (uint16_t)hi << 6 | (uint16_t)lo; + sndbg("addrhi: %02x addrlo: %02x value: %04x ret: %d\n", + regaddrhi, regaddrlo, *regval, ret); + return ret; +} + +/**************************************************************************** + * Name: as5048b_writeb8 + * + * Description: + * Write from an 8-bit register + * + ****************************************************************************/ + +static int as5048b_writeb8(FAR struct as5048b_dev_s *priv, uint8_t regaddr, + uint8_t regval) +{ + uint8_t buffer[2]; + int ret; + + sndbg("addr: %02x value: %02x\n", regaddr, regval); + + /* Set up a 2-byte message to send */ + + buffer[0] = regaddr; + buffer[1] = regval; + + /* Write the register address followed by the data (no RESTART) */ + + I2C_SETADDRESS(priv->i2c, priv->addr, 7); + ret = I2C_WRITE(priv->i2c, buffer, sizeof(buffer)); + if (ret < 0) + { + sndbg("I2C_WRITE failed: %d\n", ret); + } + + return ret; +} + +/**************************************************************************** + * Name: as5048b_writeb16 + * + * Description: + * Write to two 8-bit registers + * + ****************************************************************************/ + +static int as5048b_writeb16(FAR struct as5048b_dev_s *priv, uint8_t regaddrhi, + uint8_t regaddrlo, uint16_t regval) +{ + int ret; + + sndbg("addrhi: %02x addrlo: %02x value: %04x\n", + regaddrhi, regaddrlo, regval); + + /* Write the high 8 bits of the 13-bit value */ + + ret = as5048b_writeb8(priv, regaddrhi, (uint8_t)(regval >> 6)); + if (ret < 0) + { + sndbg("as5048b_writeb8 failed: %d\n", ret); + return ret; + } + + /* Write the low 5 bits of the 13-bit value */ + + ret = as5048b_writeb8(priv, regaddrhi, (uint8_t)regval); + if (ret < 0) + { + sndbg("as5048b_writeb8 failed: %d\n", ret); + } + + return ret; +} + +/**************************************************************************** + * Name: as5048b_readzero + * + * Description: + * Read from the zero position registers + * + ****************************************************************************/ + +static int as5048b_readzero(FAR struct as5048b_dev_s *priv, + FAR uint16_t *zero) +{ + uint16_t buffer; + int ret; + + ret = as5048b_readb16(priv, AS5048B_ZEROHI_REG, AS5048B_ZEROLO_REG, + &buffer); + if (ret < 0) + { + sndbg("as5048b_readb16 failed: %d\n", ret); + return ret; + } + + *zero = buffer; + sndbg("zero: %04x ret: %d\n", *zero, ret); + return ret; +} + +/**************************************************************************** + * Name: as5048b_writezero + * + * Description: + * Write to the zero position registers + * + ****************************************************************************/ + +static int as5048b_writezero(FAR struct as5048b_dev_s *priv, uint16_t zero) +{ + int ret; + + sndbg("zero: %04x\n", zero); + + ret = as5048b_writeb16(priv, AS5048B_ZEROHI_REG, AS5048B_ZEROLO_REG, zero); + if (ret < 0) + { + sndbg("as5048b_writeb16 failed: %d\n", ret); + } + + return ret; +} + +/**************************************************************************** + * Name: as5048b_readagc + * + * Description: + * Read from the automatic gain control register + * + ****************************************************************************/ + +static int as5048b_readagc(FAR struct as5048b_dev_s *priv, FAR uint8_t *agc) +{ + uint8_t buffer; + int ret; + + ret = as5048b_readb8(priv, AS5048B_AGC_REG, &buffer); + if (ret < 0) + { + sndbg("as5048b_readb8 failed: %d\n", ret); + return ret; + } + + *agc = buffer; + sndbg("agc: %02x ret: %d\n", *agc, ret); + return ret; +} + +/**************************************************************************** + * Name: as5048b_readdiag + * + * Description: + * Read from the diagnostics register + * + ****************************************************************************/ + +static int as5048b_readdiag(FAR struct as5048b_dev_s *priv, FAR uint8_t *diag) +{ + uint8_t buffer; + int ret; + + ret = as5048b_readb8(priv, AS5048B_DIAG_REG, &buffer); + if (ret < 0) + { + sndbg("as5048b_readb8 failed: %d\n", ret); + return ret; + } + + *diag = buffer; + sndbg("diag: %02x ret: %d\n", *diag, ret); + return ret; +} + +/**************************************************************************** + * Name: as5048b_readmag + * + * Description: + * Read from the magnitude registers + * + ****************************************************************************/ + +static int as5048b_readmag(FAR struct as5048b_dev_s *priv, FAR uint16_t *mag) +{ + uint16_t buffer; + int ret; + + ret = as5048b_readb16(priv, AS5048B_MAGHI_REG, AS5048B_MAGLO_REG, &buffer); + if (ret < 0) + { + sndbg("as5048b_readb16 failed: %d\n", ret); + return ret; + } + + *mag = buffer; + sndbg("mag: %04x ret: %d\n", *mag, ret); + return ret; +} + +/**************************************************************************** + * Name: as5048b_readang + * + * Description: + * Read from the angle registers + * + ****************************************************************************/ + +static int as5048b_readang(FAR struct as5048b_dev_s *priv, FAR uint16_t *ang) +{ + uint16_t buffer; + int ret; + + ret = as5048b_readb16(priv, AS5048B_ANGHI_REG, AS5048B_ANGLO_REG, &buffer); + if (ret < 0) + { + sndbg("as5048b_readb16 failed: %d\n", ret); + return ret; + } + + *ang = buffer; + sndbg("ang: %04x ret: %d\n", *ang, ret); + return ret; +} + +/**************************************************************************** + * Name: as5048b_open + * + * Description: + * This function is called whenever the device is opened + * + ****************************************************************************/ + +static int as5048b_open(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: as5048b_close + * + * Description: + * This function is called whenever the device is closed + * + ****************************************************************************/ + +static int as5048b_close(FAR struct file *filep) +{ + return OK; +} + +/**************************************************************************** + * Name: as5048b_read + ****************************************************************************/ + +static ssize_t as5048b_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct as5048b_dev_s *priv = inode->i_private; + FAR uint16_t *ptr; + ssize_t nsamples; + ssize_t i; + int ret; + + /* How many samples were requested? */ + + ptr = (FAR uint16_t *)buffer; + nsamples = buflen / sizeof(*ptr); + + sndbg("buflen: %u nsamples: %d\n", buflen, nsamples); + + /* Get the requested number of samples */ + + for (i = 0; i < nsamples; i++) + { + uint16_t ang = 0; + + /* Read the next uint16_t angle value */ + + ret = as5048b_readang(priv, &ang); + if (ret < 0) + { + sndbg("as5048b_readang failed: %d\n", ret); + return (ssize_t)ret; + } + + /* Save the angle value in the user buffer */ + + *ptr++ = ang; + } + + return nsamples * sizeof(*ptr); +} + +/**************************************************************************** + * Name: as5048b_write + ****************************************************************************/ + +static ssize_t as5048b_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + return -ENOSYS; +} + +/**************************************************************************** + * Name: as5048b_ioctl + ****************************************************************************/ + +static int as5048b_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct as5048b_dev_s *priv = inode->i_private; + int ret = OK; + + switch (cmd) + { + /* Read from the zero position registers. Arg: uint16_t* pointer. */ + + case SNIOC_READZERO: + { + FAR uint16_t *ptr = (FAR uint16_t *)((uintptr_t)arg); + ret = as5048b_readzero(priv, ptr); + sndbg("zero: %04x ret: %d\n", *ptr, ret); + } + break; + + /* Write to the zero position registers. Arg: uint16_t value. */ + + case SNIOC_WRITEZERO: + ret = as5048b_writezero(priv, (uint16_t)arg); + sndbg("zero: %04x ret: %d\n", *(uint16_t *)arg, ret); + break; + + /* Read from the automatic gain control register. Arg: uint8_t* pointer. */ + + case SNIOC_READAGC: + { + FAR uint8_t *ptr = (FAR uint8_t *)((uintptr_t)arg); + ret = as5048b_readagc(priv, ptr); + sndbg("agc: %02x ret: %d\n", *ptr, ret); + } + break; + + /* Read from the diagnostics register. Arg: uint8_t* pointer. */ + + case SNIOC_READDIAG: + { + FAR uint8_t *ptr = (FAR uint8_t *)((uintptr_t)arg); + ret = as5048b_readdiag(priv, ptr); + sndbg("diag: %02x ret: %d\n", *ptr, ret); + } + break; + + /* Read from the magnitude registers. Arg: uint16_t* pointer. */ + + case SNIOC_READMAG: + { + FAR uint16_t *ptr = (FAR uint16_t *)((uintptr_t)arg); + ret = as5048b_readmag(priv, ptr); + sndbg("mag: %04x ret: %d\n", *ptr, ret); + } + break; + + default: + sndbg("Unrecognized cmd: %d\n", cmd); + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: as5048b_register + * + * Description: + * Register the AS5048B character device as 'devpath'. + * + * Input Parameters: + * devpath - The full path to the driver to register, + * for example "/dev/angle0". + * i2c - An instance of the I2C interface to use to communicate + * with the AS5048B. + * addr - The I2C address of the AS5048B. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int as5048b_register(FAR const char *devpath, FAR struct i2c_dev_s *i2c, + uint8_t addr) +{ + FAR struct as5048b_dev_s *priv; + int ret; + + /* Initialize the device's structure */ + + priv = (FAR struct as5048b_dev_s *)kmm_malloc(sizeof(*priv)); + if (priv == NULL) + { + sndbg("Failed to allocate instance\n"); + return -ENOMEM; + } + + priv->i2c = i2c; + priv->addr = addr; + + /* Register the character driver */ + + ret = register_driver(devpath, &g_as5048bfops, 0666, priv); + if (ret < 0) + { + sndbg("Failed to register driver: %d\n", ret); + kmm_free(priv); + } + + return ret; +} + +#endif /* CONFIG_I2C && CONFIG_AS5048B */ diff --git a/include/nuttx/sensors/as5048b.h b/include/nuttx/sensors/as5048b.h new file mode 100644 index 00000000000..6e8c0c3aaed --- /dev/null +++ b/include/nuttx/sensors/as5048b.h @@ -0,0 +1,136 @@ +/**************************************************************************** + * include/nuttx/sensors/as5048b.h + * + * Copyright (C) 2015 Alexandru Duru. All rights reserved. + * Author: Alexandru Duru + * + * 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_SENSORS_AS5048B +#define __INCLUDE_NUTTX_SENSORS_AS5048B + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************ + * Prerequisites: + * + * CONFIG_I2C + * Enables support for I2C drivers + * CONFIG_AS5048B + * Enables support for the AS5048B driver + */ + +/* IOCTL Commands ***********************************************************/ + +#define SNIOC_READZERO _SNIOC(0x0001) /* Arg: uint16_t* pointer */ +#define SNIOC_WRITEZERO _SNIOC(0x0002) /* Arg: uint16_t value */ +#define SNIOC_READAGC _SNIOC(0x0004) /* Arg: uint8_t* pointer */ +#define SNIOC_READDIAG _SNIOC(0x0005) /* Arg: uint8_t* pointer */ +#define SNIOC_READMAG _SNIOC(0x0006) /* Arg: uint16_t* pointer */ + +/* Resolution ***************************************************************/ + +#define AS5048B_MAX 0x3fff /* Maximum value (14 bits) */ + +/* Register Definitions *****************************************************/ +/* Register Addresses */ + +#define AS5048B_PROG_REG 0x03 /* Programming Control Register */ +#define AS5048B_ADDR_REG 0x15 /* I2C Slave Address Register */ +#define AS5048B_ZEROLO_REG 0x16 /* Zero Position Register Bits 0 to 5 */ +#define AS5048B_ZEROHI_REG 0x17 /* Zero Position Register Bits 6 to 13 */ +#define AS5048B_AGC_REG 0xfa /* Automatic Gain Control Register */ +#define AS5048B_DIAG_REG 0xfb /* Diagnostics Register */ +#define AS5048B_MAGLO_REG 0xfc /* Magnitude Register Bits 0 to 5 */ +#define AS5048B_MAGHI_REG 0xfd /* Magnitude Register Bits 6 to 13 */ +#define AS5048B_ANGLO_REG 0xfe /* Angle Register Bits 0 to 5 */ +#define AS5048B_ANGHI_REG 0xff /* Angle Register Bits 6 to 13 */ + +/* Programming Control Register Bit Definitions */ + +#define AS5048B_PROG_ENABLE (1 << 0) +#define AS5048B_PROG_BURN (1 << 3) +#define AS5048B_PROG_VERIFY (1 << 6) + +/* Diagnostics Register Bit Definitions */ + +#define AS5048B_DIAG_OCF (1 << 0) /* Offset Compensation Finished */ +#define AS5048B_DIAG_COF (1 << 1) /* Cordic Overflow */ +#define AS5048B_DIAG_COMPLOW (1 << 2) /* High Magnetic Field */ +#define AS5048B_DIAG_COMPHIGH (1 << 3) /* Low Magnetic Field */ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: as5048b_register + * + * Description: + * Register the AS5048B character device as 'devpath'. + * + * Input Parameters: + * devpath - The full path to the driver to register, + * for example "/dev/angle0". + * i2c - An instance of the I2C interface to use to communicate + * with the AS5048B. + * addr - The I2C address of the AS5048B. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int as5048b_register(FAR const char *devpath, FAR struct i2c_dev_s *i2c, + uint8_t addr); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NUTTX_SENSORS_AS5048B */ From fcf1743c0ad31643be72f3452f2ee82e5fb9b59e Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 7 Aug 2015 15:45:57 -0600 Subject: [PATCH 23/35] Update ChangeLog --- ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8893499c999..67e3fc17590 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10789,3 +10789,7 @@ * drivers/sensors/lm92.c and include/nuttx/sensors/lm92.h: Add a driver for the LM92 temperature sensor. Contributed by Paul Patience (2015-08-06). + * drivers/sensors/as5048b.c and include/nuttx/sensors/as5048b.h: Add + support for an AS5048B rotary magnetic sensor. From Paul Patience + (2015-08-06). + From 567f1f4b1c472c54a2804d06fc48bf141603c02f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 8 Aug 2015 08:39:56 -0600 Subject: [PATCH 24/35] Resynch submodules --- arch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch b/arch index 451478b9366..23ecc0e1904 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 451478b9366f065d65e08489fa554668c65c2d47 +Subproject commit 23ecc0e19048944ea5391ea72b0c1d2851a66e16 From b6d6776d0226493131363ef180b7d292950db87f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 8 Aug 2015 10:45:15 -0600 Subject: [PATCH 25/35] Add a preliminary definition for an SPI slave interface --- drivers/spi/Kconfig | 17 ++++++++++++++ include/nuttx/spi/spi.h | 50 +++++++++++++++++++++-------------------- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 6bef9b56948..488c08c2513 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -5,6 +5,23 @@ if SPI +config SPI_SLAVE + bool "SPI slave" + default n + ---help--- + Enable support for SPI slave features + +if SPI_SLAVE + +config SPI_SLAVE_DMA + bool "SPI slave DMA" + default n + depends on ARCH_DMA && EXPERIMENTAL + ---help--- + Enable support for DMA data transfers (not yet implemented). + +endif + config SPI_OWNBUS bool "SPI single device" default n diff --git a/include/nuttx/spi/spi.h b/include/nuttx/spi/spi.h index 544afaa3ca8..43aa8e277c7 100644 --- a/include/nuttx/spi/spi.h +++ b/include/nuttx/spi/spi.h @@ -271,7 +271,7 @@ * * Input Parameters: * dev - Device-specific state data - * buffer - A pointer to the buffer in which to recieve data + * buffer - A pointer to the buffer in which to receive data * nwords - the length of data that can be received in the buffer in number * of words. The wordsize is determined by the number of bits- * per-word selected for the SPI interface. If nbits <= 8, the @@ -298,7 +298,7 @@ * Input Parameters: * dev - Device-specific state data * txbuffer - A pointer to the buffer of data to be sent - * rxbuffer - A pointer to the buffer in which to recieve data + * rxbuffer - A pointer to the buffer in which to receive data * nwords - the length of data that to be exchanged in units of words. * The wordsize is determined by the number of bits-per-word * selected for the SPI interface. If nbits <= 8, the data is @@ -324,7 +324,7 @@ * * Input Parameters: * dev - Device-specific state data - * callback - The funtion to call on the media change + * callback - The function to call on the media change * arg - A caller provided value to return with the callback * * Returned Value: @@ -367,7 +367,7 @@ enum spi_dev_e SPIDEV_USER /* Board-specific values start here */ }; -/* Certain SPI devices may required differnt clocking modes */ +/* Certain SPI devices may required different clocking modes */ enum spi_mode_e { @@ -383,29 +383,31 @@ struct spi_dev_s; struct spi_ops_s { #ifndef CONFIG_SPI_OWNBUS - int (*lock)(FAR struct spi_dev_s *dev, bool lock); + CODE int (*lock)(FAR struct spi_dev_s *dev, bool lock); #endif - void (*select)(FAR struct spi_dev_s *dev, enum spi_dev_e devid, - bool selected); - uint32_t (*setfrequency)(FAR struct spi_dev_s *dev, uint32_t frequency); - void (*setmode)(FAR struct spi_dev_s *dev, enum spi_mode_e mode); - void (*setbits)(FAR struct spi_dev_s *dev, int nbits); - uint8_t (*status)(FAR struct spi_dev_s *dev, enum spi_dev_e devid); + CODE void (*select)(FAR struct spi_dev_s *dev, enum spi_dev_e devid, + bool selected); + CODE uint32_t (*setfrequency)(FAR struct spi_dev_s *dev, uint32_t frequency); + CODE void (*setmode)(FAR struct spi_dev_s *dev, enum spi_mode_e mode); + CODE void (*setbits)(FAR struct spi_dev_s *dev, int nbits); + CODE uint8_t (*status)(FAR struct spi_dev_s *dev, enum spi_dev_e devid); #ifdef CONFIG_SPI_CMDDATA - int (*cmddata)(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd); + CODE int (*cmddata)(FAR struct spi_dev_s *dev, enum spi_dev_e devid + bool cmd); #endif - uint16_t (*send)(FAR struct spi_dev_s *dev, uint16_t wd); + CODE uint16_t (*send)(FAR struct spi_dev_s *dev, uint16_t wd); #ifdef CONFIG_SPI_EXCHANGE - void (*exchange)(FAR struct spi_dev_s *dev, FAR const void *txbuffer, - FAR void *rxbuffer, size_t nwords); + CODE void (*exchange)(FAR struct spi_dev_s *dev, + FAR const void *txbuffer, FAR void *rxbuffer, + size_t nwords); #else - void (*sndblock)(FAR struct spi_dev_s *dev, FAR const void *buffer, - size_t nwords); - void (*recvblock)(FAR struct spi_dev_s *dev, FAR void *buffer, - size_t nwords); + CODE void (*sndblock)(FAR struct spi_dev_s *dev, + FAR const void *buffer, size_t nwords); + CODE void (*recvblock)(FAR struct spi_dev_s *dev, FAR void *buffer, + size_t nwords); #endif - int (*registercallback)(FAR struct spi_dev_s *dev, spi_mediachange_t callback, - void *arg); + CODE int (*registercallback)(FAR struct spi_dev_s *dev, + spi_mediachange_t callback, void *arg); }; /* SPI private data. This structure only defines the initial fields of the @@ -454,14 +456,14 @@ extern "C" * * Another example would be the STM32 families that support both SPI * blocks as well as USARTs that can be configured to perform the SPI - * function as well (the STM32 USARTs do not suppor SPI as of this + * function as well (the STM32 USARTs do not support SPI as of this * writing). * * Input Parameter: - * Port number (for hardware that has mutiple SPI interfaces) + * Port number (for hardware that has multiple SPI interfaces) * * Returned Value: - * Valid SPI device structure reference on succcess; a NULL on failure + * Valid SPI device structure reference on success; a NULL on failure * ****************************************************************************/ From 0ce50caa061e3e682acab2d455cd9cc5562ffe6e Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 8 Aug 2015 10:46:13 -0600 Subject: [PATCH 26/35] Forgot to add the main SPI slave interface header file in the last commit --- include/nuttx/spi/slave.h | 330 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 330 insertions(+) create mode 100644 include/nuttx/spi/slave.h diff --git a/include/nuttx/spi/slave.h b/include/nuttx/spi/slave.h new file mode 100644 index 00000000000..3885a05e4c7 --- /dev/null +++ b/include/nuttx/spi/slave.h @@ -0,0 +1,330 @@ +/**************************************************************************** + * include/nuttx/spi/slave.h + * + * Copyright(C) 2015 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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_SPI_SLAVE_H +#define __INCLUDE_NUTTX_SPI_SLAVE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ +/* Configuration ************************************************************/ +/* CONFIG_SPI_SLAVE - Enable support for SPI slave features + * CONFIG_SPI_SLAVE_DMA - Enable support for DMA data transfers (not + * implemented in initial version). + */ + +/* Access macros ************************************************************/ + +/**************************************************************************** + * Name: SPI_SCTRLR_BIND + * + * Description: + * Bind the SPI slave device interface to the SPI slave controller + * interface and configure the SPI interface. Upon return, the + * + * Input Parameters: + * sctrlr - SPI slave controller interface instance + * sdev - SPI slave device interface instance + * mode - The SPI mode requested + * nbits - The number of bits requests. + * If value is greater > 0 then it implies MSB first + * If value is below < 0, then it implies LSB first with -nbits + * + * Returned Value: + * none + * + ****************************************************************************/ + +#define SPI_SCTRLR_BIND(c,d,m,n) ((c)->bind(c,d,m,n)) + +/**************************************************************************** + * Name: SPI_SCTRLR_SET_CMD/SPI_SCTRLR_SET_DATA + * + * Description: + * Set the next value to be shifted out from the interface. This primes + * the controller driver for the next transfer but has no effect on any + * in-process or currently "committed" transfers + * + * Input Parameters: + * sctrlr - SPI slave controller interface instance + * cmd - Command/data mode data value to be shifted out. The width of + * data the data must be the same as the nbits parameter previously + * provided to the bind() methos. + * + * Returned Value: + * none + * + ****************************************************************************/ + +#define SPI_SCTRLR_SET_CMD(c,v) ((c)->set_cmd(c,v)) +#define SPI_SCTRLR_SET_DATA(c,v) ((c)->set_data(c,v)) + +/**************************************************************************** + * Name: SPI_SDEV_SELECTED + * + * Description: + * This is a SPI device callback that used when the SPI device controller + * driver detects any change in the chip select pin. + * + * Input Parameters: + * sdev - SPI device interface instance + * isselected - True: chip select is low (selected); + * + * Returned Value: + * none + * + ****************************************************************************/ + +#define SPI_SDEV_SELECTED(d,i) ((c)->selected(d,i)) + +/**************************************************************************** + * Name: SPI_SDEV_GET_CMD/SPI_SDEV_GET_DATA + * + * Description: + * This is a SPI device callback that used when the SPI device controller + * requires data be shifted out at the next leading clock edge. This + * is necessary to "prime the pump" so that the SPI controller driver + * can keep pace with the shifted-in data. + * + * The SPI controller driver will prime for both command and data + * transfers. Normally only LCD devices distinguish command and data. + * For devices that do not distinguish between command and data, only + * the get_cmd() method is meaningful. In that case the same function + * may be provided for get_cmd() and get_data(). Or get_data() may be + * only a stub that returns zero (it should never be called). + * + * Input Parameters: + * sdev - SPI device interface instance + * + * Returned Value: + * The next data value to be shifted out + * + ****************************************************************************/ + +#define SPI_SDEV_GET_CMD(d,v) ((d)->get_cmd(d,v)) +#define SPI_SDEV_GET_DATA(d,v) ((d)->get_data(d,v)) + +/**************************************************************************** + * Name: SPI_SDEV_EXCHANGE_CMD/SPI_SDEV_EXCHANGE_DATA + * + * Description: + * This is a SPI device callback that used when the SPI device controller + * receives a new value shifted and requires the next value to be shifted- + * out. Notice that these values my be out of synchronization by as much + * as two words: The value to be shifted out may be two words beyond the + * value that was just shifted in. + * + * Normally only LCD devices distinguish command and data. For devices + * that do not distinguish between command and data, only the + * exchange_cmd() method is meaningful. In that case the same function + * may be provided for exchange_cmd() and exchange_data(). Or + * exchange_data() may be simply a stub that discards the shifted in + * value returns zero (it should never be called). + * + * Input Parameters: + * sdev - SPI device interface instance + * cmd - The last command/data value that was shifted in + * data + * + * Returned Value: + * The next data value to be shifted out + * + ****************************************************************************/ + +#define SPI_SDEV_EXCHANGE_CMD(d,v) ((d)->exchange_cmd(d,v)) +#define SPI_SDEV_EXCHANGE_DATA(d,v) ((d)->exchange_data(d,v)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ +/* There are two interfaces defined for the implementation of SPI slave: + * + * 1) struct spi_sctrlr_s - Defines one interface between the SPI + * slave device and the SPI slave controller hardware. This interface + * is implemented by the SPI slave device controller lower-half driver + * and is provided to the the SPI slave device driver when that driver + * is initialization. That SPI slave device initialization function might + * look like: + * + * int xyz_dev_initialize(FAR struct spi_sctrlr_s *sctrlr); + * + * 2) struct spi_sdev_s - Defines the second center between the SPI + * slave device and the SPI slave controller hardware. This interface + * is implemented by the SPI slave device. The slave devices passes this + * interface to the struct spi_sctrlr_s during initialization + * be calling the bind() method of the struct spi_sctrlr_s + * interface. + * + * The basic initialization steps are: + * + * 1) Board-specific logic calls board- or chip-specific logic to create an + * instance of the SPI slave controller interface, struct spi_sctrlr_s. + * 2) Board-specific logic then calls xyz_dev_initialize() to initialize + * the SPI slave device. The board-specific logic passes the instance + * of struct spi_sctrlr_s to support the initialization. + * 3) The SPI slave device driver creates and initializes an instance of + * struct spi_sdev_s; it passes this instance to the bind() method of + * of the SPI slave controller interface. + * 4) The SPI slave controller will call the slave devices get_cmd() and + * get_data() methods to get the value that will be shifted out when + * the required for the first to be word shifted out (normally all + * '0' or all '1'). The get_data() method may be the same function + * that implements the get_cmd() method if the device does not + * distinguish command and data transfers (normally only LCDs do that). + * The driver can change the next word to be shifted out at any time + * by calling the SPI slave controller's set_cmd() and set_data() method. + * 5) Upon return from the bind method, the SPI slave controller will be + * fully "armed" and ready to begin normal SPI data transfers. + * + * A typical (non-DMA) data transfer proceeds as follows: + * + * 1) Internally, the SPI slave driver detects that the SPI chip select + * has gone low, selecting this device for data transfer. If the SPI + * slave device's select method is non-NULL, the SPI slave controller + * will notify the slave device by called its selected() method. + * 2) Similarly, the SPI device driver may make a distinction between + * command and data transfer based on internal logic that is beyond + * the scope of these interface description. + * 3) As the first word is shifted in, the command or data word word + * will be shifted out. As soon as the clock is detected, the SPI + * controller driver will call the get_cmd() or get_data() method + * again to get the second word to be shifted out. NOTE: the SPI + * slave device has only one word in bit times to provide this value! + * 4) When the first word is shifted in, the SPI controller driver will + * call the device's exchange_data() or exchange_cmd() method to both + * provide the master command that was just shifted in as well to + * obtain the next value to shift out. If the SPI device responds + * with this value before clocking begins for the next word, that + * that value will be used (and the backup value obtained in 3) will + * be discarded). + * 5) The SPI device's echange_cmd/data() will will be called in a similar + * way after each subsequent word is clocked in. The only difference + * is that word returned from the previous call to exchange_cmd/data() + * will not be discard. + * 6) The activity of 5) will continue until the master raises the chip + * select signal. In that case, the SPI slave controll driver will + * again call the SPI device's selected(). At this point, the SPI + * controller driver may have two words buffered. If will discard the + * last and retain only the current word prepared to be shifted out. + * That value can be changed by the SPI device driver by calling the + * set_cmd/data() method. + * + * A typical DMA data transfer processes as follows: + * To be provided + */ + +enum spi_smode_e +{ + SPISLAVE_MODE0 = 0, /* CPOL=0 CHPHA=0 */ + SPISLAVE_MODE1, /* CPOL=0 CHPHA=1 */ + SPISLAVE_MODE2, /* CPOL=1 CHPHA=0 */ + SPISLAVE_MODE3 /* CPOL=1 CHPHA=1 */ +}; + +/* The SPI slave vtable */ + +struct spi_sctrlr_s; +struct spi_sdev_s; +struct spi_slaveops_s +{ + CODE void (*bind)(FAR struct spi_sctrlr_s *sctrlr, + FAR spi_sdev_s *sdev, enum spi_mode_e mode, int nbits); + CODE void (*set_cmd)(FAR struct spi_sctrlr_s *sctrlr, uint16_t cmd); + CODE void (*set_data)(FAR struct spi_sctrlr_s *sctrlr, uint16_t data); +}; + +/* SPI private data. This structure only defines the initial fields of the + * structure visible to the SPI device drvier. The specific implementation + * may add additional, device specific fields after the vtable structure + * pointer + */ + +struct spi_sctrlr_s +{ + FAR const struct spi_slaveops_s *ops; + + /* Private SPI slave controller driver data may follow */ +}; + +/* The SPI slave vtable */ + +struct spi_sdevops_s +{ + CODE void (*selected)(FAR struct spi_sdev_s *sdev, bool isselected); + CODE uint16_t (*get_cmd)(FAR struct spi_sdev_s *sdev); + CODE uint16_t (*exchange_cmd)(FAR struct spi_sdev_s *sdev), uint16_t cmd); + CODE uint16_t (*get_data)(FAR struct spi_sdev_s *sdev); + CODE uint16_t (*exchange_data)(FAR struct spi_sdev_s *sdev, uint16_t data)); +}; + +struct spi_sdev_s +{ + FAR const struct spi_sdevops_s *ops; + + /* Private SPI slave device driver data may follow */ +}; + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __INCLUDE_NUTTX_SPI_SLAVE_H */ From b9503c4dbc3140e4e4b43b71d94dd91d32c6f926 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 8 Aug 2015 10:47:12 -0600 Subject: [PATCH 27/35] Update ChangeLog --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 67e3fc17590..5a140302cba 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10792,4 +10792,6 @@ * drivers/sensors/as5048b.c and include/nuttx/sensors/as5048b.h: Add support for an AS5048B rotary magnetic sensor. From Paul Patience (2015-08-06). + * include/nuttx/spi/slave.h: Add a definition of an SPI slave + interface (2015-08-08). From f604c813ff49a7e10c1906275ebb56bf860eb127 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 8 Aug 2015 12:18:05 -0600 Subject: [PATCH 28/35] SPI Slave: Add an unbind() method to the slave interface --- include/nuttx/spi/slave.h | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/include/nuttx/spi/slave.h b/include/nuttx/spi/slave.h index 3885a05e4c7..111b98b5e03 100644 --- a/include/nuttx/spi/slave.h +++ b/include/nuttx/spi/slave.h @@ -62,7 +62,9 @@ * * Description: * Bind the SPI slave device interface to the SPI slave controller - * interface and configure the SPI interface. Upon return, the + * interface and configure the SPI interface. Upon return, the SPI + * slave controller driver is fully operational and ready to perform + * transfers. * * Input Parameters: * sctrlr - SPI slave controller interface instance @@ -79,6 +81,24 @@ #define SPI_SCTRLR_BIND(c,d,m,n) ((c)->bind(c,d,m,n)) +/**************************************************************************** + * Name: SPI_SCTRLR_UNBIND + * + * Description: + * Un-bind the SPI slave device interface from the SPI slave controller + * interface. Reset the SPI interface and restore the SPI slave + * controller driver to its initial state, + * + * Input Parameters: + * sctrlr - SPI slave controller interface instance + * + * Returned Value: + * none + * + ****************************************************************************/ + +#define SPI_SCTRLR_UNBIND(c) ((c)->unbind(c)) + /**************************************************************************** * Name: SPI_SCTRLR_SET_CMD/SPI_SCTRLR_SET_DATA * @@ -271,6 +291,7 @@ struct spi_slaveops_s { CODE void (*bind)(FAR struct spi_sctrlr_s *sctrlr, FAR spi_sdev_s *sdev, enum spi_mode_e mode, int nbits); + CODE void (*unbind)(FAR struct spi_sctrlr_s *sctrlr); CODE void (*set_cmd)(FAR struct spi_sctrlr_s *sctrlr, uint16_t cmd); CODE void (*set_data)(FAR struct spi_sctrlr_s *sctrlr, uint16_t data); }; From 0db86bc509cf53823d867c6a090bc7ba17276b43 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 8 Aug 2015 16:16:53 -0600 Subject: [PATCH 29/35] SPI Slave: Another big simplication to the interfqace design --- include/nuttx/spi/slave.h | 133 ++++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 63 deletions(-) diff --git a/include/nuttx/spi/slave.h b/include/nuttx/spi/slave.h index 111b98b5e03..43d79c825cd 100644 --- a/include/nuttx/spi/slave.h +++ b/include/nuttx/spi/slave.h @@ -100,7 +100,7 @@ #define SPI_SCTRLR_UNBIND(c) ((c)->unbind(c)) /**************************************************************************** - * Name: SPI_SCTRLR_SET_CMD/SPI_SCTRLR_SET_DATA + * Name: SPI_SCTRLR_SETDATA * * Description: * Set the next value to be shifted out from the interface. This primes @@ -109,17 +109,16 @@ * * Input Parameters: * sctrlr - SPI slave controller interface instance - * cmd - Command/data mode data value to be shifted out. The width of - * data the data must be the same as the nbits parameter previously - * provided to the bind() methos. + * data - Command/data mode data value to be shifted out. The width of + * the data must be the same as the nbits parameter previously + * provided to the bind() methods. * * Returned Value: * none * ****************************************************************************/ -#define SPI_SCTRLR_SET_CMD(c,v) ((c)->set_cmd(c,v)) -#define SPI_SCTRLR_SET_DATA(c,v) ((c)->set_data(c,v)) +#define SPI_SCTRLR_SETDATA(c,v) ((c)->setdata(c,v)) /**************************************************************************** * Name: SPI_SDEV_SELECTED @@ -140,7 +139,31 @@ #define SPI_SDEV_SELECTED(d,i) ((c)->selected(d,i)) /**************************************************************************** - * Name: SPI_SDEV_GET_CMD/SPI_SDEV_GET_DATA + * Name: SPI_SDEV_CMDDATA + * + * Description: + * This is a SPI device callback that used when the SPI device controller + * driver detects any change command/data condition. + * + * Normally only LCD devices distinguish command and data. For devices + * that do not distinguish between command and data, this method may be + * a stub.; For devices that do make that distinction, they should treat + * all subsequent calls to getdata() or exchange() appropriately for the + * current command/data selection. + * + * Input Parameters: + * sdev - SPI device interface instance + * isdata - True: Data is selected + * + * Returned Value: + * none + * + ****************************************************************************/ + +#define SPI_SDEV_CMDDATA(d,i) ((c)->cmddata(d,i)) + +/**************************************************************************** + * Name: SPI_SDEV_GETDATA * * Description: * This is a SPI device callback that used when the SPI device controller @@ -149,11 +172,8 @@ * can keep pace with the shifted-in data. * * The SPI controller driver will prime for both command and data - * transfers. Normally only LCD devices distinguish command and data. - * For devices that do not distinguish between command and data, only - * the get_cmd() method is meaningful. In that case the same function - * may be provided for get_cmd() and get_data(). Or get_data() may be - * only a stub that returns zero (it should never be called). + * transfers as determined by a preceding call to the device cmddata() + * method. Normally only LCD devices distinguish command and data. * * Input Parameters: * sdev - SPI device interface instance @@ -163,38 +183,28 @@ * ****************************************************************************/ -#define SPI_SDEV_GET_CMD(d,v) ((d)->get_cmd(d,v)) -#define SPI_SDEV_GET_DATA(d,v) ((d)->get_data(d,v)) +#define SPI_SDEV_GETDATA(d,v) ((d)->getdata(d,v)) /**************************************************************************** - * Name: SPI_SDEV_EXCHANGE_CMD/SPI_SDEV_EXCHANGE_DATA + * Name: SPI_SDEV_EXCHANGE * * Description: * This is a SPI device callback that used when the SPI device controller - * receives a new value shifted and requires the next value to be shifted- - * out. Notice that these values my be out of synchronization by as much - * as two words: The value to be shifted out may be two words beyond the - * value that was just shifted in. - * - * Normally only LCD devices distinguish command and data. For devices - * that do not distinguish between command and data, only the - * exchange_cmd() method is meaningful. In that case the same function - * may be provided for exchange_cmd() and exchange_data(). Or - * exchange_data() may be simply a stub that discards the shifted in - * value returns zero (it should never be called). + * receives a new value shifted in and requires the next value to be + * shifted out. Notice that these values my be out of synchronization by + * as much as two words: The value to be shifted out may be two words + * beyond the value that was just shifted in. * * Input Parameters: * sdev - SPI device interface instance - * cmd - The last command/data value that was shifted in - * data + * data - The last command/data value that was shifted in * * Returned Value: * The next data value to be shifted out * ****************************************************************************/ -#define SPI_SDEV_EXCHANGE_CMD(d,v) ((d)->exchange_cmd(d,v)) -#define SPI_SDEV_EXCHANGE_DATA(d,v) ((d)->exchange_data(d,v)) +#define SPI_SDEV_EXCHANGE(d,v) ((d)->exchange(d,v)) /**************************************************************************** * Public Types @@ -212,7 +222,7 @@ * * 2) struct spi_sdev_s - Defines the second center between the SPI * slave device and the SPI slave controller hardware. This interface - * is implemented by the SPI slave device. The slave devices passes this + * is implemented by the SPI slave device. The slave device passes this * interface to the struct spi_sctrlr_s during initialization * be calling the bind() method of the struct spi_sctrlr_s * interface. @@ -227,14 +237,14 @@ * 3) The SPI slave device driver creates and initializes an instance of * struct spi_sdev_s; it passes this instance to the bind() method of * of the SPI slave controller interface. - * 4) The SPI slave controller will call the slave devices get_cmd() and - * get_data() methods to get the value that will be shifted out when - * the required for the first to be word shifted out (normally all - * '0' or all '1'). The get_data() method may be the same function - * that implements the get_cmd() method if the device does not - * distinguish command and data transfers (normally only LCDs do that). - * The driver can change the next word to be shifted out at any time - * by calling the SPI slave controller's set_cmd() and set_data() method. + * 4) The SPI slave controller will (1) call the slaved device's cmddata() + * method to indicate the initial state of any command/data selection, + * then (2) call the slave device's getdata() method to get the value + * that will be shifted out the SPI clock is detected. The kind of + * data returned the getdata() method may be contingent on the current + * command/data setting previous reported the device cmddata() method. + * driver can change the next word to be shifted out at any time by + * The calling the SPI slave controller's setdata() method. * 5) Upon return from the bind method, the SPI slave controller will be * fully "armed" and ready to begin normal SPI data transfers. * @@ -244,32 +254,31 @@ * has gone low, selecting this device for data transfer. If the SPI * slave device's select method is non-NULL, the SPI slave controller * will notify the slave device by called its selected() method. - * 2) Similarly, the SPI device driver may make a distinction between - * command and data transfer based on internal logic that is beyond - * the scope of these interface description. - * 3) As the first word is shifted in, the command or data word word - * will be shifted out. As soon as the clock is detected, the SPI - * controller driver will call the get_cmd() or get_data() method - * again to get the second word to be shifted out. NOTE: the SPI - * slave device has only one word in bit times to provide this value! + * 2) If a change in the command/data status changes any time before, + * during, or after the chip is selected, that new command state state + * will reported to the device driver via the cmddata() method. + * 3) As the first word is shifted in, the command or data word will be + * shifted out. As soon as the clock is detected, the SPI controller + * driver will call the getdata() method again to get the second word + * to be shifted out. NOTE: the SPI slave device has only one word in + * bit times to provide this value! * 4) When the first word is shifted in, the SPI controller driver will - * call the device's exchange_data() or exchange_cmd() method to both - * provide the master command that was just shifted in as well to - * obtain the next value to shift out. If the SPI device responds - * with this value before clocking begins for the next word, that - * that value will be used (and the backup value obtained in 3) will - * be discarded). + * call the device's exchange() method to both provide the master + * command that was just shifted in as well to obtain the next value + * to shift out. If the SPI device responds with this value before + * clocking begins for the next word, that that value will be used + * (and the backup value obtained in 3) will be discarded). * 5) The SPI device's echange_cmd/data() will will be called in a similar * way after each subsequent word is clocked in. The only difference - * is that word returned from the previous call to exchange_cmd/data() + * is that word returned from the previous call to exchange/cmddata() * will not be discard. * 6) The activity of 5) will continue until the master raises the chip - * select signal. In that case, the SPI slave controll driver will + * select signal. In that case, the SPI slave controller driver will * again call the SPI device's selected(). At this point, the SPI * controller driver may have two words buffered. If will discard the * last and retain only the current word prepared to be shifted out. * That value can be changed by the SPI device driver by calling the - * set_cmd/data() method. + * setdata() method. * * A typical DMA data transfer processes as follows: * To be provided @@ -292,12 +301,11 @@ struct spi_slaveops_s CODE void (*bind)(FAR struct spi_sctrlr_s *sctrlr, FAR spi_sdev_s *sdev, enum spi_mode_e mode, int nbits); CODE void (*unbind)(FAR struct spi_sctrlr_s *sctrlr); - CODE void (*set_cmd)(FAR struct spi_sctrlr_s *sctrlr, uint16_t cmd); - CODE void (*set_data)(FAR struct spi_sctrlr_s *sctrlr, uint16_t data); + CODE void (*setdata)(FAR struct spi_sctrlr_s *sctrlr, uint16_t data); }; /* SPI private data. This structure only defines the initial fields of the - * structure visible to the SPI device drvier. The specific implementation + * structure visible to the SPI device driver. The specific implementation * may add additional, device specific fields after the vtable structure * pointer */ @@ -314,10 +322,9 @@ struct spi_sctrlr_s struct spi_sdevops_s { CODE void (*selected)(FAR struct spi_sdev_s *sdev, bool isselected); - CODE uint16_t (*get_cmd)(FAR struct spi_sdev_s *sdev); - CODE uint16_t (*exchange_cmd)(FAR struct spi_sdev_s *sdev), uint16_t cmd); - CODE uint16_t (*get_data)(FAR struct spi_sdev_s *sdev); - CODE uint16_t (*exchange_data)(FAR struct spi_sdev_s *sdev, uint16_t data)); + CODE void (*cmddata)(FAR struct spi_sdev_s *sdev, bool isdata); + CODE uint16_t (*getdata)(FAR struct spi_sdev_s *sdev); + CODE uint16_t (*exchange)(FAR struct spi_sdev_s *sdev), uint16_t cmd); }; struct spi_sdev_s From 7317f3bd88f0239096911ec0e3a473ba8ba9c93f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 9 Aug 2015 09:48:00 -0600 Subject: [PATCH 30/35] Refresh modules; trival change to comments in header file --- arch | 2 +- configs | 2 +- include/nuttx/spi/slave.h | 18 ++++++++++++------ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/arch b/arch index 23ecc0e1904..b1a50470634 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 23ecc0e19048944ea5391ea72b0c1d2851a66e16 +Subproject commit b1a50470634cf0b876af4380c42427d53aaceb06 diff --git a/configs b/configs index abab21dfa55..ac4035687c8 160000 --- a/configs +++ b/configs @@ -1 +1 @@ -Subproject commit abab21dfa553656a0ce40423931a2af2c61f3466 +Subproject commit ac4035687c824bb4a573e06feb017cb4f3ce7626 diff --git a/include/nuttx/spi/slave.h b/include/nuttx/spi/slave.h index 43d79c825cd..8a84586d5fe 100644 --- a/include/nuttx/spi/slave.h +++ b/include/nuttx/spi/slave.h @@ -292,7 +292,7 @@ enum spi_smode_e SPISLAVE_MODE3 /* CPOL=1 CHPHA=1 */ }; -/* The SPI slave vtable */ +/* The SPI slave controller driver vtable */ struct spi_sctrlr_s; struct spi_sdev_s; @@ -304,10 +304,10 @@ struct spi_slaveops_s CODE void (*setdata)(FAR struct spi_sctrlr_s *sctrlr, uint16_t data); }; -/* SPI private data. This structure only defines the initial fields of the - * structure visible to the SPI device driver. The specific implementation - * may add additional, device specific fields after the vtable structure - * pointer +/* SPI slave controller private data. This structure only defines the + * initial fields of the structure visible to the SPI device driver. The + * specific implementation may add additional, device specific fields after + * the vtable structure pointer. */ struct spi_sctrlr_s @@ -317,7 +317,7 @@ struct spi_sctrlr_s /* Private SPI slave controller driver data may follow */ }; -/* The SPI slave vtable */ +/* The SPI slave device driver vtable */ struct spi_sdevops_s { @@ -327,6 +327,12 @@ struct spi_sdevops_s CODE uint16_t (*exchange)(FAR struct spi_sdev_s *sdev), uint16_t cmd); }; +/* SPI slave device private data. This structure only defines the initial + * fields of the structure visible to the SPI slave controller driver. The + * specific implementation may add additional, device specific fields after + * the vtable structure pointer. + */ + struct spi_sdev_s { FAR const struct spi_sdevops_s *ops; From 5848101c1f9ecc46b0b2682206dd35f226ac2d25 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 9 Aug 2015 12:06:46 -0600 Subject: [PATCH 31/35] Fix/improve some issues in the SPI slave interface header file --- ChangeLog | 2 ++ arch | 2 +- include/nuttx/spi/slave.h | 14 ++++++++------ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5a140302cba..37a4b8cd75b 100755 --- a/ChangeLog +++ b/ChangeLog @@ -10794,4 +10794,6 @@ (2015-08-06). * include/nuttx/spi/slave.h: Add a definition of an SPI slave interface (2015-08-08). + * arch/arm/src/samv7: Add the framework for an SPI slave drvier. This + driver has a lot of missing logic on initial commit (2015-08-09). diff --git a/arch b/arch index b1a50470634..fa4211a00c6 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit b1a50470634cf0b876af4380c42427d53aaceb06 +Subproject commit fa4211a00c6139d9ea08105caad9f92a4f029352 diff --git a/include/nuttx/spi/slave.h b/include/nuttx/spi/slave.h index 8a84586d5fe..d78686f2f60 100644 --- a/include/nuttx/spi/slave.h +++ b/include/nuttx/spi/slave.h @@ -294,12 +294,14 @@ enum spi_smode_e /* The SPI slave controller driver vtable */ -struct spi_sctrlr_s; -struct spi_sdev_s; -struct spi_slaveops_s +struct spi_sctrlr_s; /* Forward reference */ +struct spi_sdev_s; /* Forward reference */ + +struct spi_sctrlrops_s { CODE void (*bind)(FAR struct spi_sctrlr_s *sctrlr, - FAR spi_sdev_s *sdev, enum spi_mode_e mode, int nbits); + FAR struct spi_sdev_s *sdev, enum spi_smode_e mode, + int nbits); CODE void (*unbind)(FAR struct spi_sctrlr_s *sctrlr); CODE void (*setdata)(FAR struct spi_sctrlr_s *sctrlr, uint16_t data); }; @@ -312,7 +314,7 @@ struct spi_slaveops_s struct spi_sctrlr_s { - FAR const struct spi_slaveops_s *ops; + FAR const struct spi_sctrlrops_s *ops; /* Private SPI slave controller driver data may follow */ }; @@ -324,7 +326,7 @@ struct spi_sdevops_s CODE void (*selected)(FAR struct spi_sdev_s *sdev, bool isselected); CODE void (*cmddata)(FAR struct spi_sdev_s *sdev, bool isdata); CODE uint16_t (*getdata)(FAR struct spi_sdev_s *sdev); - CODE uint16_t (*exchange)(FAR struct spi_sdev_s *sdev), uint16_t cmd); + CODE uint16_t (*exchange)(FAR struct spi_sdev_s *sdev, uint16_t cmd); }; /* SPI slave device private data. This structure only defines the initial From f570a9b770ba14d533db629a4d0471ba43d0dee0 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 9 Aug 2015 15:42:57 -0600 Subject: [PATCH 32/35] Add output queuing to SPI slave interface --- arch | 2 +- include/nuttx/spi/slave.h | 170 ++++++++++++++++++++++++++------------ 2 files changed, 120 insertions(+), 52 deletions(-) diff --git a/arch b/arch index fa4211a00c6..e9f86b4a399 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit fa4211a00c6139d9ea08105caad9f92a4f029352 +Subproject commit e9f86b4a3993dfc19ff95cb7bfcba95a5cbfc5ba diff --git a/include/nuttx/spi/slave.h b/include/nuttx/spi/slave.h index d78686f2f60..0fd78d7e0cc 100644 --- a/include/nuttx/spi/slave.h +++ b/include/nuttx/spi/slave.h @@ -79,7 +79,7 @@ * ****************************************************************************/ -#define SPI_SCTRLR_BIND(c,d,m,n) ((c)->bind(c,d,m,n)) +#define SPI_SCTRLR_BIND(c,d,m,n) ((c)->ops->bind(c,d,m,n)) /**************************************************************************** * Name: SPI_SCTRLR_UNBIND @@ -97,15 +97,15 @@ * ****************************************************************************/ -#define SPI_SCTRLR_UNBIND(c) ((c)->unbind(c)) +#define SPI_SCTRLR_UNBIND(c) ((c)->ops->unbind(c)) /**************************************************************************** - * Name: SPI_SCTRLR_SETDATA + * Name: SPI_SCTRLR_ENQUEUE * * Description: - * Set the next value to be shifted out from the interface. This primes - * the controller driver for the next transfer but has no effect on any - * in-process or currently "committed" transfers + * Enqueue the next value to be shifted out from the interface. This adds + * the word the controller driver for a subsequent transfer but has no + * effect on any in-process or currently "committed" transfers * * Input Parameters: * sctrlr - SPI slave controller interface instance @@ -114,11 +114,48 @@ * provided to the bind() methods. * * Returned Value: - * none + * Zero if the word was successfully queue; A negated errno valid is + * returned on any failure to enqueue the word (such as if the queue is + * full). * ****************************************************************************/ -#define SPI_SCTRLR_SETDATA(c,v) ((c)->setdata(c,v)) +#define SPI_SCTRLR_ENQUEUE(c,v) ((c)->ops->enqueue(c,v)) + +/**************************************************************************** + * Name: SPI_SCTRLR_QFULL + * + * Description: + * Return true if the queue is full or false if there is space to add an + * additional word to the queue. + * + * Input Parameters: + * sctrlr - SPI slave controller interface instance + * + * Returned Value: + * true if the output wueue is full + * + ****************************************************************************/ + +#define SPI_SCTRLR_QFULL(c) ((c)->ops->qfull(c)) + +/**************************************************************************** + * Name: SPI_SCTRLR_QFLUSH + * + * Description: + * Discard all saved values in the output queue. On return from this + * function the output queue will be empty. Any in-progress or otherwise + * "committed" output values may not be flushed. + * + * Input Parameters: + * sctrlr - SPI slave controller interface instance + * + * Returned Value: + * None + * + ****************************************************************************/ + +#define SPI_SCTRLR_QFLUSH(c) ((c)->ops->qflush(c)) /**************************************************************************** * Name: SPI_SDEV_SELECTED @@ -134,9 +171,12 @@ * Returned Value: * none * + * Assumptions: + * May be called from an interrupt handler. + * ****************************************************************************/ -#define SPI_SDEV_SELECTED(d,i) ((c)->selected(d,i)) +#define SPI_SDEV_SELECTED(d,i) ((c)->ops->selected(d,i)) /**************************************************************************** * Name: SPI_SDEV_CMDDATA @@ -148,7 +188,7 @@ * Normally only LCD devices distinguish command and data. For devices * that do not distinguish between command and data, this method may be * a stub.; For devices that do make that distinction, they should treat - * all subsequent calls to getdata() or exchange() appropriately for the + * all subsequent calls to enqueue() or rece() appropriately for the * current command/data selection. * * Input Parameters: @@ -158,9 +198,12 @@ * Returned Value: * none * + * Assumptions: + * May be called from an interrupt handler. + * ****************************************************************************/ -#define SPI_SDEV_CMDDATA(d,i) ((c)->cmddata(d,i)) +#define SPI_SDEV_CMDDATA(d,i) ((d)->ops->cmddata(d,i)) /**************************************************************************** * Name: SPI_SDEV_GETDATA @@ -181,46 +224,53 @@ * Returned Value: * The next data value to be shifted out * + * Assumptions: + * May be called from an interrupt handler. + * ****************************************************************************/ -#define SPI_SDEV_GETDATA(d,v) ((d)->getdata(d,v)) +#define SPI_SDEV_GETDATA(d) ((d)->ops->getdata(d)) /**************************************************************************** - * Name: SPI_SDEV_EXCHANGE + * Name: SPI_SDEV_RECEIVE * * Description: * This is a SPI device callback that used when the SPI device controller * receives a new value shifted in and requires the next value to be * shifted out. Notice that these values my be out of synchronization by - * as much as two words: The value to be shifted out may be two words - * beyond the value that was just shifted in. + * several words. * * Input Parameters: * sdev - SPI device interface instance * data - The last command/data value that was shifted in * * Returned Value: - * The next data value to be shifted out + * None + * + * Assumptions: + * May be called from an interrupt handler. * ****************************************************************************/ -#define SPI_SDEV_EXCHANGE(d,v) ((d)->exchange(d,v)) +#define SPI_SDEV_RECEIVE(d,v) ((d)->ops->receive(d,v)) /**************************************************************************** * Public Types ****************************************************************************/ /* There are two interfaces defined for the implementation of SPI slave: * - * 1) struct spi_sctrlr_s - Defines one interface between the SPI + * 1) struct spi_sctrlr_s: Defines one interface between the SPI * slave device and the SPI slave controller hardware. This interface * is implemented by the SPI slave device controller lower-half driver * and is provided to the the SPI slave device driver when that driver - * is initialization. That SPI slave device initialization function might - * look like: + * is initialized. That SPI slave device initialization function might + * look something like: * * int xyz_dev_initialize(FAR struct spi_sctrlr_s *sctrlr); * - * 2) struct spi_sdev_s - Defines the second center between the SPI + * where xyz is replaced with the SPI device name. + * + * 2) struct spi_sdev_s: Defines the second interface between the SPI * slave device and the SPI slave controller hardware. This interface * is implemented by the SPI slave device. The slave device passes this * interface to the struct spi_sctrlr_s during initialization @@ -231,54 +281,70 @@ * * 1) Board-specific logic calls board- or chip-specific logic to create an * instance of the SPI slave controller interface, struct spi_sctrlr_s. + * * 2) Board-specific logic then calls xyz_dev_initialize() to initialize * the SPI slave device. The board-specific logic passes the instance * of struct spi_sctrlr_s to support the initialization. + * * 3) The SPI slave device driver creates and initializes an instance of * struct spi_sdev_s; it passes this instance to the bind() method of * of the SPI slave controller interface. + * * 4) The SPI slave controller will (1) call the slaved device's cmddata() * method to indicate the initial state of any command/data selection, * then (2) call the slave device's getdata() method to get the value * that will be shifted out the SPI clock is detected. The kind of * data returned the getdata() method may be contingent on the current - * command/data setting previous reported the device cmddata() method. - * driver can change the next word to be shifted out at any time by - * The calling the SPI slave controller's setdata() method. + * command/data setting reported the device cmddata() method. The + * driver may enqueue additional words to be shifted out at any time by + * The calling the SPI slave controller's enqueue() method. + * * 5) Upon return from the bind method, the SPI slave controller will be * fully "armed" and ready to begin normal SPI data transfers. * * A typical (non-DMA) data transfer proceeds as follows: * * 1) Internally, the SPI slave driver detects that the SPI chip select - * has gone low, selecting this device for data transfer. If the SPI - * slave device's select method is non-NULL, the SPI slave controller - * will notify the slave device by called its selected() method. - * 2) If a change in the command/data status changes any time before, - * during, or after the chip is selected, that new command state state + * has gone low, selecting this device for data transfer. The SPI + * slave controller will notify the slave device by called its + * selected() method. + * + * 2) If a change in the command/data state changes any time before, + * during, or after the chip is selected, that new command/data state * will reported to the device driver via the cmddata() method. - * 3) As the first word is shifted in, the command or data word will be - * shifted out. As soon as the clock is detected, the SPI controller - * driver will call the getdata() method again to get the second word - * to be shifted out. NOTE: the SPI slave device has only one word in - * bit times to provide this value! - * 4) When the first word is shifted in, the SPI controller driver will - * call the device's exchange() method to both provide the master - * command that was just shifted in as well to obtain the next value - * to shift out. If the SPI device responds with this value before - * clocking begins for the next word, that that value will be used - * (and the backup value obtained in 3) will be discarded). - * 5) The SPI device's echange_cmd/data() will will be called in a similar - * way after each subsequent word is clocked in. The only difference - * is that word returned from the previous call to exchange/cmddata() - * will not be discard. + * + * 3) As the first word is shifted in, the command or data word obtained + * by the initial call to getdata() will be shifted out. As soon as + * the clock is detected, the SPI controller driver will call the + * getdata() method again to get a default second word to be shifted + * out. NOTES: (1) the SPI slave device has only one word in bit + * times to provide this value! (2) The SPI device probably cannot + * really output anything meaning until it receives a decodes the + * first word received from the master. + * + * 4) When the first word from the master is shifted in, the SPI + * controller driver will call the device's receive() method to + * provide the master with the command word that was just shifted + * in. In response to this, the SPI device driver should call + * the enqueue() method to provide the next value to shift out. + * If the SPI device responds with this value before clocking begins + * for the next word, that that value will be used. Otherwise, + * the value obtained from getdata() in step 3 will be shifted out. + * + * 5) The SPI device's receive() method will be called in a similar + * way after each subsequent word is clocked in. The SPI device + * driver can call the enqueue() methods as it has new data to + * be shifted out. + * + * The SPI device driver can detect if there is space to enqueue + * additional data by calling the qfull() method. + * * 6) The activity of 5) will continue until the master raises the chip * select signal. In that case, the SPI slave controller driver will - * again call the SPI device's selected(). At this point, the SPI - * controller driver may have two words buffered. If will discard the - * last and retain only the current word prepared to be shifted out. - * That value can be changed by the SPI device driver by calling the - * setdata() method. + * again call the SPI device's selected() metho. At this point, the SPI + * controller driver may have several words enqueued. It will not + * discard these unless the SPI device driver calls the qflush() + * method. * * A typical DMA data transfer processes as follows: * To be provided @@ -303,7 +369,9 @@ struct spi_sctrlrops_s FAR struct spi_sdev_s *sdev, enum spi_smode_e mode, int nbits); CODE void (*unbind)(FAR struct spi_sctrlr_s *sctrlr); - CODE void (*setdata)(FAR struct spi_sctrlr_s *sctrlr, uint16_t data); + CODE int (*enqueue)(FAR struct spi_sctrlr_s *sctrlr, uint16_t data); + CODE bool (*qfull)(FAR struct spi_sctrlr_s *sctrlr); + CODE void (*qflush)(FAR struct spi_sctrlr_s *sctrlr); }; /* SPI slave controller private data. This structure only defines the @@ -326,7 +394,7 @@ struct spi_sdevops_s CODE void (*selected)(FAR struct spi_sdev_s *sdev, bool isselected); CODE void (*cmddata)(FAR struct spi_sdev_s *sdev, bool isdata); CODE uint16_t (*getdata)(FAR struct spi_sdev_s *sdev); - CODE uint16_t (*exchange)(FAR struct spi_sdev_s *sdev, uint16_t cmd); + CODE void (*receive)(FAR struct spi_sdev_s *sdev, uint16_t cmd); }; /* SPI slave device private data. This structure only defines the initial From 1df8ff1de8679556335bbf7323e426f35f322fda Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 9 Aug 2015 16:22:19 -0600 Subject: [PATCH 33/35] SPI Slave Interface: Clean up/simplify some naming --- arch | 2 +- include/nuttx/spi/slave.h | 26 +++++++++++++++----------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/arch b/arch index e9f86b4a399..98596b23794 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit e9f86b4a3993dfc19ff95cb7bfcba95a5cbfc5ba +Subproject commit 98596b23794fafd7a25d7da1f3a5748ee53b47cd diff --git a/include/nuttx/spi/slave.h b/include/nuttx/spi/slave.h index 0fd78d7e0cc..2200b942c9f 100644 --- a/include/nuttx/spi/slave.h +++ b/include/nuttx/spi/slave.h @@ -158,15 +158,15 @@ #define SPI_SCTRLR_QFLUSH(c) ((c)->ops->qflush(c)) /**************************************************************************** - * Name: SPI_SDEV_SELECTED + * Name: SPI_SDEV_SELECT * * Description: * This is a SPI device callback that used when the SPI device controller * driver detects any change in the chip select pin. * * Input Parameters: - * sdev - SPI device interface instance - * isselected - True: chip select is low (selected); + * sdev - SPI device interface instance + * selected - True: chip select is low (selected); * * Returned Value: * none @@ -176,7 +176,7 @@ * ****************************************************************************/ -#define SPI_SDEV_SELECTED(d,i) ((c)->ops->selected(d,i)) +#define SPI_SDEV_SELECT(d,s) ((c)->ops->select(d,s)) /**************************************************************************** * Name: SPI_SDEV_CMDDATA @@ -192,8 +192,8 @@ * current command/data selection. * * Input Parameters: - * sdev - SPI device interface instance - * isdata - True: Data is selected + * sdev - SPI device interface instance + * data - True: Data is selected * * Returned Value: * none @@ -307,7 +307,7 @@ * 1) Internally, the SPI slave driver detects that the SPI chip select * has gone low, selecting this device for data transfer. The SPI * slave controller will notify the slave device by called its - * selected() method. + * select() method. * * 2) If a change in the command/data state changes any time before, * during, or after the chip is selected, that new command/data state @@ -334,14 +334,18 @@ * 5) The SPI device's receive() method will be called in a similar * way after each subsequent word is clocked in. The SPI device * driver can call the enqueue() methods as it has new data to - * be shifted out. + * be shifted out. The goal of the SPI device driver is to supply + * valid output data at such a rate that data underruns do not + * occur. In the event of a data underrun, the SPI slave controller + * driver will fallback to the default output value obtained from + * the last getdata() call. * * The SPI device driver can detect if there is space to enqueue * additional data by calling the qfull() method. * * 6) The activity of 5) will continue until the master raises the chip * select signal. In that case, the SPI slave controller driver will - * again call the SPI device's selected() metho. At this point, the SPI + * again call the SPI device's select() method. At this point, the SPI * controller driver may have several words enqueued. It will not * discard these unless the SPI device driver calls the qflush() * method. @@ -391,8 +395,8 @@ struct spi_sctrlr_s struct spi_sdevops_s { - CODE void (*selected)(FAR struct spi_sdev_s *sdev, bool isselected); - CODE void (*cmddata)(FAR struct spi_sdev_s *sdev, bool isdata); + CODE void (*select)(FAR struct spi_sdev_s *sdev, bool selected); + CODE void (*cmddata)(FAR struct spi_sdev_s *sdev, bool data); CODE uint16_t (*getdata)(FAR struct spi_sdev_s *sdev); CODE void (*receive)(FAR struct spi_sdev_s *sdev, uint16_t cmd); }; From 17fab9dbd5946521da17335e24f7b4f63060696b Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 9 Aug 2015 17:22:27 -0600 Subject: [PATCH 34/35] Updated comments in header file --- include/nuttx/spi/slave.h | 56 ++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/include/nuttx/spi/slave.h b/include/nuttx/spi/slave.h index 2200b942c9f..35d7cb63a36 100644 --- a/include/nuttx/spi/slave.h +++ b/include/nuttx/spi/slave.h @@ -290,14 +290,15 @@ * struct spi_sdev_s; it passes this instance to the bind() method of * of the SPI slave controller interface. * - * 4) The SPI slave controller will (1) call the slaved device's cmddata() - * method to indicate the initial state of any command/data selection, - * then (2) call the slave device's getdata() method to get the value - * that will be shifted out the SPI clock is detected. The kind of - * data returned the getdata() method may be contingent on the current - * command/data setting reported the device cmddata() method. The - * driver may enqueue additional words to be shifted out at any time by - * The calling the SPI slave controller's enqueue() method. + * 4) The SPI slave controller will (1) call the slaved device's select() + * and cmddata() methods to indicate the initial state of the chip select + * and any command/data selection, then (2) call the slave device's + * getdata() method to get the value that will be shifted out the SPI + * clock is detected. The kind of data returned the getdata() method + * may be contingent on the current command/data setting reported the + * device cmddata() method. The driver may enqueue additional words + * to be shifted out at any time by The calling the SPI slave + * controller's enqueue() method. * * 5) Upon return from the bind method, the SPI slave controller will be * fully "armed" and ready to begin normal SPI data transfers. @@ -325,24 +326,36 @@ * 4) When the first word from the master is shifted in, the SPI * controller driver will call the device's receive() method to * provide the master with the command word that was just shifted - * in. In response to this, the SPI device driver should call - * the enqueue() method to provide the next value to shift out. - * If the SPI device responds with this value before clocking begins - * for the next word, that that value will be used. Otherwise, - * the value obtained from getdata() in step 3 will be shifted out. + * in. + * + * For the case of bi-directional data transfer or of a transfer of + * data from the SPI device to the master, the SPI device driver + * should call the controller's enqueue() method to provide the next + * value(s) to be shifted out. If the SPI device responds with this + * value before clocking begins for the next word, that that value + * will be used. Otherwise, the value obtained from getdata() in + * step 3 will be shifted out. * * 5) The SPI device's receive() method will be called in a similar - * way after each subsequent word is clocked in. The SPI device - * driver can call the enqueue() methods as it has new data to - * be shifted out. The goal of the SPI device driver is to supply - * valid output data at such a rate that data underruns do not + * way after each subsequent word is clocked in. + * + * For the case of bi-directional data transfer or of a uni-directional + * transfer of data from the SPI device to the master, the SPI device + * driver can call the enqueue() methods as it has new data to be shifted + * out. The goal of the SPI device driver for this kind of transfer is + * to supply valid output data at such a rate that data underruns do not * occur. In the event of a data underrun, the SPI slave controller - * driver will fallback to the default output value obtained from - * the last getdata() call. + * driver will fallback to the default output value obtained from the + * last getdata() call. * * The SPI device driver can detect if there is space to enqueue * additional data by calling the qfull() method. * + * For the case of uni-directional transfer of data from the master to + * the SPI device, there is no need to call the enqueue() method at all; + * the value that is shifted out is not important that fallback behavior + * is suficient. + * * 6) The activity of 5) will continue until the master raises the chip * select signal. In that case, the SPI slave controller driver will * again call the SPI device's select() method. At this point, the SPI @@ -350,6 +363,11 @@ * discard these unless the SPI device driver calls the qflush() * method. * + * Some master side implementations may simply tie the chip select signal + * to ground if there are no other devices on the SPI bus. In that case, + * the initial indication of chip selected will be the only call to the + * select() method that is made. + * * A typical DMA data transfer processes as follows: * To be provided */ From 21d4f00e65ceccfaf22180bcf1d5ca35017964fc Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 9 Aug 2015 17:42:47 -0600 Subject: [PATCH 35/35] Add the prototype for up_spi_slave_initialize() to the SPI slave interface header file --- arch | 2 +- include/nuttx/spi/slave.h | 28 +++++++++++++++++++++++----- include/nuttx/spi/spi.h | 4 ++-- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/arch b/arch index 98596b23794..1efba67cba0 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 98596b23794fafd7a25d7da1f3a5748ee53b47cd +Subproject commit 1efba67cba08b28a2a4a1a4649daf2df93b2d596 diff --git a/include/nuttx/spi/slave.h b/include/nuttx/spi/slave.h index 35d7cb63a36..f57493fa53b 100644 --- a/include/nuttx/spi/slave.h +++ b/include/nuttx/spi/slave.h @@ -263,12 +263,13 @@ * slave device and the SPI slave controller hardware. This interface * is implemented by the SPI slave device controller lower-half driver * and is provided to the the SPI slave device driver when that driver - * is initialized. That SPI slave device initialization function might - * look something like: + * is initialized. That SPI slave device initialization function has + * the prototype: * - * int xyz_dev_initialize(FAR struct spi_sctrlr_s *sctrlr); + * FAR struct spi_sctrlr_s *up_spi_slave_initialize(int port); * - * where xyz is replaced with the SPI device name. + * Given an SPI port number, this function returns an instance of the + * SPI slave controller interface. * * 2) struct spi_sdev_s: Defines the second interface between the SPI * slave device and the SPI slave controller hardware. This interface @@ -282,7 +283,7 @@ * 1) Board-specific logic calls board- or chip-specific logic to create an * instance of the SPI slave controller interface, struct spi_sctrlr_s. * - * 2) Board-specific logic then calls xyz_dev_initialize() to initialize + * 2) Board-specific logic then calls up_dev_initialize() to initialize * the SPI slave device. The board-specific logic passes the instance * of struct spi_sctrlr_s to support the initialization. * @@ -449,6 +450,23 @@ extern "C" * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: up_spi_slave_initialize + * + * Description: + * Initialize the selected SPI port in slave mode. + * + * Input Parameter: + * port - Chip select number identifying the "logical" SPI port. Includes + * encoded port and chip select information. + * + * Returned Value: + * Valid SPI device structure reference on success; a NULL on failure + * + ****************************************************************************/ + +FAR struct spi_sctrlr_s *up_spi_slave_initialize(int port); + #undef EXTERN #if defined(__cplusplus) } diff --git a/include/nuttx/spi/spi.h b/include/nuttx/spi/spi.h index 43aa8e277c7..2a6e25ed034 100644 --- a/include/nuttx/spi/spi.h +++ b/include/nuttx/spi/spi.h @@ -1,7 +1,7 @@ /**************************************************************************** * include/nuttx/spi/spi.h * - * Copyright(C) 2008-2013 Gregory Nutt. All rights reserved. + * Copyright(C) 2008-2013, 2015 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -437,7 +437,7 @@ extern "C" * Name: up_spiinitialize * * Description: - * Initialize the selected SPI port. + * Initialize the selected SPI port in master mode. * * This is a generic prototype for the SPI initialize logic. Specific * architectures may support different SPI initialization functions if,