You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by GitBox <gi...@apache.org> on 2021/01/25 04:19:37 UTC

[GitHub] [incubator-nuttx] xiaoxiang781216 commented on a change in pull request #2736: Add generic support to LWL Console

xiaoxiang781216 commented on a change in pull request #2736:
URL: https://github.com/apache/incubator-nuttx/pull/2736#discussion_r563452813



##########
File path: drivers/lwl_console.c
##########
@@ -0,0 +1,314 @@
+/****************************************************************************
+ * drivers/lwlconsole.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <syscall.h>

Review comment:
       remove syscall.h and nuttx/arch.h, both should not used.

##########
File path: drivers/lwl_console.c
##########
@@ -0,0 +1,314 @@
+/****************************************************************************
+ * drivers/lwlconsole.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <syscall.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Lightweight Link (lwl)
+ * ======================
+ *
+ * Lightweight bidirectional communication between target and debug host
+ * without any need for additional hardware.
+ *
+ * Works with openOCD and other debuggers that are capable of reading and
+ * writing memory while the target is running.
+ *
+ * Principle of operation is simple; An 'upword' of 32 bits communicates
+ * from the target to the host, a 'downword' of the same size runs in the
+ * opposite direction. These two words can be in any memory that is
+ * read/write access for both the target and the debug host. A simple ping
+ * pong handshake protocol over these words allows up/down link
+ * communication.  On the upside no additional integration is needed. On
+ * the downside it may be necessary to feed lwl with cycles to poll for
+ * changes in the downword, depending on the use case.
+ *
+ * Bit configuration
+ * -----------------
+ *
+ * Downword (Host to target);
+ *
+ * A D U VV XXX
+ *
+ * A   31    1 - Service Active (Set by host)
+ * D   30    1 - Downsense (Toggled when there is data)
+ * U   29    1 - Upsense ack (Toggled to acknowledge receipt of uplink data)
+ * VV  28-27 2 - Valid Octets (Number of octets valid in the message)
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ * Upword (Target to Host);
+ *
+ * A   31    1 - Service Active (Set by device)
+ * D   30    1 - Downsense ack (Toggled to acknowledge receipt of downlink
+ *               data)
+ * U   29    1 - Upsense (Toggled when there is data)
+ * VV  28-27 2 - Valid upword octets
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ */
+
+/* Protocol bits */
+
+#define LWL_GETACTIVE(x) (((x) & (1 << 31)) != 0)
+#define LWL_ACTIVE(x) (((x)&1) << 31)
+
+#define LWL_DNSENSEBIT (1 << 30)
+#define LWL_DNSENSE(x) ((x)&LWL_DNSENSEBIT)
+#define LWL_UPSENSEBIT (1 << 29)
+#define LWL_UPSENSE(x) ((x)&LWL_UPSENSEBIT)
+#define LWL_SENSEMASK (3 << 29)
+
+#define LWL_GETOCTVAL(x) (((x) >> 27) & 3)
+#define LWL_OCTVAL(x) (((x)&3) << 27)
+#define LWL_GETPORT(x) (((x) >> 24) & 7)
+#define LWL_PORT(x) (((x)&7) << 24)
+
+#define LWL_PORT_CONSOLE 1
+#define ID_SIG 0x7216A318

Review comment:
       add LWL_ prefix?

##########
File path: drivers/Kconfig
##########
@@ -24,6 +24,22 @@ config DRVR_MKRD
 		the selecting this option will also enable the BOARDIOC_MKRD
 		command that will support creation of RAM disks from applications.
 
+# ARCH needs to support memory access while CPU is running to be able to use
+# the LWL CONSOLE
+
+config ARCH_HAVE_RDWR_MEM_CPU_RUN

Review comment:
       should we remove arm version?
   https://github.com/apache/incubator-nuttx/blob/master/arch/arm/src/common/arm_lwl_console.c

##########
File path: drivers/lwl_console.c
##########
@@ -0,0 +1,314 @@
+/****************************************************************************
+ * drivers/lwlconsole.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <syscall.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Lightweight Link (lwl)
+ * ======================
+ *
+ * Lightweight bidirectional communication between target and debug host
+ * without any need for additional hardware.
+ *
+ * Works with openOCD and other debuggers that are capable of reading and
+ * writing memory while the target is running.
+ *
+ * Principle of operation is simple; An 'upword' of 32 bits communicates
+ * from the target to the host, a 'downword' of the same size runs in the
+ * opposite direction. These two words can be in any memory that is
+ * read/write access for both the target and the debug host. A simple ping
+ * pong handshake protocol over these words allows up/down link
+ * communication.  On the upside no additional integration is needed. On
+ * the downside it may be necessary to feed lwl with cycles to poll for
+ * changes in the downword, depending on the use case.
+ *
+ * Bit configuration
+ * -----------------
+ *
+ * Downword (Host to target);
+ *
+ * A D U VV XXX
+ *
+ * A   31    1 - Service Active (Set by host)
+ * D   30    1 - Downsense (Toggled when there is data)
+ * U   29    1 - Upsense ack (Toggled to acknowledge receipt of uplink data)
+ * VV  28-27 2 - Valid Octets (Number of octets valid in the message)
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ * Upword (Target to Host);
+ *
+ * A   31    1 - Service Active (Set by device)
+ * D   30    1 - Downsense ack (Toggled to acknowledge receipt of downlink
+ *               data)
+ * U   29    1 - Upsense (Toggled when there is data)
+ * VV  28-27 2 - Valid upword octets
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ */
+
+/* Protocol bits */
+
+#define LWL_GETACTIVE(x) (((x) & (1 << 31)) != 0)
+#define LWL_ACTIVE(x) (((x)&1) << 31)
+
+#define LWL_DNSENSEBIT (1 << 30)
+#define LWL_DNSENSE(x) ((x)&LWL_DNSENSEBIT)
+#define LWL_UPSENSEBIT (1 << 29)
+#define LWL_UPSENSE(x) ((x)&LWL_UPSENSEBIT)
+#define LWL_SENSEMASK (3 << 29)
+
+#define LWL_GETOCTVAL(x) (((x) >> 27) & 3)
+#define LWL_OCTVAL(x) (((x)&3) << 27)
+#define LWL_GETPORT(x) (((x) >> 24) & 7)
+#define LWL_PORT(x) (((x)&7) << 24)
+
+#define LWL_PORT_CONSOLE 1
+#define ID_SIG 0x7216A318
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static ssize_t lwlconsole_read(struct file *filep, char *buffer,
+                               size_t buflen);
+static ssize_t lwlconsole_write(struct file *filep, const char *buffer,
+                                size_t buflen);
+static int lwlconsole_ioctl(struct file *filep, int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct lwl_entry_s
+{
+  uint32_t sig;               /* Location signature */
+  volatile uint32_t downword; /* Host to Target word */
+  uint32_t upword;            /* Target to Host word */
+};
+
+static struct lwl_entry_s g_d =
+{
+  .sig = ID_SIG
+};
+
+static const struct file_operations g_consoleops =
+{
+  NULL,                       /* open */
+  NULL,                       /* close */
+  lwlconsole_read,            /* read */
+  lwlconsole_write,           /* write */
+  NULL,                       /* seek */
+  lwlconsole_ioctl,           /* ioctl */
+  NULL                        /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+    ,
+  NULL                        /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static bool linkactive(void)
+{
+  return (LWL_GETACTIVE(g_d.downword) != 0);
+}
+
+static bool writeword(uint32_t newupword)
+{
+  /* Check link is active */
+
+  if (!linkactive())
+    {
+      return false;
+    }
+
+  /* Spin waiting for previous data to be collected */
+
+  while (LWL_UPSENSE(g_d.downword) != LWL_UPSENSE(g_d.upword))
+    {
+    }
+
+  /* Load new data, toggling UPSENSE bit to show it is new */
+
+  g_d.upword = LWL_DNSENSE(g_d.upword) | newupword |
+               (LWL_UPSENSE(g_d.upword) ? 0 : LWL_UPSENSEBIT);
+
+  return true;
+}
+
+static bool write8bits(uint8_t port, uint8_t val)
+{
+  /* Prepare new word */
+
+  uint32_t newupword = LWL_ACTIVE(true) | LWL_OCTVAL(1) |
+                       LWL_PORT(port) | (val & 0xff);
+
+  return writeword(newupword);
+}
+
+static bool write16bits(uint8_t port, uint32_t val)
+{
+  /* Prepare new word */
+
+  uint32_t newupword = LWL_ACTIVE(true) | LWL_OCTVAL(2) |
+                       LWL_PORT(port) | (val & 0xffff);
+
+  return writeword(newupword);
+}
+
+static bool write24bits(uint8_t port, uint32_t val)
+{
+  /* Prepare new word */
+
+  uint32_t newupword = LWL_ACTIVE(true) | LWL_OCTVAL(3) |
+                       LWL_PORT(port) | (val & 0xffffff);
+
+  return writeword(newupword);
+}
+
+static bool read8bits(uint8_t port, uint8_t * store)
+{
+  if (LWL_DNSENSE(g_d.downword) == LWL_DNSENSE(g_d.upword))
+    {
+      return false;
+    }
+
+  *store = g_d.downword & 255;

Review comment:
       how to handle the host transfer the data more than one byte?

##########
File path: drivers/lwl_console.c
##########
@@ -0,0 +1,314 @@
+/****************************************************************************
+ * drivers/lwlconsole.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <syscall.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Lightweight Link (lwl)
+ * ======================
+ *
+ * Lightweight bidirectional communication between target and debug host
+ * without any need for additional hardware.
+ *
+ * Works with openOCD and other debuggers that are capable of reading and
+ * writing memory while the target is running.
+ *
+ * Principle of operation is simple; An 'upword' of 32 bits communicates
+ * from the target to the host, a 'downword' of the same size runs in the
+ * opposite direction. These two words can be in any memory that is
+ * read/write access for both the target and the debug host. A simple ping
+ * pong handshake protocol over these words allows up/down link
+ * communication.  On the upside no additional integration is needed. On
+ * the downside it may be necessary to feed lwl with cycles to poll for
+ * changes in the downword, depending on the use case.
+ *
+ * Bit configuration
+ * -----------------
+ *
+ * Downword (Host to target);
+ *
+ * A D U VV XXX
+ *
+ * A   31    1 - Service Active (Set by host)
+ * D   30    1 - Downsense (Toggled when there is data)
+ * U   29    1 - Upsense ack (Toggled to acknowledge receipt of uplink data)
+ * VV  28-27 2 - Valid Octets (Number of octets valid in the message)
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ * Upword (Target to Host);
+ *
+ * A   31    1 - Service Active (Set by device)
+ * D   30    1 - Downsense ack (Toggled to acknowledge receipt of downlink
+ *               data)
+ * U   29    1 - Upsense (Toggled when there is data)
+ * VV  28-27 2 - Valid upword octets
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ */
+
+/* Protocol bits */
+
+#define LWL_GETACTIVE(x) (((x) & (1 << 31)) != 0)
+#define LWL_ACTIVE(x) (((x)&1) << 31)
+
+#define LWL_DNSENSEBIT (1 << 30)
+#define LWL_DNSENSE(x) ((x)&LWL_DNSENSEBIT)
+#define LWL_UPSENSEBIT (1 << 29)
+#define LWL_UPSENSE(x) ((x)&LWL_UPSENSEBIT)
+#define LWL_SENSEMASK (3 << 29)
+
+#define LWL_GETOCTVAL(x) (((x) >> 27) & 3)
+#define LWL_OCTVAL(x) (((x)&3) << 27)
+#define LWL_GETPORT(x) (((x) >> 24) & 7)
+#define LWL_PORT(x) (((x)&7) << 24)
+
+#define LWL_PORT_CONSOLE 1
+#define ID_SIG 0x7216A318
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static ssize_t lwlconsole_read(struct file *filep, char *buffer,
+                               size_t buflen);
+static ssize_t lwlconsole_write(struct file *filep, const char *buffer,
+                                size_t buflen);
+static int lwlconsole_ioctl(struct file *filep, int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct lwl_entry_s
+{
+  uint32_t sig;               /* Location signature */
+  volatile uint32_t downword; /* Host to Target word */
+  uint32_t upword;            /* Target to Host word */
+};
+
+static struct lwl_entry_s g_d =
+{
+  .sig = ID_SIG
+};
+
+static const struct file_operations g_consoleops =
+{
+  NULL,                       /* open */
+  NULL,                       /* close */
+  lwlconsole_read,            /* read */
+  lwlconsole_write,           /* write */
+  NULL,                       /* seek */
+  lwlconsole_ioctl,           /* ioctl */
+  NULL                        /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+    ,
+  NULL                        /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static bool linkactive(void)
+{
+  return (LWL_GETACTIVE(g_d.downword) != 0);
+}
+
+static bool writeword(uint32_t newupword)
+{
+  /* Check link is active */
+
+  if (!linkactive())
+    {
+      return false;
+    }
+
+  /* Spin waiting for previous data to be collected */
+
+  while (LWL_UPSENSE(g_d.downword) != LWL_UPSENSE(g_d.upword))
+    {
+    }
+
+  /* Load new data, toggling UPSENSE bit to show it is new */
+
+  g_d.upword = LWL_DNSENSE(g_d.upword) | newupword |
+               (LWL_UPSENSE(g_d.upword) ? 0 : LWL_UPSENSEBIT);
+
+  return true;
+}
+
+static bool write8bits(uint8_t port, uint8_t val)
+{
+  /* Prepare new word */
+
+  uint32_t newupword = LWL_ACTIVE(true) | LWL_OCTVAL(1) |
+                       LWL_PORT(port) | (val & 0xff);
+
+  return writeword(newupword);
+}
+
+static bool write16bits(uint8_t port, uint32_t val)
+{
+  /* Prepare new word */
+
+  uint32_t newupword = LWL_ACTIVE(true) | LWL_OCTVAL(2) |
+                       LWL_PORT(port) | (val & 0xffff);
+
+  return writeword(newupword);
+}
+
+static bool write24bits(uint8_t port, uint32_t val)
+{
+  /* Prepare new word */
+
+  uint32_t newupword = LWL_ACTIVE(true) | LWL_OCTVAL(3) |
+                       LWL_PORT(port) | (val & 0xffffff);
+
+  return writeword(newupword);
+}
+
+static bool read8bits(uint8_t port, uint8_t * store)
+{
+  if (LWL_DNSENSE(g_d.downword) == LWL_DNSENSE(g_d.upword))

Review comment:
       why not change to while here and remove the loop from lwlconsole_read to make it like writeword?

##########
File path: drivers/lwl_console.c
##########
@@ -0,0 +1,314 @@
+/****************************************************************************
+ * drivers/lwlconsole.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <syscall.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Lightweight Link (lwl)
+ * ======================
+ *
+ * Lightweight bidirectional communication between target and debug host
+ * without any need for additional hardware.
+ *
+ * Works with openOCD and other debuggers that are capable of reading and
+ * writing memory while the target is running.
+ *
+ * Principle of operation is simple; An 'upword' of 32 bits communicates
+ * from the target to the host, a 'downword' of the same size runs in the
+ * opposite direction. These two words can be in any memory that is
+ * read/write access for both the target and the debug host. A simple ping
+ * pong handshake protocol over these words allows up/down link
+ * communication.  On the upside no additional integration is needed. On
+ * the downside it may be necessary to feed lwl with cycles to poll for
+ * changes in the downword, depending on the use case.
+ *
+ * Bit configuration
+ * -----------------
+ *
+ * Downword (Host to target);
+ *
+ * A D U VV XXX
+ *
+ * A   31    1 - Service Active (Set by host)
+ * D   30    1 - Downsense (Toggled when there is data)
+ * U   29    1 - Upsense ack (Toggled to acknowledge receipt of uplink data)
+ * VV  28-27 2 - Valid Octets (Number of octets valid in the message)
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ * Upword (Target to Host);
+ *
+ * A   31    1 - Service Active (Set by device)
+ * D   30    1 - Downsense ack (Toggled to acknowledge receipt of downlink
+ *               data)
+ * U   29    1 - Upsense (Toggled when there is data)
+ * VV  28-27 2 - Valid upword octets
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ */
+
+/* Protocol bits */
+
+#define LWL_GETACTIVE(x) (((x) & (1 << 31)) != 0)
+#define LWL_ACTIVE(x) (((x)&1) << 31)
+
+#define LWL_DNSENSEBIT (1 << 30)
+#define LWL_DNSENSE(x) ((x)&LWL_DNSENSEBIT)
+#define LWL_UPSENSEBIT (1 << 29)
+#define LWL_UPSENSE(x) ((x)&LWL_UPSENSEBIT)
+#define LWL_SENSEMASK (3 << 29)
+
+#define LWL_GETOCTVAL(x) (((x) >> 27) & 3)
+#define LWL_OCTVAL(x) (((x)&3) << 27)
+#define LWL_GETPORT(x) (((x) >> 24) & 7)
+#define LWL_PORT(x) (((x)&7) << 24)
+
+#define LWL_PORT_CONSOLE 1
+#define ID_SIG 0x7216A318
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static ssize_t lwlconsole_read(struct file *filep, char *buffer,
+                               size_t buflen);
+static ssize_t lwlconsole_write(struct file *filep, const char *buffer,
+                                size_t buflen);
+static int lwlconsole_ioctl(struct file *filep, int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct lwl_entry_s
+{
+  uint32_t sig;               /* Location signature */
+  volatile uint32_t downword; /* Host to Target word */
+  uint32_t upword;            /* Target to Host word */
+};
+
+static struct lwl_entry_s g_d =
+{
+  .sig = ID_SIG
+};
+
+static const struct file_operations g_consoleops =
+{
+  NULL,                       /* open */
+  NULL,                       /* close */
+  lwlconsole_read,            /* read */
+  lwlconsole_write,           /* write */
+  NULL,                       /* seek */
+  lwlconsole_ioctl,           /* ioctl */
+  NULL                        /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+    ,
+  NULL                        /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static bool linkactive(void)
+{
+  return (LWL_GETACTIVE(g_d.downword) != 0);
+}
+
+static bool writeword(uint32_t newupword)
+{
+  /* Check link is active */
+
+  if (!linkactive())
+    {
+      return false;
+    }
+
+  /* Spin waiting for previous data to be collected */
+
+  while (LWL_UPSENSE(g_d.downword) != LWL_UPSENSE(g_d.upword))
+    {
+    }
+
+  /* Load new data, toggling UPSENSE bit to show it is new */
+
+  g_d.upword = LWL_DNSENSE(g_d.upword) | newupword |
+               (LWL_UPSENSE(g_d.upword) ? 0 : LWL_UPSENSEBIT);

Review comment:
       remove LWL_DNSENSE(g_d.upword) | ?

##########
File path: drivers/lwl_console.c
##########
@@ -0,0 +1,314 @@
+/****************************************************************************
+ * drivers/lwlconsole.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <syscall.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Lightweight Link (lwl)
+ * ======================
+ *
+ * Lightweight bidirectional communication between target and debug host
+ * without any need for additional hardware.
+ *
+ * Works with openOCD and other debuggers that are capable of reading and
+ * writing memory while the target is running.
+ *
+ * Principle of operation is simple; An 'upword' of 32 bits communicates
+ * from the target to the host, a 'downword' of the same size runs in the
+ * opposite direction. These two words can be in any memory that is
+ * read/write access for both the target and the debug host. A simple ping
+ * pong handshake protocol over these words allows up/down link
+ * communication.  On the upside no additional integration is needed. On
+ * the downside it may be necessary to feed lwl with cycles to poll for
+ * changes in the downword, depending on the use case.
+ *
+ * Bit configuration
+ * -----------------
+ *
+ * Downword (Host to target);
+ *
+ * A D U VV XXX
+ *
+ * A   31    1 - Service Active (Set by host)
+ * D   30    1 - Downsense (Toggled when there is data)
+ * U   29    1 - Upsense ack (Toggled to acknowledge receipt of uplink data)
+ * VV  28-27 2 - Valid Octets (Number of octets valid in the message)
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ * Upword (Target to Host);
+ *
+ * A   31    1 - Service Active (Set by device)
+ * D   30    1 - Downsense ack (Toggled to acknowledge receipt of downlink
+ *               data)
+ * U   29    1 - Upsense (Toggled when there is data)
+ * VV  28-27 2 - Valid upword octets
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ */
+
+/* Protocol bits */
+
+#define LWL_GETACTIVE(x) (((x) & (1 << 31)) != 0)
+#define LWL_ACTIVE(x) (((x)&1) << 31)
+
+#define LWL_DNSENSEBIT (1 << 30)
+#define LWL_DNSENSE(x) ((x)&LWL_DNSENSEBIT)
+#define LWL_UPSENSEBIT (1 << 29)
+#define LWL_UPSENSE(x) ((x)&LWL_UPSENSEBIT)
+#define LWL_SENSEMASK (3 << 29)
+
+#define LWL_GETOCTVAL(x) (((x) >> 27) & 3)
+#define LWL_OCTVAL(x) (((x)&3) << 27)
+#define LWL_GETPORT(x) (((x) >> 24) & 7)
+#define LWL_PORT(x) (((x)&7) << 24)
+
+#define LWL_PORT_CONSOLE 1
+#define ID_SIG 0x7216A318
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static ssize_t lwlconsole_read(struct file *filep, char *buffer,
+                               size_t buflen);
+static ssize_t lwlconsole_write(struct file *filep, const char *buffer,
+                                size_t buflen);
+static int lwlconsole_ioctl(struct file *filep, int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct lwl_entry_s
+{
+  uint32_t sig;               /* Location signature */
+  volatile uint32_t downword; /* Host to Target word */
+  uint32_t upword;            /* Target to Host word */
+};
+
+static struct lwl_entry_s g_d =
+{
+  .sig = ID_SIG
+};
+
+static const struct file_operations g_consoleops =
+{
+  NULL,                       /* open */
+  NULL,                       /* close */
+  lwlconsole_read,            /* read */
+  lwlconsole_write,           /* write */
+  NULL,                       /* seek */
+  lwlconsole_ioctl,           /* ioctl */
+  NULL                        /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+    ,
+  NULL                        /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static bool linkactive(void)
+{
+  return (LWL_GETACTIVE(g_d.downword) != 0);
+}
+
+static bool writeword(uint32_t newupword)
+{
+  /* Check link is active */
+
+  if (!linkactive())
+    {
+      return false;
+    }
+
+  /* Spin waiting for previous data to be collected */
+
+  while (LWL_UPSENSE(g_d.downword) != LWL_UPSENSE(g_d.upword))
+    {
+    }
+
+  /* Load new data, toggling UPSENSE bit to show it is new */
+
+  g_d.upword = LWL_DNSENSE(g_d.upword) | newupword |
+               (LWL_UPSENSE(g_d.upword) ? 0 : LWL_UPSENSEBIT);
+
+  return true;
+}
+
+static bool write8bits(uint8_t port, uint8_t val)
+{
+  /* Prepare new word */
+
+  uint32_t newupword = LWL_ACTIVE(true) | LWL_OCTVAL(1) |
+                       LWL_PORT(port) | (val & 0xff);
+
+  return writeword(newupword);
+}
+
+static bool write16bits(uint8_t port, uint32_t val)
+{
+  /* Prepare new word */
+
+  uint32_t newupword = LWL_ACTIVE(true) | LWL_OCTVAL(2) |
+                       LWL_PORT(port) | (val & 0xffff);
+
+  return writeword(newupword);
+}
+
+static bool write24bits(uint8_t port, uint32_t val)
+{
+  /* Prepare new word */
+
+  uint32_t newupword = LWL_ACTIVE(true) | LWL_OCTVAL(3) |
+                       LWL_PORT(port) | (val & 0xffffff);
+
+  return writeword(newupword);
+}
+
+static bool read8bits(uint8_t port, uint8_t * store)
+{
+  if (LWL_DNSENSE(g_d.downword) == LWL_DNSENSE(g_d.upword))
+    {
+      return false;
+    }
+
+  *store = g_d.downword & 255;
+
+  /* Flip the bit to indicate the datum is read */
+
+  g_d.upword = (g_d.upword & ~LWL_DNSENSEBIT) | LWL_DNSENSE(g_d.downword);
+
+  return true;
+}
+
+/****************************************************************************
+ * Name: lwlconsole_ioctl
+ ****************************************************************************/
+
+static int lwlconsole_ioctl(struct file *filep, int cmd, unsigned long arg)
+{
+  return -ENOTTY;
+}
+
+/****************************************************************************
+ * Name: lwlconsole_read
+ ****************************************************************************/
+
+static ssize_t lwlconsole_read(struct file *filep, char *buffer,
+                               size_t buflen)
+{
+  if (buflen == 0 || !linkactive())
+    {
+      return 0;
+    }
+
+  while (!read8bits(LWL_PORT_CONSOLE, (uint8_t *) buffer))
+    {
+    }
+
+  return 1;
+}
+
+/****************************************************************************
+ * Name: lwlconsole_write
+ ****************************************************************************/
+
+static ssize_t lwlconsole_write(struct file *filep, const char *buffer,
+                                size_t buflen)
+{
+  uint32_t oc = 0;
+
+  while (buflen)
+    {
+      switch (buflen)
+        {
+          case 0:
+            return oc;
+
+          case 1:
+            if (write8bits(LWL_PORT_CONSOLE, buffer[0]))
+              {
+                oc++;
+                buffer++;
+                buflen--;
+              }
+            break;
+
+          case 2:
+            if (write16bits(LWL_PORT_CONSOLE, buffer[0] | (buffer[1] << 8)))
+              {
+                oc += 2;
+                buffer += 2;
+                buflen -= 2;
+              }
+            break;
+
+          default:
+            if (write24bits(LWL_PORT_CONSOLE, buffer[0] |
+                            (buffer[1] << 8) | (buffer[2] << 16)))
+              {
+                oc += 3;
+                buffer += 3;
+                buflen -= 3;
+              }
+            break;
+        }
+    }
+
+  return oc;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: lwlconsole_init
+ ****************************************************************************/
+
+void lwlconsole_init(void)
+{
+  g_d.upword = 0;

Review comment:
       don't need?

##########
File path: drivers/lwl_console.c
##########
@@ -0,0 +1,314 @@
+/****************************************************************************
+ * drivers/lwlconsole.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <syscall.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Lightweight Link (lwl)
+ * ======================
+ *
+ * Lightweight bidirectional communication between target and debug host
+ * without any need for additional hardware.
+ *
+ * Works with openOCD and other debuggers that are capable of reading and
+ * writing memory while the target is running.
+ *
+ * Principle of operation is simple; An 'upword' of 32 bits communicates
+ * from the target to the host, a 'downword' of the same size runs in the
+ * opposite direction. These two words can be in any memory that is
+ * read/write access for both the target and the debug host. A simple ping
+ * pong handshake protocol over these words allows up/down link
+ * communication.  On the upside no additional integration is needed. On
+ * the downside it may be necessary to feed lwl with cycles to poll for
+ * changes in the downword, depending on the use case.
+ *
+ * Bit configuration
+ * -----------------
+ *
+ * Downword (Host to target);
+ *
+ * A D U VV XXX
+ *
+ * A   31    1 - Service Active (Set by host)
+ * D   30    1 - Downsense (Toggled when there is data)
+ * U   29    1 - Upsense ack (Toggled to acknowledge receipt of uplink data)
+ * VV  28-27 2 - Valid Octets (Number of octets valid in the message)
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ * Upword (Target to Host);
+ *
+ * A   31    1 - Service Active (Set by device)
+ * D   30    1 - Downsense ack (Toggled to acknowledge receipt of downlink
+ *               data)
+ * U   29    1 - Upsense (Toggled when there is data)
+ * VV  28-27 2 - Valid upword octets
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ */
+
+/* Protocol bits */
+
+#define LWL_GETACTIVE(x) (((x) & (1 << 31)) != 0)
+#define LWL_ACTIVE(x) (((x)&1) << 31)
+
+#define LWL_DNSENSEBIT (1 << 30)
+#define LWL_DNSENSE(x) ((x)&LWL_DNSENSEBIT)
+#define LWL_UPSENSEBIT (1 << 29)
+#define LWL_UPSENSE(x) ((x)&LWL_UPSENSEBIT)
+#define LWL_SENSEMASK (3 << 29)
+
+#define LWL_GETOCTVAL(x) (((x) >> 27) & 3)
+#define LWL_OCTVAL(x) (((x)&3) << 27)
+#define LWL_GETPORT(x) (((x) >> 24) & 7)
+#define LWL_PORT(x) (((x)&7) << 24)
+
+#define LWL_PORT_CONSOLE 1
+#define ID_SIG 0x7216A318
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static ssize_t lwlconsole_read(struct file *filep, char *buffer,
+                               size_t buflen);
+static ssize_t lwlconsole_write(struct file *filep, const char *buffer,
+                                size_t buflen);
+static int lwlconsole_ioctl(struct file *filep, int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+struct lwl_entry_s
+{
+  uint32_t sig;               /* Location signature */
+  volatile uint32_t downword; /* Host to Target word */
+  uint32_t upword;            /* Target to Host word */
+};
+
+static struct lwl_entry_s g_d =
+{
+  .sig = ID_SIG
+};
+
+static const struct file_operations g_consoleops =
+{
+  NULL,                       /* open */
+  NULL,                       /* close */
+  lwlconsole_read,            /* read */
+  lwlconsole_write,           /* write */
+  NULL,                       /* seek */
+  lwlconsole_ioctl,           /* ioctl */
+  NULL                        /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+    ,
+  NULL                        /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static bool linkactive(void)
+{
+  return (LWL_GETACTIVE(g_d.downword) != 0);
+}
+
+static bool writeword(uint32_t newupword)
+{
+  /* Check link is active */
+
+  if (!linkactive())
+    {
+      return false;
+    }
+
+  /* Spin waiting for previous data to be collected */
+
+  while (LWL_UPSENSE(g_d.downword) != LWL_UPSENSE(g_d.upword))
+    {
+    }
+
+  /* Load new data, toggling UPSENSE bit to show it is new */
+
+  g_d.upword = LWL_DNSENSE(g_d.upword) | newupword |
+               (LWL_UPSENSE(g_d.upword) ? 0 : LWL_UPSENSEBIT);
+
+  return true;
+}
+
+static bool write8bits(uint8_t port, uint8_t val)
+{
+  /* Prepare new word */
+
+  uint32_t newupword = LWL_ACTIVE(true) | LWL_OCTVAL(1) |
+                       LWL_PORT(port) | (val & 0xff);
+
+  return writeword(newupword);
+}
+
+static bool write16bits(uint8_t port, uint32_t val)
+{
+  /* Prepare new word */
+
+  uint32_t newupword = LWL_ACTIVE(true) | LWL_OCTVAL(2) |
+                       LWL_PORT(port) | (val & 0xffff);
+
+  return writeword(newupword);
+}
+
+static bool write24bits(uint8_t port, uint32_t val)
+{
+  /* Prepare new word */
+
+  uint32_t newupword = LWL_ACTIVE(true) | LWL_OCTVAL(3) |
+                       LWL_PORT(port) | (val & 0xffffff);
+
+  return writeword(newupword);
+}
+
+static bool read8bits(uint8_t port, uint8_t * store)
+{
+  if (LWL_DNSENSE(g_d.downword) == LWL_DNSENSE(g_d.upword))
+    {
+      return false;
+    }
+
+  *store = g_d.downword & 255;
+
+  /* Flip the bit to indicate the datum is read */
+
+  g_d.upword = (g_d.upword & ~LWL_DNSENSEBIT) | LWL_DNSENSE(g_d.downword);
+
+  return true;
+}
+
+/****************************************************************************
+ * Name: lwlconsole_ioctl
+ ****************************************************************************/
+
+static int lwlconsole_ioctl(struct file *filep, int cmd, unsigned long arg)
+{
+  return -ENOTTY;
+}
+
+/****************************************************************************
+ * Name: lwlconsole_read
+ ****************************************************************************/
+
+static ssize_t lwlconsole_read(struct file *filep, char *buffer,
+                               size_t buflen)
+{
+  if (buflen == 0 || !linkactive())

Review comment:
       move linkactive to read8bits like writeword

##########
File path: drivers/lwl_console.c
##########
@@ -0,0 +1,314 @@
+/****************************************************************************
+ * drivers/lwlconsole.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <syscall.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Lightweight Link (lwl)
+ * ======================
+ *
+ * Lightweight bidirectional communication between target and debug host
+ * without any need for additional hardware.
+ *
+ * Works with openOCD and other debuggers that are capable of reading and
+ * writing memory while the target is running.
+ *
+ * Principle of operation is simple; An 'upword' of 32 bits communicates
+ * from the target to the host, a 'downword' of the same size runs in the
+ * opposite direction. These two words can be in any memory that is
+ * read/write access for both the target and the debug host. A simple ping
+ * pong handshake protocol over these words allows up/down link
+ * communication.  On the upside no additional integration is needed. On
+ * the downside it may be necessary to feed lwl with cycles to poll for
+ * changes in the downword, depending on the use case.
+ *
+ * Bit configuration
+ * -----------------
+ *
+ * Downword (Host to target);
+ *
+ * A D U VV XXX
+ *
+ * A   31    1 - Service Active (Set by host)
+ * D   30    1 - Downsense (Toggled when there is data)
+ * U   29    1 - Upsense ack (Toggled to acknowledge receipt of uplink data)
+ * VV  28-27 2 - Valid Octets (Number of octets valid in the message)
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ * Upword (Target to Host);
+ *
+ * A   31    1 - Service Active (Set by device)
+ * D   30    1 - Downsense ack (Toggled to acknowledge receipt of downlink
+ *               data)
+ * U   29    1 - Upsense (Toggled when there is data)
+ * VV  28-27 2 - Valid upword octets
+ * XXX 26-24 3 - Port in use (Type of the message)
+ * O2  23-16 8 - Octet 2
+ * O1  15-08 8 - Octet 1
+ * O0  07-00 8 - Octet 0
+ *
+ */
+
+/* Protocol bits */
+
+#define LWL_GETACTIVE(x) (((x) & (1 << 31)) != 0)
+#define LWL_ACTIVE(x) (((x)&1) << 31)
+
+#define LWL_DNSENSEBIT (1 << 30)
+#define LWL_DNSENSE(x) ((x)&LWL_DNSENSEBIT)
+#define LWL_UPSENSEBIT (1 << 29)
+#define LWL_UPSENSE(x) ((x)&LWL_UPSENSEBIT)
+#define LWL_SENSEMASK (3 << 29)
+
+#define LWL_GETOCTVAL(x) (((x) >> 27) & 3)
+#define LWL_OCTVAL(x) (((x)&3) << 27)
+#define LWL_GETPORT(x) (((x) >> 24) & 7)
+#define LWL_PORT(x) (((x)&7) << 24)
+
+#define LWL_PORT_CONSOLE 1
+#define ID_SIG 0x7216A318
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static ssize_t lwlconsole_read(struct file *filep, char *buffer,

Review comment:
       add FAR for all pointer




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org