stm32wl5: add lower half driver for IPCC
Signed-off-by: Michał Łyszczek <michal.lyszczek@bofc.pl>
This commit is contained in:
parent
a9f78a64db
commit
e887a4a5b7
@ -201,6 +201,17 @@ config STM32WL5_SPI1
|
||||
depends on STM32WL5_HAVE_SPI1
|
||||
select STM32WL5_SPI
|
||||
|
||||
comment "AHB3 Peripherals"
|
||||
|
||||
config STM32WL5_IPCC
|
||||
bool "IPCC"
|
||||
select IPCC
|
||||
default n
|
||||
---help---
|
||||
IPCC - Inter Processor Communication Controller. A very simple
|
||||
character device stream driver to exchange data between
|
||||
CM0 and CM4.
|
||||
|
||||
endmenu # STM32WL5 Peripheral Support
|
||||
|
||||
|
||||
@ -300,4 +311,99 @@ config STM32WL5_SPI2S2_DMA_BUFFER
|
||||
|
||||
endmenu # SPI Configuration
|
||||
|
||||
menu "IPCC Configuration"
|
||||
depends on STM32WL5_IPCC
|
||||
|
||||
config STM32WL5_IPCC_CHAN1_RX_SIZE
|
||||
int "Channel 1 RX size"
|
||||
default 256
|
||||
---help---
|
||||
Size of the receive buffer. Another CPU will write to this
|
||||
buffer and currently running CPU will read from it.
|
||||
|
||||
config STM32WL5_IPCC_CHAN1_TX_SIZE
|
||||
int "Channel 1 TX size"
|
||||
default 256
|
||||
---help---
|
||||
Size of the send buffer. Another CPU will read from this
|
||||
buffer and currently running CPU will write to it.
|
||||
|
||||
config STM32WL5_IPCC_CHAN2
|
||||
bool "Enable channel 2"
|
||||
default n
|
||||
|
||||
if STM32WL5_IPCC_CHAN2
|
||||
|
||||
config STM32WL5_IPCC_CHAN2_RX_SIZE
|
||||
int "Channel 2 RX size"
|
||||
default 256
|
||||
|
||||
config STM32WL5_IPCC_CHAN2_TX_SIZE
|
||||
int "Channel 2 TX size"
|
||||
default 256
|
||||
|
||||
config STM32WL5_IPCC_CHAN3
|
||||
bool "Enable channel 3"
|
||||
default n
|
||||
|
||||
if STM32WL5_IPCC_CHAN3
|
||||
|
||||
config STM32WL5_IPCC_CHAN3_RX_SIZE
|
||||
int "Channel 3 RX size"
|
||||
default 256
|
||||
|
||||
config STM32WL5_IPCC_CHAN3_TX_SIZE
|
||||
int "Channel 3 TX size"
|
||||
default 256
|
||||
|
||||
config STM32WL5_IPCC_CHAN4
|
||||
bool "Enable channel 4"
|
||||
default n
|
||||
|
||||
if STM32WL5_IPCC_CHAN4
|
||||
|
||||
config STM32WL5_IPCC_CHAN4_RX_SIZE
|
||||
int "Channel 4 RX size"
|
||||
default 256
|
||||
|
||||
config STM32WL5_IPCC_CHAN4_TX_SIZE
|
||||
int "Channel 4 TX size"
|
||||
default 256
|
||||
|
||||
config STM32WL5_IPCC_CHAN5
|
||||
bool "Enable channel 5"
|
||||
default n
|
||||
|
||||
if STM32WL5_IPCC_CHAN5
|
||||
|
||||
config STM32WL5_IPCC_CHAN5_RX_SIZE
|
||||
int "Channel 5 RX size"
|
||||
default 256
|
||||
|
||||
config STM32WL5_IPCC_CHAN5_TX_SIZE
|
||||
int "Channel 5 TX size"
|
||||
default 256
|
||||
|
||||
config STM32WL5_IPCC_CHAN6
|
||||
bool "Enable channel 6"
|
||||
default n
|
||||
|
||||
if STM32WL5_IPCC_CHAN6
|
||||
|
||||
config STM32WL5_IPCC_CHAN6_RX_SIZE
|
||||
int "Channel 6 RX size"
|
||||
default 256
|
||||
|
||||
config STM32WL5_IPCC_CHAN6_TX_SIZE
|
||||
int "Channel 6 TX size"
|
||||
default 256
|
||||
|
||||
endif # STM32WL5_IPCC_CHAN2
|
||||
endif # STM32WL5_IPCC_CHAN3
|
||||
endif # STM32WL5_IPCC_CHAN4
|
||||
endif # STM32WL5_IPCC_CHAN5
|
||||
endif # STM32WL5_IPCC_CHAN6
|
||||
|
||||
endmenu # IPCC Configuration
|
||||
|
||||
endif # ARCH_CHIP_STM32WL5
|
||||
|
@ -33,3 +33,7 @@ CHIP_CSRCS += stm32wl5_serial.c stm32wl5_start.c stm32wl5_waste.c stm32wl5_uid.c
|
||||
CHIP_CSRCS += stm32wl5_lse.c stm32wl5_lsi.c stm32wl5_idle.c
|
||||
CHIP_CSRCS += stm32wl5_pwr.c stm32wl5_tim.c stm32wl5_flash.c stm32wl5_timerisr.c
|
||||
CHIP_CSRCS += stm32wl5_spi.c
|
||||
|
||||
CSRCS-$(CONFIG_STM32WL5_IPCC) = stm32wl5_ipcc.c
|
||||
|
||||
CHIP_CSRCS += $(CSRCS-y)
|
||||
|
79
arch/arm/src/stm32wl5/hardware/stm32wl5_ipcc.h
Normal file
79
arch/arm/src/stm32wl5/hardware/stm32wl5_ipcc.h
Normal file
@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32wl5/hardware/stm32wl5_ipcc.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_IPCC_H
|
||||
#define __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_IPCC_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include "chip.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define STM32WL5_IPCC_CPU1_OFFSET 0x00
|
||||
#define STM32WL5_IPCC_CPU2_OFFSET 0x10
|
||||
|
||||
/* Register Offsets *********************************************************/
|
||||
|
||||
#define STM32WL5_IPCC_CR_OFFSET 0x00 /* IPCC control register */
|
||||
#define STM32WL5_IPCC_MR_OFFSET 0x04 /* IPCC mask register */
|
||||
#define STM32WL5_IPCC_SCR_OFFSET 0x08 /* IPCC status set clear register */
|
||||
#define STM32WL5_IPCC_CTOCSR_OFFSET 0x0c /* IPCC processor to processor status register */
|
||||
|
||||
/* Register Addresses *******************************************************/
|
||||
|
||||
#define STM32WL5_IPCC_C1CR (STM32WL5_IPCC_BASE+STM32WL5_IPCC_CR_OFFSET+STM32WL5_IPCC_CPU1_OFFSET)
|
||||
#define STM32WL5_IPCC_C1MR (STM32WL5_IPCC_BASE+STM32WL5_IPCC_MR_OFFSET+STM32WL5_IPCC_CPU1_OFFSET)
|
||||
#define STM32WL5_IPCC_C1SCR (STM32WL5_IPCC_BASE+STM32WL5_IPCC_SCR_OFFSET+STM32WL5_IPCC_CPU1_OFFSET)
|
||||
#define STM32WL5_IPCC_C1TOC2SR (STM32WL5_IPCC_BASE+STM32WL5_IPCC_CTOCSR_OFFSET+STM32WL5_IPCC_CPU1_OFFSET)
|
||||
#define STM32WL5_IPCC_C2CR (STM32WL5_IPCC_BASE+STM32WL5_IPCC_CR_OFFSET+STM32WL5_IPCC_CPU2_OFFSET)
|
||||
#define STM32WL5_IPCC_C2MR (STM32WL5_IPCC_BASE+STM32WL5_IPCC_MR_OFFSET+STM32WL5_IPCC_CPU2_OFFSET)
|
||||
#define STM32WL5_IPCC_C2SCR (STM32WL5_IPCC_BASE+STM32WL5_IPCC_SCR_OFFSET+STM32WL5_IPCC_CPU2_OFFSET)
|
||||
#define STM32WL5_IPCC_C2TOC1SR (STM32WL5_IPCC_BASE+STM32WL5_IPCC_CTOCSR_OFFSET+STM32WL5_IPCC_CPU2_OFFSET)
|
||||
|
||||
/* Register Bitfield Definitions ********************************************/
|
||||
|
||||
#define STM32WL5_IPCC_TX_SHIFT (16) /* TX shift for all registers */
|
||||
|
||||
/* IPCC control register */
|
||||
|
||||
#define STM32WL5_IPCC_CR_RXOIE (1 << 0) /* Bit 0: Receive channel occupied interrupt enable */
|
||||
#define STM32WL5_IPCC_CR_TXFIE (1 << 16) /* Bit 16: Transmit channel free interrupt enable */
|
||||
|
||||
/* IPCC mask register */
|
||||
|
||||
#define STM32WL5_IPCC_MR_CHNOM(n) (1 << (n)) /* Bit 0..5: Receive channel n occupied interrupt enable, Channels 0..5 */
|
||||
#define STM32WL5_IPCC_MR_CHNFM(n) (1 << (16 + (n))) /* Bit 16..21: Transmit channel n free interrupt enable, Channels 0..5 */
|
||||
|
||||
/* IPCC status set clear register */
|
||||
|
||||
#define STM32WL5_IPCC_SCR_CHNC(n) (1 << (n)) /* Bit 0..5: Receive channel n status bit clear, Channels 0..5 */
|
||||
#define STM32WL5_IPCC_SCR_CHNS(n) (1 << (16 + (n))) /* Bit 16..21: Transmit channel n status bit set, Channels 0..5 */
|
||||
|
||||
/* IPCC processor to processor status register */
|
||||
|
||||
#define STM32WL5_IPCC_CTOCSR_CHNF(n) (1 << (n)) /* Bit 0..5: Channel n occupied, Channels 0..5 */
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_IPCC_H */
|
@ -41,6 +41,7 @@
|
||||
#include "arm_internal.h"
|
||||
#include "arm_internal.h"
|
||||
#include "stm32wl5_mpuinit.h"
|
||||
#include "stm32wl5_ipcc.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
@ -69,7 +70,11 @@
|
||||
|
||||
/* Set the range of SRAM2 as well, requires a second memory region */
|
||||
|
||||
#define SRAM2_START STM32WL5_SRAM2_BASE
|
||||
#ifdef CONFIG_IPCC
|
||||
# define SRAM2_START IPCC_END
|
||||
#else
|
||||
# define SRAM2_START STM32WL5_SRAM2_BASE
|
||||
#endif
|
||||
#define SRAM2_END (SRAM2_START + STM32WL5_SRAM2_SIZE)
|
||||
|
||||
/* Some sanity checking. If multiple memory regions are defined, verify
|
||||
|
812
arch/arm/src/stm32wl5/stm32wl5_ipcc.c
Normal file
812
arch/arm/src/stm32wl5/stm32wl5_ipcc.c
Normal file
@ -0,0 +1,812 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32wl5/stm32wl5_ipcc.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/ipcc.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
|
||||
#include <arm_internal.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <arch/stm32wl5/stm32wl5xxx_cpu1_irq.h>
|
||||
#include "hardware/stm32wl5_ipcc.h"
|
||||
#include "stm32wl5.h"
|
||||
#include "stm32wl5_ipcc.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure describes tx or rx of single channel in memory */
|
||||
|
||||
struct stm32wl5_ipcc_chan_mem_s
|
||||
{
|
||||
unsigned len; /* Number of valid bytes in data[] */
|
||||
char data[]; /* Data in IPCC memory */
|
||||
};
|
||||
|
||||
/* Internal stm32wl5 ipcc structure describing channel state. */
|
||||
|
||||
struct stm32wl5_ipcc_s
|
||||
{
|
||||
/* Pointer to API connecting upper and lower half of the driver */
|
||||
|
||||
struct ipcc_lower_s *ipcc;
|
||||
|
||||
/* Physical memory address where second CPU will write data for us,
|
||||
* we will be reading from this memory.
|
||||
*/
|
||||
|
||||
char *rxmem;
|
||||
|
||||
/* Maximum length of data that rxmem can hold. It is size of the
|
||||
* reserved space for rxmem minus sizeof(stm32wl5_ipcc_chan_mem_s.len)
|
||||
*/
|
||||
|
||||
unsigned rxlen;
|
||||
|
||||
#if CONFIG_IPCC_BUFFERED
|
||||
/* Number of bytes copied from IPCC memory to buffer. Can be less than
|
||||
* stm32wl5_ipcc_chan_mem_s.len after copy operation when buffer is full.
|
||||
* Value can persist between multiple ISR and stm32wl5_ipcc_buffer_data()
|
||||
* calls, until all data from IPCC memory is successfully buffered.
|
||||
*/
|
||||
|
||||
unsigned rxcopied;
|
||||
#endif
|
||||
|
||||
/* Physical memory address where we will write data for the second
|
||||
* CPU to read.
|
||||
*/
|
||||
|
||||
char *txmem;
|
||||
|
||||
/* Maximum length of data that txmem can hold. It is size of the
|
||||
* reserved space for txmem minus sizeof(stm32wl5_ipcc_chan_mem_s.len)
|
||||
*/
|
||||
|
||||
unsigned txlen;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t stm32wl5_ipcc_read(struct ipcc_lower_s *ipcc,
|
||||
char *buffer, size_t buflen);
|
||||
static ssize_t stm32wl5_ipcc_write(struct ipcc_lower_s *ipcc,
|
||||
const char *buffer, size_t buflen);
|
||||
static ssize_t stm32wl5_ipcc_buffer_data(struct ipcc_lower_s *ipcc,
|
||||
struct circbuf_s *rxbuf);
|
||||
static ssize_t stm32wl5_ipcc_copy_to_buffer(int chan,
|
||||
struct circbuf_s *rxbuf);
|
||||
static int stm32wl5_ipcc_rx_isr(int irq, void *context, void *arg);
|
||||
static int stm32wl5_ipcc_tx_isr(int irq, void *context, void *arg);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
struct stm32wl5_ipcc_s g_ipccpriv[IPCC_NCHAN] =
|
||||
{
|
||||
/* Channel 1 is always enabled when IPCC is enabled */
|
||||
|
||||
{
|
||||
.rxmem = (char *)(IPCC_CHAN1_START),
|
||||
.rxlen = IPCC_CHAN1_RX_SIZE - sizeof(unsigned),
|
||||
.txmem = (char *)(IPCC_CHAN1_START + IPCC_CHAN1_RX_SIZE),
|
||||
.txlen = IPCC_CHAN1_TX_SIZE - sizeof(unsigned)
|
||||
}
|
||||
|
||||
#if IPCC_CHAN2
|
||||
,
|
||||
{
|
||||
.rxmem = (char *)(IPCC_CHAN2_START),
|
||||
.rxlen = IPCC_CHAN2_RX_SIZE - sizeof(unsigned),
|
||||
.txmem = (char *)(IPCC_CHAN2_START + IPCC_CHAN2_RX_SIZE),
|
||||
.txlen = IPCC_CHAN2_TX_SIZE - sizeof(unsigned)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IPCC_CHAN3
|
||||
,
|
||||
{
|
||||
.rxmem = (char *)(IPCC_CHAN3_START),
|
||||
.rxlen = IPCC_CHAN3_RX_SIZE - sizeof(unsigned),
|
||||
.txmem = (char *)(IPCC_CHAN3_START + IPCC_CHAN3_RX_SIZE),
|
||||
.txlen = IPCC_CHAN3_TX_SIZE - sizeof(unsigned)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IPCC_CHAN4
|
||||
,
|
||||
{
|
||||
.rxmem = (char *)(IPCC_CHAN4_START),
|
||||
.rxlen = IPCC_CHAN4_RX_SIZE - sizeof(unsigned),
|
||||
.txmem = (char *)(IPCC_CHAN4_START + IPCC_CHAN4_RX_SIZE),
|
||||
.txlen = IPCC_CHAN4_TX_SIZE - sizeof(unsigned)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IPCC_CHAN5
|
||||
,
|
||||
{
|
||||
.rxmem = (char *)(IPCC_CHAN5_START),
|
||||
.rxlen = IPCC_CHAN5_RX_SIZE - sizeof(unsigned),
|
||||
.txmem = (char *)(IPCC_CHAN5_START + IPCC_CHAN5_RX_SIZE),
|
||||
.txlen = IPCC_CHAN5_TX_SIZE - sizeof(unsigned)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IPCC_CHAN6
|
||||
,
|
||||
{
|
||||
.rxmem = (char *)(IPCC_CHAN6_START),
|
||||
.rxlen = IPCC_CHAN6_RX_SIZE - sizeof(unsigned),
|
||||
.txmem = (char *)(IPCC_CHAN6_START + IPCC_CHAN6_RX_SIZE),
|
||||
.txlen = IPCC_CHAN6_TX_SIZE - sizeof(unsigned)
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32wl5_ipcc_tx_isr
|
||||
*
|
||||
* Description:
|
||||
* IPCC TX interrupt service routine. This interrupt is called when
|
||||
* second CPU read all data from IPCC TX memory and we are free to
|
||||
* write new data to that memory.
|
||||
*
|
||||
* For buffered IPCC, we will immediately write data from buffer to
|
||||
* IPCC memory and notify second CPU. Also blocked writer will be
|
||||
* notified that there is free space on tx buffer.
|
||||
*
|
||||
* For unbuffered IPCC, we won't copy anything but only notify blocked
|
||||
* writers that IPCC TX memory is free.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - Number of IRQ that generated interrupt
|
||||
* context - Interrupt register state save info (architecture-specific)
|
||||
* arg - user data (not used by us)
|
||||
*
|
||||
* Returned Value:
|
||||
* Always OK
|
||||
*
|
||||
* Assumptions/Limitations:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32wl5_ipcc_tx_isr(int irq, void *context, void *arg)
|
||||
{
|
||||
int chan;
|
||||
size_t nwritten;
|
||||
uint32_t mr;
|
||||
uint32_t sr;
|
||||
uint32_t status;
|
||||
struct stm32wl5_ipcc_s *priv;
|
||||
struct stm32wl5_ipcc_chan_mem_s *txmem;
|
||||
|
||||
(void)context;
|
||||
(void)arg;
|
||||
(void)irq;
|
||||
|
||||
mr = getreg32(STM32WL5_IPCC_C1MR) >> STM32WL5_IPCC_TX_SHIFT;
|
||||
sr = getreg32(STM32WL5_IPCC_C1TOC2SR);
|
||||
|
||||
/* Consider only channels that have tx memory free and are unmasked */
|
||||
|
||||
status = sr | mr;
|
||||
|
||||
/* Check which channels have data ready to read */
|
||||
|
||||
for (chan = 0; chan != IPCC_NCHAN; chan++)
|
||||
{
|
||||
if (status & (1 << chan))
|
||||
{
|
||||
/* Transmit on channel is either masked or TX memory is not
|
||||
* ready to write (second CPU is still read data from it,
|
||||
* CHnF == 1).
|
||||
*/
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get internal data structure for current chan */
|
||||
|
||||
priv = &g_ipccpriv[chan];
|
||||
txmem = (struct stm32wl5_ipcc_chan_mem_s *)priv->txmem;
|
||||
|
||||
#if CONFIG_IPCC_BUFFERED
|
||||
/* Copy as much as we can into IPCC memory, circbuf won't copy
|
||||
* more than there is in the buffer.
|
||||
*/
|
||||
|
||||
nwritten = circbuf_read(&priv->ipcc->txbuf, txmem->data, priv->txlen);
|
||||
|
||||
/* Did we write anything to TX memory? */
|
||||
|
||||
if (nwritten)
|
||||
{
|
||||
/* Yes, tell another CPU that data is available to read */
|
||||
|
||||
txmem->len = nwritten;
|
||||
modifyreg32(STM32WL5_IPCC_C1SCR, 0, STM32WL5_IPCC_SCR_CHNS(chan));
|
||||
}
|
||||
#else /* CONFIG_IPCC_BUFFERED */
|
||||
/* In unbuffered operations we only notify blocked writers, these
|
||||
* writers will write to IPCC memory directly.
|
||||
*/
|
||||
#endif /* CONFIG_IPCC_BUFFERED */
|
||||
|
||||
/* Wake up all blocked writers that there is free space available
|
||||
* in IPCC memory (or txbuffer) to write.
|
||||
*/
|
||||
|
||||
ipcc_txfree_notify(priv->ipcc->upper);
|
||||
|
||||
if (circbuf_used(&priv->ipcc->txbuf) == 0)
|
||||
{
|
||||
/* Mask tx free interrupt - if tx buffer is empty and we
|
||||
* did not write anything and we don't mask interrupt, we
|
||||
* will be constantly interrupted by tx free irq.
|
||||
*/
|
||||
|
||||
modifyreg32(STM32WL5_IPCC_C1MR, 0, STM32WL5_IPCC_MR_CHNFM(chan));
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32wl5_ipcc_write
|
||||
*
|
||||
* Description:
|
||||
* Function writes buffer to IPCC memory that will be later read by
|
||||
* second CPU.
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipcc - ipcc channel instance to write to
|
||||
* buffer - data to write to IPCC memory
|
||||
* buflen - number of bytes requested to write
|
||||
*
|
||||
* Returned Value:
|
||||
* Number of bytes that has been successfully written, or 0 when no
|
||||
* bytes could be written for any reason.
|
||||
*
|
||||
* Assumptions/Limitations:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t stm32wl5_ipcc_write(struct ipcc_lower_s *ipcc,
|
||||
const char *buffer, size_t buflen)
|
||||
{
|
||||
size_t to_copy;
|
||||
struct stm32wl5_ipcc_s *priv;
|
||||
struct stm32wl5_ipcc_chan_mem_s *txmem;
|
||||
uint32_t sr;
|
||||
|
||||
sr = getreg32(STM32WL5_IPCC_C1TOC2SR);
|
||||
|
||||
if ((sr & (1 << ipcc->chan)))
|
||||
{
|
||||
/* CHnF == 1 means that channel is occupied and second CPU can read
|
||||
* data from it. In any case second CPU did not yet read all data
|
||||
* and we should not write to that memory. Unmask TX interrupt
|
||||
* so we are notified when we can write to memory.
|
||||
*/
|
||||
|
||||
modifyreg32(STM32WL5_IPCC_C1MR, STM32WL5_IPCC_MR_CHNFM(ipcc->chan), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
priv = &g_ipccpriv[ipcc->chan];
|
||||
txmem = (struct stm32wl5_ipcc_chan_mem_s *)priv->txmem;
|
||||
|
||||
/* Disable TX interrupt since we will modify shared data */
|
||||
|
||||
up_disable_irq(STM32WL5_IRQ_IPCC_C1_TX_IT);
|
||||
|
||||
/* Copy as much as we can into IPCC memory */
|
||||
|
||||
to_copy = buflen > priv->txlen ? priv->txlen : buflen;
|
||||
memcpy(txmem->data, buffer, to_copy);
|
||||
txmem->len = to_copy;
|
||||
|
||||
/* Tell another CPU that data is available to read */
|
||||
|
||||
modifyreg32(STM32WL5_IPCC_C1SCR, 0, STM32WL5_IPCC_SCR_CHNS(ipcc->chan));
|
||||
|
||||
/* Reenable interrupts */
|
||||
|
||||
modifyreg32(STM32WL5_IPCC_C1MR, STM32WL5_IPCC_MR_CHNFM(ipcc->chan), 0);
|
||||
up_enable_irq(STM32WL5_IRQ_IPCC_C1_TX_IT);
|
||||
|
||||
/* Return number of successfully copied bytes to IPCC memory */
|
||||
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32wl5_ipcc_rx_isr
|
||||
*
|
||||
* Description:
|
||||
* Interrupt service routine - this function is called when another CPU
|
||||
* has copied data to IPCC memory. Function will wake up blocked readers.
|
||||
*
|
||||
* If buffering is enabled, function will also try to copy all data from
|
||||
* IPCC memory to buffer. If buffer gets full, we will copy as many bytes
|
||||
* as we can fit into buffer, internally save how many bytes we managed
|
||||
* to copy and set overflow flag to 1.
|
||||
*
|
||||
* Input Parameters:
|
||||
* irq - Number of IRQ that generated interrupt
|
||||
* context - Interrupt register state save info (architecture-specific)
|
||||
* arg - user data (not used by us)
|
||||
*
|
||||
* Returned Value:
|
||||
* Always OK
|
||||
*
|
||||
* Assumptions/Limitations:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32wl5_ipcc_rx_isr(int irq, void *context, void *arg)
|
||||
{
|
||||
int chan;
|
||||
ssize_t nread;
|
||||
uint32_t mr;
|
||||
uint32_t sr;
|
||||
uint32_t status;
|
||||
struct stm32wl5_ipcc_s *priv;
|
||||
|
||||
(void)context;
|
||||
(void)arg;
|
||||
(void)irq;
|
||||
|
||||
mr = getreg32(STM32WL5_IPCC_C1MR);
|
||||
sr = getreg32(STM32WL5_IPCC_C2TOC1SR);
|
||||
|
||||
/* Consider only channels that have data in rx memory and are unmasked */
|
||||
|
||||
status = sr & ~mr;
|
||||
|
||||
/* Check which channels have data ready to read */
|
||||
|
||||
for (chan = 0; chan != IPCC_NCHAN; chan++)
|
||||
{
|
||||
if (!(status & (1 << chan)))
|
||||
{
|
||||
/* Receive on channel is either masked or there is no data
|
||||
* ready for us to read (CHnF == 0)
|
||||
*/
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get internal data structure for current chan */
|
||||
|
||||
priv = &g_ipccpriv[chan];
|
||||
|
||||
#if CONFIG_IPCC_BUFFERED
|
||||
nread = stm32wl5_ipcc_copy_to_buffer(chan, &priv->ipcc->rxbuf);
|
||||
#else /* CONFIG_IPCC_BUFFERED */
|
||||
/* In unbuffered operations we only notify blocked readers, these
|
||||
* readers will read from IPCC memory directly.
|
||||
*/
|
||||
#endif /* CONFIG_IPCC_BUFFERED */
|
||||
|
||||
if (nread)
|
||||
{
|
||||
/* Wake up all blocked readers that there is data
|
||||
* available to read
|
||||
*/
|
||||
|
||||
ipcc_rxfree_notify(priv->ipcc->upper);
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32wl5_ipcc_read
|
||||
*
|
||||
* Description:
|
||||
* Function will copy requests number of bytes to buffer. If there is not
|
||||
* enough data in IPCC memory, less bytes than requests will be copied.
|
||||
* Buflen does not have to be bigger than IPCC memory - function can be
|
||||
* called multiple times and only new data will be transfered. If we don't
|
||||
* have control over IPCC memory (CHnF is 0 - second CPU is writing data
|
||||
* to memory) then it's assumed no data is there to read and 0 is returned.
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipcc - ipcc channel struct
|
||||
* buffer - location where data shall be copied
|
||||
* buflen - size of buffer and number of requested bytes to copy
|
||||
*
|
||||
* Returned Value:
|
||||
* Number of bytes that have been successfully copied to buffer (which
|
||||
* may be less than buflen), or 0 when there was no data to be copied.
|
||||
*
|
||||
* Assumptions/Limitations:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t stm32wl5_ipcc_read(struct ipcc_lower_s *ipcc,
|
||||
char *buffer, size_t buflen)
|
||||
{
|
||||
size_t to_copy;
|
||||
uint32_t sr;
|
||||
struct stm32wl5_ipcc_s *priv;
|
||||
struct stm32wl5_ipcc_chan_mem_s *rxmem;
|
||||
|
||||
sr = getreg32(STM32WL5_IPCC_C2TOC1SR);
|
||||
|
||||
if (!(sr & (1 << ipcc->chan)))
|
||||
{
|
||||
/* CHnF == 0 means that channel is free and second CPU can write
|
||||
* data to it. In any case data is not yet ready to read - so no
|
||||
* data can be read.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
priv = &g_ipccpriv[ipcc->chan];
|
||||
rxmem = (struct stm32wl5_ipcc_chan_mem_s *)priv->rxmem;
|
||||
|
||||
/* Disable RX interrupt since we will modify shared data */
|
||||
|
||||
up_disable_irq(STM32WL5_IRQ_IPCC_C1_RX_IT);
|
||||
|
||||
/* This function may be called multiple times to get only part
|
||||
* of data from IPCC memory, ie. There are 8 bytes of data in
|
||||
* IPCC memory and upper half calls this function 4 times, each
|
||||
* time only reading 2 bytes. Check how many bytes we can copy
|
||||
*/
|
||||
|
||||
to_copy = rxmem->len - priv->rxcopied;
|
||||
to_copy = to_copy > buflen ? buflen : to_copy;
|
||||
|
||||
/* Copy as much data to upper half as possible */
|
||||
|
||||
memcpy(buffer, rxmem->data + priv->rxcopied, to_copy);
|
||||
priv->rxcopied += to_copy;
|
||||
if (priv->rxcopied == priv->rxlen)
|
||||
{
|
||||
/* We have copied all data from IPCC memory */
|
||||
|
||||
priv->rxcopied = 0;
|
||||
|
||||
/* Tell another CPU that IPCC rx buffer is free to be populated */
|
||||
|
||||
modifyreg32(STM32WL5_IPCC_C1SCR, 0,
|
||||
STM32WL5_IPCC_SCR_CHNC(ipcc->chan));
|
||||
}
|
||||
|
||||
/* Reenable interrupt */
|
||||
|
||||
up_enable_irq(STM32WL5_IRQ_IPCC_C1_RX_IT);
|
||||
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32wl5_ipcc_copy_to_buffer
|
||||
*
|
||||
* Description:
|
||||
* Copies as much bytes from channel as possible to rxbuf circ buffer.
|
||||
*
|
||||
* Input Parameters:
|
||||
* chan - channel number to get data from
|
||||
* rxbuf - circural buffer to copy data to
|
||||
*
|
||||
* Returned Value:
|
||||
* Number of bytes copied to rxbuf
|
||||
*
|
||||
* Assumptions/Limitations:
|
||||
* This is helper function, it does not perform any locking. It may
|
||||
* be called from interrupt.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t stm32wl5_ipcc_copy_to_buffer(int chan,
|
||||
struct circbuf_s *rxbuf)
|
||||
{
|
||||
size_t to_copy;
|
||||
size_t rxbuf_space;
|
||||
struct stm32wl5_ipcc_s *priv;
|
||||
struct stm32wl5_ipcc_chan_mem_s *rxmem;
|
||||
uint32_t sr;
|
||||
|
||||
sr = getreg32(STM32WL5_IPCC_C2TOC1SR);
|
||||
|
||||
if (!(sr & (1 << chan)))
|
||||
{
|
||||
/* CHnF == 0 means that channel is free and second CPU can write
|
||||
* data to it. In any case data is not yet ready to read - so no
|
||||
* data can be read.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
priv = &g_ipccpriv[chan];
|
||||
rxmem = (struct stm32wl5_ipcc_chan_mem_s *)priv->rxmem;
|
||||
|
||||
/* If buffer is full, it's possible we did not copy everything from
|
||||
* IPCC memory to buffer in previous interrupt. Then when another
|
||||
* channel triggers interrupt we may only need to copy what is left
|
||||
* in IPCC memory to buffer.
|
||||
*/
|
||||
|
||||
to_copy = rxmem->len - priv->rxcopied;
|
||||
rxbuf_space = circbuf_space(rxbuf);
|
||||
|
||||
if (to_copy > rxbuf_space)
|
||||
{
|
||||
/* we can't fit all data into buffer, copy as much as
|
||||
* possible and set overflow flag to 1, to tell upper
|
||||
* half that there is still data in IPCC memory.
|
||||
*/
|
||||
|
||||
to_copy = rxbuf_space;
|
||||
priv->ipcc->overflow = 1;
|
||||
|
||||
/* Also disable RX interrupt. If data is still in the ipcc
|
||||
* memory and we don't set rxbuffer as free, we will
|
||||
* immediately get another RX interrupt once we leave
|
||||
* this one.
|
||||
*/
|
||||
|
||||
modifyreg32(STM32WL5_IPCC_C1MR, 0, STM32WL5_IPCC_MR_CHNOM(chan));
|
||||
}
|
||||
|
||||
/* Buffer data. This function cannot really fail us if we
|
||||
* pass valid input parameters.
|
||||
*/
|
||||
|
||||
circbuf_write(&priv->ipcc->rxbuf, rxmem->data + priv->rxcopied, to_copy);
|
||||
|
||||
/* Increment number of bytes that has been buffered */
|
||||
|
||||
if ((priv->rxcopied += to_copy) == rxmem->len)
|
||||
{
|
||||
/* We have buffered all data from IPCC memory */
|
||||
|
||||
priv->rxcopied = 0;
|
||||
priv->ipcc->overflow = 0;
|
||||
|
||||
/* Tell another CPU that IPCC rx buffer is free to be populated */
|
||||
|
||||
modifyreg32(STM32WL5_IPCC_C1SCR, 0, STM32WL5_IPCC_SCR_CHNC(chan));
|
||||
|
||||
/* Unmask RX interrupt to know when second CPU sends us a message */
|
||||
|
||||
modifyreg32(STM32WL5_IPCC_C1MR, STM32WL5_IPCC_MR_CHNOM(chan), 0);
|
||||
}
|
||||
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32wl5_ipcc_buffer_data
|
||||
*
|
||||
* Description:
|
||||
* Copies as many bytes as possible from ipcc channel to rxbuf.
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipcc - ipcc channel to copy data from
|
||||
* rxbuf - circural buffer to copy data to
|
||||
*
|
||||
* Returned Value:
|
||||
* Number of successfully buffered bytes.
|
||||
*
|
||||
* Assumptions/Limitations:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t stm32wl5_ipcc_buffer_data(struct ipcc_lower_s *ipcc,
|
||||
struct circbuf_s *rxbuf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Disable RX interrupt since we will modify shared data */
|
||||
|
||||
up_disable_irq(STM32WL5_IRQ_IPCC_C1_RX_IT);
|
||||
|
||||
/* Copy data to buffer */
|
||||
|
||||
ret = stm32wl5_ipcc_copy_to_buffer(ipcc->chan, rxbuf);
|
||||
|
||||
/* Reenable interrupt */
|
||||
|
||||
up_enable_irq(STM32WL5_IRQ_IPCC_C1_RX_IT);
|
||||
|
||||
/* Return number of bytes that were successfully buffered */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32wl5_ipcc_write_notify
|
||||
*
|
||||
* Description:
|
||||
* This function is called when there is new data on circ buffer.
|
||||
* All copy operations from buffer to ipcc memory is done in interrupt,
|
||||
* so we simply unmask the interrupt. Interrupt will arrive once ipcc
|
||||
* TX memory is free to be written.
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipcc - ipcc channel
|
||||
*
|
||||
* Returned Value:
|
||||
* Always OK
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static ssize_t stm32wl5_ipcc_write_notify(struct ipcc_lower_s *ipcc)
|
||||
{
|
||||
modifyreg32(STM32WL5_IPCC_C1MR, STM32WL5_IPCC_MR_CHNFM(ipcc->chan), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32wl5_ipcc_cleanup
|
||||
*
|
||||
* Description:
|
||||
* Cleans up resources initialized by stm32wl5_ipcc_init(). This will
|
||||
* free() ipcc pointer!
|
||||
*
|
||||
* Input Parameters:
|
||||
* ipcc - ipcc channel to cleanup
|
||||
*
|
||||
* Returned Value:
|
||||
* Always OK
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int stm32wl5_ipcc_cleanup(FAR struct ipcc_lower_s *ipcc)
|
||||
{
|
||||
DEBUGASSERT(ipcc);
|
||||
DEBUGASSERT(ipcc->chan <= IPCC_NCHAN);
|
||||
|
||||
/* Mask interrupts for given channel */
|
||||
|
||||
modifyreg32(STM32WL5_IPCC_C1MR, 1, STM32WL5_IPCC_MR_CHNFM(ipcc->chan));
|
||||
modifyreg32(STM32WL5_IPCC_C1MR, 1, STM32WL5_IPCC_MR_CHNOM(ipcc->chan));
|
||||
|
||||
/* Free allocated ipcc memory */
|
||||
|
||||
kmm_free(ipcc);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stm32wl5_ipcc_init
|
||||
*
|
||||
* Description:
|
||||
* Function initializes runtime options for IPCC. This function is called
|
||||
* by upper half of the IPCC driver from ipcc_register(). This function
|
||||
* is called once for every registered channel - so it can be called
|
||||
* multiple times with different input parameters during system bring up.
|
||||
*
|
||||
* Input Parameters:
|
||||
* chan - channel to initialize
|
||||
*
|
||||
* Returned Value:
|
||||
* Structure to link lower and upper halfs of the driver, or NULL on
|
||||
* initialization failure.
|
||||
*
|
||||
* Assumptions/Limitations:
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
struct ipcc_lower_s *stm32wl5_ipcc_init(int chan)
|
||||
{
|
||||
int ret;
|
||||
static int ipcc_fti;
|
||||
struct ipcc_lower_s *ipcc;
|
||||
|
||||
DEBUGASSERT(ipcc);
|
||||
DEBUGASSERT(chan <= IPCC_NCHAN);
|
||||
|
||||
if ((ipcc = kmm_zalloc(sizeof(*ipcc))) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Link internal stm32wl5 ipcc struct with character device driver
|
||||
* via ipcc_lower struct.
|
||||
*/
|
||||
|
||||
g_ipccpriv[chan].ipcc = ipcc;
|
||||
|
||||
/* Give upper half driver pointers to mcu specific functions that
|
||||
* upper half needs to call to work properly.
|
||||
*/
|
||||
|
||||
ipcc->ops.read = stm32wl5_ipcc_read;
|
||||
ipcc->ops.write = stm32wl5_ipcc_write;
|
||||
ipcc->ops.buffer_data = stm32wl5_ipcc_buffer_data;
|
||||
ipcc->ops.write_notify = stm32wl5_ipcc_write_notify;
|
||||
ipcc->ops.cleanup = stm32wl5_ipcc_cleanup;
|
||||
|
||||
ipcc->chan = chan;
|
||||
|
||||
/* Unmask channel interrupt */
|
||||
|
||||
modifyreg32(STM32WL5_IPCC_C1MR, STM32WL5_IPCC_MR_CHNFM(chan), 0);
|
||||
modifyreg32(STM32WL5_IPCC_C1MR, STM32WL5_IPCC_MR_CHNOM(chan), 0);
|
||||
|
||||
if (ipcc_fti)
|
||||
{
|
||||
return ipcc;
|
||||
}
|
||||
|
||||
/* For the first time initialization we also need to attach rx/tx
|
||||
* interrupt functions
|
||||
*/
|
||||
|
||||
ret = irq_attach(STM32WL5_IRQ_IPCC_C1_RX_IT, stm32wl5_ipcc_rx_isr, NULL);
|
||||
if (ret)
|
||||
{
|
||||
kmm_free(ipcc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = irq_attach(STM32WL5_IRQ_IPCC_C1_TX_IT, stm32wl5_ipcc_tx_isr, NULL);
|
||||
if (ret)
|
||||
{
|
||||
kmm_free(ipcc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Enable interrupts when:
|
||||
* - we receive data from CPU2
|
||||
* - CPU2 has read message from us and TX memory is free to be used again
|
||||
*/
|
||||
|
||||
putreg32(STM32WL5_IPCC_CR_RXOIE | STM32WL5_IPCC_CR_TXFIE,
|
||||
STM32WL5_IPCC_C1CR);
|
||||
|
||||
up_enable_irq(STM32WL5_IRQ_IPCC_C1_RX_IT);
|
||||
up_enable_irq(STM32WL5_IRQ_IPCC_C1_TX_IT);
|
||||
|
||||
ipcc_fti = 1;
|
||||
|
||||
return ipcc;
|
||||
}
|
145
arch/arm/src/stm32wl5/stm32wl5_ipcc.h
Normal file
145
arch/arm/src/stm32wl5/stm32wl5_ipcc.h
Normal file
@ -0,0 +1,145 @@
|
||||
/****************************************************************************
|
||||
* arch/arm/src/stm32wl5/stm32wl5_ipcc.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ARCH_ARM_SRC_STM32WL5_IPCC_H
|
||||
#define __ARCH_ARM_SRC_STM32WL5_IPCC_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/ipcc.h>
|
||||
#include "hardware/stm32wl5_memorymap.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Channels are sequential, that is, if channel 3 is enabled that means
|
||||
* channel 2 and 1 are also enabled. Kconfig makes sure there is no
|
||||
* situation where channel 3 is enabled while channel 2 is not.
|
||||
*/
|
||||
|
||||
/* channel 1 configuration **************************************************/
|
||||
|
||||
#define IPCC_CHAN1_RX_SIZE (CONFIG_STM32WL5_IPCC_CHAN1_RX_SIZE)
|
||||
#define IPCC_CHAN1_TX_SIZE (CONFIG_STM32WL5_IPCC_CHAN1_TX_SIZE)
|
||||
#define IPCC_CHAN1_START (IPCC_START)
|
||||
#define IPCC_CHAN1_SIZE (IPCC_CHAN1_RX_SIZE + IPCC_CHAN1_TX_SIZE)
|
||||
#define IPCC_CHAN1 (1)
|
||||
|
||||
/* channel 2 configuration **************************************************/
|
||||
|
||||
#if defined(CONFIG_STM32WL5_IPCC_CHAN2)
|
||||
# define IPCC_CHAN2_RX_SIZE (CONFIG_STM32WL5_IPCC_CHAN2_RX_SIZE)
|
||||
# define IPCC_CHAN2_TX_SIZE (CONFIG_STM32WL5_IPCC_CHAN2_TX_SIZE)
|
||||
# define IPCC_CHAN2_START (IPCC_CHAN1_START + IPCC_CHAN1_SIZE)
|
||||
# define IPCC_CHAN2_SIZE (IPCC_CHAN2_RX_SIZE + IPCC_CHAN2_TX_SIZE)
|
||||
# define IPCC_CHAN2 (1)
|
||||
#else
|
||||
# define IPCC_CHAN2_SIZE (0)
|
||||
# define IPCC_CHAN2 (0)
|
||||
#endif
|
||||
|
||||
/* channel 3 configuration **************************************************/
|
||||
|
||||
#if defined(CONFIG_STM32WL5_IPCC_CHAN3)
|
||||
# define IPCC_CHAN3_RX_SIZE (CONFIG_STM32WL5_IPCC_CHAN3_RX_SIZE)
|
||||
# define IPCC_CHAN3_TX_SIZE (CONFIG_STM32WL5_IPCC_CHAN3_TX_SIZE)
|
||||
# define IPCC_CHAN3_START (IPCC_CHAN2_START + IPCC_CHAN2_SIZE)
|
||||
# define IPCC_CHAN3_SIZE (IPCC_CHAN3_RX_SIZE + IPCC_CHAN3_TX_SIZE)
|
||||
# define IPCC_CHAN3 (1)
|
||||
#else
|
||||
# define IPCC_CHAN3_SIZE (0)
|
||||
# define IPCC_CHAN3 (0)
|
||||
#endif
|
||||
|
||||
/* channel 4 configuration **************************************************/
|
||||
|
||||
#if defined(CONFIG_STM32WL5_IPCC_CHAN4)
|
||||
# define IPCC_CHAN4_RX_SIZE (CONFIG_STM32WL5_IPCC_CHAN4_RX_SIZE)
|
||||
# define IPCC_CHAN4_TX_SIZE (CONFIG_STM32WL5_IPCC_CHAN4_TX_SIZE)
|
||||
# define IPCC_CHAN4_START (IPCC_CHAN3_START + IPCC_CHAN3_SIZE)
|
||||
# define IPCC_CHAN4_SIZE (IPCC_CHAN4_RX_SIZE + IPCC_CHAN4_TX_SIZE)
|
||||
# define IPCC_CHAN4 (1)
|
||||
#else
|
||||
# define IPCC_CHAN4_SIZE (0)
|
||||
# define IPCC_CHAN4 (0)
|
||||
#endif
|
||||
|
||||
/* channel 5 configuration **************************************************/
|
||||
|
||||
#if defined(CONFIG_STM32WL5_IPCC_CHAN5)
|
||||
# define IPCC_CHAN5_RX_SIZE (CONFIG_STM32WL5_IPCC_CHAN5_RX_SIZE)
|
||||
# define IPCC_CHAN5_TX_SIZE (CONFIG_STM32WL5_IPCC_CHAN5_TX_SIZE)
|
||||
# define IPCC_CHAN5_START (IPCC_CHAN4_START + IPCC_CHAN4_SIZE)
|
||||
# define IPCC_CHAN5_SIZE (IPCC_CHAN5_RX_SIZE + IPCC_CHAN5_TX_SIZE)
|
||||
# define IPCC_CHAN5 (1)
|
||||
#else
|
||||
# define IPCC_CHAN5_SIZE (0)
|
||||
# define IPCC_CHAN5 (0)
|
||||
#endif
|
||||
|
||||
/* channel 6 configuration **************************************************/
|
||||
|
||||
#if defined(CONFIG_STM32WL5_IPCC_CHAN6)
|
||||
# define IPCC_CHAN6_RX_SIZE (CONFIG_STM32WL5_IPCC_CHAN6_RX_SIZE)
|
||||
# define IPCC_CHAN6_TX_SIZE (CONFIG_STM32WL5_IPCC_CHAN6_TX_SIZE)
|
||||
# define IPCC_CHAN6_START (IPCC_CHAN5_START + IPCC_CHAN5_SIZE)
|
||||
# define IPCC_CHAN6_SIZE (IPCC_CHAN6_RX_SIZE + IPCC_CHAN6_TX_SIZE)
|
||||
# define IPCC_CHAN6 (1)
|
||||
#else
|
||||
# define IPCC_CHAN6_SIZE (0)
|
||||
# define IPCC_CHAN6 (0)
|
||||
#endif
|
||||
|
||||
/* ipcc general configuration ***********************************************/
|
||||
|
||||
/* Memory layout is:
|
||||
*
|
||||
* +----------+
|
||||
* | CHAN1_RX | CHAN1_START (IPCC_START)
|
||||
* | CHAN1_TX | CHAN1_START + IPCC_CHAN1_RX_SIZE
|
||||
* +----------+
|
||||
* | CHAN2_RX | CHAN2_START
|
||||
* | CHAN2_TX | CHAN2_START + IPCC_CHAN2_RX_SIZE
|
||||
* | . |
|
||||
* | . |
|
||||
* | . |
|
||||
* | CHAN6_RX | CHAN6_START
|
||||
* | CHAN6_TX | CHAN6_START + IPCC_CHAN6_RX_SIZE
|
||||
* +----------+
|
||||
*/
|
||||
|
||||
/* IPCC needs continous memory of known address that is shared
|
||||
* between CPUs. Because of that we reserve memory at beginning
|
||||
* of SRAM2. SRAM2 region will be right after IPCC reserved memory
|
||||
*/
|
||||
|
||||
#define IPCC_START STM32WL5_SRAM2_BASE
|
||||
#define IPCC_NCHAN (IPCC_CHAN1 + IPCC_CHAN2 + IPCC_CHAN3 + \
|
||||
IPCC_CHAN4 + IPCC_CHAN5 + IPCC_CHAN6)
|
||||
#define IPCC_END (IPCC_START + IPCC_CHAN1_SIZE + IPCC_CHAN2_SIZE + \
|
||||
IPCC_CHAN3_SIZE + IPCC_CHAN4_SIZE + \
|
||||
IPCC_CHAN5_SIZE + IPCC_CHAN6_SIZE)
|
||||
|
||||
struct ipcc_lower_s *stm32wl5_ipcc_init(int chan);
|
||||
|
||||
#endif /* __ARCH_ARM_SRC_STM32WL5_IPCC_H */
|
@ -294,6 +294,12 @@ static inline void stm32wl5_rcc_enableahb3(void)
|
||||
regval |= RCC_AHB3ENR_FLASHEN;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STM32WL5_IPCC
|
||||
/* IPCC interface clock enable */
|
||||
|
||||
regval |= RCC_AHB3ENR_IPCCEN;
|
||||
#endif
|
||||
|
||||
putreg32(regval, STM32WL5_RCC_AHB3ENR); /* Enable peripherals */
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user