blob: f99a175594265172682a344818a6e25d416a0e28 [file] [log] [blame]
/****************************************************************************
* arch/arm/src/stm32wb/stm32wb_mbox.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 <assert.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/wqueue.h>
#include "arm_internal.h"
#include "stm32wb_ipcc.h"
#include "stm32wb_mbox.h"
#include "hardware/stm32wb_memorymap.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Mailbox shared buffer base address. Normally it is located at
* the beginning of SRAM2a.
*/
#define STM32WB_MBOX_SHARED_BASE STM32WB_SRAM2A_BASE
/* Mailbox shared buffer fields */
#define stm32wb_mbox_shared \
(*(struct stm32wb_mbox_shared_buffer_s *)STM32WB_MBOX_SHARED_BASE)
#define stm32wb_mbox_ref_table (stm32wb_mbox_shared.ref_table)
#define stm32wb_mbox_di_table (stm32wb_mbox_shared.dev_info_table)
#define stm32wb_mbox_sys_table (stm32wb_mbox_shared.sys_table)
#define stm32wb_mbox_mm_table (stm32wb_mbox_shared.mm_table)
#define stm32wb_mbox_ble_table (stm32wb_mbox_shared.ble_table)
/* Mailbox buffer sizes */
#define STM32WB_MBOX_CS_BUF_SIZE 16
#define STM32WB_MBOX_CMDPKT_BUF_SIZE 268
#define STM32WB_MBOX_ACLPKT_BUF_SIZE 264
#define STM32WB_MBOX_RX_BUF_SIZE \
(CONFIG_STM32WB_MBOX_RX_EVT_QUEUE_LEN * STM32WB_MBOX_CMDPKT_BUF_SIZE)
/****************************************************************************
* Private Types
****************************************************************************/
/* Mailbox shared buffer structures */
begin_packed_struct struct stm32wb_mbox_safe_boot_info_table_s
{
uint32_t version;
} end_packed_struct;
begin_packed_struct struct stm32wb_mbox_fus_info_table_s
{
uint32_t version;
uint32_t memory_size;
uint32_t fus_info;
} end_packed_struct;
begin_packed_struct struct stm32wb_mbox_wireless_fw_info_table_s
{
uint32_t version;
uint32_t memory_size;
uint32_t info_stack;
uint32_t reserved;
} end_packed_struct;
begin_packed_struct struct stm32wb_mbox_device_info_table_s
{
struct stm32wb_mbox_safe_boot_info_table_s safe_boot_info_table;
struct stm32wb_mbox_fus_info_table_s fus_info_table;
struct stm32wb_mbox_wireless_fw_info_table_s wireless_fw_info_table;
} end_packed_struct;
begin_packed_struct struct stm32wb_mbox_ble_table_s
{
void *cmd_buffer;
void *cs_buffer;
void *evt_queue;
void *acl_buffer;
} end_packed_struct;
begin_packed_struct struct stm32wb_mbox_sys_table_s
{
void *cmd_buffer;
void *evt_queue;
} end_packed_struct;
begin_packed_struct struct stm32wb_mbox_mem_manager_table_s
{
void *ble_spare_buffer;
void *sys_spare_buffer;
void *evtpool_buffer;
uint32_t evtpool_size;
void *evtfree_buffer;
void *traces_evtpool_buffer;
uint32_t traces_evtpool_size;
} end_packed_struct;
begin_packed_struct struct stm32wb_mbox_ref_table_s
{
struct stm32wb_mbox_device_info_table_s *dev_info_table;
struct stm32wb_mbox_ble_table_s *ble_table;
void *thread_table;
struct stm32wb_mbox_sys_table_s *sys_table;
struct stm32wb_mbox_mem_manager_table_s *mm_table;
void *traces_table;
void *mac_802_15_4_table;
void *zigbee_table;
void *ble_lld_test_table;
void *ble_lld_table;
} end_packed_struct;
/* Mailbox shared buffer memory layout structure */
struct stm32wb_mbox_shared_buffer_s
{
aligned_data(4) struct stm32wb_mbox_ref_table_s ref_table;
aligned_data(4) struct stm32wb_mbox_device_info_table_s dev_info_table;
aligned_data(4) struct stm32wb_mbox_ble_table_s ble_table;
aligned_data(4) struct stm32wb_mbox_sys_table_s sys_table;
aligned_data(4) struct stm32wb_mbox_mem_manager_table_s mm_table;
aligned_data(4) stm32wb_mbox_list_t evtfree_buffer;
#ifdef CONFIG_STM32WB_BLE
aligned_data(4) stm32wb_mbox_list_t ble_evt_queue;
#endif
aligned_data(4) stm32wb_mbox_list_t sys_evt_queue;
#ifdef CONFIG_STM32WB_BLE
aligned_data(4) uint8_t ble_cs_buffer[STM32WB_MBOX_CS_BUF_SIZE];
#endif
aligned_data(4) uint8_t evtpool_buffer[STM32WB_MBOX_RX_BUF_SIZE];
aligned_data(4) uint8_t sys_cmd_buffer[STM32WB_MBOX_CMDPKT_BUF_SIZE];
aligned_data(4) uint8_t sys_spare_buffer[STM32WB_MBOX_CMDPKT_BUF_SIZE];
#ifdef CONFIG_STM32WB_BLE
aligned_data(4) uint8_t ble_spare_buffer[STM32WB_MBOX_CMDPKT_BUF_SIZE];
aligned_data(4) uint8_t ble_cmd_buffer[STM32WB_MBOX_CMDPKT_BUF_SIZE];
aligned_data(4) uint8_t ble_acl_buffer[STM32WB_MBOX_ACLPKT_BUF_SIZE];
#endif
};
/* Mailbox channel data type */
struct stm32wb_mbox_channel_s
{
uint8_t ch_num;
stm32wb_mbox_list_t cmd_buf_queue;
struct stm32wb_mbox_cmd_s *cmd_buf;
bool ack_ready;
};
/****************************************************************************
* Private Function prototypes
****************************************************************************/
static void stm32wb_ipcc_rxoisr(int irq, uint32_t *regs, void *arg);
static void stm32wb_ipcc_txfisr(int irq, uint32_t *regs, void *arg);
static void stm32wb_mbox_rxworker(void *arg);
static void stm32wb_mbox_txworker(void *arg);
static void stm32wb_mbox_eventfree(stm32wb_mbox_list_t *evt);
static void stm32wb_mbox_acksyscmd(void);
static int stm32wb_mbox_txdata(struct stm32wb_mbox_channel_s *chan,
uint8_t type, void *data, size_t len);
static bool stm32wb_mbox_txnext(struct stm32wb_mbox_channel_s *chan);
/****************************************************************************
* Private Data
****************************************************************************/
static struct work_s g_rx_evt_work;
static struct work_s g_tx_cmd_work;
static stm32wb_mbox_list_t g_rx_evt_queue;
static stm32wb_mbox_list_t g_tx_evtfree_queue;
static uint8_t g_free_buffers[CONFIG_STM32WB_MBOX_TX_CMD_QUEUE_LEN]
[STM32WB_MBOX_CMDPKT_BUF_SIZE];
static stm32wb_mbox_list_t g_free_buffers_pool;
static struct stm32wb_mbox_channel_s g_syscmd_channel;
#ifdef CONFIG_STM32WB_BLE
static struct stm32wb_mbox_channel_s g_blecmd_channel;
static struct stm32wb_mbox_channel_s g_bleacl_channel;
#endif
static stm32wb_mbox_evt_handler_t receive_evt_handler;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: stm32wb_ipcc_rxoisr
*
* Description:
* RX channel occupied interrupt handler (communication data posted
* by sending processor).
*
****************************************************************************/
static void stm32wb_ipcc_rxoisr(int irq, uint32_t *regs, void *arg)
{
uint32_t clrmask = 0;
/* Pull events from system channel into processing queue */
if (stm32wb_ipcc_rxactive(STM32WB_MBOX_SYSEVT_CHANNEL))
{
stm32wb_mbox_list_moveall(&stm32wb_mbox_shared.sys_evt_queue,
&g_rx_evt_queue);
clrmask |= IPCC_C1SCR_CLR_BIT(STM32WB_MBOX_SYSEVT_CHANNEL);
}
#ifdef CONFIG_STM32WB_BLE
/* Pull events from BLE channel into processing queue */
if (stm32wb_ipcc_rxactive(STM32WB_MBOX_BLEEVT_CHANNEL))
{
stm32wb_mbox_list_moveall(&stm32wb_mbox_shared.ble_evt_queue,
&g_rx_evt_queue);
clrmask |= IPCC_C1SCR_CLR_BIT(STM32WB_MBOX_BLEEVT_CHANNEL);
}
#endif
/* Process collected events in the work queue */
if (work_available(&g_rx_evt_work))
{
work_queue(HPWORK, &g_rx_evt_work, stm32wb_mbox_rxworker, NULL, 0);
}
/* Clear active statuses */
putreg32(clrmask, STM32WB_IPCC_C1SCR);
}
/****************************************************************************
* Name: stm32wb_ipcc_txfisr
*
* Description:
* TX channel free interrupt handler (communication data retrieved
* by receiving processor).
*
****************************************************************************/
static void stm32wb_ipcc_txfisr(int irq, uint32_t *regs, void *arg)
{
uint32_t c1mr = getreg32(STM32WB_IPCC_C1MR);
uint32_t txfsrc;
/* TXF interrupt can be triggered by not masked channels and active status
* of the source channel is cleared by CPU2. So we ignore masked and active
* channels and rise other C1MR bits to highlight needed channels.
*/
txfsrc = ~(c1mr | (getreg32(STM32WB_IPCC_C1TOC2SR) << IPCC_C1MR_FM_SHIFT))
& IPCC_C1MR_FM_MASK;
/* Check if the release channel triggered the interrupt */
if (txfsrc & IPCC_C1MR_FM_BIT(STM32WB_MBOX_EVT_RELEASE_CHANNEL))
{
/* Move all released events (if any) into transmission mailbox */
if (!stm32wb_mbox_list_is_empty(&g_tx_evtfree_queue))
{
stm32wb_mbox_list_moveall(&g_tx_evtfree_queue,
&stm32wb_mbox_shared.evtfree_buffer);
/* Start release channel transmission */
stm32wb_ipcc_settxactive(STM32WB_MBOX_EVT_RELEASE_CHANNEL);
}
}
/* Check other channels, except the release channel */
if (txfsrc & ~IPCC_C1MR_FM_BIT(STM32WB_MBOX_EVT_RELEASE_CHANNEL))
{
/* Check if the system channel triggered the interrupt */
if (txfsrc & IPCC_C1MR_FM_BIT(STM32WB_MBOX_SYSCMD_CHANNEL))
{
/* System channel works in 'half-duplex' mode and acks
* immediately on each command before TXF, so it needs
* to process ack response before sending next command.
*/
g_syscmd_channel.ack_ready = true;
}
/* Continue command processing in a work queue */
if (work_available(&g_tx_cmd_work))
{
work_queue(HPWORK, &g_tx_cmd_work, stm32wb_mbox_txworker, NULL, 0);
}
}
/* Mask triggered channels */
putreg32(c1mr | txfsrc, STM32WB_IPCC_C1MR);
}
/****************************************************************************
* Name: stm32wb_mbox_txworker
****************************************************************************/
static void stm32wb_mbox_txworker(void *arg)
{
bool handled;
/* Process all queued commands if a dedicated channel is free */
do
{
handled = false;
if (!stm32wb_ipcc_txactive(STM32WB_MBOX_SYSCMD_CHANNEL))
{
/* Process ack response before send new command */
if (g_syscmd_channel.ack_ready)
{
stm32wb_mbox_acksyscmd();
g_syscmd_channel.ack_ready = false;
}
handled = stm32wb_mbox_txnext(&g_syscmd_channel);
}
#ifdef CONFIG_STM32WB_BLE
if (!stm32wb_ipcc_txactive(STM32WB_MBOX_BLECMD_CHANNEL))
{
handled |= stm32wb_mbox_txnext(&g_blecmd_channel);
}
if (!stm32wb_ipcc_txactive(STM32WB_MBOX_BLEACL_CHANNEL))
{
handled |= stm32wb_mbox_txnext(&g_bleacl_channel);
}
#endif
}
while (handled);
}
/****************************************************************************
* Name: stm32wb_mbox_rxworker
****************************************************************************/
static void stm32wb_mbox_rxworker(void *arg)
{
stm32wb_mbox_list_t *evt;
irqstate_t flags;
while (1)
{
flags = enter_critical_section();
/* Pull an event from the queue */
evt = stm32wb_mbox_list_remove_head(&g_rx_evt_queue);
leave_critical_section(flags);
if (evt == NULL)
{
break;
}
/* Pass event to a callback function without a list header */
receive_evt_handler((struct stm32wb_mbox_evt_s *)(evt + 1));
/* Free completed event. Released event needs to return to CPU2
* via release channel.
*/
stm32wb_mbox_eventfree((stm32wb_mbox_list_t *)evt);
}
}
/****************************************************************************
* Name: stm32wb_mbox_txdata
*
* Description:
* Send data over specified mailbox channel if possible. If the
* channel is busy then add a prepared packet into awaiting queue.
*
****************************************************************************/
static int stm32wb_mbox_txdata(struct stm32wb_mbox_channel_s *chan,
uint8_t type, void *data, size_t len)
{
irqstate_t flags;
struct stm32wb_mbox_cmd_s *pkt_buf;
flags = enter_critical_section();
/* To start transmission the channel needs to be free, there should be
* none of other waiting commands and none of unprocessed ack responses.
*/
if (stm32wb_mbox_list_is_empty(&chan->cmd_buf_queue) &&
!stm32wb_ipcc_txactive(chan->ch_num) && !chan->ack_ready)
{
/* Channel is ready, copy command into transmission buffer */
pkt_buf = chan->cmd_buf;
}
else
{
/* Otherwise get temp buffer for command */
pkt_buf = (struct stm32wb_mbox_cmd_s *)
stm32wb_mbox_list_remove_head(&g_free_buffers_pool);
}
leave_critical_section(flags);
if (pkt_buf == NULL)
{
return -ENOBUFS;
}
pkt_buf->type = type;
memcpy(&pkt_buf->cmd_hdr, data, len);
if (pkt_buf == chan->cmd_buf)
{
/* Command is ready in mailbox buffer, start transmission now */
stm32wb_ipcc_settxactive(chan->ch_num);
if (!stm32wb_mbox_list_is_empty(&chan->cmd_buf_queue) ||
chan->ch_num == STM32WB_MBOX_SYSCMD_CHANNEL)
{
/* There are more commands awaiting, so unmask interrupt to get
* notified when channel gets ready to process a next one.
* And the system channel needs to check ack on completion.
*/
stm32wb_ipcc_unmasktxf(chan->ch_num);
}
}
else
{
/* Command is in temp buffer, push it into queue */
flags = enter_critical_section();
stm32wb_mbox_list_add_tail(&chan->cmd_buf_queue, &pkt_buf->list_hdr);
leave_critical_section(flags);
/* Unmask interrupt to get notified when channel gets free */
stm32wb_ipcc_unmasktxf(chan->ch_num);
}
return OK;
}
/****************************************************************************
* Name: stm32wb_mbox_txnext
*
* Description:
* Send next command from the queue.
*
****************************************************************************/
static bool stm32wb_mbox_txnext(struct stm32wb_mbox_channel_s *chan)
{
struct stm32wb_mbox_cmd_s *pkt_buf;
pkt_buf = (struct stm32wb_mbox_cmd_s *)
stm32wb_mbox_list_remove_head(&chan->cmd_buf_queue);
if (pkt_buf != NULL)
{
chan->cmd_buf->type = pkt_buf->type;
if (chan->ch_num == STM32WB_MBOX_BLEACL_CHANNEL)
{
memcpy(&chan->cmd_buf->acl_hdr, &pkt_buf->acl_hdr,
sizeof(pkt_buf->acl_hdr) + pkt_buf->acl_hdr.len);
}
else
{
memcpy(&chan->cmd_buf->cmd_hdr, &pkt_buf->cmd_hdr,
sizeof(pkt_buf->cmd_hdr) + pkt_buf->cmd_hdr.param_len);
}
/* Start transmission */
stm32wb_ipcc_settxactive(chan->ch_num);
if (!stm32wb_mbox_list_is_empty(&chan->cmd_buf_queue))
{
/* Unmask TXF interrupt to get notified when completed */
stm32wb_ipcc_unmasktxf(chan->ch_num);
}
/* Put back to pool the freed command buffer */
stm32wb_mbox_list_add_tail(&g_free_buffers_pool, &pkt_buf->list_hdr);
}
return pkt_buf != NULL;
}
/****************************************************************************
* Name: stm32wb_mbox_eventfree
*
* Description:
* Free handled mailbox event.
*
****************************************************************************/
static void stm32wb_mbox_eventfree(stm32wb_mbox_list_t *evt)
{
irqstate_t flags;
flags = enter_critical_section();
/* Collect releasing events in the global list */
stm32wb_mbox_list_add_tail(&g_tx_evtfree_queue, evt);
/* Check if release channel is ready to process now */
if (!stm32wb_ipcc_txactive(STM32WB_MBOX_EVT_RELEASE_CHANNEL))
{
/* Move all collected events into transmission queue */
stm32wb_mbox_list_moveall(&g_tx_evtfree_queue,
&stm32wb_mbox_shared.evtfree_buffer);
/* Start transmission */
stm32wb_ipcc_settxactive(STM32WB_MBOX_EVT_RELEASE_CHANNEL);
}
else
{
/* Unmask interrupt to get notified when channel gets free */
stm32wb_ipcc_unmasktxf(STM32WB_MBOX_EVT_RELEASE_CHANNEL);
}
leave_critical_section(flags);
}
/****************************************************************************
* Name: stm32wb_mbox_acksyscmd
*
* Description:
* Send ACK response event for completed system command.
*
****************************************************************************/
static void stm32wb_mbox_acksyscmd(void)
{
struct stm32wb_mbox_evt_s *evt;
/* System command ACK response is placed at the same address as the
* processed command but without a list header.
*/
evt = (struct stm32wb_mbox_evt_s *)(&g_syscmd_channel.cmd_buf);
evt->type = STM32WB_MBOX_SYSACK;
receive_evt_handler(evt);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: stm32wb_mboxinitialize
*
* Description:
* Initialize mailbox driver memory.
*
* Input Parameters:
* evt_handler - the function to call on event receive
*
****************************************************************************/
void stm32wb_mboxinitialize(stm32wb_mbox_evt_handler_t evt_handler)
{
int i;
/* Init mailbox shared data */
stm32wb_mbox_list_initialize(&stm32wb_mbox_shared.sys_evt_queue);
stm32wb_mbox_list_initialize(&stm32wb_mbox_shared.evtfree_buffer);
#ifdef CONFIG_STM32WB_BLE
stm32wb_mbox_list_initialize(&stm32wb_mbox_shared.ble_evt_queue);
#endif
stm32wb_mbox_ref_table.dev_info_table = &stm32wb_mbox_di_table;
stm32wb_mbox_ref_table.ble_table = &stm32wb_mbox_ble_table;
stm32wb_mbox_ref_table.sys_table = &stm32wb_mbox_sys_table;
stm32wb_mbox_ref_table.mm_table = &stm32wb_mbox_mm_table;
stm32wb_mbox_sys_table.cmd_buffer = &stm32wb_mbox_shared.sys_cmd_buffer;
stm32wb_mbox_sys_table.evt_queue = &stm32wb_mbox_shared.sys_evt_queue;
stm32wb_mbox_mm_table.evtpool_buffer = &stm32wb_mbox_shared
.evtpool_buffer;
stm32wb_mbox_mm_table.evtpool_size = sizeof(stm32wb_mbox_shared
.evtpool_buffer);
stm32wb_mbox_mm_table.evtfree_buffer = &stm32wb_mbox_shared
.evtfree_buffer;
stm32wb_mbox_mm_table.sys_spare_buffer = &stm32wb_mbox_shared
.sys_spare_buffer;
#ifdef CONFIG_STM32WB_BLE
stm32wb_mbox_mm_table.ble_spare_buffer = &stm32wb_mbox_shared
.ble_spare_buffer;
#endif
#ifdef CONFIG_STM32WB_BLE
stm32wb_mbox_ble_table.cmd_buffer = &stm32wb_mbox_shared.ble_cmd_buffer;
stm32wb_mbox_ble_table.acl_buffer = &stm32wb_mbox_shared.ble_acl_buffer;
stm32wb_mbox_ble_table.cs_buffer = &stm32wb_mbox_shared.ble_cs_buffer;
stm32wb_mbox_ble_table.evt_queue = &stm32wb_mbox_shared.ble_evt_queue;
#endif
/* Init system channel data */
g_syscmd_channel.ch_num = STM32WB_MBOX_SYSCMD_CHANNEL;
g_syscmd_channel.cmd_buf = (struct stm32wb_mbox_cmd_s *)
stm32wb_mbox_shared.sys_cmd_buffer;
stm32wb_mbox_list_initialize(&g_syscmd_channel.cmd_buf_queue);
#ifdef CONFIG_STM32WB_BLE
/* Init BLE command channel data */
g_blecmd_channel.ch_num = STM32WB_MBOX_BLECMD_CHANNEL;
g_blecmd_channel.cmd_buf = (struct stm32wb_mbox_cmd_s *)
stm32wb_mbox_shared.ble_cmd_buffer;
stm32wb_mbox_list_initialize(&g_blecmd_channel.cmd_buf_queue);
/* Init BLE ACL channel data */
g_bleacl_channel.ch_num = STM32WB_MBOX_BLEACL_CHANNEL;
g_bleacl_channel.cmd_buf = (struct stm32wb_mbox_cmd_s *)
stm32wb_mbox_shared.ble_acl_buffer;
stm32wb_mbox_list_initialize(&g_bleacl_channel.cmd_buf_queue);
#endif
/* Init local (not shared) queues */
stm32wb_mbox_list_initialize(&g_rx_evt_queue);
stm32wb_mbox_list_initialize(&g_tx_evtfree_queue);
stm32wb_mbox_list_initialize(&g_free_buffers_pool);
for (i = 0; i < CONFIG_STM32WB_MBOX_TX_CMD_QUEUE_LEN; i++)
{
stm32wb_mbox_list_add_tail(&g_free_buffers_pool,
(stm32wb_mbox_list_t *)g_free_buffers[i]);
}
/* Set event receive function */
receive_evt_handler = evt_handler;
}
/****************************************************************************
* Name: stm32wb_mboxenable
*
* Description:
* Enable mailbox hardware and start communication. The CPU2 responses
* with C2Ready event on success.
*
****************************************************************************/
void stm32wb_mboxenable(void)
{
uint32_t regval;
/* Setup RXO and TXF interrupts */
irq_attach(STM32WB_IRQ_IPCCRX, (xcpt_t)stm32wb_ipcc_rxoisr, NULL);
up_enable_irq(STM32WB_IRQ_IPCCRX);
irq_attach(STM32WB_IRQ_IPCCTX, (xcpt_t)stm32wb_ipcc_txfisr, NULL);
up_enable_irq(STM32WB_IRQ_IPCCTX);
regval = getreg32(STM32WB_IPCC_C1CR);
regval |= IPCC_C1CR_RXOIE | IPCC_C1CR_TXFIE;
putreg32(regval, STM32WB_IPCC_C1CR);
/* Unmask system channel RXO interrupt. Once CPU2 started we expect
* to receive C2READY event via system channel.
*/
stm32wb_ipcc_unmaskrxo(STM32WB_MBOX_SYSEVT_CHANNEL);
/* Enable IPCC hardware and bootup CPU2 */
stm32wb_ipccenable();
}
/****************************************************************************
* Name: stm32wb_mbox_syscmd
*
* Description:
* Send command over mailbox system channel. Command data must be
* prepended with HCI header.
*
****************************************************************************/
int stm32wb_mbox_syscmd(void *data, size_t len)
{
return stm32wb_mbox_txdata(&g_syscmd_channel, STM32WB_MBOX_SYSCMD,
data, len);
}
#ifdef CONFIG_STM32WB_BLE
/****************************************************************************
* Name: stm32wb_mbox_blecmd
*
* Description:
* Send command over mailbox BLE channel. Command data must be
* prepended with HCI header.
*
****************************************************************************/
int stm32wb_mbox_blecmd(void *data, size_t len)
{
return stm32wb_mbox_txdata(&g_blecmd_channel, STM32WB_MBOX_HCICMD,
data, len);
}
/****************************************************************************
* Name: stm32wb_mbox_bleacl
*
* Description:
* Send BLE ACL data over mailbox BLE ACL channel. Data must be
* prepended with HCI ACL header.
*
****************************************************************************/
int stm32wb_mbox_bleacl(void *data, size_t len)
{
return stm32wb_mbox_txdata(&g_bleacl_channel, STM32WB_MBOX_HCIACL,
data, len);
}
/****************************************************************************
* Name: stm32wb_mbox_bleinit
*
* Description:
* Initialize and start BLE subsystem with provided configuration params.
*
****************************************************************************/
void stm32wb_mbox_bleinit(struct stm32wb_shci_ble_init_cfg_s *params)
{
struct bt_hci_cmd_hdr_s *cmd;
/* Just borrow a temporary free buffer for command data */
cmd = (struct bt_hci_cmd_hdr_s *)stm32wb_mbox_shared.sys_spare_buffer;
/* Prepare command data */
cmd->opcode = STM32WB_SHCI_BLE_INIT;
cmd->param_len = sizeof(*cmd);
memcpy(cmd + 1, params, sizeof(*params));
/* Send BLE init command to CPU2 */
stm32wb_mbox_syscmd(cmd, sizeof(*cmd) + sizeof(*params));
/* Unmask BLE event channel RXO interrupt */
stm32wb_ipcc_unmaskrxo(STM32WB_MBOX_BLEEVT_CHANNEL);
}
#endif /* CONFIG_STM32WB_BLE */