Merged nuttx/nuttx into master

This commit is contained in:
Masayuki Ishikawa 2017-05-22 09:10:04 +09:00
commit c9e817dc4d
29 changed files with 7123 additions and 52 deletions

View File

@ -12,7 +12,7 @@
<h1><big><font color="#3c34ec">
<i>NuttX RTOS Porting Guide</i>
</font></big></h1>
<p>Last Updated: February 7, 2017</p>
<p>Last Updated: May 20, 2017</p>
</td>
</tr>
</table>
@ -178,6 +178,13 @@
<a href="#leddefinitions">4.11.2 LED Definitions</a><br>
<a href="#ledapis">4.11.3 Common LED interfaces</a>
</ul>
<a href="#iobs">4.12 I/O Buffer Management</a>
<ul>
<a href="#iobconfig">4.12.1 Configuration Options</a><br>
<a href="#iobthrottle">4.12.2 Throttling</a><br>
<a href="#iobtypes">4.12.3 Public Types</a><br>
<a href="#iobprotos">4.12.4 Public Function Prototypes</a>
</ul>
</ul>
<a href="#NxFileSystem">5.0 NuttX File System</a><br>
<a href="#DeviceDrivers">6.0 NuttX Device Drivers</a>
@ -4172,6 +4179,429 @@ void board_autoled_off(int led);
</li>
</ul>
<h2><a name="iobs">4.12 I/O Buffer Management</a></h2>
NuttX supports generic I/O buffer management (IOB) logic.
This logic was originally added to support network I/O buffering, but has been generalized to meet buffering requirements by all device drivers.
At the time of this writing, IOBs are currently used not only be networking but also by logic in <code>drivers/syslog</code> and <code>drivers/wireless</code>.
NOTE that some of the wording in this section still reflects those legacy roots as a part of the networking subsystem.
This objectives of this feature are:
<ol>
<li>
Provide common I/O buffer management logic for all drivers,
</li>
<li>
Support I/O buffer allocation from both the tasking and interrupt level contexts.
</li>
<li>
Use a fixed amount of pre-allocated memory.
</li>
<li>
No costly, non-deterministic dynamic memory allocation.
</li>
<li>
When the fixed number of pre-allocated I/O buffers is exhausted, further attempts to allocate memory from tasking logic will cause the task to block and wait until a an I/O buffer to be freed.
</li>
<li>
Each I/O buffer should be small, but can be chained together to support buffering of larger thinks such as full size network packets.
</li>
<li>
Support <i>throttling</i> logic to prevent lower priority tasks from hogging all available I/O buffering.
</li>
</ol>
<h3><a name="iobconfig">4.12.1 Configuration Options</a></h3>
<dl>
<dt><code>CONFIG_MM_IOB</code>
<dd>Enables generic I/O buffer support. This setting will build the common I/O buffer (IOB) support library.
<dt><code>CONFIG_IOB_NBUFFERS</code>
<dd>Number of pre-allocated I/O buffers. Each packet is represented by a series of small I/O buffers in a chain. This setting determines the number of preallocated I/O buffers available for packet data.
The default value is setup for network support. The default is 8 buffers if neither TCP read-ahead or TCP write buffering is enabled (neither <code>CONFIG_NET_TCP_WRITE_BUFFERS</code> nor <code>CONFIG_NET_TCP_READAHEAD</code>), 24 if only write buffering is enabled, and 36 if both read-ahead and write buffering are enabled.
<dt><code>CONFIG_IOB_BUFSIZE</code>
<dd>Payload size of one I/O buffer. Each packet is represented by a series of small I/O buffers in a chain. This setting determines the data payload each preallocated I/O buffer. The default value is 196 bytes.
<dt><code>CONFIG_IOB_NCHAINS</code>
<dd>Number of pre-allocated I/O buffer chain heads. These tiny nodes are used as <i>containers</i> to support queueing of I/O buffer chains. This will limit the number of I/O transactions that can be <i>in-flight</i> at any give time. The default value of zero disables this features.
<dd>These generic I/O buffer chain containers are not currently used by any logic in NuttX. That is because their other other specialized I/O buffer chain containers that also carry a payload of usage specific information.
The default value is zero if nether TCP nor UDP read-ahead buffering is enabled (i.e., neither <code>CONFIG_NET_TCP_READAHEAD</code> && !<code>CONFIG_NET_UDP_READAHEAD</code> or eight if either is enabled.
<dt><code>CONFIG_IOB_THROTTLE</code>
<dd>I/O buffer throttle value. TCP write buffering and read-ahead buffer use the same pool of free I/O buffers. In order to prevent uncontrolled incoming TCP packets from hogging all of the available, pre-allocated I/O buffers, a throttling value is required. This throttle value assures that I/O buffers will be denied to the read-ahead logic before TCP writes are halted.
The default 0 if neither TCP write buffering nor TCP reada-ahead buffering is enabled. Otherwise, the default is 8.
<dt><code>CONFIG_IOB_DEBUG</code>
<dd>Force I/O buffer debug. This option will force debug output from I/O buffer logic. This is not normally something that would want to do but is convenient if you are debugging the I/O buffer logic and do not want to get overloaded with other un-related debug output.
NOTE that this selection is not avaiable if DEBUG features are not enabled (<code>CONFIG_DEBUG_FEATURES</code>) with IOBs are being used to syslog buffering logic (<code>CONFIG_SYSLOG_BUFFER</code>).
</dl>
<h3><a name="iobthrottle">4.12.2 Throttling</a></h3>
<b></b>
An allocation throttle was added. I/O buffer allocation logic supports a throttle value originally for read-ahead buffering to prevent the read-ahead logic from consuming all available I/O buffers and blocking the write buffering logic. This throttle logic is only needed for networking only if both write buffering and read-ahead buffering are used. Of use of I/O buffering might have other motivations for throttling.
<h3><a name="iobtypes">4.12.3 Public Types</a></h3>
<p>
This structure epresents one I/O buffer. A packet is contained by one or more I/O buffers in a chain. The <code>io_pktlen</code> is only valid for the I/O buffer at the head of the chain.
</p>
<pre>
struct iob_s
{
/* Singly-link list support */
FAR struct iob_s *io_flink;
/* Payload */
#if CONFIG_IOB_BUFSIZE < 256
uint8_t io_len; /* Length of the data in the entry */
uint8_t io_offset; /* Data begins at this offset */
#else
uint16_t io_len; /* Length of the data in the entry */
uint16_t io_offset; /* Data begins at this offset */
#endif
uint16_t io_pktlen; /* Total length of the packet */
uint8_t io_data[CONFIG_IOB_BUFSIZE];
};
</pre>
<p>
This container structure supports queuing of I/O buffer chains. This structure is intended only for internal use by the IOB module.
</p>
<pre>
#if CONFIG_IOB_NCHAINS > 0
struct iob_qentry_s
{
/* Singly-link list support */
FAR struct iob_qentry_s *qe_flink;
/* Payload -- Head of the I/O buffer chain */
FAR struct iob_s *qe_head;
};
#endif /* CONFIG_IOB_NCHAINS > 0 */
</pre>
<p>
The I/O buffer queue head structure.
</p>
<pre>
#if CONFIG_IOB_NCHAINS > 0
struct iob_queue_s
{
/* Head of the I/O buffer chain list */
FAR struct iob_qentry_s *qh_head;
FAR struct iob_qentry_s *qh_tail;
};
#endif /* CONFIG_IOB_NCHAINS > 0 */
</pre>
<h3><a name="iobprotos">4.12.4 Public Function Prototypes</a></h3>
<ul>
<li><a href="#iob_initialize">4.12.4.1 <code>iob_initialize()</code></a></li>
<li><a href="#iob_alloc">4.12.4.2 <code>iob_alloc()</code></a></li>
<li><a href="#iob_tryalloc">4.12.4.3 <code>iob_tryalloc()</code></a></li>
<li><a href="#iob_free">4.12.4.4 <code>iob_free()</code></a></li>
<li><a href="#iob_free_chain">4.12.4.5 <code>iob_free_chain()</code></a></li>
<li><a href="#iob_add_queue">4.12.4.6 <code>iob_add_queue()</code></a></li>
<li><a href="#iob_tryadd_queue">4.12.4.7 <code>iob_tryadd_queue()</code></a></li>
<li><a href="#iob_remove_queue">4.12.4.8 <code>iob_remove_queue()</code></a></li>
<li><a href="#iob_peek_queue">4.12.4.9 <code>iob_peek_queue()</code></a></li>
<li><a href="#iob_free_queue">4.12.4.10 <code>iob_free_queue()</code></a></li>
<li><a href="#iob_copyin">4.12.4.11 <code>iob_copyin()</code></a></li>
<li><a href="#iob_trycopyin">4.12.4.12 <code>iob_trycopyin()</code></a></li>
<li><a href="#iob_copyout">4.12.4.13 <code>iob_copyout()</code></a></li>
<li><a href="#iob_clone">4.12.4.14 <code>iob_clone()</code></a></li>
<li><a href="#iob_concat">4.12.4.15 <code>iob_concat()</code></a></li>
<li><a href="#iob_trimhead">4.12.4.16 <code>iob_trimhead()</code></a></li>
<li><a href="#iob_trimhead_queue">4.12.4.17 <code>iob_trimhead_queue()</code></a></li>
<li><a href="#iob_trimtail">4.12.4.18 <code>iob_trimtail()</code></a></li>
<li><a href="#iob_pack">4.12.4.19 <code>iob_pack()</code></a></li>
<li><a href="#iob_contig">4.12.4.20 <code>iob_contig()</code></a></li>
<li><a href="#iob_dump">4.12.4.21 <code>iob_dump()</code></a></li>
</ul>
<h4><a name="iob_initialize">4.12.4.1 <code>iob_initialize()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
void iob_initialize(void);
</pre>
<p><b>Description</b>.
Set up the I/O buffers for normal operations.
</p>
<h4><a name="iob_alloc">4.12.4.2 <code>iob_alloc()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
FAR struct iob_s *iob_alloc(bool throttled);
</pre>
<p><b>Description</b>.
Allocate an I/O buffer by taking the buffer at the head of the free list.
</p>
<h4><a name="iob_tryalloc">4.12.4.3 <code>iob_tryalloc()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
FAR struct iob_s *iob_tryalloc(bool throttled);
</pre>
<p><b>Description</b>.
Try to allocate an I/O buffer by taking the buffer at the head of the free list without waiting for a buffer to become free.
</p>
<h4><a name="iob_free">4.12.4.4 <code>iob_free()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
FAR struct iob_s *iob_free(FAR struct iob_s *iob);
</pre>
<p><b>Description</b>.
Free the I/O buffer at the head of a buffer chain returning it to the free list. The link to the next I/O buffer in the chain is return.
</p>
<h4><a name="iob_free_chain">4.12.4.5 <code>iob_free_chain()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
void iob_free_chain(FAR struct iob_s *iob);
</pre>
<p><b>Description</b>.
Free an entire buffer chain, starting at the beginning of the I/O buffer chain
</p>
<h4><a name="iob_add_queue">4.12.4.6 <code>iob_add_queue()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
#if CONFIG_IOB_NCHAINS > 0
int iob_add_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq);
#endif /* CONFIG_IOB_NCHAINS > 0 */
</pre>
<p><b>Description</b>.
Add one I/O buffer chain to the end of a queue. May fail due to lack of resources.
</p>
<h4><a name="iob_tryadd_queue">4.12.4.7 <code>iob_tryadd_queue()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
#if CONFIG_IOB_NCHAINS > 0
int iob_tryadd_queue(FAR struct iob_s *iob, FAR struct iob_queue_s *iobq);
#endif /* CONFIG_IOB_NCHAINS > 0 */
</pre>
<p><b>Description</b>.
Add one I/O buffer chain to the end of a queue without waiting for resources to become free.
</p>
<h4><a name="iob_remove_queue">4.12.4.8 <code>iob_remove_queue()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
#if CONFIG_IOB_NCHAINS > 0
FAR struct iob_s *iob_remove_queue(FAR struct iob_queue_s *iobq);
#endif /* CONFIG_IOB_NCHAINS > 0 */
</pre>
<p><b>Description</b>.
Remove and return one I/O buffer chain from the head of a queue.
</p>
<p><b>Returned Value</b>.
Returns a reference to the I/O buffer chain at the head of the queue.
</p>
<h4><a name="iob_peek_queue">4.12.4.9 <code>iob_peek_queue()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
#if CONFIG_IOB_NCHAINS > 0
FAR struct iob_s *iob_peek_queue(FAR struct iob_queue_s *iobq);
#endif
</pre>
<p><b>Description</b>.
Return a reference to the I/O buffer chain at the head of a queue. This is similar to iob_remove_queue except that the I/O buffer chain is in place at the head of the queue. The I/O buffer chain may safely be modified by the caller but must be removed from the queue before it can be freed.
</p>
<p><b>Returned Value</b>.
Returns a reference to the I/O buffer chain at the head of the queue.
</p>
<h4><a name="iob_free_queue">4.12.4.10 <code>iob_free_queue()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
#if CONFIG_IOB_NCHAINS > 0
void iob_free_queue(FAR struct iob_queue_s *qhead);
#endif /* CONFIG_IOB_NCHAINS > 0 */
</pre>
<p><b>Description</b>.
Free an entire queue of I/O buffer chains.
</p>
<h4><a name="iob_copyin">4.12.4.11 <code>iob_copyin()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
int iob_copyin(FAR struct iob_s *iob, FAR const uint8_t *src,
unsigned int len, unsigned int offset, bool throttled);
</pre>
<p><b>Description</b>.
Copy data <code>len</code> bytes from a user buffer into the I/O buffer chain, starting at <code>offset</code>, extending the chain as necessary.
</p>
<h4><a name="iob_trycopyin">4.12.4.12 <code>iob_trycopyin()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
int iob_trycopyin(FAR struct iob_s *iob, FAR const uint8_t *src,
unsigned int len, unsigned int offset, bool throttled);
</pre>
<p><b>Description</b>.
Copy data <code>len</code> bytes from a user buffer into the I/O buffer chain, starting at <code>offset</code>, extending the chain as necessary BUT without waiting if buffers are not available.
</p>
<h4><a name="iob_copyout">4.12.4.13 <code>iob_copyout()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
int iob_copyout(FAR uint8_t *dest, FAR const struct iob_s *iob,
unsigned int len, unsigned int offset);
</pre>
<p><b>Description</b>.
Copy data <code>len</code> bytes of data into the user buffer starting at <code>offset</code> in the I/O buffer, returning that actual number of bytes copied out.
</p>
<h4><a name="iob_clone">4.12.4.14 <code>iob_clone()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
int iob_clone(FAR struct iob_s *iob1, FAR struct iob_s *iob2, bool throttled);
</pre>
<p><b>Description</b>.
Duplicate (and pack) the data in <code>iob1</code> in <code>iob2</code>. <code>iob2</code> must be empty.
</p>
<h4><a name="iob_concat">4.12.4.15 <code>iob_concat()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
void iob_concat(FAR struct iob_s *iob1, FAR struct iob_s *iob2);
</pre>
<p><b>Description</b>.
Concatenate iob_s chain iob2 to iob1.
</p>
<h4><a name="iob_trimhead">4.12.4.16 <code>iob_trimhead()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
FAR struct iob_s *iob_trimhead(FAR struct iob_s *iob, unsigned int trimlen);
</pre>
<p><b>Description</b>.
Remove bytes from the beginning of an I/O chain. Emptied I/O buffers are freed and, hence, the beginning of the chain may change.
</p>
<h4><a name="iob_trimhead_queue">4.12.4.17 <code>iob_trimhead_queue()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
#if CONFIG_IOB_NCHAINS > 0
FAR struct iob_s *iob_trimhead_queue(FAR struct iob_queue_s *qhead,
unsigned int trimlen);
#endif
</pre>
<p><b>Description</b>.
Remove bytes from the beginning of an I/O chain at the head of the queue. Emptied I/O buffers are freed and, hence, the head of the queue may change.
</p>
<p>
This function is just a wrapper around iob_trimhead() that assures that the iob at the head of queue is modified with the trimming operations.
</p>
<p><b>Returned Value</b>.
The new iob at the head of the queue is returned.
</p>
<h4><a name="iob_trimtail">4.12.4.18 <code>iob_trimtail()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
FAR struct iob_s *iob_trimtail(FAR struct iob_s *iob, unsigned int trimlen);
</pre>
<p><b>Description</b>.
Remove bytes from the end of an I/O chain. Emptied I/O buffers are freed NULL will be returned in the special case where the entry I/O buffer chain is freed.
</p>
<h4><a name="iob_pack">4.12.4.19 <code>iob_pack()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
FAR struct iob_s *iob_pack(FAR struct iob_s *iob);
</pre>
<p><b>Description</b>.
Pack all data in the I/O buffer chain so that the data offset is zero and all but the final buffer in the chain are filled. Any emptied buffers at the end of the chain are freed.
</p>
<h4><a name="iob_contig">4.12.4.20 <code>iob_contig()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
int iob_contig(FAR struct iob_s *iob, unsigned int len);
</pre>
<p><b>Description</b>.
Ensure that there is <code>len</code> bytes of contiguous space at the beginning of the I/O buffer chain starting at <code>iob</code>.
</p>
<h4><a name="iob_dump">4.12.4.21 <code>iob_dump()</code></a></h4>
<p><b>Function Prototype</b>:
<pre>
#include &lt;nuttx/mm/iob.h&gt;
#ifdef CONFIG_DEBUG_FEATURES
void iob_dump(FAR const char *msg, FAR struct iob_s *iob, unsigned int len,
unsigned int offset);
#endif
</pre>
<p><b>Description</b>.
Dump the contents of a I/O buffer chain
</p>
<table width ="100%">
<tr bgcolor="#e4e4e4">
<td>

View File

@ -1530,6 +1530,7 @@ config STM32_STM32F40XX
select STM32_HAVE_TIM4
select STM32_HAVE_SPI2
select STM32_HAVE_SPI3
select STM32_HAVE_I2S3
select STM32_HAVE_I2C2
select STM32_HAVE_I2C3
@ -1542,6 +1543,9 @@ config STM32_STM32F401
select STM32_HAVE_TIM9
select STM32_HAVE_TIM10
select STM32_HAVE_TIM11
select STM32_HAVE_SPI2
select STM32_HAVE_SPI3
select STM32_HAVE_I2S3
config STM32_STM32F410
bool
@ -1563,6 +1567,9 @@ config STM32_STM32F411
select STM32_HAVE_TIM9
select STM32_HAVE_TIM10
select STM32_HAVE_TIM11
select STM32_HAVE_SPI2
select STM32_HAVE_SPI3
select STM32_HAVE_I2S3
select STM32_HAVE_SPI4
select STM32_HAVE_SPI5
@ -1655,6 +1662,9 @@ config STM32_STM32F427
select STM32_HAVE_DAC2
select STM32_HAVE_RNG
select STM32_HAVE_ETHMAC
select STM32_HAVE_SPI2
select STM32_HAVE_SPI3
select STM32_HAVE_I2S3
select STM32_HAVE_SPI4
select STM32_HAVE_SPI5
select STM32_HAVE_SPI6
@ -1691,6 +1701,9 @@ config STM32_STM32F429
select STM32_HAVE_DAC2
select STM32_HAVE_RNG
select STM32_HAVE_ETHMAC
select STM32_HAVE_SPI2
select STM32_HAVE_SPI3
select STM32_HAVE_I2S3
select STM32_HAVE_SPI4
select STM32_HAVE_SPI5
select STM32_HAVE_SPI6
@ -2016,6 +2029,10 @@ config STM32_HAVE_SPI3
bool
default n
config STM32_HAVE_I2S3
bool
default n
config STM32_HAVE_SPI4
bool
default n
@ -2353,6 +2370,13 @@ config STM32_SPI3
select SPI
select STM32_SPI
config STM32_I2S3
bool "I2S3"
default n
depends on STM32_HAVE_I2S3
select I2S
select STM32_I2S
config STM32_SPI4
bool "SPI4"
default n
@ -2610,6 +2634,11 @@ config STM32_SPI3_REMAP
default n
depends on STM32_STM32F10XX && STM32_SPI3 && !STM32_VALUELINE
config STM32_I2S3_REMAP
bool "I2S3 Alternate Pin Mapping"
default n
depends on STM32_STM32F10XX && STM32_I2S3 && !STM32_VALUELINE
choice
prompt "TIM1 Alternate Pin Mappings"
depends on STM32_STM32F10XX && STM32_TIM1
@ -6270,6 +6299,66 @@ config STM32_SPI_DMA
endmenu
menu "I2S Configuration"
depends on STM32_I2S3
config STM32_I2S_MCK
bool "I2S_MCK"
default n
---help---
TBD.
config STM32_I2S_MAXINFLIGHT
int "I2S queue size"
default 16
---help---
This is the total number of transfers, both RX and TX, that can be
enqueue before the caller is required to wait. This setting
determines the number certain queue data structures that will be
pre-allocated.
comment "I2S3 Configuration"
config STM32_I2S3_DATALEN
int "Data width (bits)"
default 16
---help---
Data width in bits. This is a default value and may be change
via the I2S interface
#if STM32_I2S
config STM32_I2S3_RX
bool "Enable I2C receiver"
default n
---help---
Enable I2S receipt logic
config STM32_I2S3_TX
bool "Enable I2C transmitter"
default n
---help---
Enable I2S transmission logic
config STM32_I2S_DMADEBUG
bool "I2S DMA transfer debug"
depends on DEBUG_DMA
default n
---help---
Enable special debug instrumentation analyze I2S DMA data transfers.
This logic is as non-invasive as possible: It samples DMA
registers at key points in the data transfer and then dumps all of
the registers at the end of the transfer.
config STM32_I2S_REGDEBUG
bool "SSC Register level debug"
depends on DEBUG
default n
---help---
Output detailed register-level SSC device debug information.
Very invasive! Requires also DEBUG.
endmenu # I2S Configuration
menu "I2C Configuration"
depends on STM32_I2C

View File

@ -101,7 +101,7 @@ CHIP_ASRCS =
CHIP_CSRCS = stm32_allocateheap.c stm32_start.c stm32_rcc.c stm32_lse.c
CHIP_CSRCS += stm32_lsi.c stm32_gpio.c stm32_exti_gpio.c stm32_flash.c
CHIP_CSRCS += stm32_irq.c stm32_dma.c stm32_lowputc.c
CHIP_CSRCS += stm32_serial.c stm32_spi.c stm32_sdio.c stm32_tim.c
CHIP_CSRCS += stm32_serial.c stm32_spi.c stm32_i2s.c stm32_sdio.c stm32_tim.c
CHIP_CSRCS += stm32_waste.c stm32_ccm.c stm32_uid.c stm32_capture.c
ifeq ($(CONFIG_TIMER),y)

View File

@ -615,7 +615,7 @@
#endif
#define GPIO_SPI3_MISO_1 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN4)
#define GPIO_SPI3_MISO_2 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN11)
#define GPIO_SPI3_MISO_2 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN7)
#define GPIO_SPI3_MOSI_1 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTB|GPIO_PIN5)
#define GPIO_SPI3_MOSI_2 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTC|GPIO_PIN12)
#define GPIO_SPI3_NSS_1 (GPIO_ALT|GPIO_AF6|GPIO_SPEED_50MHz|GPIO_PORTA|GPIO_PIN15)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,90 @@
/************************************************************************************
* arch/arm/src/stm32/stm32_i2s.h
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 __ARCH_ARM_SRC_STM32_I2S_H
#define __ARCH_ARM_SRC_STM32_I2S_H
/************************************************************************************
* Included Files
************************************************************************************/
#include <nuttx/config.h>
#include <nuttx/audio/i2s.h>
#include "chip.h"
#include "chip/stm32_i2s.h"
#ifndef __ASSEMBLY__
/************************************************************************************
* Public Data
************************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/************************************************************************************
* Public Function Prototypes
************************************************************************************/
/************************************************************************************
* Name: stm32_i2sdev_initialize
*
* Description:
* Initialize the selected I2S port
*
* Input Parameter:
* Port number (for hardware that has mutiple I2S interfaces)
*
* Returned Value:
* Valid I2S device structure reference on succcess; a NULL on failure
*
************************************************************************************/
FAR struct i2s_dev_s *stm32_i2sdev_initialize(int port);
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_ARM_SRC_STM32_I2S_H */

View File

@ -1952,14 +1952,25 @@ static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
delay = 1000;
}
/* Wait for the next polling interval.
/* Wait for the next polling interval. For interrupt and
* isochronous endpoints, this is necessaryto assure the
* polling interval. It is used in other cases only to
* prevent the polling from consuming too much CPU bandwith.
*
* REVISIT: This delay could require more resolution than
* is provided by the system timer. In that case, the
* delay could be significantly longer than required.
* Small delays could require more resolution than is provided
* by the system timer. For example, if the system timer
* resolution is 10MS, then usleep(1000) will actually request
* a delay 20MS (due to both quantization and rounding).
*
* REVISIT: So which is better? To ignore tiny delays and
* hog the system bandwidth? Or to wait for an excessive
* amount and destroy system throughput?
*/
usleep(delay);
if (delay > CONFIG_USEC_PER_TICK)
{
usleep(delay - CONFIG_USEC_PER_TICK);
}
}
}
else

View File

@ -1957,14 +1957,25 @@ static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
delay = 1000;
}
/* Wait for the next polling interval.
/* Wait for the next polling interval. For interrupt and
* isochronous endpoints, this is necessaryto assure the
* polling interval. It is used in other cases only to
* prevent the polling from consuming too much CPU bandwith.
*
* REVISIT: This delay could require more resolution than
* is provided by the system timer. In that case, the
* delay could be significantly longer than required.
* Small delays could require more resolution than is provided
* by the system timer. For example, if the system timer
* resolution is 10MS, then usleep(1000) will actually request
* a delay 20MS (due to both quantization and rounding).
*
* REVISIT: So which is better? To ignore tiny delays and
* hog the system bandwidth? Or to wait for an excessive
* amount and destroy system throughput?
*/
usleep(delay);
if (delay > CONFIG_USEC_PER_TICK)
{
usleep(delay - CONFIG_USEC_PER_TICK);
}
}
}
else

View File

@ -1951,14 +1951,25 @@ static ssize_t stm32_in_transfer(FAR struct stm32_usbhost_s *priv, int chidx,
delay = 1000;
}
/* Wait for the next polling interval.
/* Wait for the next polling interval. For interrupt and
* isochronous endpoints, this is necessaryto assure the
* polling interval. It is used in other cases only to
* prevent the polling from consuming too much CPU bandwith.
*
* REVISIT: This delay could require more resolution than
* is provided by the system timer. In that case, the
* delay could be significantly longer than required.
* Small delays could require more resolution than is provided
* by the system timer. For example, if the system timer
* resolution is 10MS, then usleep(1000) will actually request
* a delay 20MS (due to both quantization and rounding).
*
* REVISIT: So which is better? To ignore tiny delays and
* hog the system bandwidth? Or to wait for an excessive
* amount and destroy system throughput?
*/
usleep(delay);
if (delay > CONFIG_USEC_PER_TICK)
{
usleep(delay - CONFIG_USEC_PER_TICK);
}
}
}
else

View File

@ -1956,14 +1956,25 @@ static ssize_t stm32l4_in_transfer(FAR struct stm32l4_usbhost_s *priv,
delay = 1000;
}
/* Wait for the next polling interval.
/* Wait for the next polling interval. For interrupt and
* isochronous endpoints, this is necessaryto assure the
* polling interval. It is used in other cases only to
* prevent the polling from consuming too much CPU bandwith.
*
* REVISIT: This delay could require more resolution than
* is provided by the system timer. In that case, the
* delay could be significantly longer than required.
* Small delays could require more resolution than is provided
* by the system timer. For example, if the system timer
* resolution is 10MS, then usleep(1000) will actually request
* a delay 20MS (due to both quantization and rounding).
*
* REVISIT: So which is better? To ignore tiny delays and
* hog the system bandwidth? Or to wait for an excessive
* amount and destroy system throughput?
*/
usleep(delay);
if (delay > CONFIG_USEC_PER_TICK)
{
usleep(delay - CONFIG_USEC_PER_TICK);
}
}
}
else

View File

@ -0,0 +1,17 @@
STATUS
======
05/17: The basic NSH configuration is functional and shows that there is
3-4KB of free heap space. However, attempts to extend this have
failed. I suspect that 8KB of SRAM is insufficient to do much
with the existing NSH configuration. Perhaps some fine tuning
can improve this situation but at this point, I think this board
is only useful for the initial STM32 F0 bring-up, perhaps for
embedded solutions that do not use NSH and for general
experimentation.
There is also support for the Nucleo boards with the STM32 F072
and F092 MCUs. Those ports do not suffer from these problems and
seem to work well in fairly complex configurations. Apparently 8KB
is SRAM is not usable but the parts with larger 16KB and 32KB SRAMs
are better matches.

View File

@ -300,9 +300,9 @@
/* SPI - There is a MEMS device on SPI1 using these pins: */
#define GPIO_SPI1_MISO GPIO_SPI1_MISO_1
#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1
#define GPIO_SPI1_SCK GPIO_SPI1_SCK_1
#define GPIO_SPI1_MISO GPIO_SPI1_MISO_1
#define GPIO_SPI1_MOSI GPIO_SPI1_MOSI_1
#define GPIO_SPI1_SCK GPIO_SPI1_SCK_1
/* SPI2 - Test MAX31855 on SPI2 PB10 = SCK, PB14 = MISO */
@ -310,10 +310,38 @@
#define GPIO_SPI2_MOSI GPIO_SPI2_MOSI_1
#define GPIO_SPI2_SCK GPIO_SPI2_SCK_1
/* SPI3 - Onboard devices use SPI3 */
#define GPIO_SPI3_MISO GPIO_SPI3_MISO_2
#define GPIO_SPI3_MOSI GPIO_SPI3_MOSI_2
#define GPIO_SPI3_SCK GPIO_SPI3_SCK_2
#define GPIO_SPI3_NSS GPIO_SPI3_NSS_2
/* I2S3 - Onboard devices use I2S3 */
#define GPIO_I2S3_SD GPIO_I2S3_SD_2
#define GPIO_I2S3_CK GPIO_I2S3_CK_2
#define GPIO_I2S3_WS GPIO_I2S3_WS_1
#define DMACHAN_SPI3_RX DMAMAP_SPI3_RX_2
#define DMACHAN_SPI3_TX DMAMAP_SPI3_TX_2
/* I2C config to use with Nunchuk PB7 (SDA) and PB8 (SCL) */
#if 0
#define GPIO_I2C1_SCL GPIO_I2C1_SCL_2
#define GPIO_I2C1_SDA GPIO_I2C1_SDA_1
#endif
/* I2C. Only I2C1 is available on the stm32f4discovery. I2C1_SCL and I2C1_SDA are
* available on the following pins:
*
* - PB6 is I2C1_SCL
* - PB9 is I2C1_SDA
*/
#define GPIO_I2C1_SCL GPIO_I2C1_SCL_1
#define GPIO_I2C1_SDA GPIO_I2C1_SDA_2
/* Timer Inputs/Outputs (see the README.txt file for options) */

View File

@ -44,6 +44,10 @@ else
CSRCS += stm32_userleds.c
endif
ifeq ($(CONFIG_AUDIO_CS43L22),y)
CSRCS += stm32_cs43l22.c
endif
ifeq ($(CONFIG_ARCH_BUTTONS),y)
CSRCS += stm32_buttons.c
endif

View File

@ -216,6 +216,16 @@ int stm32_bringup(void)
}
#endif
#ifdef HAVE_CS43L22
/* Configure CS43L22 audio */
ret = stm32_cs43l22_initialize(1);
if (ret != OK)
{
serr("Failed to initialize CS43L22 audio: %d\n", ret);
}
#endif
#ifdef HAVE_ELF
/* Initialize the ELF binary loader */

View File

@ -0,0 +1,389 @@
/************************************************************************************
* configs/stm32f4discovery/src/stm32_cs43l22.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Taras Drozdovskiy <t.drozdovskiy@gmail.com>
*
* 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 <nuttx/config.h>
#include <stdbool.h>
#include <stdio.h>
#include <debug.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/irq.h>
#include <nuttx/i2c/i2c_master.h>
#include <nuttx/audio/i2s.h>
#include <nuttx/audio/pcm.h>
#include <nuttx/audio/cs43l22.h>
#include <arch/board/board.h>
#include "stm32.h"
#include "stm32f4discovery.h"
#ifdef HAVE_CS43L22
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
struct stm32_mwinfo_s
{
/* Standard CS43L22 interface */
struct cs43l22_lower_s lower;
/* Extensions for the stm32f4discovery board */
cs43l22_handler_t handler;
FAR void *arg;
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* IRQ/PIO access callbacks. These operations all hidden behind
* callbacks to isolate the CS43L22 driver from differences in PIO
* interrupt handling by varying boards and MCUs. If possible,
* interrupts should be configured on both rising and falling edges
* so that contact and loss-of-contact events can be detected.
*
* attach - Attach the CS43L22 interrupt handler to the PIO interrupt
* enable - Enable or disable the PIO interrupt
*/
static int cs43l22_attach(FAR const struct cs43l22_lower_s *lower,
cs43l22_handler_t isr, FAR void *arg);
static bool cs43l22_enable(FAR const struct cs43l22_lower_s *lower,
bool enable);
static void cs43l22_hw_reset(FAR const struct cs43l22_lower_s *lower);
/****************************************************************************
* Private Data
****************************************************************************/
/* A reference to a structure of this type must be passed to the CS43L22
* driver. This structure provides information about the configuration
* of the CS43L22 and provides some board-specific hooks.
*
* Memory for this structure is provided by the caller. It is not copied
* by the driver and is presumed to persist while the driver is active.
*/
#define CONFIG_STM32_CS43L22_I2CFREQUENCY 100000
#define BOARD_MAINCK_FREQUENCY 8000000
static struct stm32_mwinfo_s g_cs43l22info =
{
.lower =
{
.address = CS43L22_I2C_ADDRESS,
.frequency = CONFIG_STM32_CS43L22_I2CFREQUENCY,
#ifdef CONFIG_STM32_CS43L22_SRCSCK
.mclk = BOARD_SLOWCLK_FREQUENCY,
#else
.mclk = BOARD_MAINCK_FREQUENCY,
#endif
.attach = cs43l22_attach,
.enable = cs43l22_enable,
.reset = cs43l22_hw_reset,
},
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* IRQ/PIO access callbacks. These operations all hidden behind
* callbacks to isolate the CS43L22 driver from differences in PIO
* interrupt handling by varying boards and MCUs. If possible,
* interrupts should be configured on both rising and falling edges
* so that contact and loss-of-contact events can be detected.
*
* attach - Attach the CS43L22 interrupt handler to the PIO interrupt
* enable - Enable or disable the PIO interrupt
* clear - Acknowledge/clear any pending PIO interrupt
*
****************************************************************************/
static int cs43l22_attach(FAR const struct cs43l22_lower_s *lower,
cs43l22_handler_t isr, FAR void *arg)
{
if (isr)
{
/* Just save the address of the handler and its argument for now. The
* new handler will called via cs43l22_interrupt() when the interrupt occurs.
*/
audinfo("Attaching %p\n", isr);
g_cs43l22info.handler = isr;
g_cs43l22info.arg = arg;
}
else
{
audinfo("Detaching %p\n", g_cs43l22info.handler);
(void)cs43l22_enable(lower, false);
g_cs43l22info.handler = NULL;
g_cs43l22info.arg = NULL;
}
return OK;
}
static bool cs43l22_enable(FAR const struct cs43l22_lower_s *lower, bool enable)
{
static bool enabled;
irqstate_t flags;
bool ret;
/* Has the interrupt state changed */
flags = enter_critical_section();
if (enable != enabled)
{
/* Enable or disable interrupts */
if (enable && g_cs43l22info.handler)
{
audinfo("Enabling\n");
/* TODO: stm32_pioirqenable(IRQ_INT_CS43L22); */
enabled = true;
}
else
{
audinfo("Disabling\n");
/* TODO: stm32_pioirqdisable(IRQ_INT_CS43L22); */
enabled = false;
}
}
ret = enabled;
leave_critical_section(flags);
return ret;
}
#if 0
static int cs43l22_interrupt(int irq, FAR void *context)
{
Just forward the interrupt to the CS43L22 driver
audinfo("handler %p\n", g_cs43l22info.handler);
if (g_cs43l22info.handler)
{
return g_cs43l22info.handler(&g_cs43l22info.lower, g_cs43l22info.arg);
}
We got an interrupt with no handler. This should not
happen.
TODO: stm32_pioirqdisable(IRQ_INT_CS43L22);
return OK;
}
#endif
static void cs43l22_hw_reset(FAR const struct cs43l22_lower_s *lower)
{
int i;
/* Reset the codec */
stm32_gpiowrite(GPIO_CS43L22_RESET, false);
for (i = 0; i < 0x4fff; i++)
{
__asm__ volatile("nop");
}
stm32_gpiowrite(GPIO_CS43L22_RESET, true);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: stm32_cs43l22_initialize
*
* Description:
* This function is called by platform-specific, setup logic to configure
* and register the CS43L22 device. This function will register the driver
* as /dev/audio/pcm[x] where x is determined by the minor device number.
*
* Input Parameters:
* minor - The input device minor number
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
int stm32_cs43l22_initialize(int minor)
{
FAR struct audio_lowerhalf_s *cs43l22;
FAR struct audio_lowerhalf_s *pcm;
FAR struct i2c_master_s *i2c;
FAR struct i2s_dev_s *i2s;
static bool initialized = false;
char devname[12];
int ret;
audinfo("minor %d\n", minor);
DEBUGASSERT(minor >= 0 && minor <= 25);
/* Have we already initialized? Since we never uninitialize we must prevent
* multiple initializations. This is necessary, for example, when the
* touchscreen example is used as a built-in application in NSH and can be
* called numerous time. It will attempt to initialize each time.
*/
if (!initialized)
{
stm32_configgpio(GPIO_CS43L22_RESET);
/* Configure the CS43L22 interrupt pin */
/* TODO: (void)stm32_configgpio(PIO_INT_CS43L22); */
/* Get an instance of the I2C interface for the CS43L22 chip select */
i2c = stm32_i2cbus_initialize(CS43L22_I2C_BUS);
if (!i2c)
{
auderr("ERROR: Failed to initialize TWI%d\n", CS43L22_I2C_BUS);
ret = -ENODEV;
goto errout;
}
/* Get an instance of the I2S interface for the CS43L22 data channel */
i2s = stm32_i2sdev_initialize(CS43L22_I2S_BUS);
if (!i2s)
{
auderr("ERROR: Failed to initialize I2S%d\n", CS43L22_I2S_BUS);
ret = -ENODEV;
goto errout_with_i2c;
}
/* Configure the DAC master clock. This clock is provided by PCK2 (PB10)
* that is connected to the CS43L22 MCLK.
*/
/* Configure CS43L22 interrupts */
#if 0 /* TODO: */
stm32_pioirq(PIO_INT_CS43L22);
ret = irq_attach(IRQ_INT_CS43L22, cs43l22_interrupt);
if (ret < 0)
{
auderr("ERROR: Failed to attach CS43L22 interrupt: %d\n", ret);
goto errout_with_i2s;
}
#endif
/* Now we can use these I2C and I2S interfaces to initialize the
* CS43L22 which will return an audio interface.
*/
cs43l22 = cs43l22_initialize(i2c, i2s, &g_cs43l22info.lower);
if (!cs43l22)
{
auderr("ERROR: Failed to initialize the CS43L22\n");
ret = -ENODEV;
goto errout_with_irq;
}
/* No we can embed the CS43L22/I2C/I2S conglomerate into a PCM decoder
* instance so that we will have a PCM front end for the the CS43L22
* driver.
*/
pcm = pcm_decode_initialize(cs43l22);
if (!pcm)
{
auderr("ERROR: Failed create the PCM decoder\n");
ret = -ENODEV;
goto errout_with_cs43l22;
}
/* Create a device name */
snprintf(devname, 12, "pcm%d", minor);
/* Finally, we can register the PCM/CS43L22/I2C/I2S audio device.
*
* Is anyone young enough to remember Rube Goldberg?
*/
ret = audio_register(devname, pcm);
if (ret < 0)
{
auderr("ERROR: Failed to register /dev/%s device: %d\n",
devname, ret);
goto errout_with_pcm;
}
/* Now we are initialized */
initialized = true;
}
return OK;
/* Error exits. Unfortunately there is no mechanism in place now to
* recover resources from most errors on initialization failures.
*/
errout_with_pcm:
errout_with_cs43l22:
errout_with_irq:
#if 0
irq_detach(IRQ_INT_CS43L22);
errout_with_i2s:
#endif
errout_with_i2c:
errout:
return ret;
}
#endif /* HAVE_CS43L22 */

View File

@ -77,6 +77,7 @@
#define HAVE_USBHOST 1
#define HAVE_USBMONITOR 1
#define HAVE_SDIO 1
#define HAVE_CS43L22 1
#define HAVE_RTC_DRIVER 1
#define HAVE_ELF 1
#define HAVE_NETMONITOR 1
@ -148,6 +149,26 @@
# endif
#endif
/* The CS43L22 depends on the CS43L22 driver, I2C1, and I2S3 support */
#if !defined(CONFIG_AUDIO_CS43L22) || !defined(CONFIG_STM32_I2C1) || \
!defined(CONFIG_STM32_I2S3)
# undef HAVE_CS43L22
#endif
#ifdef HAVE_CS43L22
/* The CS43L22 communicates on I2C1, I2C address 0x1a for control
* operations
*/
# define CS43L22_I2C_BUS 1
# define CS43L22_I2C_ADDRESS (0x94 >> 1)
/* The CS43L22 transfers data on I2S3 */
# define CS43L22_I2S_BUS 3
#endif
/* Check if we can support the RTC driver */
#if !defined(CONFIG_RTC) || !defined(CONFIG_RTC_DRIVER)
@ -216,6 +237,8 @@
#define GPIO_ZEROCROSS (GPIO_INPUT|GPIO_FLOAT|GPIO_EXTI|GPIO_PORTD|GPIO_PIN0)
#define GPIO_CS43L22_RESET (GPIO_OUTPUT|GPIO_SPEED_50MHz|GPIO_PORTD|GPIO_PIN4)
/* PWM
*
* The STM32F4 Discovery has no real on-board PWM devices, but the board can be
@ -369,6 +392,17 @@
void weak_function stm32_spidev_initialize(void);
/****************************************************************************
* Name: stm32_i2sdev_initialize
*
* Description:
* Called to configure I2S chip select GPIO pins for the stm32f4discovery
* board.
*
****************************************************************************/
FAR struct i2s_dev_s *stm32_i2sdev_initialize(int port);
/****************************************************************************
* Name: stm32_bh1750initialize
*
@ -608,6 +642,27 @@ int stm32_zerocross_initialize(void);
int stm32_max6675initialize(FAR const char *devpath);
#endif
/****************************************************************************
* Name: stm32_cs43l22_initialize
*
* Description:
* This function is called by platform-specific, setup logic to configure
* and register the CS43L22 device. This function will register the driver
* as /dev/cs43l22[x] where x is determined by the minor device number.
*
* Input Parameters:
* minor - The input device minor number
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
#ifdef HAVE_CS43L22
int stm32_cs43l22_initialize(int minor);
#endif /* HAVE_CS43L22 */
/****************************************************************************
* Name: stm32_pca9635_initialize
*

View File

@ -95,6 +95,67 @@ endif # AUDIO_DRIVER_SPECIFIC_BUFFERS
endif # VS1053
config AUDIO_CS43L22
bool "CS43L22 audio chip"
default n
depends on AUDIO
---help---
Select to enable support for the CS43L22 Audio codec by Cirrus Logic.
This chip is a lower level audio chip.. basically
an exotic D-to-A. It includes no built-in support for audio CODECS
The CS43L22 provides:
- Low power consumption
- High SNR
- Stereo digital microphone input
- Digital Dynamic Range Controller (compressor / limiter)
- Digital sidetone mixing
- Ground-referenced headphone driver
- Ground-referenced line outputs
NOTE: This driver also depends on both I2C and I2S support although
that dependency is not explicit here.
if AUDIO_CS43L22
config CS43L22_INITVOLUME
int "CS43L22 initial volume setting"
default 250
config CS43L22_INFLIGHT
int "CS43L22 maximum in-flight audio buffers"
default 2
config CS43L22_MSG_PRIO
int "CS43L22 message priority"
default 1
config CS43L22_BUFFER_SIZE
int "CS43L22 preferred buffer size"
default 8192
config CS43L22_NUM_BUFFERS
int "CS43L22 preferred number of buffers"
default 4
config CS43L22_WORKER_STACKSIZE
int "CS43L22 worker thread stack size"
default 768
config CS43L22_REGDUMP
bool "CS43L22 register dump"
default n
---help---
Enable logic to dump the contents of all CS43L22 registers.
config CS43L22_CLKDEBUG
bool "CS43L22 clock analysis"
default n
---help---
Enable logic to analyze CS43L22 clock configuation.
endif # AUDIO_CS43L22
config AUDIO_WM8904
bool "WM8904 audio chip"
default n

View File

@ -43,6 +43,17 @@ ifeq ($(CONFIG_VS1053),y)
CSRCS += vs1053.c
endif
ifeq ($(CONFIG_AUDIO_CS43L22),y)
CSRCS += cs43l22.c
ifeq ($(CONFIG_CS43L22_REGDUMP),y)
CSRCS += cs43l22_debug.c
else
ifeq ($(CONFIG_CS43L22_CLKDEBUG),y)
CSRCS += cs43l22_debug.c
endif
endif
endif
ifeq ($(CONFIG_AUDIO_WM8904),y)
CSRCS += wm8904.c
ifeq ($(CONFIG_WM8904_REGDUMP),y)

1959
drivers/audio/cs43l22.c Normal file

File diff suppressed because it is too large Load Diff

388
drivers/audio/cs43l22.h Normal file
View File

@ -0,0 +1,388 @@
/****************************************************************************
* drivers/audio/cs43l22.h
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Reference:
* "CS43L22 Ultra Low Power CODEC for Portable Audio Applications, Pre-
* Production", September 2012, Rev 3.3, Wolfson Microelectronics
*
* 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 __DRIVERS_AUDIO_CS43L22_H
#define __DRIVERS_AUDIO_CS43L22_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <pthread.h>
#include <mqueue.h>
#include <nuttx/wqueue.h>
#include <nuttx/fs/ioctl.h>
#define getreg32(a) (*(volatile uint32_t *)(a))
#define putreg32(v,a) (*(volatile uint32_t *)(a) = (v))
#define getreg16(a) (*(volatile uint16_t *)(a))
#define putreg16(v,a) (*(volatile uint16_t *)(a) = (v))
#ifdef CONFIG_AUDIO
/****************************************************************************
* Pre-Processor Definitions
****************************************************************************/
/* So far, I have not been able to get FLL lock interrupts. Worse, I have
* been able to get the FLL to claim that it is locked at all even when
* polling. What am I doing wrong?
*
* Hmmm.. seems unnecessary anyway
*/
#undef CS43L22_USE_FFLOCK_INT
#undef CS43L22_USE_FFLOCK_POLL
/* Registers Addresses ******************************************************/
#define CS43L22_ID_REV 0x01 /* Chip I.D. and Revision */
#define CS43L22_POWER_CTRL1 0x02 /* Power Control 1 */
#define CS43L22_POWER_CTRL2 0x04 /* Power Control 2 */
#define CS43L22_CLOCK_CTRL 0x05 /* Clocking Control */
#define CS43L22_INTERFACE_CTRL1 0x06 /* Interface Control 1 */
#define CS43L22_INTERFACE_CTRL2 0x07 /* Interface Control 2 */
#define CS43L22_PASS_SEL_A 0x08 /* Passthrough x Select: PassA */
#define CS43L22_PASS_SEL_B 0x09 /* Passthrough x Select: PassB */
#define CS43L22_ANLG_ZC_SR_SEL 0x0A /* Analog ZC and SR Settings */
#define CS43L22_PASS_GANG_CTRL 0x0C /* Passthrough Gang Control */
#define CS43L22_PLAYBACK_CTRL1 0x0D /* Playback Control 1 */
#define CS43L22_MISCLLNS_CTRL 0x0E /* Miscellaneous Controls */
#define CS43L22_PLAYBACK_CTRL2 0x0F /* Playback Control 2 */
#define CS43L22_PASS_VOL_A 0x14 /* Passthrough x Volume: PASSAVOL */
#define CS43L22_PASS_VOL_B 0x15 /* Passthrough x Volume: PASSBVOL */
#define CS43L22_PCM_VOL_A 0x1A /* PCMx Volume: PCMA */
#define CS43L22_PCM_VOL_B 0x1B /* PCMx Volume: PCMB */
#define CS43L22_BP_FREQ_ON_TIME 0x1C /* Beep Frequency & On Time */
#define CS43L22_BP_VOL_OFF_TIME 0x1D /* Beep Volume & Off Time */
#define CS43L22_BP_TONE_CFG 0x1E /* Beep & Tone Configuration */
#define CS43L22_TONE_CTRL 0x1F /* Tone Control */
#define CS43L22_MS_VOL_CTRL_A 0x20 /* Master Volume Control: MSTA */
#define CS43L22_MS_VOL_CTRL_B 0x21 /* Master Volume Control: MSTB */
#define CS43L22_HP_VOL_CTRL_A 0x22 /* Headphone Volume Control: HPA */
#define CS43L22_HP_VOL_CTRL_B 0x23 /* Headphone Volume Control: HPB */
#define CS43L22_SPK_VOL_CTRL_A 0x24 /* Speaker Volume Control: SPKA */
#define CS43L22_SPK_VOL_CTRL_B 0x25 /* Speaker Volume Control: SPKB */
#define CS43L22_PCM_CH_SWAP 0x26 /* PCM Channel Swap */
#define CS43L22_LIM_CTRL1 0x27 /* Limiter Control 1, Min/Max Thresholds */
#define CS43L22_LIM_CTRL2 0x28 /* Limiter Control 2, Release Rate */
#define CS43L22_LIM_ATTACK_RATE 0x29 /* Limiter Attack Rate */
#define CS43L22_STATUS 0x2E /* Status */
#define CS43L22_BAT_COMP 0x2F /* Battery Compensation */
#define CS43L22_VP_BAT_LEVEL 0x30 /* VP Battery Level */
#define CS43L22_SPK_STATUS 0x31 /* Speaker Status */
#define CS43L22_TEMP_MON_CTRL 0x32 /* Temperature Monitor Control */
#define CS43L22_THERMAL_FOLDBACK 0x33 /* Thermal Foldback */
#define CS43L22_CHRG_PUMP_FREQ 0x34 /* Charge Pump Frequency */
#define CS43L22_HPBMUTE (1 << 7)
#define CS43L22_HPAMUTE (1 << 6)
#define CS43L22_SPKBMUTE (1 << 5)
#define CS43L22_SPKAMUTE (1 << 4)
/* Register Default Values **************************************************/
/* Registers have some undocumented bits set on power up. These probably
* should be retained on writes (?).
*/
#define CS43L22_ID_REV_DEFAULT 0xe3 /* Chip I.D. and Revision */
#define CS43L22_POWER_CTRL1_DEFAULT 0x01 /* Power Control 1 */
#define CS43L22_POWER_CTRL2_DEFAULT 0x05 /* Power Control 2 */
#define CS43L22_CLOCK_CTRL_DEFAULT 0xa0 /* Clocking Control */
#define CS43L22_INTERFACE_CTRL1_DEFAULT 0x00 /* Interface Control 1 */
#define CS43L22_INTERFACE_CTRL2_DEFAULT 0x00 /* Interface Control 2 */
#define CS43L22_PASS_SEL_A_DEFAULT 0x81 /* Passthrough x Select: PassA */
#define CS43L22_PASS_SEL_B_DEFAULT 0x81 /* Passthrough x Select: PassB */
#define CS43L22_ANLG_ZC_SR_SEL_DEFAULT 0xa5 /* Analog ZC and SR Settings */
#define CS43L22_PASS_GANG_CTRL_DEFAULT 0x00 /* Passthrough Gang Control */
#define CS43L22_PLAYBACK_CTRL1_DEFAULT 0x60 /* Playback Control 1 */
#define CS43L22_MISCLLNS_CTRL_DEFAULT 0x02 /* Miscellaneous Controls */
#define CS43L22_PLAYBACK_CTRL2_DEFAULT 0x00 /* Playback Control 2 */
#define CS43L22_PASS_VOL_A_DEFAULT 0x00 /* Passthrough x Volume: PASSAVOL */
#define CS43L22_PASS_VOL_B_DEFAULT 0x00 /* Passthrough x Volume: PASSBVOL */
#define CS43L22_PCM_VOL_A_DEFAULT 0x00 /* PCMx Volume: PCMA */
#define CS43L22_PCM_VOL_B_DEFAULT 0x00 /* PCMx Volume: PCMB */
#define CS43L22_BP_FREQ_ON_TIME_DEFAULT 0x00 /* Beep Frequency & On Time */
#define CS43L22_BP_VOL_OFF_TIME_DEFAULT 0x00 /* Beep Volume & Off Time */
#define CS43L22_BP_TONE_CFG_DEFAULT 0x00 /* Beep & Tone Configuration */
#define CS43L22_TONE_CTRL_DEFAULT 0x88 /* Tone Control */
#define CS43L22_MS_VOL_CTRL_A_DEFAULT 0x00 /* Master Volume Control: MSTA */
#define CS43L22_MS_VOL_CTRL_B_DEFAULT 0x00 /* Master Volume Control: MSTB */
#define CS43L22_HP_VOL_CTRL_A_DEFAULT 0x00 /* Headphone Volume Control: HPA */
#define CS43L22_HP_VOL_CTRL_B_DEFAULT 0x00 /* Headphone Volume Control: HPB */
#define CS43L22_SPK_VOL_CTRL_A_DEFAULT 0x00 /* Speaker Volume Control: SPKA */
#define CS43L22_SPK_VOL_CTRL_B_DEFAULT 0x00 /* Speaker Volume Control: SPKB */
#define CS43L22_PCM_CH_SWAP_DEFAULT 0x00 /* PCM Channel Swap */
#define CS43L22_LIM_CTRL1_DEFAULT 0x00 /* Limiter Control 1, Min/Max Thresholds */
#define CS43L22_LIM_CTRL2_DEFAULT 0x7f /* Limiter Control 2, Release Rate */
#define CS43L22_LIM_ATTACK_RATE_DEFAULT 0xc0 /* Limiter Attack Rate */
#define CS43L22_STATUS_DEFAULT 0x00 /* Status */
#define CS43L22_BAT_COMP_DEFAULT 0x00 /* Battery Compensation */
#define CS43L22_VP_BAT_LEVEL_DEFAULT 0x00 /* VP Battery Level */
#define CS43L22_SPK_STATUS_DEFAULT 0x00 /* Speaker Status */
#define CS43L22_TEMP_MON_CTRL_DEFAULT 0x3b /* Temperature Monitor Control */
#define CS43L22_THERMAL_FOLDBACK_DEFAULT 0x00 /* Thermal Foldback */
#define CS43L22_CHRG_PUMP_FREQ_DEFAULT 0x5f /* Charge Pump Frequency */
/* Register Bit Definitions *************************************************/
/* 0x01 Chip I.D. and Revision (Read Only) */
#define CS43L22_DEV_ID_REV (0xe3)
#define CS43L22_ID_SHIFT (3)
#define CS43L22_ID_MASK (0x1f << CS43L22_ID_SHIFT)
#define CS43L22_REV_SHIFT (0)
#define CS43L22_REV_MASK (0x07 << CS43L22_REV_SHIFT)
/* 0x02 Power Control 1 */
#define CS43L22_POWER_DOWN (0x01) /* Powered Down */
#define CS43L22_POWER_UP (0x9e) /* Powered Up */
/* 0x04 Power Control 2 */
#define CS43L22_PDN_HPB_SHIFT (6) /* Bits 6-7: Headphone channel B Control */
#define CS43L22_PDN_HPB_ON_HW_PIN_LO (0 << CS43L22_PDN_HPB_SHIFT) /* PDN_HPx[1:0] 00 Headphone channel is ON when the SPK/HP_SW pin, 6, is LO
Headphone channel is OFF when the SPK/HP_SW pin, 6, is HI */
#define CS43L22_PDN_HPB_ON_HW_PIN_HI (1 << CS43L22_PDN_HPB_SHIFT) /* PDN_HPx[1:0] 01 Headphone channel is ON when the SPK/HP_SW pin, 6, is HI
Headphone channel is OFF when the SPK/HP_SW pin, 6, is LO */
#define CS43L22_PDN_HPB_ON (2 << CS43L22_PDN_HPB_SHIFT) /* PDN_HPx[1:0] 10 Headphone channel is always ON */
#define CS43L22_PDN_HPB_OFF (3 << CS43L22_PDN_HPB_SHIFT) /* PDN_HPx[1:0] 11 Headphone channel is always OFF */
#define CS43L22_PDN_HPA_SHIFT (4) /* Bits 4-5: Headphone channel A Control */
#define CS43L22_PDN_HPA_ON_HW_PIN_LO (0 << CS43L22_PDN_HPA_SHIFT) /* PDN_HPx[1:0] 00 Headphone channel is ON when the SPK/HP_SW pin, 6, is LO
Headphone channel is OFF when the SPK/HP_SW pin, 6, is HI */
#define CS43L22_PDN_HPA_ON_HW_PIN_HI (1 << CS43L22_PDN_HPA_SHIFT) /* PDN_HPx[1:0] 01 Headphone channel is ON when the SPK/HP_SW pin, 6, is HI
Headphone channel is OFF when the SPK/HP_SW pin, 6, is LO */
#define CS43L22_PDN_HPA_ON (2 << CS43L22_PDN_HPA_SHIFT) /* PDN_HPx[1:0] 10 Headphone channel is always ON */
#define CS43L22_PDN_HPA_OFF (3 << CS43L22_PDN_HPA_SHIFT) /* PDN_HPx[1:0] 11 Headphone channel is always OFF */
#define CS43L22_PDN_SPKB_SHIFT (2) /* Bits 2-3: Speaker channel B Control */
#define CS43L22_PDN_SPKB_ON_HW_PIN_LO (0 << CS43L22_PDN_SPKB_SHIFT) /* PDN_HPx[1:0] 00 Speaker channel is ON when the SPK/HP_SW pin, 6, is LO
Speaker channel is OFF when the SPK/HP_SW pin, 6, is HI */
#define CS43L22_PDN_SPKB_ON_HW_PIN_HI (1 << CS43L22_PDN_SPKB_SHIFT) /* PDN_HPx[1:0] 01 Speaker channel is ON when the SPK/HP_SW pin, 6, is HI
Speaker channel is OFF when the SPK/HP_SW pin, 6, is LO */
#define CS43L22_PDN_SPKB_ON (2 << CS43L22_PDN_SPKB_SHIFT) /* PDN_HPx[1:0] 10 Speaker channel is always ON */
#define CS43L22_PDN_SPKB_OFF (3 << CS43L22_PDN_SPKB_SHIFT) /* PDN_HPx[1:0] 11 Speaker channel is always OFF */
#define CS43L22_PDN_SPKA_SHIFT (0) /* Bits 0-1: Speaker channel A Control */
#define CS43L22_PDN_SPKA_ON_HW_PIN_LO (0 << CS43L22_PDN_SPKA_SHIFT) /* PDN_HPx[1:0] 00 Speaker channel is ON when the SPK/HP_SW pin, 6, is LO
Speaker channel is OFF when the SPK/HP_SW pin, 6, is HI */
#define CS43L22_PDN_SPKA_ON_HW_PIN_HI (1 << CS43L22_PDN_SPKA_SHIFT) /* PDN_HPx[1:0] 01 Speaker channel is ON when the SPK/HP_SW pin, 6, is HI
Speaker channel is OFF when the SPK/HP_SW pin, 6, is LO */
#define CS43L22_PDN_SPKA_ON (2 << CS43L22_PDN_SPKA_SHIFT) /* PDN_HPx[1:0] 10 Speaker channel is always ON */
#define CS43L22_PDN_SPKA_OFF (3 << CS43L22_PDN_SPKA_SHIFT) /* PDN_HPx[1:0] 11 Speaker channel is always OFF */
/* 0x05 Clocking Control */
#define CS43L22_AUTO_DETECT_ENABLE (1 << 7) /* Auto-detection of speed mode enable */
#define CS43L22_SPEED_SHIFT (5) /* Bits 5-6: Speed mode */
#define CS43L22_SPEED_DOUBLE (0 << CS43L22_SPEED_SHIFT) /* Slave: Double-Speed Mode (DSM - 50 kHz -100 kHz Fs) Master: MCLK=512 SCLK=64*/
#define CS43L22_SPEED_SINGLE (1 << CS43L22_SPEED_SHIFT) /* Slave: Single-Speed Mode (SSM - 4 kHz -50 kHz Fs) Master: MCLK=256 SCLK=64*/
#define CS43L22_SPEED_HALF (2 << CS43L22_SPEED_SHIFT) /* Slave: Half-Speed Mode (HSM - 12.5kHz -25 kHz Fs) Master: MCLK=128 SCLK=64*/
#define CS43L22_SPEED_QUARTER (3 << CS43L22_SPEED_SHIFT) /* Slave: Quarter-Speed Mode (QSM - 4 kHz -12.5 kHz Fs)Master: MCLK=128 SCLK=64*/
#define CS43L22_32k_GROUP_ENABLE (1 << 4) /* Bit 4: Specifies whether or not the input/output sample rate is 8 kHz, 16 kHz or 32 kHz */
#define CS43L22_VIDEOCLK_ENABLE (1 << 3) /* Bit 3: Specifies whether or not the external MCLK frequency is 27 MHz */
#define CS43L22_MCLK_LRCK_RATIO_SHIFT (1) /* Bits 1-2: Internal MCLK/LRCK Ratio */
#define CS43L22_RATIO_128_64 (0 << CS43L22_MCLK_LRCK_RATIO_SHIFT) /* RATIO[1:0] Internal MCLK Cycles per LRCK=128, SCLK/LRCK=64 Ratio in Master Mode */
#define CS43L22_RATIO_125_62 (1 << CS43L22_MCLK_LRCK_RATIO_SHIFT) /* RATIO[1:0] Internal MCLK Cycles per LRCK=125, SCLK/LRCK=62 Ratio in Master Mode */
#define CS43L22_RATIO_132_66 (2 << CS43L22_MCLK_LRCK_RATIO_SHIFT) /* RATIO[1:0] Internal MCLK Cycles per LRCK=132, SCLK/LRCK=66 Ratio in Master Mode */
#define CS43L22_RATIO_136_68 (3 << CS43L22_MCLK_LRCK_RATIO_SHIFT) /* RATIO[1:0] Internal MCLK Cycles per LRCK=136, SCLK/LRCK=68 Ratio in Master Mode */
#define CS43L22_CLKDIV2_ENABLE (1 << 0) /* Bit 0: Divided by 2 */
/* 0x06 Interface Control 1 */
#define CS43L22_MODE_MASTER (1 << 7) /* Configures the serial port I/O clocking */
#define CS43L22_SCLK_POLARITY_INVERT (1 << 6) /* Configures the polarity of the SCLK signal */
#define CS43L22_DSP_MODE_ENABLE (1 << 4) /* Configures a data-packed interface format for the DAC */
#define CS43L22_DAC_IF_FORMAT_SHIFT (2) /* Bits 2-3: Configures the digital interface format for data on SDIN */
#define CS43L22_DAC_IF_LEFT_JUSTIFIED (0 << CS43L22_DAC_IF_FORMAT_SHIFT) /* DACDIF[1:0] Left Justified, up to 24-bit data */
#define CS43L22_DAC_IF_I2S (1 << CS43L22_DAC_IF_FORMAT_SHIFT) /* DACDIF[1:0] I2S, up to 24-bit data */
#define CS43L22_DAC_IF_RIGHT_JUSTIFIED (2 << CS43L22_DAC_IF_FORMAT_SHIFT) /* DACDIF[1:0] Right Justified */
#define CS43L22_DAC_IF_RESERVED (3 << CS43L22_DAC_IF_FORMAT_SHIFT) /* DACDIF[1:0] Reserved */
#define CS43L22_AUDIO_WORD_LENGHT_SHIFT (0) /* Bits 0-1: Configures the audio sample word length used for the data into SDIN */
#define CS43L22_AWL_DSP_32_RJ_24 (0 << CS43L22_AUDIO_WORD_LENGHT_SHIFT)/* AWL[1:0] DSP Mode: 32-bit data, Right Justified: 24-bit data */
#define CS43L22_AWL_DSP_24_RJ_20 (1 << CS43L22_AUDIO_WORD_LENGHT_SHIFT)/* AWL[1:0] DSP Mode: 24-bit data, Right Justified: 20-bit data */
#define CS43L22_AWL_DSP_20_RJ_18 (2 << CS43L22_AUDIO_WORD_LENGHT_SHIFT)/* AWL[1:0] DSP Mode: 20-bit data, Right Justified: 18-bit data */
#define CS43L22_AWL_DSP_16_RJ_16 (3 << CS43L22_AUDIO_WORD_LENGHT_SHIFT)/* AWL[1:0] DSP Mode: 16 bit data, Right Justified: 16-bit data */
/* 0x0E Miscellaneous Controls */
#define CS43L22_FREEZE (1 << 3) /* Configures a hold on all register settings */
#define CS43L22_DEEMPHASIS_ENABLE (1 << 2) /* Configures a 15μs/50μs digital de-emphasis filter response on the headphone/line and speaker outputs */
/* 0x1F Tone Control */
#define CS43L22_TREB_GAIN_SHIFT (4) /* Sets the gain of the treble shelving filter */
#define CS43L22_TREB_GAIN(a) ((a) << CS43L22_TREB_GAIN_SHIFT)
/* TREB[3:0] Gain Setting:*/
/* 0000 +12.0 dB */
/* ··· ··· */
/* 0111 +1.5 dB */
/* 1000 0 dB */
/* 1001 -1.5 dB */
/* 1111 -10.5 dB */
/* Step Size: 1.5 dB */
#define CS43L22_BASS_GAIN_SHIFT (0) /* Sets the gain of the bass shelving filter */
#define CS43L22_BASS_GAIN(a) ((a) << CS43L22_BASS_GAIN_SHIFT)
/* BASS[3:0] Gain Setting:*/
/* 0000 +12.0 dB */
/* ··· ··· */
/* 0111 +1.5 dB */
/* 1000 0 dB */
/* 1001 -1.5 dB */
/* 1111 -10.5 dB */
/* Step Size: 1.5 dB */
/* FLL Configuration *********************************************************/
/* Default FLL configuration */
#define CS43L22_DEFAULT_SAMPRATE 11025 /* Initial sample rate */
#define CS43L22_DEFAULT_NCHANNELS 1 /* Initial number of channels */
#define CS43L22_DEFAULT_BPSAMP 16 /* Initial bits per sample */
#define CS43L22_NFLLRATIO 5 /* Number of FLL_RATIO values */
#define CS43L22_MINOUTDIV 4 /* Minimum FLL_OUTDIV divider */
#define CS43L22_MAXOUTDIV 64 /* Maximum FLL_OUTDIV divider */
#define CS43L22_BCLK_MAXDIV 20 /* Maximum BCLK divider */
#define CS43L22_FRAMELEN8 14 /* Bits per frame for 8-bit data */
#define CS43L22_FRAMELEN16 32 /* Bits per frame for 16-bit data */
/* Commonly defined and redefined macros */
#ifndef MIN
# define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
# define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
/****************************************************************************
* Public Types
****************************************************************************/
struct cs43l22_dev_s
{
/* We are an audio lower half driver (We are also the upper "half" of
* the CS43L22 driver with respect to the board lower half driver).
*
* Terminology: Our "lower" half audio instances will be called dev for the
* publicly visible version and "priv" for the version that only this driver
* knows. From the point of view of this driver, it is the board lower
* "half" that is referred to as "lower".
*/
struct audio_lowerhalf_s dev; /* CS43L22 audio lower half (this device) */
/* Our specific driver data goes here */
const FAR struct cs43l22_lower_s *lower; /* Pointer to the board lower functions */
FAR struct i2c_master_s *i2c; /* I2C driver to use */
FAR struct i2s_dev_s *i2s; /* I2S driver to use */
struct dq_queue_s pendq; /* Queue of pending buffers to be sent */
struct dq_queue_s doneq; /* Queue of sent buffers to be returned */
mqd_t mq; /* Message queue for receiving messages */
char mqname[16]; /* Our message queue name */
pthread_t threadid; /* ID of our thread */
uint32_t bitrate; /* Actual programmed bit rate */
sem_t pendsem; /* Protect pendq */
#ifdef CS43L22_USE_FFLOCK_INT
struct work_s work; /* Interrupt work */
#endif
uint16_t samprate; /* Configured samprate (samples/sec) */
#ifndef CONFIG_AUDIO_EXCLUDE_VOLUME
#ifndef CONFIG_AUDIO_EXCLUDE_BALANCE
uint16_t balance; /* Current balance level (b16) */
#endif /* CONFIG_AUDIO_EXCLUDE_BALANCE */
uint8_t volume; /* Current volume level {0..63} */
#endif /* CONFIG_AUDIO_EXCLUDE_VOLUME */
uint8_t nchannels; /* Number of channels (1 or 2) */
uint8_t bpsamp; /* Bits per sample (8 or 16) */
volatile uint8_t inflight; /* Number of audio buffers in-flight */
#ifdef CS43L22_USE_FFLOCK_INT
volatile bool locked; /* FLL is locked */
#endif
bool running; /* True: Worker thread is running */
bool paused; /* True: Playing is paused */
bool mute; /* True: Output is muted */
#ifndef CONFIG_AUDIO_EXCLUDE_STOP
bool terminating; /* True: Stop requested */
#endif
bool reserved; /* True: Device is reserved */
volatile int result; /* The result of the last transfer */
};
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef CONFIG_CS43L22_CLKDEBUG
extern const uint8_t g_sysclk_scaleb1[CS43L22_BCLK_MAXDIV+1];
extern const uint8_t g_fllratio[CS43L22_NFLLRATIO];
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: cs43l22_readreg
*
* Description
* Read the specified 8-bit register from the CS43L22 device.
*
****************************************************************************/
#if defined(CONFIG_CS43L22_REGDUMP) || defined(CONFIG_CS43L22_CLKDEBUG)
struct cs43l22_dev_s;
uint8_t cs43l22_readreg(FAR struct cs43l22_dev_s *priv, uint8_t regaddr);
#endif
#endif /* CONFIG_AUDIO */
#endif /* __DRIVERS_AUDIO_CS43L22_H */

View File

@ -0,0 +1,184 @@
/****************************************************************************
* drivers/audio/cs43l22_debug.c
* Audio device driver for Cirrus Logic CS43L22 Audio codec.
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Taras Drozdovsky <t.drozdovskiy@gmail.comnuttx.org>
*
* References:
* - "CS43L22 Ultra Low Power CODEC for Portable Audio Applications, Pre-
* Production", September 2012, Rev b1, Cirrus Logic
* - The framework for this driver is based on Ken Pettit's VS1053 driver.
*
* 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 <nuttx/config.h>
#include <stdint.h>
#include <assert.h>
#include <fixedmath.h>
#include <syslog.h>
#include <nuttx/audio/audio.h>
#include <nuttx/audio/cs43l22.h>
#include "cs43l22.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
#ifdef CONFIG_CS43L22_REGDUMP
struct cs43l22_regdump_s
{
FAR const char *regname;
uint8_t regaddr;
};
#endif
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
#ifdef CONFIG_CS43L22_REGDUMP
static const struct cs43l22_regdump_s g_cs43l22_debug[] =
{
{"CHIP_ID_REV", CS43L22_ID_REV },
{"POWER_CTRL1", CS43L22_POWER_CTRL1 },
{"POWER_CTRL2", CS43L22_POWER_CTRL2 },
{"CLOCK_CTRL", CS43L22_CLOCK_CTRL },
{"INTERFACE_CTRL1", CS43L22_INTERFACE_CTRL1 },
{"INTERFACE_CTRL2", CS43L22_INTERFACE_CTRL2 },
{"PASS_SEL_A", CS43L22_PASS_SEL_A },
{"PASS_SEL_B", CS43L22_PASS_SEL_B },
{"ANLG_ZC_SR_SEL", CS43L22_ANLG_ZC_SR_SEL },
{"PASS_GANG_CTRL", CS43L22_PASS_GANG_CTRL },
{"PLAYBACK_CTRL1", CS43L22_PLAYBACK_CTRL1 },
{"MISCLLNS_CTRL", CS43L22_MISCLLNS_CTRL },
{"PLAYBACK_CTRL2", CS43L22_PLAYBACK_CTRL2 },
{"PASS_VOL_A", CS43L22_PASS_VOL_A },
{"PASS_VOL_B", CS43L22_PASS_VOL_B },
{"PCM_VOL_A", CS43L22_PCM_VOL_A },
{"PCM_VOL_B", CS43L22_PCM_VOL_B },
{"BP_FREQ_ON_T", CS43L22_BP_FREQ_ON_TIME },
{"BP_VOL_OFF_T", CS43L22_BP_VOL_OFF_TIME },
{"BP_TONE_CFG", CS43L22_BP_TONE_CFG },
{"TONE_CTRL", CS43L22_TONE_CTRL },
{"MS_VOL_CTRL_A", CS43L22_MS_VOL_CTRL_A },
{"MS_VOL_CTRL_B", CS43L22_MS_VOL_CTRL_B },
{"HP_VOL_CTRL_A", CS43L22_HP_VOL_CTRL_A },
{"HP_VOL_CTRL_B", CS43L22_HP_VOL_CTRL_B },
{"SPK_VOL_CTRL_A", CS43L22_SPK_VOL_CTRL_A },
{"SPK_VOL_CTRL_B", CS43L22_SPK_VOL_CTRL_B },
{"PCM_CH_SWAP", CS43L22_PCM_CH_SWAP },
{"LIM_CTRL1", CS43L22_LIM_CTRL1 },
{"LIM_CTRL2", CS43L22_LIM_CTRL2 },
{"LIM_ATTACK_RATE", CS43L22_LIM_ATTACK_RATE },
{"STATUS", CS43L22_STATUS },
{"BAT_COMP", CS43L22_BAT_COMP },
{"VP_BAT_LEVEL", CS43L22_VP_BAT_LEVEL },
{"SPK_STATUS", CS43L22_SPK_STATUS },
{"TEMP_MON_CTRL", CS43L22_TEMP_MON_CTRL },
{"THERMAL_FOLDBACK",CS43L22_THERMAL_FOLDBACK},
{"CHRG_PUMP_FREQ", CS43L22_CHRG_PUMP_FREQ }
};
# define CS43L22_NREGISTERS (sizeof(g_cs43l22_debug)/sizeof(struct cs43l22_regdump_s))
#endif /* CONFIG_CS43L22_REGDUMP */
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: cs43l22_dump_registers
*
* Description:
* Dump the contents of all CS43L22 registers to the syslog device
*
* Input Parameters:
* dev - The device instance returned by cs43l22_initialize
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_CS43L22_REGDUMP
void cs43l22_dump_registers(FAR struct audio_lowerhalf_s *dev,
FAR const char *msg)
{
int i;
syslog(LOG_INFO, "CS43L22 Registers: %s\n", msg);
for (i = 0; i < CS43L22_NREGISTERS; i++)
{
syslog(LOG_INFO, "%16s[%02x]: %02x\n",
g_cs43l22_debug[i].regname, g_cs43l22_debug[i].regaddr,
cs43l22_readreg((FAR struct cs43l22_dev_s *)dev,
g_cs43l22_debug[i].regaddr));
}
}
#endif /* CONFIG_CS43L22_REGDUMP */
/****************************************************************************
* Name: cs43l22_clock_analysis
*
* Description:
* Analyze the settings in the clock chain and dump to syslog.
*
* Input Parameters:
* dev - The device instance returned by cs43l22_initialize
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_CS43L22_CLKDEBUG
void cs43l22_clock_analysis(FAR struct audio_lowerhalf_s *dev,
FAR const char *msg)
{
#warning Missing logic
/* TODO */
}
#endif /* CONFIG_CS43L22_CLKDEBUG */

View File

@ -50,6 +50,8 @@
#include <nuttx/kmalloc.h>
#include <nuttx/wdog.h>
#include <nuttx/sdio.h>
#include <nuttx/net/arp.h>
#include <nuttx/wireless/ieee80211/ieee80211.h>
#include "bcmf_driver.h"
#include "bcmf_cdc.h"
@ -65,6 +67,12 @@
#define DOT11_BSSTYPE_ANY 2
#define BCMF_SCAN_TIMEOUT_TICK (5*CLOCKS_PER_SEC)
#define BCMF_AUTH_TIMEOUT_MS 10000
#define BCMF_SCAN_RESULT_SIZE 1024
/* Helper to get iw_event size */
#define BCMF_IW_EVENT_SIZE(field) \
(offsetof(struct iw_event, u)+sizeof(((union iwreq_data*)0)->field))
/****************************************************************************
* Private Types
@ -366,6 +374,9 @@ void bcmf_wl_auth_event_handler(FAR struct bcmf_dev_s *priv,
}
}
/* bcmf_wl_scan_event_handler must run at high priority else
* race condition may occur on priv->scan_result field
*/
void bcmf_wl_scan_event_handler(FAR struct bcmf_dev_s *priv,
struct bcmf_event_s *event, unsigned int len)
{
@ -414,7 +425,7 @@ void bcmf_wl_scan_event_handler(FAR struct bcmf_dev_s *priv,
goto exit_invalid_frame;
}
/* wl_escan_result already cointains a wl_bss_info field */
/* wl_escan_result structure cointains a wl_bss_info field */
len = result->buflen - sizeof(struct wl_escan_result)
+ sizeof(struct wl_bss_info);
@ -425,6 +436,15 @@ void bcmf_wl_scan_event_handler(FAR struct bcmf_dev_s *priv,
while (len > 0 && bss_count < result->bss_count)
{
struct iw_event *iwe;
unsigned int result_size;
size_t essid_len;
size_t essid_len_aligned;
uint8_t *ie_buffer;
unsigned int ie_offset;
unsigned int check_offset;
result_size = BCMF_SCAN_RESULT_SIZE - priv->scan_result_size;
bss_info_len = bss->length;
if (len < bss_info_len)
@ -433,11 +453,211 @@ void bcmf_wl_scan_event_handler(FAR struct bcmf_dev_s *priv,
goto exit_invalid_frame;
}
/* Append current bss_info to priv->scan_results
* FIXME protect this against race conditions
*/
/* Check if current bss AP is not already detected */
check_offset = 0;
while (priv->scan_result_size - check_offset
>= offsetof(struct iw_event, u))
{
iwe = (struct iw_event*)&priv->scan_result[check_offset];
if (iwe->cmd == SIOCGIWAP)
{
if (memcmp(&iwe->u.ap_addr.sa_data, bss->BSSID.ether_addr_octet,
sizeof(bss->BSSID.ether_addr_octet)) == 0)
{
goto process_next_bss;
}
}
check_offset += iwe->len;
}
wlinfo("Scan result: <%.32s> %02x:%02x:%02x:%02x:%02x:%02x\n", bss->SSID,
bss->BSSID.ether_addr_octet[0], bss->BSSID.ether_addr_octet[1],
bss->BSSID.ether_addr_octet[3], bss->BSSID.ether_addr_octet[3],
bss->BSSID.ether_addr_octet[2], bss->BSSID.ether_addr_octet[3],
bss->BSSID.ether_addr_octet[4], bss->BSSID.ether_addr_octet[5]);
/* Copy BSSID */
if (result_size < BCMF_IW_EVENT_SIZE(ap_addr))
{
goto scan_result_full;
}
iwe = (struct iw_event*)&priv->scan_result[priv->scan_result_size];
iwe->len = BCMF_IW_EVENT_SIZE(ap_addr);
iwe->cmd = SIOCGIWAP;
memcpy(&iwe->u.ap_addr.sa_data, bss->BSSID.ether_addr_octet,
sizeof(bss->BSSID.ether_addr_octet));
iwe->u.ap_addr.sa_family = ARPHRD_ETHER;
priv->scan_result_size += BCMF_IW_EVENT_SIZE(ap_addr);
result_size -= BCMF_IW_EVENT_SIZE(ap_addr);
/* Copy ESSID */
essid_len = min(strlen((const char*)bss->SSID), 32);
essid_len_aligned = (essid_len + 3) & -4;
if (result_size < BCMF_IW_EVENT_SIZE(essid)+essid_len_aligned)
{
goto scan_result_full;
}
iwe = (struct iw_event*)&priv->scan_result[priv->scan_result_size];
iwe->len = BCMF_IW_EVENT_SIZE(essid)+essid_len_aligned;
iwe->cmd = SIOCGIWESSID;
iwe->u.essid.flags = 0;
iwe->u.essid.length = essid_len;
/* Special processing for iw_point, set offset in pointer field */
iwe->u.essid.pointer = (FAR void*)sizeof(iwe->u.essid);
memcpy(&iwe->u.essid+1, bss->SSID, essid_len);
priv->scan_result_size += BCMF_IW_EVENT_SIZE(essid)+essid_len_aligned;
result_size -= BCMF_IW_EVENT_SIZE(essid)+essid_len_aligned;
/* Copy link quality info */
if (result_size < BCMF_IW_EVENT_SIZE(qual))
{
goto scan_result_full;
}
iwe = (struct iw_event*)&priv->scan_result[priv->scan_result_size];
iwe->len = BCMF_IW_EVENT_SIZE(qual);
iwe->cmd = IWEVQUAL;
iwe->u.qual.qual = bss->SNR;
wlinfo("signal %d %d %d\n", bss->RSSI, bss->phy_noise, bss->SNR);
iwe->u.qual.level = bss->RSSI;
iwe->u.qual.noise = bss->phy_noise;
iwe->u.qual.updated = IW_QUAL_DBM | IW_QUAL_ALL_UPDATED;
priv->scan_result_size += BCMF_IW_EVENT_SIZE(qual);
result_size -= BCMF_IW_EVENT_SIZE(qual);
/* Copy AP mode */
if (result_size < BCMF_IW_EVENT_SIZE(mode))
{
goto scan_result_full;
}
iwe = (struct iw_event*)&priv->scan_result[priv->scan_result_size];
iwe->len = BCMF_IW_EVENT_SIZE(mode);
iwe->cmd = SIOCGIWMODE;
if (bss->capability & DOT11_CAP_ESS)
{
iwe->u.mode = IW_MODE_INFRA;
}
else if (bss->capability & DOT11_CAP_IBSS)
{
iwe->u.mode = IW_MODE_ADHOC;
}
else
{
iwe->u.mode = IW_MODE_AUTO;
}
priv->scan_result_size += BCMF_IW_EVENT_SIZE(mode);
result_size -= BCMF_IW_EVENT_SIZE(mode);
/* Copy AP encryption mode */
if (result_size < BCMF_IW_EVENT_SIZE(data))
{
goto scan_result_full;
}
iwe = (struct iw_event*)&priv->scan_result[priv->scan_result_size];
iwe->len = BCMF_IW_EVENT_SIZE(data);
iwe->cmd = SIOCGIWENCODE;
iwe->u.data.flags = bss->capability & DOT11_CAP_PRIVACY ?
IW_ENCODE_ENABLED | IW_ENCODE_NOKEY :
IW_ENCODE_DISABLED;
iwe->u.data.length = 0;
iwe->u.essid.pointer = NULL;
priv->scan_result_size += BCMF_IW_EVENT_SIZE(data);
result_size -= BCMF_IW_EVENT_SIZE(data);
/* Copy relevant raw IE frame */
if (bss->ie_offset >= bss_info_len ||
bss->ie_length > bss_info_len-bss->ie_offset)
{
goto process_next_bss;
}
ie_offset = 0;
ie_buffer = (uint8_t*)bss + bss->ie_offset;
while (1)
{
size_t ie_frame_size;
if (bss->ie_length - ie_offset < 2)
{
/* Minimum Information element size is 2 bytes */
break;
}
ie_frame_size = ie_buffer[ie_offset+1] + 2;
if (ie_frame_size > bss->ie_length - ie_offset)
{
/* Entry too big */
break;
}
switch (ie_buffer[ie_offset])
{
case IEEE80211_ELEMID_RSN:
{
size_t ie_frame_size_aligned;
ie_frame_size_aligned = (ie_frame_size + 3) & -4;
wlinfo("found RSN\n");
if (result_size < BCMF_IW_EVENT_SIZE(data) + ie_frame_size_aligned)
{
break;
}
iwe = (struct iw_event*)&priv->scan_result[priv->scan_result_size];
iwe->len = BCMF_IW_EVENT_SIZE(data)+ie_frame_size_aligned;
iwe->cmd = IWEVGENIE;
iwe->u.data.flags = 0;
iwe->u.data.length = ie_frame_size;
iwe->u.data.pointer = (FAR void*)sizeof(iwe->u.data);
memcpy(&iwe->u.data+1, &ie_buffer[ie_offset], ie_frame_size);
priv->scan_result_size += BCMF_IW_EVENT_SIZE(essid)+ie_frame_size_aligned;
result_size -= BCMF_IW_EVENT_SIZE(essid)+ie_frame_size_aligned;
break;
}
default:
// wlinfo("unhandled IE entry %d %d\n", ie_buffer[ie_offset],
// ie_buffer[ie_offset+1]);
break;
}
ie_offset += ie_buffer[ie_offset+1] + 2;
}
goto process_next_bss;
scan_result_full:
/* Continue instead of break to log dropped AP results */
wlerr("No more space in scan_result buffer\n");
process_next_bss:
/* Process next bss_info */
len -= bss_info_len;
@ -632,12 +852,26 @@ int bcmf_wl_start_scan(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
/* Lock control_mutex semaphore */
if ((ret = sem_wait(&priv->control_mutex)) != OK)
{
goto exit_failed;
}
/* Allocate buffer to store scan result */
if (priv->scan_result == NULL)
{
goto exit_failed;
priv->scan_result = kmm_malloc(BCMF_SCAN_RESULT_SIZE);
if (priv->scan_result == NULL)
{
wlerr("Cannot allocate result buffer\n");
ret = -ENOMEM;
goto exit_sem_post;
}
}
wlinfo("start scan\n");
priv->scan_result_size = 0;
priv->scan_status = BCMF_SCAN_RUN;
out_len = sizeof(scan_params);
@ -658,8 +892,8 @@ int bcmf_wl_start_scan(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
return OK;
exit_sem_post:
sem_post(&priv->control_mutex);
priv->scan_status = BCMF_SCAN_DISABLED;
sem_post(&priv->control_mutex);
exit_failed:
wlinfo("Failed\n");
return ret;
@ -667,19 +901,80 @@ exit_failed:
int bcmf_wl_get_scan_results(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)
{
/* Not implemented yet, set len to zero */
iwr->u.data.length = 0;
int ret = OK;
if (priv->scan_status == BCMF_SCAN_RUN)
{
return -EAGAIN;
ret = -EAGAIN;
goto exit_failed;
}
if (priv->scan_status == BCMF_SCAN_DONE)
if (priv->scan_status != BCMF_SCAN_DONE)
{
return OK;
ret = -EINVAL;
goto exit_failed;
}
return -EINVAL;
/* Lock control_mutex semaphore to avoid race condition */
if ((ret = sem_wait(&priv->control_mutex)) != OK)
{
ret = -EIO;
goto exit_failed;
}
if (!priv->scan_result)
{
/* Result have already been requested */
ret = OK;
iwr->u.data.length = 0;
goto exit_sem_post;
}
if (iwr->u.data.pointer == NULL ||
iwr->u.data.length < priv->scan_result_size)
{
/* Stat request, return scan_result_size */
ret = -E2BIG;
iwr->u.data.pointer = NULL;
iwr->u.data.length = priv->scan_result_size;
goto exit_sem_post;
}
if (priv->scan_result_size <= 0)
{
ret = OK;
iwr->u.data.length = 0;
goto exit_free_buffer;
}
/* Copy result to user buffer */
if (iwr->u.data.length > priv->scan_result_size)
{
iwr->u.data.length = priv->scan_result_size;
}
memcpy(iwr->u.data.pointer, priv->scan_result, iwr->u.data.length);
exit_free_buffer:
/* Free scan result buffer */
kmm_free(priv->scan_result);
priv->scan_result = NULL;
priv->scan_result_size = 0;
exit_sem_post:
sem_post(&priv->control_mutex);
exit_failed:
if (ret)
{
iwr->u.data.length = 0;
}
return ret;
}
int bcmf_wl_set_auth_param(FAR struct bcmf_dev_s *priv, struct iwreq *iwr)

View File

@ -93,6 +93,8 @@ struct bcmf_dev_s
int scan_status; /* Current scan status */
WDOG_ID scan_timeout; /* Scan timeout timer */
FAR uint8_t *scan_result; /* Temp buffer that holds results */
unsigned int scan_result_size; /* Current size of temp buffer */
sem_t auth_signal; /* Authentication notification signal */
int auth_status; /* Authentication status */

View File

@ -106,6 +106,10 @@ typedef struct wl_bss_info
/* variable length Information Elements */
} wl_bss_info_t;
#define DOT11_CAP_ESS 0x0001
#define DOT11_CAP_IBSS 0x0002
#define DOT11_CAP_PRIVACY 0x0010
typedef struct wlc_ssid
{
uint32_t SSID_len;

View File

@ -47,6 +47,14 @@
#define container_of(ptr, type, member) \
(type *)((uint8_t *)(ptr) - offsetof(type, member))
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/

View File

@ -0,0 +1,280 @@
/****************************************************************************
* include/nuttx/audio/cs43l22.h
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Reference:
* "CS43L22 Ultra Low Power CODEC for Portable Audio Applications, Pre-
* Production", September 2012, Rev 3.3, Wolfson Microelectronics
*
* 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_AUDIO_CS43L22_H
#define __INCLUDE_NUTTX_AUDIO_CS43L22_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include <stdbool.h>
#include <nuttx/irq.h>
#ifdef CONFIG_AUDIO_CS43L22
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************
*
* CONFIG_AUDIO_CS43L22 - Enables CS43L22 support
* CONFIG_CS43L22_INITVOLUME - The initial volume level in the range {0..1000}
* CONFIG_CS43L22_INFLIGHT - Maximum number of buffers that the CS43L22 driver
* will send to the I2S driver before any have completed.
* CONFIG_CS43L22_MSG_PRIO - Priority of messages sent to the CS43L22 worker
* thread.
* CONFIG_CS43L22_BUFFER_SIZE - Preferred buffer size
* CONFIG_CS43L22_NUM_BUFFERS - Preferred number of buffers
* CONFIG_CS43L22_WORKER_STACKSIZE - Stack size to use when creating the the
* CS43L22 worker thread.
* CONFIG_CS43L22_REGDUMP - Enable logic to dump all CS43L22 registers to
* the SYSLOG device.
*/
/* Pre-requisites */
#ifndef CONFIG_AUDIO
# error CONFIG_AUDIO is required for audio subsystem support
#endif
#ifndef CONFIG_I2S
# error CONFIG_I2S is required by the CS43L22 driver
#endif
#ifndef CONFIG_I2C
# error CONFIG_I2C is required by the CS43L22 driver
#endif
#ifndef CONFIG_SCHED_WORKQUEUE
# error CONFIG_SCHED_WORKQUEUE is required by the CS43L22 driver
#endif
/* Default configuration values */
#ifndef CONFIG_CS43L22_INITVOLUME
# define CONFIG_CS43L22_INITVOLUME 400
#endif
#ifndef CONFIG_CS43L22_INFLIGHT
# define CONFIG_CS43L22_INFLIGHT 2
#endif
#if CONFIG_CS43L22_INFLIGHT > 255
# error CONFIG_CS43L22_INFLIGHT must fit in a uint8_t
#endif
#ifndef CONFIG_CS43L22_MSG_PRIO
# define CONFIG_CS43L22_MSG_PRIO 1
#endif
#ifndef CONFIG_CS43L22_BUFFER_SIZE
# define CONFIG_CS43L22_BUFFER_SIZE 8192
#endif
#ifndef CONFIG_CS43L22_NUM_BUFFERS
# define CONFIG_CS43L22_NUM_BUFFERS 4
#endif
#ifndef CONFIG_CS43L22_WORKER_STACKSIZE
# define CONFIG_CS43L22_WORKER_STACKSIZE 768
#endif
/* Helper macros ************************************************************/
#define CS43L22_ATTACH(s,isr,arg) ((s)->attach(s,isr,arg))
#define CS43L22_DETACH(s) ((s)->attach(s,NULL,NULL))
#define CS43L22_ENABLE(s) ((s)->enable(s,true))
#define CS43L22_DISABLE(s) ((s)->enable(s,false))
#define CS43L22_RESTORE(s,e) ((s)->enable(s,e))
#define CS43L22_HW_RESET(s) ((s)->reset(s))
/****************************************************************************
* Public Types
****************************************************************************/
/* This is the type of the CS43L22 interrupt handler. The lower level code
* will intercept the interrupt and provide the upper level with the private
* data that was provided when the interrupt was attached.
*/
struct cs43l22_lower_s; /* Forward reference. Defined below */
typedef CODE int (*cs43l22_handler_t)(FAR const struct cs43l22_lower_s *lower,
FAR void *arg);
/* A reference to a structure of this type must be passed to the CS43L22
* driver. This structure provides information about the configuration
* of the CS43L22 and provides some board-specific hooks.
*
* Memory for this structure is provided by the caller. It is not copied
* by the driver and is presumed to persist while the driver is active.
*/
struct cs43l22_lower_s
{
/* I2C characterization */
uint32_t frequency; /* Initial I2C frequency */
uint8_t address; /* 7-bit I2C address (only bits 0-6 used) */
/* Clocking is provided via MCLK. The CS43L22 driver will need to know
* the frequency of MCLK in order to generate the correct bitrates.
*/
uint32_t mclk; /* CS43L22 Master clock frequency */
/* IRQ/GPIO access callbacks. These operations all hidden behind
* callbacks to isolate the CS43L22 driver from differences in GPIO
* interrupt handling by varying boards and MCUs. If possible,
* interrupts should be configured on both rising and falling edges
* so that contact and loss-of-contact events can be detected.
*
* attach - Attach or detach the CS43L22 interrupt handler to the GPIO
* interrupt
* enable - Enable or disable the GPIO interrupt. Returns the
* previous interrupt state.
* reset - HW reset of the CS43L22 chip
*/
CODE int (*attach)(FAR const struct cs43l22_lower_s *lower,
cs43l22_handler_t isr, FAR void *arg);
CODE bool (*enable)(FAR const struct cs43l22_lower_s *lower, bool enable);
CODE void (*reset)(FAR const struct cs43l22_lower_s *lower);
};
/****************************************************************************
* Public Data
****************************************************************************/
#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: cs43l22_initialize
*
* Description:
* Initialize the CS43L22 device.
*
* Input Parameters:
* i2c - An I2C driver instance
* i2s - An I2S driver instance
* lower - Persistent board configuration data
*
* Returned Value:
* A new lower half audio interface for the CS43L22 device is returned on
* success; NULL is returned on failure.
*
****************************************************************************/
struct i2c_master_s; /* Forward reference. Defined in include/nuttx/i2c/i2c_master.h */
struct i2s_dev_s; /* Forward reference. Defined in include/nuttx/audio/i2s.h */
struct audio_lowerhalf_s; /* Forward reference. Defined in nuttx/audio/audio.h */
FAR struct audio_lowerhalf_s *
cs43l22_initialize(FAR struct i2c_master_s *i2c, FAR struct i2s_dev_s *i2s,
FAR const struct cs43l22_lower_s *lower);
/****************************************************************************
* Name: cs43l22_dump_registers
*
* Description:
* Dump the contents of all CS43L22 registers to the syslog device
*
* Input Parameters:
* dev - The device instance returned by cs43l22_initialize
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_CS43L22_REGDUMP
void cs43l22_dump_registers(FAR struct audio_lowerhalf_s *dev,
FAR const char *msg);
#else
/* This eliminates the need for any conditional compilation in the
* including file.
*/
# define cs43l22_dump_registers(d,m)
#endif
/****************************************************************************
* Name: cs43l22_clock_analysis
*
* Description:
* Analyze the settings in the clock chain and dump to syslog.
*
* Input Parameters:
* dev - The device instance returned by cs43l22_initialize
*
* Returned Value:
* None.
*
****************************************************************************/
#ifdef CONFIG_CS43L22_CLKDEBUG
void cs43l22_clock_analysis(FAR struct audio_lowerhalf_s *dev,
FAR const char *msg);
#else
/* This eliminates the need for any conditional compilation in the
* including file.
*/
# define cs43l22_clock_analysis(d,m)
#endif
#undef EXTERN
#ifdef __cplusplus
}
#endif
#endif /* CONFIG_AUDIO_CS43L22 */
#endif /* __INCLUDE_NUTTX_AUDIO_CS43L22_H */

View File

@ -504,7 +504,7 @@ begin_packed_struct struct ieee80211_qosframe
uint8_t i_addr3[IEEE80211_ADDR_LEN];
uint8_t i_seq[2];
uint8_t i_qos[2];
} end_packet_struct;
} end_packed_struct;
begin_packed_struct struct ieee80211_htframe /* 11n */
{
@ -516,7 +516,7 @@ begin_packed_struct struct ieee80211_htframe /* 11n */
uint8_t i_seq[2];
uint8_t i_qos[2];
uint8_t i_ht[4];
} end_packet_struct;
} end_packed_struct;
begin_packed_struct struct ieee80211_frame_addr4
{
@ -527,7 +527,7 @@ begin_packed_struct struct ieee80211_frame_addr4
uint8_t i_addr3[IEEE80211_ADDR_LEN];
uint8_t i_seq[2];
uint8_t i_addr4[IEEE80211_ADDR_LEN];
} end_packet_struct;
} end_packed_struct;
begin_packed_struct struct ieee80211_qosframe_addr4
{
@ -539,7 +539,7 @@ begin_packed_struct struct ieee80211_qosframe_addr4
uint8_t i_seq[2];
uint8_t i_addr4[IEEE80211_ADDR_LEN];
uint8_t i_qos[2];
} end_packet_struct;
} end_packed_struct;
begin_packed_struct struct ieee80211_htframe_addr4 /* 11n */
{
@ -552,7 +552,7 @@ begin_packed_struct struct ieee80211_htframe_addr4 /* 11n */
uint8_t i_addr4[IEEE80211_ADDR_LEN];
uint8_t i_qos[2];
uint8_t i_ht[4];
} end_packet_struct;
} end_packed_struct;
/* Control frames. */
@ -565,7 +565,7 @@ begin_packed_struct struct ieee80211_frame_min
/* FCS */
} end_packet_struct;
} end_packed_struct;
begin_packed_struct struct ieee80211_frame_rts
{
@ -576,7 +576,7 @@ begin_packed_struct struct ieee80211_frame_rts
/* FCS */
} end_packet_struct;
} end_packed_struct;
struct ieee80211_frame_cts
{
@ -586,7 +586,7 @@ struct ieee80211_frame_cts
/* FCS */
} end_packet_struct;
} end_packed_struct;
struct ieee80211_frame_ack
{
@ -596,7 +596,7 @@ struct ieee80211_frame_ack
/* FCS */
} end_packet_struct;
} end_packed_struct;
struct ieee80211_frame_pspoll
{
@ -607,7 +607,7 @@ struct ieee80211_frame_pspoll
/* FCS */
} end_packet_struct;
} end_packed_struct;
struct ieee80211_frame_cfend
{ /* NB: also CF-End+CF-Ack */
@ -618,7 +618,7 @@ struct ieee80211_frame_cfend
/* FCS */
} end_packet_struct;
} end_packed_struct;
/* Information elements (see Table 7-26). */
@ -818,7 +818,7 @@ struct ieee80211_eapol_key
uint8_t reserved[8];
uint8_t mic[EAPOL_KEY_MIC_LEN];
uint8_t paylen[2];
} end_packet_struct;
} end_packed_struct;
/* Pairwise Transient Key (see 8.5.1.2) */
@ -827,7 +827,7 @@ struct ieee80211_ptk
uint8_t kck[16]; /* Key Confirmation Key */
uint8_t kek[16]; /* Key Encryption Key */
uint8_t tk[32]; /* Temporal Key */
} end_packet_struct;
} end_packed_struct;
/* Key Data Encapsulation (see Table 62) */

View File

@ -160,6 +160,47 @@
#define WL_NNETCMDS 0x0032 /* Number of network commands */
#define WL_USERFIRST (WL_NETFIRST + WL_NNETCMDS)
/* ----------------------- WIRELESS EVENTS ----------------------- */
/* Those are *NOT* ioctls, do not issue request on them !!! */
/* Most events use the same identifier as ioctl requests */
#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */
#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */
#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
* (scan results); This includes id and
* length fields. One IWEVGENIE may
* contain more than one IE. Scan
* results may contain one or more
* IWEVGENIE events. */
#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure
* (struct iw_michaelmicfailure)
*/
#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request.
* The data includes id and length
* fields and may contain more than one
* IE. This event is required in
* Managed mode if the driver
* generates its own WPA/RSN IE. This
* should be sent just before
* IWEVREGISTERED event for the
* association. */
#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association
* Response. The data includes id and
* length fields and may contain more
* than one IE. This may be sent
* between IWEVASSOCREQIE and
* IWEVREGISTERED events for the
* association. */
#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN
* pre-authentication
* (struct iw_pmkid_cand) */
#define IWEVFIRST 0x8C00
#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST)
/* Other Common Wireless Definitions ***********************************************/
/* Maximum size of the ESSID and NICKN strings */
@ -178,6 +219,31 @@
#define IW_MODE_MESH 7 /* Mesh (IEEE 802.11s) network */
#define IW_MODE_NFLAGS 8
/* Statistics flags (bitmask in updated) */
#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */
#define IW_QUAL_LEVEL_UPDATED 0x02
#define IW_QUAL_NOISE_UPDATED 0x04
#define IW_QUAL_ALL_UPDATED 0x07
#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */
#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */
#define IW_QUAL_LEVEL_INVALID 0x20
#define IW_QUAL_NOISE_INVALID 0x40
#define IW_QUAL_RCPI 0x80 /* Level + Noise are 802.11k RCPI */
#define IW_QUAL_ALL_INVALID 0x70
/* Flags for encoding (along with the token) */
#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */
#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */
#define IW_ENCODE_MODE 0xF000 /* Modes defined below */
#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */
#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */
#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */
#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */
#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */
#define IW_ENCODE_TEMP 0x0400 /* Temporary key */
/* Frequency flags */
#define IW_FREQ_AUTO 0 /* Let the driver decides */

View File

@ -51,7 +51,6 @@ config IOB_THROTTLE
int "I/O buffer throttle value"
default 0 if !NET_TCP_WRITE_BUFFERS || !NET_TCP_READAHEAD
default 8 if NET_TCP_WRITE_BUFFERS && NET_TCP_READAHEAD
depends on NET_TCP_WRITE_BUFFERS && NET_TCP_READAHEAD
---help---
TCP write buffering and read-ahead buffer use the same pool of free
I/O buffers. In order to prevent uncontrolled incoming TCP packets
@ -70,7 +69,7 @@ config IOB_DEBUG
if you are debugging the I/O buffer logic and do not want to get
overloaded with other un-related debug output.
NOTE that this selection is not avaiable with IOBs are being used
NOTE that this selection is not available if IOBs are being used
to syslog buffering logic (CONFIG_SYSLOG_BUFFER=y)!
endif # MM_IOB