BL808学习日志-1-三核通讯

接上个博客,今天实验了一下BL808的IPC通讯,使用的是博流自己的SDK;参考手册上并没有说明各个寄存器,是通过网友的结论和自己的部分修改达成的。

一、实验代码

1.目前仅测试了LP内核和M0内核之间的通讯,使用SIPEED的M1S_Dock开发板,修改了\bouffalo_sdk\bsp\board\bl808dk\board.c文件,先将debug的管脚14 15分配给M0内核使用,方便打印M0内核的日志;

static void console_init()
{
    struct bflb_device_s *gpio;

    gpio = bflb_device_get_by_name("gpio");
#if defined(CPU_M0)
    bflb_gpio_uart_init(gpio, GPIO_PIN_14, GPIO_UART_FUNC_UART0_TX);
    bflb_gpio_uart_init(gpio, GPIO_PIN_15, GPIO_UART_FUNC_UART0_RX);
#elif defined(CPU_D0)
    /* sipeed m1s dock */
    bflb_gpio_init(gpio, GPIO_PIN_16, 21 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
    bflb_gpio_init(gpio, GPIO_PIN_17, 21 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
#elif defined(CPU_LP)
    /* map GPIO_PIN_18 and GPIO_PIN_19 as UART for LP core */
    bflb_gpio_uart_init(gpio, GPIO_PIN_18, GPIO_UART_FUNC_UART1_TX);
    bflb_gpio_uart_init(gpio, GPIO_PIN_19, GPIO_UART_FUNC_UART1_RX);
#endif
    struct bflb_uart_config_s cfg;
    cfg.baudrate = 2000000;
    cfg.data_bits = UART_DATA_BITS_8;
    cfg.stop_bits = UART_STOP_BITS_1;
    cfg.parity = UART_PARITY_NONE;
    cfg.flow_ctrl = 0;
    cfg.tx_fifo_threshold = 7;
    cfg.rx_fifo_threshold = 7;
#if defined(CPU_M0)
    uart0 = bflb_device_get_by_name("uart0");
#elif defined(CPU_D0)
    uart0 = bflb_device_get_by_name("uart3");
#elif defined(CPU_LP)
    uart0 = bflb_device_get_by_name("uart1");
#endif
    bflb_uart_init(uart0, &cfg);
    bflb_uart_set_console(uart0);
}

2.在bouffalo_sdk\examples\bl808_triplecore\helloworld_m0例程上进行修改,M0主函数中对中断寄存器进行了初始化,定义了中断回调函数;并在中断函数中输出IPC中断号;其中对LED灯进行了一个0.5Hz的闪烁,来提示系统进行了正常的IPC通讯。

#include "bflb_mtimer.h"
#include "board.h"
#include "bflb_gpio.h"
#include "bl808.h"
#include "ipc_reg.h"
#include "bl808_ipc.h"
#include "bl808_common.h"

#define DBG_TAG "M0"
#include "log.h"

struct bflb_device_s *gpio;
uint32_t value = 0;
void IPC_M0_IRQHandler(void)
{
	gpio = bflb_device_get_by_name("gpio");
	// Read Interrupt Status
	uint32_t irqStatus = BL_RD_REG(IPC0_BASE, IPC_CPU0_IPC_IRSRR);

	//Interrupt handle
	bflb_gpio_set(gpio,GPIO_PIN_8);
	 LOG_F("the irqStatus value is %d\r\n",irqStatus);
	value = 1;
	//Clear Interrypt
	BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_ICR, irqStatus);
}

void m0_ipc_init(void)
{
	/* setup the IPC Interupt */
	bflb_irq_attach(IPC_M0_IRQn, IPC_M0_IRQHandler, NULL);
	BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_IUSR, 1 << 1);
	bflb_irq_enable(IPC_M0_IRQn);
}


int main(void)
{
    board_init();
    m0_ipc_init();
    while (1) {
        if(value == 1)
        {
        	bflb_gpio_set(gpio,GPIO_PIN_8);
        	bflb_mtimer_delay_ms(1000);
        	bflb_gpio_reset(gpio,GPIO_PIN_8);
            LOG_F("hello world m0\r\n");
            LOG_E("hello world m0\r\n");
            LOG_W("hello world m0\r\n");
            LOG_I("hello world m0\r\n");
            LOG_D("hello world m0\r\n");
            LOG_T("hello world m0\r\n");

        }
        bflb_mtimer_delay_ms(1000);

    }

}

将M0程序烧录到开发板中;

2.在bouffalo_sdk\examples\bl808_triplecore\helloworld_lp将LP板载外设初始化,然后打开开发板上的LED灯,使用IO8控制;默认上电拉低IO8,打开闪光灯;进入主循环之前,使能M0内核的IPC通道1;

#include "bflb_mtimer.h"
#include "board.h"
#include "bflb_gpio.h"
#include "bl808.h"
#include "ipc_reg.h"
#include "bl808_common.h"

#define DBG_TAG "MAIN"
#include "log.h"
struct bflb_device_s *gpio;



int main(void)
{

    board_init();
    gpio = bflb_device_get_by_name("gpio");
    bflb_gpio_init(gpio, GPIO_PIN_8, GPIO_OUTPUT | GPIO_FLOAT | GPIO_SMT_EN | GPIO_DRV_0);
    bflb_gpio_reset(gpio,GPIO_PIN_8);


    LOG_F("hello world lp\r\n");
    LOG_E("hello world lp\r\n");
    LOG_W("hello world lp\r\n");
    LOG_I("hello world lp\r\n");
    LOG_D("hello world lp\r\n");
    LOG_T("hello world lp\r\n");
    LOG_I("LPcore will comunity to M0 core");
    BL_WR_REG(IPC0_BASE, IPC_CPU1_IPC_ISWR, 1 << 1);

    while (1) {

        bflb_mtimer_delay_ms(1000);
    }
}

 将LP内核程序烧录到开发板中,会看到LED灯先是亮起,然后被M0主程序改为1秒闪烁1次;

3.若是想看debug日志,默认是查看M0内核的日志,可以把board.c文件中LP和M0的串口引脚对换。输出的LP内核的日志:

  ____               __  __      _       _       _
 |  _ \             / _|/ _|    | |     | |     | |
 | |_) | ___  _   _| |_| |_ __ _| | ___ | | __ _| |__
 |  _ < / _ \| | | |  _|  _/ _` | |/ _ \| |/ _` | '_ \
 | |_) | (_) | |_| | | | || (_| | | (_) | | (_| | |_) |
 |____/ \___/ \__,_|_| |_| \__,_|_|\___/|_|\__,_|_.__/

Build:18:11:43,Oct  1 2023
Copyright (c) 2022 Bouffalolab team
lp does not use memheap due to little ram
sig1:ffff76ff
sig2:0000ffff
cgen1:9f7ffffd
[F][LP] hello world lp
[E][LP] hello world lp
[W][LP] hello world lp
[I][LP] hello world lp
[I][LP] LPcore will comunity to M0 core

4.输出的M0内核日志:


  ____               __  __      _       _       _
 |  _ \             / _|/ _|    | |     | |     | |
 | |_) | ___  _   _| |_| |_ __ _| | ___ | | __ _| |__
 |  _ < / _ \| | | |  _|  _/ _` | |/ _ \| |/ _` | '_ \
 | |_) | (_) | |_| | | | || (_| | | (_) | | (_| | |_) |
 |____/ \___/ \__,_|_| |_| \__,_|_|\___/|_|\__,_|_.__/

Build:18:21:31,Oct  1 2023
Copyright (c) 2022 Bouffalolab team
======== flash cfg ========
flash size 0x01000000
jedec id     0xEF4018
mid              0xEF
iomode           0x04
clk delay        0x01
clk invert       0x01
read reg cmd0    0x05
read reg cmd1    0x35
write reg cmd0   0x01
write reg cmd1   0x31
qe write len     0x01
cread support    0x00
cread code       0xFF
burst wrap cmd   0x77
===========================
dynamic memory init success,heap size = 21 Kbyte
sig1:ffff32ff
sig2:0000ffff
[F][M0] the irqStatus value is 2
[F][M0] hello world m0
[E][M0] hello world m0

可以看到,M0日志显示"the irqSstatus value is 2",也就是通道1触发; 

4.随机试验了一下其他的通道,试验通道0能否正常触发,修改LP内核main.c文件的触发为

int main(void)
{

    board_init();
    gpio = bflb_device_get_by_name("gpio");
    bflb_gpio_init(gpio, GPIO_PIN_8, GPIO_OUTPUT | GPIO_FLOAT | GPIO_SMT_EN | GPIO_DRV_0);
    bflb_gpio_reset(gpio,GPIO_PIN_8);

    LOG_F("hello world lp\r\n");
    LOG_E("hello world lp\r\n");
    LOG_W("hello world lp\r\n");
    LOG_I("hello world lp\r\n");
    LOG_D("hello world lp\r\n");
    LOG_T("hello world lp\r\n");
    LOG_I("LPcore will comunity to M0 core");
    BL_WR_REG(IPC0_BASE, IPC_CPU1_IPC_ISWR, 1 << 0);

    while (1) {

        bflb_mtimer_delay_ms(1000);
    }
}

修改M0内核中main.c文件中的使能通道

void m0_ipc_init(void)
{
	/* setup the IPC Interupt */
	bflb_irq_attach(IPC_M0_IRQn, IPC_M0_IRQHandler, NULL);
	BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_IUSR, 1 << 0);
	bflb_irq_enable(IPC_M0_IRQn);
}

 编译烧录到开发板,发现M0内核的输出日志发生变化为"the irqSstatus value is 1",也就是通道0触发; 


  ____               __  __      _       _       _
 |  _ \             / _|/ _|    | |     | |     | |
 | |_) | ___  _   _| |_| |_ __ _| | ___ | | __ _| |__
 |  _ < / _ \| | | |  _|  _/ _` | |/ _ \| |/ _` | '_ \
 | |_) | (_) | |_| | | | || (_| | | (_) | | (_| | |_) |
 |____/ \___/ \__,_|_| |_| \__,_|_|\___/|_|\__,_|_.__/

Build:18:21:31,Oct  1 2023
Copyright (c) 2022 Bouffalolab team
======== flash cfg ========
flash size 0x01000000
jedec id     0xEF4018
mid              0xEF
iomode           0x04
clk delay        0x01
clk invert       0x01
read reg cmd0    0x05
read reg cmd1    0x35
write reg cmd0   0x01
write reg cmd1   0x31
qe write len     0x01
cread support    0x00
cread code       0xFF
burst wrap cmd   0x77
===========================
dynamic memory init success,heap size = 21 Kbyte
sig1:ffff32ff
sig2:0000ffff
[F][M0] the irqStatus value is 1
[F][M0] hello world m0
[E][M0] hello world m0

二、SIPEED默认库IPC描述

SIPEED的默认M1S_BL808_SDK中对IPC和XRAM进行了更深层次的封装,也实现了XRAM的数据交互,包括bl808_ipc.c文件,其中XRAM是作为一个组件使用,封装的相当好,这里也是很不明白为什么博流自己的SDK却删掉了这部分的内容。贴个代码,应该就知道怎么使用了。

/*
 * Copyright (c) 2020 Bouffalolab.
 *
 * This file is part of
 *     *** Bouffalolab Software Dev Kit ***
 *      (see www.bouffalolab.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 of Bouffalo Lab 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 HOLDER 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.
 */

#include "bl808_ipc.h"

/** @addtogroup  BL606P_Peripheral_Driver
 *  @{
 */

/** @addtogroup  IPC
 *  @{
 */

/** @defgroup  IPC_Private_Macros
 *  @{
 */
#define IPC_LP_OFFSET_IN_M0 0
#define IPC_D0_OFFSET_IN_M0 16

#define IPC_M0_OFFSET_IN_LP 0
#define IPC_D0_OFFSET_IN_LP 16

#define IPC_M0_OFFSET_IN_D0 0
#define IPC_LP_OFFSET_IN_D0 16

/*@} end of group IPC_Private_Macros */

/** @defgroup  IPC_Private_Types
 *  @{
 */

/*@} end of group IPC_Private_Types */

/** @defgroup  IPC_Private_Variables
 *  @{
 */

ipcIntCallback *m0IpcIntCbfArra[GLB_CORE_ID_MAX - 1] = { NULL };
ipcIntCallback *lpIpcIntCbfArra[GLB_CORE_ID_MAX - 1] = { NULL };
ipcIntCallback *d0IpcIntCbfArra[GLB_CORE_ID_MAX - 1] = { NULL };

/*@} end of group IPC_Private_Variables */

/** @defgroup  IPC_Global_Variables
 *  @{
 */

/*@} end of group IPC_Global_Variables */

/** @defgroup  IPC_Private_Fun_Declaration
 *  @{
 */

/*@} end of group IPC_Private_Fun_Declaration */

/** @defgroup  IPC_Private_Functions
 *  @{
 */

/*@} end of group IPC_Private_Functions */

/** @defgroup  IPC_Public_Functions
 *  @{
 */
#if defined(CPU_M0) || defined(CPU_LP)
/****************************************************************************/ /**
 * @brief  M0 IPC interrupt init
 *
 * @param  onLPTriggerCallBack: Callback when LP trigger
 *
 * @param  onD0TriggerCallBack: Callback when D0 trigger
 *
 * @return None
 *
*******************************************************************************/
void IPC_M0_Init(ipcIntCallback *onLPTriggerCallBack,
                 ipcIntCallback *onD0TriggerCallBack)
{
    m0IpcIntCbfArra[0] = onLPTriggerCallBack;
    m0IpcIntCbfArra[1] = onD0TriggerCallBack;

    IPC_M0_Int_Unmask_By_Word(0xffffffff);

#ifndef BFLB_USE_HAL_DRIVER
    Interrupt_Handler_Register(IPC_M0_IRQn, IPC_M0_IRQHandler);
#endif
    CPU_Interrupt_Enable(IPC_M0_IRQn);
}
#endif

/****************************************************************************/ /**
 * @brief  M0 unmask IPC interrupt
 *
 * @param  src: M0 IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_M0_Int_Unmask(IPC_Int_Src_Type src)
{
    uint32_t tmpVal = 0;

    /* Check the parameters */
    CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));

    tmpVal = (1 << src);

    BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_IUSR, tmpVal);
}

/****************************************************************************/ /**
 * @brief  M0 unmask IPC interrupt by word
 *
 * @param  src: IPC interrupt source in word,every bit is interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_M0_Int_Unmask_By_Word(uint32_t src)
{
    BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_IUSR, src);
}

/****************************************************************************/ /**
 * @brief  M0 get IPC interrupt raw status
 *
 * @param  None
 *
 * @return IPC interrupt raw status
 *
*******************************************************************************/
uint32_t IPC_M0_Get_Int_Raw_Status(void)
{
    return BL_RD_REG(IPC0_BASE, IPC_CPU0_IPC_IRSRR);
}

/****************************************************************************/ /**
 * @brief  M0 clear IPC interrupt
 *
 * @param  src: M0 IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_M0_Clear_Int(IPC_Int_Src_Type src)
{
    uint32_t tmpVal = 0;

    /* Check the parameters */
    CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));

    tmpVal = (1 << src);

    BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_ICR, tmpVal);
}

/****************************************************************************/ /**
 * @brief  M0 clear IPC interrupt by word
 *
 * @param  src: IPC interrupt source in word,every bit is interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_M0_Clear_Int_By_Word(uint32_t src)
{
    BL_WR_REG(IPC0_BASE, IPC_CPU0_IPC_ICR, src);
}

/****************************************************************************/ /**
 * @brief  CPUx trigger IPC interrupt to M0
 *
 * @param  src: IPC interrupt source
 * 
 * @param  cpuxOffset: CPU interrupt offset
 *
 * @return None
 *
*******************************************************************************/
void IPC_CPUx_Trigger_M0(IPC_Grp_Int_Src_Type src, uint8_t cpuxOffset)
{
    uint32_t tmpVal = 0;

    /* Check the parameters */
    //CHECK_PARAM(IS_IPC_Grp_Int_Src_Type(src));

    tmpVal = (1 << (src + cpuxOffset));

    BL_WR_REG(IPC0_BASE, IPC_CPU1_IPC_ISWR, tmpVal);
}

/****************************************************************************/ /**
 * @brief  LP trigger IPC interrupt to M0
 *
 * @param  src: LP IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_LP_Trigger_M0(IPC_Grp_Int_Src_Type src)
{
    IPC_CPUx_Trigger_M0(src, IPC_LP_OFFSET_IN_M0);
}

/****************************************************************************/ /**
 * @brief  D0 trigger IPC interrupt to M0
 *
 * @param  src: D0 IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_D0_Trigger_M0(IPC_Grp_Int_Src_Type src)
{
    IPC_CPUx_Trigger_M0(src, IPC_D0_OFFSET_IN_M0);
}

#if defined(CPU_M0) || defined(CPU_LP)
/****************************************************************************/ /**
 * @brief  LP IPC interrupt init
 *
 * @param  onM0TriggerCallBack: Callback when M0 trigger
 *
 * @param  onD0TriggerCallBack: Callback when D0 trigger
 *
 * @return None
 *
*******************************************************************************/
void IPC_LP_Init(ipcIntCallback *onM0TriggerCallBack,
                 ipcIntCallback *onD0TriggerCallBack)
{
    lpIpcIntCbfArra[0] = onM0TriggerCallBack;
    lpIpcIntCbfArra[1] = onD0TriggerCallBack;

    IPC_LP_Int_Unmask_By_Word(0xffffffff);

#ifndef BFLB_USE_HAL_DRIVER
    Interrupt_Handler_Register(IPC_LP_IRQn, IPC_LP_IRQHandler);
#endif
    CPU_Interrupt_Enable(IPC_LP_IRQn);
}
#endif

/****************************************************************************/ /**
 * @brief  LP unmask IPC interrupt
 *
 * @param  src: LP IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_LP_Int_Unmask(IPC_Int_Src_Type src)
{
    uint32_t tmpVal = 0;

    /* Check the parameters */
    CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));

    tmpVal = (1 << src);

    BL_WR_REG(IPC1_BASE, IPC_CPU0_IPC_IUSR, tmpVal);
}

/****************************************************************************/ /**
 * @brief  LP unmask IPC interrupt by word
 *
 * @param  src: IPC interrupt source in word,every bit is interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_LP_Int_Unmask_By_Word(uint32_t src)
{
    BL_WR_REG(IPC1_BASE, IPC_CPU0_IPC_IUSR, src);
}

/****************************************************************************/ /**
 * @brief  LP get IPC interrupt raw status
 *
 * @param  None
 *
 * @return IPC interrupt raw status
 *
*******************************************************************************/
uint32_t IPC_LP_Get_Int_Raw_Status(void)
{
    return BL_RD_REG(IPC1_BASE, IPC_CPU0_IPC_IRSRR);
}

/****************************************************************************/ /**
 * @brief  LP clear IPC interrupt
 *
 * @param  src: LP IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_LP_Clear_Int(IPC_Int_Src_Type src)
{
    uint32_t tmpVal = 0;

    /* Check the parameters */
    CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));

    tmpVal = (1 << src);

    BL_WR_REG(IPC1_BASE, IPC_CPU0_IPC_ICR, tmpVal);
}

/****************************************************************************/ /**
 * @brief  LP clear IPC interrupt by word
 *
 * @param  src: IPC interrupt source in word,every bit is interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_LP_Clear_Int_By_Word(uint32_t src)
{
    BL_WR_REG(IPC1_BASE, IPC_CPU0_IPC_ICR, src);
}

/****************************************************************************/ /**
 * @brief  CPUx trigger IPC interrupt to LP
 *
 * @param  src: IPC interrupt source
 *
 * @param  cpuxOffset: CPU interrupt offset
 *
 * @return None
 *
*******************************************************************************/
void IPC_CPUx_Trigger_LP(IPC_Grp_Int_Src_Type src, uint8_t cpuxOffset)
{
    uint32_t tmpVal = 0;

    /* Check the parameters */
    //CHECK_PARAM(IS_IPC_Grp_Int_Src_Type(src));

    tmpVal = (1 << (src + cpuxOffset));

    BL_WR_REG(IPC1_BASE, IPC_CPU1_IPC_ISWR, tmpVal);
}

/****************************************************************************/ /**
 * @brief  M0 trigger IPC interrupt to LP
 *
 * @param  src: M0 IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_M0_Trigger_LP(IPC_Grp_nIt_Src_Type src)
{
    IPC_CPUx_Trigger_LP(src, IPC_M0_OFFSET_IN_LP);
}

/****************************************************************************/ /**
 * @brief  D0 trigger IPC interrupt to LP
 *
 * @param  src: D0 IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_D0_Trigger_LP(IPC_Grp_Int_Src_Type src)
{
    IPC_CPUx_Trigger_LP(src, IPC_D0_OFFSET_IN_LP);
}

#if defined(CPU_D0) || defined(CPU_D1)
/****************************************************************************/ /**
 * @brief  D0 IPC interrupt init
 *
 * @param  onM0TriggerCallBack: Callback when M0 trigger
 *
 * @param  onLPTriggerCallBack: Callback when LP trigger
 *
 * @return None
 *
*******************************************************************************/
void IPC_D0_Init(ipcIntCallback *onM0TriggerCallBack,
                 ipcIntCallback *onLPTriggerCallBack)
{
    d0IpcIntCbfArra[0] = onM0TriggerCallBack;
    d0IpcIntCbfArra[1] = onLPTriggerCallBack;

    IPC_D0_Int_Unmask_By_Word(0xffffffff);

#ifndef BFLB_USE_HAL_DRIVER
    Interrupt_Handler_Register(IPC_D0_IRQn, IPC_D0_IRQHandler);
#endif
    CPU_Interrupt_Enable(IPC_D0_IRQn);
}
#endif

/****************************************************************************/ /**
 * @brief  D0 unmask IPC interrupt
 *
 * @param  src: D0 IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_D0_Int_Unmask(IPC_Int_Src_Type src)
{
    uint32_t tmpVal = 0;

    /* Check the parameters */
    CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));

    tmpVal = (1 << src);

    BL_WR_REG(IPC2_BASE, IPC_CPU0_IPC_IUSR, tmpVal);
}

/****************************************************************************/ /**
 * @brief  D0 unmask IPC interrupt by word
 *
 * @param  src: D0 IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_D0_Int_Unmask_By_Word(uint32_t src)
{
    BL_WR_REG(IPC2_BASE, IPC_CPU0_IPC_IUSR, src);
}

/****************************************************************************/ /**
 * @brief  D0 get IPC interrupt raw status
 *
 * @param  None
 *
 * @return IPC interrupt raw status
 *
*******************************************************************************/
uint32_t IPC_D0_Get_Int_Raw_Status(void)
{
    return BL_RD_REG(IPC2_BASE, IPC_CPU0_IPC_IRSRR);
}

/****************************************************************************/ /**
 * @brief  D0 clear IPC interrupt
 *
 * @param  src: D0 IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_D0_Clear_Int(IPC_Int_Src_Type src)
{
    uint32_t tmpVal = 0;

    /* Check the parameters */
    CHECK_PARAM(IS_IPC_INT_SRC_TYPE(src));

    tmpVal = (1 << src);

    BL_WR_REG(IPC2_BASE, IPC_CPU0_IPC_ICR, tmpVal);
}

/****************************************************************************/ /**
 * @brief  D0 clear IPC interrupt by word
 *
 * @param  src: IPC interrupt source in word,every bit is interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_D0_Clear_Int_By_Word(uint32_t src)
{
    BL_WR_REG(IPC2_BASE, IPC_CPU0_IPC_ICR, src);
}

/****************************************************************************/ /**
 * @brief  CPUx trigger IPC interrupt to D0
 *
 * @param  src: IPC interrupt source
 *
 * @param  cpuxOffset: CPU interrupt offset
 *
 * @return None
 *
*******************************************************************************/
void IPC_CPUx_Trigger_D0(IPC_Grp_Int_Src_Type src, uint8_t cpuxOffset)
{
    uint32_t tmpVal = 0;

    /* Check the parameters */
    //CHECK_PARAM(IS_IPC_Grp_Int_Src_Type(src));

    tmpVal = (1 << (src + cpuxOffset));

    BL_WR_REG(IPC2_BASE, IPC_CPU1_IPC_ISWR, tmpVal);
}

/****************************************************************************/ /**
 * @brief  M0 trigger IPC interrupt to D0
 *
 * @param  src: M0 IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_M0_Trigger_D0(IPC_Grp_Int_Src_Type src)
{
    IPC_CPUx_Trigger_D0(src, IPC_M0_OFFSET_IN_D0);
}

/****************************************************************************/ /**
 * @brief  LP trigger IPC interrupt to D0
 *
 * @param  src: LP IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_LP_Trigger_D0(IPC_Grp_Int_Src_Type src)
{
    IPC_CPUx_Trigger_D0(src, IPC_LP_OFFSET_IN_D0);
}

/****************************************************************************/ /**
 * @brief  M0 trigger IPC interrupt to CPUx
 *
 * @param  tgtCPU: Target CPU
 *
 * @param  src: IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_M0_Trigger_CPUx(GLB_CORE_ID_Type tgtCPU, IPC_Grp_Int_Src_Type src)
{
    switch (tgtCPU) {
        case GLB_CORE_ID_LP:
            IPC_M0_Trigger_LP(src);
            break;
        case GLB_CORE_ID_D0:
            IPC_M0_Trigger_D0(src);
            break;
        default:
            break;
    }
}

/****************************************************************************/ /**
 * @brief  LP trigger IPC interrupt to CPUx
 *
 * @param  tgtCPU: Target CPU
 *
 * @param  src: IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_LP_Trigger_CPUx(GLB_CORE_ID_Type tgtCPU, IPC_Grp_Int_Src_Type src)
{
    switch (tgtCPU) {
        case GLB_CORE_ID_M0:
            IPC_LP_Trigger_M0(src);
            break;
        case GLB_CORE_ID_D0:
            IPC_LP_Trigger_D0(src);
            break;
        default:
            break;
    }
}

/****************************************************************************/ /**
 * @brief  D0 trigger IPC interrupt to CPUx
 *
 * @param  tgtCPU: Target CPU
 *
 * @param  src: IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_D0_Trigger_CPUx(GLB_CORE_ID_Type tgtCPU, IPC_Grp_Int_Src_Type src)
{
    switch (tgtCPU) {
        case GLB_CORE_ID_M0:
            IPC_D0_Trigger_M0(src);
            break;
        case GLB_CORE_ID_LP:
            IPC_D0_Trigger_LP(src);
            break;
        default:
            break;
    }
}

/****************************************************************************/ /**
 * @brief  D0 trigger IPC interrupt to D1
 *
 * @param  src: D0 IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_Trigger_Target_CPU(GLB_CORE_ID_Type tgtCPU, IPC_Grp_Int_Src_Type src)
{
    GLB_CORE_ID_Type localCPU = GLB_Get_Core_Type();

    switch (localCPU) {
        case GLB_CORE_ID_M0:
            IPC_M0_Trigger_CPUx(tgtCPU, src);
            break;
        case GLB_CORE_ID_LP:
            IPC_LP_Trigger_CPUx(tgtCPU, src);
            break;
        case GLB_CORE_ID_D0:
            IPC_D0_Trigger_CPUx(tgtCPU, src);
            break;
        default:
            break;
    }
}

/****************************************************************************/ /**
 * @brief  D0 trigger IPC interrupt to D1
 *
 * @param  src: D0 IPC interrupt source
 *
 * @return None
 *
*******************************************************************************/
void IPC_Common_Interrupt_Handler(uint32_t irqStatus, ipcIntCallback *callBack[GLB_CORE_ID_MAX - 1])
{
    uint32_t tmp;
    uint32_t grp = 0;

    for (grp = 0; grp < GLB_CORE_ID_MAX - 1; grp++) {
        tmp = (irqStatus >> (16 * grp)) & 0xffff;
        if (tmp != 0) {
            if (callBack[grp] != NULL) {
                callBack[grp](tmp);
            }
        }
    }
}

/****************************************************************************/ /**
 * @brief  M0 IPC IRQ handler
 *
 * @param  None
 *
 * @return None
 *
*******************************************************************************/
#ifndef BFLB_USE_HAL_DRIVER
void IPC_M0_IRQHandler(void)
{
    uint32_t irqStatus;
    irqStatus = IPC_M0_Get_Int_Raw_Status();
    IPC_Common_Interrupt_Handler(irqStatus, m0IpcIntCbfArra);
    IPC_M0_Clear_Int_By_Word(irqStatus);
}
#endif

/****************************************************************************/ /**
 * @brief  LP IPC IRQ handler
 *
 * @param  None
 *
 * @return None
 *
*******************************************************************************/
#ifndef BFLB_USE_HAL_DRIVER
void IPC_LP_IRQHandler(void)
{
    uint32_t irqStatus;
    irqStatus = IPC_LP_Get_Int_Raw_Status();
    IPC_Common_Interrupt_Handler(irqStatus, lpIpcIntCbfArra);
    IPC_LP_Clear_Int_By_Word(irqStatus);
}
#endif

/****************************************************************************/ /**
 * @brief  D0 IPC IRQ handler
 *
 * @param  None
 *
 * @return None
 *
*******************************************************************************/
#ifndef BFLB_USE_HAL_DRIVER
void IPC_D0_IRQHandler(void)
{
    uint32_t irqStatus;
    irqStatus = IPC_D0_Get_Int_Raw_Status();
    IPC_Common_Interrupt_Handler(irqStatus, d0IpcIntCbfArra);
    IPC_D0_Clear_Int_By_Word(irqStatus);
}
#endif

/*@} end of group IPC_Public_Functions */

/*@} end of group IPC */

/*@} end of group BL606P_Peripheral_Driver */

三、总结 

基本试验了IPC通讯,寄存器和触发动作应该是没问题的;看来后续要使用M1S_BL808_SDK作为开发主力的SDK了,好多函数封装了,功能实现的也比较好;只是目前只能在Linux下的开发环境使用,对于笔记本性能有限,懒得开虚拟机的我,还是eciplse的Windows客户端使用起来更方便一点。

你可能感兴趣的:(BL808,学习)