提交 77f08149 编写于 作者: Q qiyongzhong0

Merge branch 'master' of https://github.com/RT-Thread/rt-thread into fix_bug_of_dataqueue

......@@ -16,15 +16,22 @@
#include "exception.h"
#include "drv_uart.h"
#include "board.h"
#include "ls2k1000.h"
/**
* this function will reset CPU
*
*/
void rt_hw_cpu_reset(void)
{
WDT_EN = 0x01;
WDT_TIMER = 0x01;
WDT_SET = 0x01;
rt_kprintf("reboot system...\n");
while (1);
}
MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_reset, reboot, reset cpu);
/**
* this function will shutdown CPU
......@@ -32,10 +39,13 @@ void rt_hw_cpu_reset(void)
*/
void rt_hw_cpu_shutdown(void)
{
PM1_STS &= 0xffffffff;
PM1_CNT = 0x3c00;
rt_kprintf("shutdown...\n");
while (1);
}
MSH_CMD_EXPORT_ALIAS(rt_hw_cpu_shutdown, poweroff, shutdown cpu);
/**
......
......@@ -3,6 +3,7 @@
#include <mips.h>
#include "interrupt.h"
#include <rthw.h>
#define APB_BASE CKSEG1ADDR(0xbfe00000)
......@@ -24,6 +25,28 @@
#define GEN_CONFIG0_REG (0xFFFFFFFFBfe10420)
/*
* General PM Configuration Register
*/
#define PMCON_BASE (APB_BASE | (0x7 << 12))
/*
* Power Management1 Configuration Registers
*/
#define PM1_BASE (PMCON_BASE + 0x0C)
#define PM1_STS HWREG32(PM1_BASE)
#define PM1_EN HWREG32(PM1_BASE + 0x04)
#define PM1_CNT HWREG32(PM1_BASE + 0x08)
/*
* Watch Dog Configuration Registers
*/
#define WDT_BASE (PMCON_BASE + 0x30)
#define WDT_EN HWREG32(WDT_BASE)
#define WDT_SET HWREG32(WDT_BASE + 0x04)
#define WDT_TIMER HWREG32(WDT_BASE + 0x08)
void rt_hw_timer_handler(void);
void rt_hw_uart_init(void);
......
......@@ -32,6 +32,9 @@ if GetDepend(['BSP_USING_PWM']):
if GetDepend(['BSP_USING_WDT']):
src += ['drv_wdt.c']
if GetDepend(['BSP_USING_ONCHIP_RTC']):
src += ['drv_rtc.c']
path = [cwd]
group = DefineGroup('Drivers', src, depend = [''], CPPPATH = path)
......
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-09-08 Chenyingchun first version
*/
#include "board.h"
#include <rtthread.h>
#include <rtdevice.h>
#include <nrfx_rtc.h>
#include <nrfx_clock.h>
#ifdef BSP_USING_ONCHIP_RTC
#define LOG_TAG "drv.rtc"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
/* 2018-01-30 14:44:50 = RTC_TIME_INIT(2018, 1, 30, 14, 44, 50) */
#define RTC_TIME_INIT(year, month, day, hour, minute, second) \
{.tm_year = year - 1900, .tm_mon = month - 1, .tm_mday = day, .tm_hour = hour, .tm_min = minute, .tm_sec = second}
#ifndef ONCHIP_RTC_TIME_DEFAULT
#define ONCHIP_RTC_TIME_DEFAULT RTC_TIME_INIT(2018, 1, 1, 0, 0 ,0)
#endif
#ifndef RTC_INSTANCE_ID
#define RTC_INSTANCE_ID (2)
#endif
#define TICK_FREQUENCE_HZ (RT_TICK_PER_SECOND) // RTC tick frequence, in HZ
static struct rt_device rtc;
static time_t init_time;
static uint32_t tick = 0;
static void rtc_callback(nrfx_rtc_int_type_t int_type)
{
static uint32_t count = 0;
if (int_type == NRFX_RTC_INT_TICK)
{
count++;
if((count % TICK_FREQUENCE_HZ) == 0)
{
tick++;
}
}
}
static rt_err_t rt_rtc_config(struct rt_device *dev)
{
#define SYSTICK_CLOCK_HZ (32768UL)
#define RTC_PRESCALER ((uint32_t) (NRFX_ROUNDED_DIV(SYSTICK_CLOCK_HZ, TICK_FREQUENCE_HZ) - 1))
const nrfx_rtc_t rtc_instance = NRFX_RTC_INSTANCE(RTC_INSTANCE_ID);
nrf_clock_lf_src_set(NRF_CLOCK, (nrf_clock_lfclk_t)NRFX_CLOCK_CONFIG_LF_SRC);
nrfx_clock_lfclk_start();
//Initialize RTC instance
nrfx_rtc_config_t config = NRFX_RTC_DEFAULT_CONFIG;
config.prescaler = RTC_PRESCALER;
nrfx_rtc_init(&rtc_instance, &config, rtc_callback);
nrfx_rtc_tick_enable(&rtc_instance, true);
//Power on RTC instance
nrfx_rtc_enable(&rtc_instance);
return RT_EOK;
}
static rt_err_t rt_rtc_control(rt_device_t dev, int cmd, void *args)
{
time_t *time;
RT_ASSERT(dev != RT_NULL);
switch (cmd)
{
case RT_DEVICE_CTRL_RTC_GET_TIME:
{
time = (time_t *) args;
*time = init_time + tick;
break;
}
case RT_DEVICE_CTRL_RTC_SET_TIME:
{
time = (time_t *) args;
init_time = *time - tick;
break;
}
}
return RT_EOK;
}
#ifdef RT_USING_DEVICE_OPS
const static struct rt_device_ops rtc_ops =
{
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
rt_rtc_control
};
#endif
static rt_err_t rt_hw_rtc_register(rt_device_t device, const char *name, rt_uint32_t flag)
{
struct tm time_new = ONCHIP_RTC_TIME_DEFAULT;
RT_ASSERT(device != RT_NULL);
init_time = mktime(&time_new);
if (rt_rtc_config(device) != RT_EOK)
{
return -RT_ERROR;
}
#ifdef RT_USING_DEVICE_OPS
device->ops = &rtc_ops;
#else
device->init = RT_NULL;
device->open = RT_NULL;
device->close = RT_NULL;
device->read = RT_NULL;
device->write = RT_NULL;
device->control = rt_rtc_control;
#endif
device->type = RT_Device_Class_RTC;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
device->user_data = RT_NULL;
/* register a character device */
rt_device_register(device, name, flag);
return RT_EOK;
}
int rt_hw_rtc_init(void)
{
rt_err_t result;
result = rt_hw_rtc_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR);
if (result != RT_EOK)
{
LOG_E("rtc register err code: %d", result);
return result;
}
LOG_D("rtc init success");
return RT_EOK;
}
INIT_DEVICE_EXPORT(rt_hw_rtc_init);
#endif /* BSP_USING_ONCHIP_RTC */
......@@ -313,6 +313,39 @@ endif
int
default 1
endif
menuconfig BSP_USING_ONCHIP_RTC
bool "Enable RTC"
select RT_USING_RTC
select RT_USING_LIBC
default n
if BSP_USING_ONCHIP_RTC
config NRFX_CLOCK_ENABLED
int
default 1
config NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY
int
default 7
config NRFX_RTC_ENABLED
int
default 1
config NRFX_RTC0_ENABLED
int
default 1
config NRFX_RTC1_ENABLED
int
default 1
config NRFX_RTC2_ENABLED
int
default 1
config RTC_INSTANCE_ID
int
default 2
config RTC_INSTANCE_ID
int "select RTC instance id, must be 0, 1, 2"
range 0 2
default 2
endif
endmenu
endmenu
......@@ -346,8 +346,41 @@ menu "On-chip Peripheral Drivers"
int
default 1
endif
endmenu
menuconfig BSP_USING_ONCHIP_RTC
bool "Enable RTC"
select RT_USING_RTC
select RT_USING_LIBC
default n
if BSP_USING_ONCHIP_RTC
config NRFX_CLOCK_ENABLED
int
default 1
config NRFX_CLOCK_DEFAULT_CONFIG_IRQ_PRIORITY
int
default 7
config NRFX_RTC_ENABLED
int
default 1
config NRFX_RTC0_ENABLED
int
default 1
config NRFX_RTC1_ENABLED
int
default 1
config NRFX_RTC2_ENABLED
int
default 1
config RTC_INSTANCE_ID
int
default 2
config RTC_INSTANCE_ID
int "select RTC instance id, must be 0, 1, 2"
range 0 2
default 2
endif
endmenu
choice
prompt "BLE STACK"
......
......@@ -8,6 +8,7 @@
* 2018-11-06 balanceTWK first version
* 2020-06-16 thread-liu add stm32mp1
* 2020-09-01 thread-liu add GPIOZ
* 2020-09-18 geniusgogo optimization design pin-index algorithm
*/
#ifndef __DRV_GPIO_H__
......@@ -16,6 +17,10 @@
#include <drv_common.h>
#include <board.h>
#ifdef __cplusplus
extern "C" {
#endif
#define __STM32_PORT(port) GPIO##port##_BASE
#if defined(SOC_SERIES_STM32MP1)
......@@ -24,24 +29,6 @@
#define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__STM32_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN)
#endif
#define __STM32_PIN(index, gpio, gpio_index) \
{ \
index, GPIO##gpio, GPIO_PIN_##gpio_index \
}
#define __STM32_PIN_RESERVE \
{ \
-1, 0, 0 \
}
/* STM32 GPIO driver */
struct pin_index
{
int index;
GPIO_TypeDef *gpio;
uint32_t pin;
};
struct pin_irq_map
{
rt_uint16_t pinbit;
......@@ -50,5 +37,9 @@ struct pin_irq_map
int rt_hw_pin_init(void);
#ifdef __cplusplus
}
#endif
#endif /* __DRV_GPIO_H__ */
......@@ -426,6 +426,7 @@ CONFIG_BSP_USING_STLINK_TO_USART=y
# CONFIG_BSP_USING_PMIC is not set
# CONFIG_BSP_USING_PWR is not set
# CONFIG_BSP_USING_RCC is not set
# CONFIG_BSP_USING_OPENAMP is not set
#
# On-chip Peripheral Drivers
......
......@@ -37,25 +37,25 @@ For more details about this board, please refer to the ST official documentation
Each peripheral supporting condition for this BSP is as follows:
| On-board Peripheral | **Support** | **Remark** |
| :----------------------------- | :---------: | :-----------------: |
| USB TO UART | YES | |
| PWR | YES | |
| RCC | YES | |
| SD Card (SDMMC) | NO | |
| ETH | NO | |
| AUDIO | NO | |
| **On-chip Peripheral Drivers** | **Support** | **Remark** |
| GPIO | YES | GPIOA-GPIOK, GPIOZ |
| UART | YES | UART4 (ST-Link) |
| EXTI | YES | |
| SPI | YES | |
| TIM | YES | |
| LPTIM | YES | |
| I2C | YES | Software & Hardware |
| ADC | YES | |
| DAC | YES | |
| WWDG | YES | |
| On-board Peripheral | **Support** | **Remark** |
| :----------------------------- | :---------: | :----------------: |
| USB TO UART | YES | |
| PWR | YES | |
| RCC | YES | |
| SD Card (SDMMC) | NO | |
| ETH | NO | |
| AUDIO | NO | |
| **On-chip Peripheral Drivers** | **Support** | **Remark** |
| GPIO | YES | GPIOA-GPIOK, GPIOZ |
| UART | YES | UART4 (ST-Link) |
| EXTI | YES | |
| SPI | YES | |
| TIM | YES | |
| LPTIM | YES | |
| I2C | YES | Software |
| ADC | YES | |
| DAC | YES | |
| WWDG | YES | |
## Execution Instruction
......
/**
******************************************************************************
* File Name : IPCC.h
* Description : This file provides code for the configuration
* of the IPCC instances.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under Ultimate Liberty license
* SLA0044, the "License"; You may not use this file except in compliance with
* the License. You may obtain a copy of the License at:
* www.st.com/SLA0044
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __ipcc_H
#define __ipcc_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern IPCC_HandleTypeDef hipcc;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_IPCC_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /*__ ipcc_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/**
******************************************************************************
* @file mbox_ipcc.h
* @author MCD Application Team
* @brief Header for mbox_ipcc.c module
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#ifndef MBOX_IPCC_H_
#define MBOX_IPCC_H_
/* USER CODE BEGIN firstSection */
/* can be used to modify / undefine following code or add new definitions */
/* USER CODE END firstSection */
/* Includes ------------------------------------------------------------------*/
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
int MAILBOX_Notify(void *priv, uint32_t id);
int MAILBOX_Init(void);
int MAILBOX_Poll(struct virtio_device *vdev);
/* USER CODE BEGIN lastSection */
/* can be used to modify / undefine previous code or add new definitions */
/* USER CODE END lastSection */
#endif /* MBOX_IPCC_H_ */
/**
******************************************************************************
* @file openamp.h
* @brief Header for openamp applications
* @author MCD Application Team
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __openamp_H
#define __openamp_H
#ifdef __cplusplus
extern "C" {
#endif
#include "openamp/open_amp.h"
#include "openamp_conf.h"
#define OPENAMP_send rpmsg_send
#define OPENAMP_destroy_ept rpmsg_destroy_ept
/* Initialize the openamp framework*/
int MX_OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb);
/* Deinitialize the openamp framework*/
void OPENAMP_DeInit(void);
/* Initialize the endpoint struct*/
void OPENAMP_init_ept(struct rpmsg_endpoint *ept);
/* Create and register the endpoint */
int OPENAMP_create_endpoint(struct rpmsg_endpoint *ept, const char *name,
uint32_t dest, rpmsg_ept_cb cb,
rpmsg_ns_unbind_cb unbind_cb);
/* Check for new rpmsg reception */
void OPENAMP_check_for_message(void);
/* Wait loop on endpoint ready ( message dest address is know)*/
void OPENAMP_Wait_EndPointready(struct rpmsg_endpoint *rp_ept);
#ifdef __cplusplus
}
#endif
#endif /*__openamp_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/**
******************************************************************************
* @file openamp_conf.h
* @author MCD Application Team
* @brief Configuration file for OpenAMP MW
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __OPENAMP_CONF__H__
#define __OPENAMP_CONF__H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#if defined (__LOG_TRACE_IO_) || defined(__LOG_UART_IO_)
#include "openamp_log.h"
#endif
/* ########################## Mailbox Interface Selection ############################## */
/**
* @brief This is the list of Mailbox interface to be used in the OpenAMP MW
* Please note that not all interfaces are supported by a STM32 device
*/
#define MAILBOX_IPCC_IF_ENABLED
//#define MAILBOX_HSEM_IF_ENABLED
/* Includes ------------------------------------------------------------------*/
/**
* @brief Include Maibox interface header file
*/
#ifdef MAILBOX_IPCC_IF_ENABLED
#include "mbox_ipcc.h"
#endif /* MAILBOX_IPCC_IF_ENABLED */
#ifdef MAILBOX_HSEM_IF_ENABLED
#include "mbox_hsem.h"
#endif /* MAILBOX_HSEM_IF_ENABLED */
/* ########################## Virtual Diver Module Selection ############################## */
/**
* @brief This is the list of modules to be used in the OpenAMP Virtual driver module
* Please note that virtual driver are not supported on all stm32 families
*/
//#define VIRTUAL_UART_MODULE_ENABLED
//#define VIRTUAL_I2C_MODULE_ENABLED
/* Includes ------------------------------------------------------------------*/
/**
* @brief Include Virtual Driver module's header file
*/
#ifdef VIRTUAL_UART_MODULE_ENABLED
#include "virt_uart.h"
#endif /* VIRTUAL_UART_MODULE_ENABLED */
#ifdef VIRTUAL_I2C_MODULE_ENABLED
#include "virt_i2c.h"
#endif /* VIRTUAL_I2C_MODULE_ENABLED */
/* ########################## Linux Master Selection ############################## */
/**
* @brief Due to Linux compatibility, it's important to distinguish if the MASTER is Linux or not.
* In that case, the LINUX_RPROC_MASTER define is required
*/
#define LINUX_RPROC_MASTER
/* USER CODE BEGIN INCLUDE */
/* USER CODE END INCLUDE */
/** @addtogroup OPENAMP_MW
* @{
*/
/** @defgroup OPENAMP_CONF OPENAMP_CONF
* @brief Configuration file for Openamp mw
* @{
*/
/** @defgroup OPENAMP_CONF_Exported_Variables OPENAMP_CONF_Exported_Variables
* @brief Public variables.
* @{
*/
/**
* @}
*/
/** @defgroup OPENAMP_CONF_Exported_Defines OPENAMP_CONF_Exported_Defines
* @brief Defines for configuration of the Openamp mw
* @{
*/
#if defined (__ICCARM__)
/*
* For IAR, the .icf file should contain the following lines:
* define symbol __OPENAMP_region_start__ = BASE_ADDRESS; (0x38000400 for example)
* define symbol __OPENAMP_region_size__ = MEM_SIZE; (0xB000 as example)
*
* export symbol __OPENAMP_region_start__;
* export symbol __OPENAMP_region_size__;
*/
extern const uint32_t __OPENAMP_region_start__;
extern const uint8_t __OPENAMP_region_size__;
#define SHM_START_ADDRESS ((metal_phys_addr_t)&__OPENAMP_region_start__)
#define SHM_SIZE ((size_t)&__OPENAMP_region_size__)
#elif defined(__CC_ARM)
/*
* For MDK-ARM, the scatter file .sct should contain the following line:
* LR_IROM1 .... {
* ...
* __OpenAMP_SHMEM__ 0x38000400 EMPTY 0x0000B000 {} ; Shared Memory area used by OpenAMP
* }
*
*/
extern unsigned int Image$$__OpenAMP_SHMEM__$$Base;
extern unsigned int Image$$__OpenAMP_SHMEM__$$ZI$$Length;
#define SHM_START_ADDRESS (unsigned int)&Image$$__OpenAMP_SHMEM__$$Base
#define SHM_SIZE ((size_t)&Image$$__OpenAMP_SHMEM__$$ZI$$Length)
#else
/*
* for GCC add the following content to the .ld file:
* MEMORY
* {
* ...
* OPEN_AMP_SHMEM (xrw) : ORIGIN = 0x38000400, LENGTH = 63K
* }
* __OPENAMP_region_start__ = ORIGIN(OPEN_AMP_SHMEM);
* __OPENAMP_region_end__ = ORIGIN(OPEN_AMP_SHMEM) + LENGTH(OPEN_AMP_SHMEM);
*
* using the LENGTH(OPEN_AMP_SHMEM) to set the SHM_SIZE lead to a crash thus we
* use the start and end address.
*/
extern int __OPENAMP_region_start__[]; /* defined by linker script */
extern int __OPENAMP_region_end__[]; /* defined by linker script */
#define SHM_START_ADDRESS ((metal_phys_addr_t)__OPENAMP_region_start__)
#define SHM_SIZE (size_t)((void *)__OPENAMP_region_end__ - (void *) __OPENAMP_region_start__)
#endif
#if defined LINUX_RPROC_MASTER
#define VRING_RX_ADDRESS -1 /* allocated by Master processor: CA7 */
#define VRING_TX_ADDRESS -1 /* allocated by Master processor: CA7 */
#define VRING_BUFF_ADDRESS -1 /* allocated by Master processor: CA7 */
#define VRING_ALIGNMENT 16 /* fixed to match with linux constraint */
#define VRING_NUM_BUFFS 16 /* number of rpmsg buffer */
#else
#define VRING_RX_ADDRESS 0x10040000 /* allocated by Master processor: CA7 */
#define VRING_TX_ADDRESS 0x10040400 /* allocated by Master processor: CA7 */
#define VRING_BUFF_ADDRESS 0x10040800 /* allocated by Master processor: CA7 */
#define VRING_ALIGNMENT 16 /* fixed to match with 4k page alignement requested by linux */
#define VRING_NUM_BUFFS 16 /* number of rpmsg buffer */
#endif
/* Fixed parameter */
#define NUM_RESOURCE_ENTRIES 2
#define VRING_COUNT 2
#define VDEV_ID 0xFF
#define VRING0_ID 0 /* VRING0 ID (master to remote) fixed to 0 for linux compatibility*/
#define VRING1_ID 1 /* VRING1 ID (remote to master) fixed to 1 for linux compatibility */
/**
* @}
*/
/** @defgroup OPENAMP_CONF_Exported_Macros OPENAMP_CONF_Exported_Macros
* @brief Aliases.
* @{
*/
/* DEBUG macros */
#if defined (__LOG_TRACE_IO_) || defined(__LOG_UART_IO_)
#define OPENAMP_log_dbg log_dbg
#define OPENAMP_log_info log_info
#define OPENAMP_log_warn log_warn
#define OPENAMP_log_err log_err
#else
#define OPENAMP_log_dbg(...)
#define OPENAMP_log_info(...)
#define OPENAMP_log_warn(...)
#define OPENAMP_log_err(...)
#endif
/**
* @}
*/
/** @defgroup OPENAMP_CONF_Exported_Types OPENAMP_CONF_Exported_Types
* @brief Types.
* @{
*/
/**
* @}
*/
/** @defgroup OPENAMP_CONF_Exported_FunctionsPrototype OPENAMP_CONF_Exported_FunctionsPrototype
* @brief Declaration of public functions for OpenAMP mw.
* @{
*/
/* Exported functions -------------------------------------------------------*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* __OPENAMP_CONF__H__ */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/**
******************************************************************************
* @file log.h
* @author MCD Application Team
* @brief logging services
******************************************************************************
*
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*
******************************************************************************
*/
/** @addtogroup LOG
* @{
*/
/** @addtogroup stm32mp1xx_Log
* @{
*/
/**
* @brief Define to prevent recursive inclusion
*/
#ifndef __LOG_STM32MP1XX_H
#define __LOG_STM32MP1XX_H
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup STM32MP1xx_Log_Includes
* @{
*/
#include "stm32mp1xx_hal.h"
/**
* @}
*/
/** @addtogroup STM32MP1xx_Log_Exported_Constants
* @{
*/
#if defined (__LOG_TRACE_IO_)
#define SYSTEM_TRACE_BUF_SZ 2048
#endif
#define LOGQUIET 0
#define LOGERR 1
#define LOGWARN 2
#define LOGINFO 3
#define LOGDBG 4
#ifndef LOGLEVEL
#define LOGLEVEL LOGINFO
#endif
/**
* @}
*/
/** @addtogroup STM32MP1xx_Log_Exported_types
* @{
*/
#if defined (__LOG_TRACE_IO_)
extern char system_log_buf[SYSTEM_TRACE_BUF_SZ]; /*!< buffer for debug traces */
#endif /* __LOG_TRACE_IO_ */
/**
* @}
*/
/** @addtogroup STM32MP1xx_Log_Exported_Macros
* @{
*/
#if defined (__LOG_TRACE_IO_) || defined(__LOG_UART_IO_)
#if LOGLEVEL >= LOGDBG
#define log_dbg(fmt, ...) printf("[%05ld.%03ld][DBG ]" fmt, HAL_GetTick()/1000, HAL_GetTick() % 1000, ##__VA_ARGS__)
#else
#define log_dbg(fmt, ...)
#endif
#if LOGLEVEL >= LOGINFO
#define log_info(fmt, ...) printf("[%05ld.%03ld][INFO ]" fmt, HAL_GetTick()/1000, HAL_GetTick() % 1000, ##__VA_ARGS__)
#else
#define log_info(fmt, ...)
#endif
#if LOGLEVEL >= LOGWARN
#define log_warn(fmt, ...) printf("[%05ld.%03ld][WARN ]" fmt, HAL_GetTick()/1000, HAL_GetTick() % 1000, ##__VA_ARGS__)
#else
#define log_warn(fmt, ...)
#endif
#if LOGLEVEL >= LOGERR
#define log_err(fmt, ...) printf("[%05ld.%03ld][ERR ]" fmt, HAL_GetTick()/1000, HAL_GetTick() % 1000, ##__VA_ARGS__)
#else
#define log_err(fmt, ...)
#endif
#else
#define log_dbg(fmt, ...)
#define log_info(fmt, ...)
#define log_warn(fmt, ...)
#define log_err(fmt, ...)
#endif /* __LOG_TRACE_IO_ */
/**
* @}
*/
/** @addtogroup STM32MP1xx_Log_Exported_Functions
* @{
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /*__LOG_STM32MP1XX_H */
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/*
* Copyright (c) 2019 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*/
/* This file populates resource table for BM remote
* for use by the Linux Master */
#ifndef RSC_TABLE_H_
#define RSC_TABLE_H_
#include "openamp/open_amp.h"
#include "openamp_conf.h"
/* Place resource table in special ELF section */
//#define __section_t(S) __attribute__((__section__(#S)))
//#define __resource __section_t(.resource_table)
/* Resource table for the given remote */
struct shared_resource_table {
unsigned int version;
unsigned int num;
unsigned int reserved[2];
unsigned int offset[NUM_RESOURCE_ENTRIES];
/* text carveout entry */
/* rpmsg vdev entry */
struct fw_rsc_vdev vdev;
struct fw_rsc_vdev_vring vring0;
struct fw_rsc_vdev_vring vring1;
struct fw_rsc_trace cm_trace;
};
void resource_table_init(int RPMsgRole, void **table_ptr, int *length);
#endif /* RSC_TABLE_H_ */
/**
******************************************************************************
* @file mbox_ipcc.c
* @author MCD Application Team
* @brief This file provides code for the configuration
* of the mailbox_ipcc_if.c MiddleWare.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/*
* Channel direction and usage:
*
* ======== <-- new msg ---=============--------<------ =======
* || || || CHANNEL 1 || || ||
* || A7 || ------->-------=============--- buf free--> || M4 ||
* || || || ||
* ||master|| <-- buf free---=============--------<------ ||slave||
* || || || CHANNEL 2 || || ||
* ======== ------->-------=============----new msg --> =======
*/
/* Includes ------------------------------------------------------------------*/
#include "openamp/open_amp.h"
#include "stm32mp1xx_hal.h"
#include "openamp_conf.h"
/* Within 'USER CODE' section, code will be kept by default at each generation */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* Private define ------------------------------------------------------------*/
#define MASTER_CPU_ID 0
#define REMOTE_CPU_ID 1
#define IPCC_CPU_A7 MASTER_CPU_ID
#define IPCC_CPU_M4 REMOTE_CPU_ID
#define RX_NO_MSG 0
#define RX_NEW_MSG 1
#define RX_BUF_FREE 2
/* Private variables ---------------------------------------------------------*/
extern IPCC_HandleTypeDef hipcc;
int msg_received_ch1 = RX_NO_MSG;
int msg_received_ch2 = RX_NO_MSG;
uint32_t vring0_id = 0; /* used for channel 1 */
uint32_t vring1_id = 1; /* used for channel 2 */
/* Private function prototypes -----------------------------------------------*/
void IPCC_channel1_callback(IPCC_HandleTypeDef * hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir);
void IPCC_channel2_callback(IPCC_HandleTypeDef * hipcc, uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir);
/**
* @brief Initialize MAILBOX with IPCC peripheral
* @param None
* @retval : Operation result
*/
int MAILBOX_Init(void)
{
if (HAL_IPCC_ActivateNotification(&hipcc, IPCC_CHANNEL_1, IPCC_CHANNEL_DIR_RX,
IPCC_channel1_callback) != HAL_OK) {
OPENAMP_log_err("%s: ch_1 RX fail\n", __func__);
return -1;
}
if (HAL_IPCC_ActivateNotification(&hipcc, IPCC_CHANNEL_2, IPCC_CHANNEL_DIR_RX,
IPCC_channel2_callback) != HAL_OK) {
OPENAMP_log_err("%s: ch_2 RX fail\n", __func__);
return -1;
}
return 0;
}
/**
* @brief Initialize MAILBOX with IPCC peripheral
* @param virtio device
* @retval : Operation result
*/
int MAILBOX_Poll(struct virtio_device *vdev)
{
/* If we got an interrupt, ask for the corresponding virtqueue processing */
if (msg_received_ch1 == RX_BUF_FREE) {
OPENAMP_log_dbg("Running virt0 (ch_1 buf free)\r\n");
rproc_virtio_notified(vdev, VRING0_ID);
msg_received_ch1 = RX_NO_MSG;
return 0;
}
if (msg_received_ch2 == RX_NEW_MSG) {
OPENAMP_log_dbg("Running virt1 (ch_2 new msg)\r\n");
rproc_virtio_notified(vdev, VRING1_ID);
msg_received_ch2 = RX_NO_MSG;
/* The OpenAMP framework does not notify for free buf: do it here */
rproc_virtio_notified(NULL, VRING1_ID);
return 0;
}
return -1;
}
/**
* @brief Callback function called by OpenAMP MW to notify message processing
* @param VRING id
* @retval Operation result
*/
int MAILBOX_Notify(void *priv, uint32_t id)
{
uint32_t channel;
(void)priv;
/* Called after virtqueue processing: time to inform the remote */
if (id == VRING0_ID) {
channel = IPCC_CHANNEL_1;
OPENAMP_log_dbg("Send msg on ch_1\r\n");
}
else if (id == VRING1_ID) {
/* Note: the OpenAMP framework never notifies this */
channel = IPCC_CHANNEL_2;
OPENAMP_log_dbg("Send 'buff free' on ch_2\r\n");
}
else {
OPENAMP_log_err("invalid vring (%d)\r\n", (int)id);
return -1;
}
/* Check that the channel is free (otherwise wait until it is) */
if (HAL_IPCC_GetChannelStatus(&hipcc, channel, IPCC_CHANNEL_DIR_TX) == IPCC_CHANNEL_STATUS_OCCUPIED) {
OPENAMP_log_dbg("Waiting for channel to be freed\r\n");
while (HAL_IPCC_GetChannelStatus(&hipcc, channel, IPCC_CHANNEL_DIR_TX) == IPCC_CHANNEL_STATUS_OCCUPIED)
;
}
/* Inform A7 (either new message, or buf free) */
HAL_IPCC_NotifyCPU(&hipcc, channel, IPCC_CHANNEL_DIR_TX);
return 0;
}
/* Private function ---------------------------------------------------------*/
/* Callback from IPCC Interrupt Handler: Master Processor informs that there are some free buffers */
void IPCC_channel1_callback(IPCC_HandleTypeDef * hipcc,
uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
{
if (msg_received_ch1 != RX_NO_MSG)
OPENAMP_log_dbg("IPCC_channel1_callback: previous IRQ not treated (status = %d)\r\n", msg_received_ch1);
msg_received_ch1 = RX_BUF_FREE;
/* Inform A7 that we have received the 'buff free' msg */
OPENAMP_log_dbg("Ack 'buff free' message on ch1\r\n");
HAL_IPCC_NotifyCPU(hipcc, ChannelIndex, IPCC_CHANNEL_DIR_RX);
}
/* Callback from IPCC Interrupt Handler: new message received from Master Processor */
void IPCC_channel2_callback(IPCC_HandleTypeDef * hipcc,
uint32_t ChannelIndex, IPCC_CHANNELDirTypeDef ChannelDir)
{
if (msg_received_ch2 != RX_NO_MSG)
OPENAMP_log_dbg("IPCC_channel2_callback: previous IRQ not treated (status = %d)\r\n", msg_received_ch2);
msg_received_ch2 = RX_NEW_MSG;
/* Inform A7 that we have received the new msg */
OPENAMP_log_dbg("Ack new message on ch2\r\n");
HAL_IPCC_NotifyCPU(hipcc, ChannelIndex, IPCC_CHANNEL_DIR_RX);
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/**
******************************************************************************
* @file openamp.c
* @author MCD Application Team
* @brief Code for openamp applications
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "openamp.h"
#include "rsc_table.h"
#include "metal/sys.h"
#include "metal/device.h"
/* Private define ------------------------------------------------------------*/
#define SHM_DEVICE_NAME "STM32_SHM"
/* Globals */
static struct metal_io_region *shm_io;
static struct metal_io_region *rsc_io;
static struct shared_resource_table *rsc_table;
static struct rpmsg_virtio_shm_pool shpool;
static struct rpmsg_virtio_device rvdev;
static metal_phys_addr_t shm_physmap;
struct metal_device shm_device = {
.name = SHM_DEVICE_NAME,
.num_regions = 2,
.regions = {
{.virt = NULL}, /* shared memory */
{.virt = NULL}, /* rsc_table memory */
},
.node = { NULL },
.irq_num = 0,
.irq_info = NULL
};
static int OPENAMP_shmem_init(int RPMsgRole)
{
int status = 0;
struct metal_device *device;
struct metal_init_params metal_params = METAL_INIT_DEFAULTS;
void* rsc_tab_addr;
int rsc_size;
metal_init(&metal_params);
status = metal_register_generic_device(&shm_device);
if (status != 0) {
return status;
}
status = metal_device_open("generic", SHM_DEVICE_NAME, &device);
if (status != 0) {
return status;
}
shm_physmap = SHM_START_ADDRESS;
metal_io_init(&device->regions[0], (void *)SHM_START_ADDRESS, &shm_physmap,
SHM_SIZE, -1, 0, NULL);
shm_io = metal_device_io_region(device, 0);
if (shm_io == NULL) {
return -1;
}
/* Initialize resources table variables */
resource_table_init(RPMsgRole, &rsc_tab_addr, &rsc_size);
rsc_table = (struct shared_resource_table *)rsc_tab_addr;
if (!rsc_table)
{
return -1;
}
metal_io_init(&device->regions[1], rsc_table,
(metal_phys_addr_t *)rsc_table, rsc_size, -1U, 0, NULL);
rsc_io = metal_device_io_region(device, 1);
if (rsc_io == NULL) {
return -1;
}
return 0;
}
int MX_OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb)
{
struct fw_rsc_vdev_vring *vring_rsc;
struct virtio_device *vdev;
int status = 0;
MAILBOX_Init();
/* Libmetal Initilalization */
status = OPENAMP_shmem_init(RPMsgRole);
if(status)
{
return status;
}
vdev = rproc_virtio_create_vdev(RPMsgRole, VDEV_ID, &rsc_table->vdev,
rsc_io, NULL, MAILBOX_Notify, NULL);
if (vdev == NULL)
{
return -1;
}
rproc_virtio_wait_remote_ready(vdev);
vring_rsc = &rsc_table->vring0;
status = rproc_virtio_init_vring(vdev, 0, vring_rsc->notifyid,
(void *)vring_rsc->da, shm_io,
vring_rsc->num, vring_rsc->align);
if (status != 0)
{
return status;
}
vring_rsc = &rsc_table->vring1;
status = rproc_virtio_init_vring(vdev, 1, vring_rsc->notifyid,
(void *)vring_rsc->da, shm_io,
vring_rsc->num, vring_rsc->align);
if (status != 0)
{
return status;
}
rpmsg_virtio_init_shm_pool(&shpool, (void *)VRING_BUFF_ADDRESS,
(size_t)SHM_SIZE);
rpmsg_init_vdev(&rvdev, vdev, ns_bind_cb, shm_io, &shpool);
return 0;
}
void OPENAMP_DeInit()
{
rpmsg_deinit_vdev(&rvdev);
metal_finish();
}
void OPENAMP_init_ept(struct rpmsg_endpoint *ept)
{
rpmsg_init_ept(ept, "", RPMSG_ADDR_ANY, RPMSG_ADDR_ANY, NULL, NULL);
}
int OPENAMP_create_endpoint(struct rpmsg_endpoint *ept, const char *name,
uint32_t dest, rpmsg_ept_cb cb,
rpmsg_ns_unbind_cb unbind_cb)
{
return rpmsg_create_ept(ept, &rvdev.rdev, name, RPMSG_ADDR_ANY, dest, cb,
unbind_cb);
}
void OPENAMP_check_for_message(void)
{
MAILBOX_Poll(rvdev.vdev);
}
void OPENAMP_Wait_EndPointready(struct rpmsg_endpoint *rp_ept)
{
while(!is_rpmsg_ept_ready(rp_ept))
MAILBOX_Poll(rvdev.vdev);
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/**
******************************************************************************
* @file log.c
* @author MCD Application Team
* @brief Ressource table
*
* This file provides services for logging
*
******************************************************************************
*
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*
******************************************************************************
*/
/** @addtogroup LOG
* @{
*/
/** @addtogroup STM32MP1xx_log
* @{
*/
/** @addtogroup STM32MP1xx_Log_Private_Includes
* @{
*/
#include "openamp_log.h"
/**
* @}
*/
/** @addtogroup STM32MP1xx_Log_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup STM32MP1xx_Log_Private_Defines
* @{
*/
/**
* @}
*/
#if defined (__LOG_TRACE_IO_)
char system_log_buf[SYSTEM_TRACE_BUF_SZ];
__weak void log_buff(int ch)
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART1 and Loop until the end of transmission */
static int offset = 0;
if (offset + 1 >= SYSTEM_TRACE_BUF_SZ)
offset = 0;
system_log_buf[offset] = ch;
system_log_buf[offset++ + 1] = '\0';
}
#endif
#if defined ( __CC_ARM) || (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#define PUTCHAR_PROTOTYPE int stdout_putchar(int ch)
#elif __GNUC__
/* With GCC/RAISONANCE, small log_info (option LD Linker->Libraries->Small log_info
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __attribute__(( weak )) __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int __attribute__(( weak )) fputc(int ch, FILE *f)
#endif /* __GNUC__ */
#if defined (__LOG_UART_IO_) || defined (__LOG_TRACE_IO_)
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the USART1 and Loop until the end of transmission */
#if defined (__LOG_UART_IO_)
extern UART_HandleTypeDef huart;
HAL_UART_Transmit(&huart, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
#endif
#if defined (__LOG_TRACE_IO_)
log_buff(ch);
#endif
return ch;
}
#else
/* No printf output */
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
/**
******************************************************************************
* @file rsc_table.c
* @author MCD Application Team
* @brief Ressource table
*
* This file provides a default resource table requested by remote proc to
* load the elf file. It also allows to add debug trace using a shared buffer.
*
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/** @addtogroup RSC_TABLE
* @{
*/
/** @addtogroup resource_table
* @{
*/
/** @addtogroup resource_table_Private_Includes
* @{
*/
#if defined(__ICCARM__) || defined (__CC_ARM)
#include <stddef.h> /* needed for offsetof definition*/
#endif
#include "rsc_table.h"
#include "openamp/open_amp.h"
/**
* @}
*/
/** @addtogroup resource_table_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup resource_table_Private_Defines
* @{
*/
/* Place resource table in special ELF section */
#if defined(__GNUC__)
#define __section_t(S) __attribute__((__section__(#S)))
#define __resource __section_t(.resource_table)
#endif
#if defined (LINUX_RPROC_MASTER)
#ifdef VIRTIO_MASTER_ONLY
#define CONST
#else
#define CONST const
#endif
#else
#define CONST
#endif
#define RPMSG_IPU_C0_FEATURES 1
#define VRING_COUNT 2
/* VirtIO rpmsg device id */
#define VIRTIO_ID_RPMSG_ 7
#if defined (__LOG_TRACE_IO_)
extern char system_log_buf[];
#endif
#if defined(__GNUC__)
#if !defined (__CC_ARM) && !defined (LINUX_RPROC_MASTER)
/* Since GCC is not initializing the resource_table at startup, it is declared as volatile to avoid compiler optimization
* for the CM4 (see resource_table_init() below)
*/
volatile struct shared_resource_table __resource __attribute__((used)) resource_table;
#else
CONST struct shared_resource_table __resource __attribute__((used)) resource_table = {
#endif
#elif defined(__ICCARM__)
__root CONST struct shared_resource_table resource_table @ ".resource_table" = {
#endif
#if defined(__ICCARM__) || defined (__CC_ARM) || defined (LINUX_RPROC_MASTER)
.version = 1,
#if defined (__LOG_TRACE_IO_)
.num = 2,
#else
.num = 1,
#endif
.reserved = {0, 0},
.offset = {
offsetof(struct shared_resource_table, vdev),
offsetof(struct shared_resource_table, cm_trace),
},
/* Virtio device entry */
.vdev= {
RSC_VDEV, VIRTIO_ID_RPMSG_, 0, RPMSG_IPU_C0_FEATURES, 0, 0, 0,
VRING_COUNT, {0, 0},
},
/* Vring rsc entry - part of vdev rsc entry */
.vring0 = {VRING_TX_ADDRESS, VRING_ALIGNMENT, VRING_NUM_BUFFS, VRING0_ID, 0},
.vring1 = {VRING_RX_ADDRESS, VRING_ALIGNMENT, VRING_NUM_BUFFS, VRING1_ID, 0},
#if defined (__LOG_TRACE_IO_)
.cm_trace = {
RSC_TRACE,
(uint32_t)system_log_buf, SYSTEM_TRACE_BUF_SZ, 0, "cm4_log",
},
#endif
} ;
#endif
void resource_table_init(int RPMsgRole, void **table_ptr, int *length)
{
#if !defined (LINUX_RPROC_MASTER)
#if defined (__GNUC__) && ! defined (__CC_ARM)
#ifdef VIRTIO_MASTER_ONLY
/*
* Currently the GCC linker doesn't initialize the resource_table global variable at startup
* it is done here by the master application.
*/
memset(&resource_table, '\0', sizeof(struct shared_resource_table));
resource_table.num = 1;
resource_table.version = 1;
resource_table.offset[0] = offsetof(struct shared_resource_table, vdev);
resource_table.vring0.da = VRING_TX_ADDRESS;
resource_table.vring0.align = VRING_ALIGNMENT;
resource_table.vring0.num = VRING_NUM_BUFFS;
resource_table.vring0.notifyid = VRING0_ID;
resource_table.vring1.da = VRING_RX_ADDRESS;
resource_table.vring1.align = VRING_ALIGNMENT;
resource_table.vring1.num = VRING_NUM_BUFFS;
resource_table.vring1.notifyid = VRING1_ID;
resource_table.vdev.type = RSC_VDEV;
resource_table.vdev.id = VIRTIO_ID_RPMSG_;
resource_table.vdev.num_of_vrings=VRING_COUNT;
resource_table.vdev.dfeatures = RPMSG_IPU_C0_FEATURES;
#else
/* For the slave application let's wait until the resource_table is correctly initialized */
while(resource_table.vring1.da != VRING_RX_ADDRESS)
{
}
#endif
#endif
#endif
(void)RPMsgRole;
*length = sizeof(resource_table);
*table_ptr = (void *)&resource_table;
}
......@@ -73,6 +73,11 @@ void HAL_MspInit(void)
/* System interrupt init*/
/* USER CODE BEGIN MspInit 1 */
#if !defined(BSP_USING_OPENAMP)
__HAL_RCC_SYSRAM_CLK_ENABLE();
__HAL_RCC_RETRAM_CLK_ENABLE();
#endif
HAL_NVIC_SetPriority(RCC_WAKEUP_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(RCC_WAKEUP_IRQn);
__HAL_RCC_ENABLE_IT(RCC_IT_WKUP);
......@@ -284,7 +289,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim)
/** Initializes the peripherals clock
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;
PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSE;
PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSI;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
......@@ -531,12 +536,13 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
__HAL_RCC_GPIOF_CLK_ENABLE();
/**SPI5 GPIO Configuration
PF9 ------> SPI5_MOSI
PF8 ------> SPI5_MISO
PF7 ------> SPI5_SCK
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_7;
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_8|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI5;
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
......
......@@ -32,6 +32,12 @@ menu "Onboard Peripheral Drivers"
config BSP_USING_RCC
bool "Enable rcc use sample"
default n
config BSP_USING_OPENAMP
bool "Enable OpenAMP"
select RT_USING_OPENAMP
default n
endmenu
menu "On-chip Peripheral Drivers"
......
......@@ -13,6 +13,9 @@ CubeMX_Config/Common/System/system_stm32mp1xx.c
CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c
''')
if GetDepend(['BSP_USING_SPI5']):
src += Glob('ports/spi_sample.c')
if GetDepend(['BSP_USING_RCC']):
src += Glob('ports/drv_rcc.c')
......@@ -34,10 +37,32 @@ if GetDepend(['BSP_USING_TIM14']):
if GetDepend(['BSP_USING_PMIC']):
src += Glob('ports/drv_pmic.c')
if GetDepend(['BSP_USING_OPENAMP']):
src += Glob('CubeMX_Config/CM4/Src/ipcc.c')
src += Glob('CubeMX_Config/CM4/Src/openamp.c')
src += Glob('CubeMX_Config/CM4/Src/openamp_log.c')
src += Glob('CubeMX_Config/CM4/Src/mbox_ipcc.c')
src += Glob('CubeMX_Config/CM4/Src/rsc_table.c')
src += Glob('ports/OpenAMP/libmetal/lib/*.c')
src += Glob('ports/OpenAMP/libmetal/lib/system/generic/*.c')
src += Glob('ports/OpenAMP/libmetal/lib/system/generic/cortexm/*.c')
src += Glob('ports/OpenAMP/open-amp/lib/rpmsg/*.c')
src += Glob('ports/OpenAMP/open-amp/lib/remoteproc/*.c')
src += Glob('ports/OpenAMP/open-amp/lib/virtio/*.c')
src += Glob('ports/OpenAMP/virtual_driver/*.c')
src += Glob('ports/OpenAMP/drv_openamp.c')
path = [cwd]
path += [cwd + '/CubeMX_Config/CM4/Inc']
path += [cwd + '/ports']
if GetDepend(['BSP_USING_OPENAMP']):
path += [cwd + '/ports/OpenAMP']
path += [cwd + '/ports/OpenAMP/open-amp/lib/include']
path += [cwd + '/ports/OpenAMP/libmetal/lib/include']
path += [cwd + '/ports/OpenAMP/virtual_driver']
path += [cwd + '/CubeMX_Config/CM4/Inc']
startup_path_prefix = SDK_LIB
if rtconfig.CROSS_TOOL == 'gcc':
......
......@@ -28,13 +28,17 @@ void SystemClock_Config(void)
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_HSE
|RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS_DIG;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.HSIDivValue = RCC_HSI_DIV1;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI
|RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE
|RCC_OSCILLATORTYPE_CSI;
RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS_DIG;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 0x0; /* Default reset value */
RCC_OscInitStruct.HSIDivValue = RCC_HSI_DIV1;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.CSIState = RCC_CSI_ON;
RCC_OscInitStruct.CSICalibrationValue = 0x10; /* Default reset value */
/**PLL1 Config
*/
......@@ -166,7 +170,7 @@ void rt_hw_board_init()
#if defined(RT_USING_HEAP)
rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
#endif
/* Pin driver initialization is open by default */
#ifdef RT_USING_PIN
rt_hw_pin_init();
......
......@@ -22,23 +22,25 @@
extern "C" {
#endif
#define STM32_FLASH_START_ADRESS ((uint32_t)0x10000000)
#define STM32_FLASH_SIZE (256 * 1024)
#define STM32_FLASH_START_ADRESS ((uint32_t)0x10000000)
#if defined(BSP_USING_OPENAMP)
#define STM32_FLASH_SIZE (64 * 1024)
#else
#define STM32_FLASH_SIZE (256 * 1024)
#endif
#define STM32_FLASH_END_ADDRESS ((uint32_t)(STM32_FLASH_START_ADRESS + STM32_FLASH_SIZE))
#define STM32_SRAM_SIZE (128)
#define STM32_SRAM_END ((uint32_t)0x10040000 + (STM32_SRAM_SIZE * 1024))
#if defined(__CC_ARM) || defined(__CLANG_ARM)
extern int Image$$RW_IRAM1$$ZI$$Limit;
#define HEAP_BEGIN (&Image$$RW_IRAM1$$ZI$$Limit)
#elif __ICCARM__
#pragma section="CSTACK"
#define HEAP_BEGIN (__segment_end("CSTACK"))
#if defined(BSP_USING_OPENAMP)
#define STM32_SRAM_BEGIN (uint32_t)0x10020000
#else
extern int __bss_end__;
#define HEAP_BEGIN (0x10040000 + 64 * 1024)
#define STM32_SRAM_BEGIN (uint32_t)0x2FFF0000
#endif
#define STM32_SRAM_SIZE (64)
#define STM32_SRAM_END (STM32_SRAM_BEGIN + (STM32_SRAM_SIZE * 1024))
#define HEAP_BEGIN STM32_SRAM_BEGIN
#define HEAP_END STM32_SRAM_END
#define HEAP_END STM32_SRAM_END
......
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x00000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x10000000;
define symbol __ICFEDIT_region_ROM_end__ = 0x1003FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x10040000;
define symbol __ICFEDIT_region_RAM_end__ = 0x1005FFFF;
define symbol __ICFEDIT_region_text_start__ = 0x10000000;
define symbol __ICFEDIT_region_text_end__ = 0x1001FFFF;
define symbol __ICFEDIT_region_data_start__ = 0x10030000;
define symbol __ICFEDIT_region_data_end__ = 0x1003FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x400;
define symbol __ICFEDIT_size_heap__ = 0x000;
/**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G;
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
define region text_region = mem:[from __ICFEDIT_region_text_start__ to __ICFEDIT_region_text_end__];
define region data_region = mem:[from __ICFEDIT_region_data_start__ to __ICFEDIT_region_data_end__];
keep { section .resource_table };
".resource_table" : place in data_region {section .resource_table};
/* Create region for OPENAMP */
/* !!! These 4 lines can be commented if OPENAMP is not used !!!*/
define symbol __OPENAMP_region_start__ = 0x10040000;
define symbol __OPENAMP_region_size__ = 0x8000;
export symbol __OPENAMP_region_start__;
export symbol __OPENAMP_region_size__;
define symbol __SDMMC_region_start__ = 0x10048000;
define symbol __SDMMC_region_size__ = 0x1FFFF;
export symbol __SDMMC_region_start__;
export symbol __SDMMC_region_size__;
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
initialize by copy { readwrite };
do not initialize { section .noinit };
do not initialize { section .noinit};
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in ROM_region { readonly };
place in RAM_region { readwrite, last block CSTACK};
place in text_region { readonly };
place in data_region { readwrite,
block CSTACK, block HEAP};
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-06-24 thread-liu first version
*/
#include <board.h>
#ifdef BSP_USING_OPENAMP
#include <drv_openamp.h>
#include <openamp.h>
#include <virt_uart.h>
#include <openamp/rpmsg_virtio.h>
//#define DRV_DEBUG
#define LOG_TAG "drv.openamp"
#include <drv_log.h>
IPCC_HandleTypeDef hipcc;
static VIRT_UART_HandleTypeDef huart0;
static rt_uint8_t rx_buffer[MAX_BUFFER_SIZE];
static rt_uint8_t tx_buffer[MAX_BUFFER_SIZE];
struct rthw_openamp
{
struct rt_device parent;
struct rt_openamp serial;
struct rt_semaphore sema;
};
static struct rthw_openamp dev_openamp;
void IPCC_RX1_IRQHandler(void)
{
rt_interrupt_enter();
HAL_IPCC_RX_IRQHandler(&hipcc);
rt_interrupt_leave();
}
void IPCC_TX1_IRQHandler(void)
{
rt_interrupt_enter();
HAL_IPCC_TX_IRQHandler(&hipcc);
rt_interrupt_leave();
}
void VIRT_UART0_RxCpltCallback(VIRT_UART_HandleTypeDef *huart)
{
rt_uint16_t rx_size = 0, i = 0;
rt_size_t count, size, offset;
rt_uint8_t *buf = RT_NULL;
struct rthw_openamp *device;
device = (struct rthw_openamp *)rt_device_find("openamp");
RT_ASSERT(device != RT_NULL);
buf = device->serial.rbuf;
count = device->serial.rbuf_count;
size = device->serial.rbuf_size;
offset = device->serial.rbuf_start + count;
rt_sem_take(&device->sema, RT_WAITING_FOREVER);
rx_size = (huart->RxXferSize < MAX_BUFFER_SIZE) ? huart->RxXferSize : MAX_BUFFER_SIZE - 1;
if (count < size)
{
if (offset >= size)
{
offset -= size;
}
for (i = 0; i < rx_size; i++)
{
buf[offset++] = huart->pRxBuffPtr[i];
count++;
}
}
device->serial.rbuf_count = count;
rt_sem_release(&device->sema);
}
static rt_err_t _init(struct rt_device *dev)
{
struct rthw_openamp *device;
device = (struct rthw_openamp *)dev;
RT_ASSERT(device != RT_NULL);
device->serial.rbuf_start = 0;
device->serial.rbuf_count = 0;
device->serial.tbuf_start = 0;
device->serial.tbuf_count = 0;
device->serial.rbuf_size = MAX_BUFFER_SIZE;
device->serial.tbuf_size = MAX_BUFFER_SIZE;
device->serial.rbuf = rx_buffer;
device->serial.tbuf = tx_buffer;
if (rt_sem_init(&device->sema, "openamplock", 1, RT_IPC_FLAG_FIFO) != RT_EOK)
{
return RT_ERROR;
}
return RT_EOK;
}
static rt_size_t _read(struct rt_device *dev, rt_off_t pos, void *buffer, rt_size_t size)
{
rt_size_t count, rbsize, offset;
rt_uint8_t *buf = RT_NULL;
rt_uint8_t *pBuffer = RT_NULL;
rt_uint16_t i = 0;
struct rthw_openamp *device;
device = (struct rthw_openamp *)dev;
RT_ASSERT(device != RT_NULL);
pBuffer = (unsigned char*)buffer;
count = device->serial.rbuf_count;
buf = device->serial.rbuf;
if (count == 0)
{
return -RT_ERROR;
}
rt_sem_take(&device->sema, RT_WAITING_FOREVER);
if (count >= size)
{
count = size;
}
offset = device->serial.rbuf_start;
rbsize = device->serial.rbuf_size;
for (i = 0; i < count; i++)
{
*pBuffer++ = buf[offset++];
if (offset > rbsize)
{
offset = 0;
}
}
device->serial.rbuf_start = offset;
device->serial.rbuf_count -= count;
rt_sem_release(&device->sema);
return count;
}
static rt_size_t _write(struct rt_device *dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
rt_err_t result = VIRT_UART_OK;
struct rthw_openamp *device;
device = (struct rthw_openamp *)dev;
RT_ASSERT(device != RT_NULL);
rt_sem_take(&device->sema, RT_WAITING_FOREVER);
result = VIRT_UART_Transmit(&huart0, (uint8_t *)buffer, size);
rt_sem_release(&device->sema);
if (result != VIRT_UART_OK)
{
return -RT_ERROR;
}
return size;
}
static rt_err_t rt_hw_openamp_register(struct rthw_openamp *openamp, const char *name, rt_uint32_t flag, void *data)
{
struct rt_device *device;
RT_ASSERT(openamp != RT_NULL);
device = &(openamp->parent);
device->type = RT_Device_Class_Char;
device->rx_indicate = RT_NULL;
device->tx_complete = RT_NULL;
device->init = _init;
device->open = RT_NULL;
device->close = RT_NULL;
device->read = _read;
device->write = _write;
device->control = RT_NULL;
device->user_data = data;
/* register a character device */
return rt_device_register(device, name, flag);
}
static int openamp_init(void)
{
extern int MX_OPENAMP_Init(int RPMsgRole, rpmsg_ns_bind_cb ns_bind_cb);
/* IPCC init */
hipcc.Instance = IPCC;
if (HAL_IPCC_Init(&hipcc) != HAL_OK)
{
return RT_ERROR;
}
/* openamp slave device */
MX_OPENAMP_Init(RPMSG_REMOTE, NULL);
if (VIRT_UART_Init(&huart0) != VIRT_UART_OK)
{
return RT_ERROR;
}
if (VIRT_UART_RegisterCallback(&huart0, VIRT_UART_RXCPLT_CB_ID, VIRT_UART0_RxCpltCallback) != VIRT_UART_OK)
{
return RT_ERROR;
}
return RT_EOK;
}
int rt_hw_openamp_init(void)
{
openamp_init();
rt_hw_openamp_register(&dev_openamp, "openamp", 0, NULL);
rt_console_set_device("openamp");
return RT_EOK;
}
INIT_PREV_EXPORT(rt_hw_openamp_init);
static void openamp_thread_entry(void *parameter)
{
rt_size_t size = 0;
struct rthw_openamp *device = RT_NULL;
device = (struct rthw_openamp *)rt_device_find("openamp");
RT_ASSERT(device != RT_NULL);
for (;;)
{
OPENAMP_check_for_message();
size = device->serial.rbuf_count;
if (size > 0)
{
if (device->parent.rx_indicate != RT_NULL)
{
device->parent.rx_indicate(&device->parent, size);
}
}
rt_thread_mdelay(1);
}
}
static int creat_openamp_thread(void)
{
rt_thread_t tid = RT_NULL;
tid = rt_thread_create("OpenAMP",
openamp_thread_entry,
RT_NULL,
OPENAMP_THREAD_STACK_SIZE,
OPENAMP_THREAD_PRIORITY,
OPENAMP_THREAD_TIMESLICE);
if (tid == RT_NULL)
{
LOG_E("openamp thread create failed!");
return RT_ERROR;
}
rt_thread_startup(tid);
return RT_EOK;
}
INIT_APP_EXPORT(creat_openamp_thread);
#endif
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2020-06-24 thread-liu first version
*/
#ifndef __DRV_OPENAMP_H__
#define __DRV_OPENAMP_H__
#include "board.h"
#ifdef __cplusplus
extern "C" {
#endif
struct rt_openamp
{
rt_uint8_t *rbuf;
rt_uint8_t *tbuf;
volatile rt_uint16_t rbuf_size;
volatile rt_uint16_t tbuf_size;
volatile rt_uint16_t rbuf_start;
volatile rt_uint16_t rbuf_count;
volatile rt_uint16_t tbuf_start;
volatile rt_uint16_t tbuf_count;
};
#define OPENAMP_THREAD_STACK_SIZE 512
#define OPENAMP_THREAD_PRIORITY 5
#define OPENAMP_THREAD_TIMESLICE 10
#define MAX_BUFFER_SIZE 256
#ifdef __cplusplus
}
#endif
#endif
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <metal/errno.h>
#include <string.h>
#include <metal/device.h>
#include <metal/log.h>
#include <metal/dma.h>
#include <metal/atomic.h>
int metal_dma_map(struct metal_device *dev,
uint32_t dir,
struct metal_sg *sg_in,
int nents_in,
struct metal_sg *sg_out)
{
int nents_out;
if (!dev || !sg_in || !sg_out)
return -EINVAL;
if (!dev->bus->ops.dev_dma_map)
return -ENODEV;
/* memory barrier */
if (dir == METAL_DMA_DEV_R)
/* If it is device read, apply memory write fence. */
atomic_thread_fence(memory_order_release);
else
/* If it is device write or device r/w,
apply memory r/w fence. */
atomic_thread_fence(memory_order_acq_rel);
nents_out = dev->bus->ops.dev_dma_map(dev->bus,
dev, dir, sg_in, nents_in, sg_out);
return nents_out;
}
void metal_dma_unmap(struct metal_device *dev,
uint32_t dir,
struct metal_sg *sg,
int nents)
{
/* memory barrier */
if (dir == METAL_DMA_DEV_R)
/* If it is device read, apply memory write fence. */
atomic_thread_fence(memory_order_release);
else
/* If it is device write or device r/w,
apply memory r/w fence. */
atomic_thread_fence(memory_order_acq_rel);
if (!dev || !dev->bus->ops.dev_dma_unmap || !sg)
return;
dev->bus->ops.dev_dma_unmap(dev->bus,
dev, dir, sg, nents);
}
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file alloc.h
* @brief Memory allocation handling primitives for libmetal.
*/
#ifndef __METAL_ALLOC__H__
#define __METAL_ALLOC__H__
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup Memory Allocation Interfaces
* @{ */
/**
* @brief allocate requested memory size
* return a pointer to the allocated memory
*
* @param[in] size size in byte of requested memory
* @return memory pointer, or 0 if it failed to allocate
*/
static inline void *metal_allocate_memory(unsigned int size);
/**
* @brief free the memory previously allocated
*
* @param[in] ptr pointer to memory
*/
static inline void metal_free_memory(void *ptr);
#include <metal/system/generic/alloc.h>
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* __METAL_ALLOC__H__ */
/*
* Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file assert.h
* @brief Assertion support.
*/
#ifndef __METAL_ASSERT__H__
#define __METAL_ASSERT__H__
#include <metal/system/generic/assert.h>
/**
* @brief Assertion macro.
* @param cond Condition to test.
*/
#define metal_assert(cond) metal_sys_assert(cond)
#endif /* __METAL_ASSERT_H__ */
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file atomic.h
* @brief Atomic primitives for libmetal.
*/
#ifndef __METAL_ATOMIC__H__
#define __METAL_ATOMIC__H__
#include <metal/config.h>
#if defined(HAVE_STDATOMIC_H) && !defined (__CC_ARM) && \
!defined(__STDC_NO_ATOMICS__) && !defined(__cplusplus)
# include <stdatomic.h>
#ifndef atomic_thread_fence
#define atomic_thread_fence(order)
#endif
#elif defined(__GNUC__)
# include <metal/compiler/gcc/atomic.h>
#else
# include <metal/processor/arm/atomic.h>
#endif
#endif /* __METAL_ATOMIC__H__ */
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file cache.h
* @brief CACHE operation primitives for libmetal.
*/
#ifndef __METAL_CACHE__H__
#define __METAL_CACHE__H__
#include <metal/system/generic/cache.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup cache CACHE Interfaces
* @{ */
/**
* @brief flush specified data cache
*
* @param[in] addr start memory logical address
* @param[in] len length of memory
* If addr is NULL, and len is 0,
* It will flush the whole data cache.
*/
static inline void metal_cache_flush(void *addr, unsigned int len)
{
__metal_cache_flush(addr, len);
}
/**
* @brief invalidate specified data cache
*
* @param[in] addr start memory logical address
* @param[in] len length of memory
* If addr is NULL, and len is 0,
* It will invalidate the whole data cache.
*/
static inline void metal_cache_invalidate(void *addr, unsigned int len)
{
__metal_cache_invalidate(addr, len);
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* __METAL_CACHE__H__ */
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file compiler.h
* @brief Compiler specific primitives for libmetal.
*/
#ifndef __METAL_COMPILER__H__
#define __METAL_COMPILER__H__
#if defined(__GNUC__)
# include <metal/compiler/gcc/compiler.h>
#elif defined(__ICCARM__)
# include <metal/compiler/iar/compiler.h>
#elif defined (__CC_ARM)
# error "MDK-ARM ARMCC compiler requires the GNU extentions to work correctly"
#else
# error "Missing compiler support"
#endif
#endif /* __METAL_COMPILER__H__ */
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file gcc/atomic.h
* @brief GCC specific atomic primitives for libmetal.
*/
#ifndef __METAL_GCC_ATOMIC__H__
#define __METAL_GCC_ATOMIC__H__
#ifdef __cplusplus
extern "C" {
#endif
typedef int atomic_flag;
typedef char atomic_char;
typedef unsigned char atomic_uchar;
typedef short atomic_short;
typedef unsigned short atomic_ushort;
typedef int atomic_int;
typedef unsigned int atomic_uint;
typedef long atomic_long;
typedef unsigned long atomic_ulong;
typedef long long atomic_llong;
typedef unsigned long long atomic_ullong;
#define ATOMIC_FLAG_INIT 0
#define ATOMIC_VAR_INIT(VAL) (VAL)
typedef enum {
memory_order_relaxed,
memory_order_consume,
memory_order_acquire,
memory_order_release,
memory_order_acq_rel,
memory_order_seq_cst,
} memory_order;
#define atomic_flag_test_and_set(FLAG) \
__sync_lock_test_and_set((FLAG), 1)
#define atomic_flag_test_and_set_explicit(FLAG, MO) \
atomic_flag_test_and_set(FLAG)
#define atomic_flag_clear(FLAG) \
__sync_lock_release((FLAG))
#define atomic_flag_clear_explicit(FLAG, MO) \
atomic_flag_clear(FLAG)
#define atomic_init(OBJ, VAL) \
do { *(OBJ) = (VAL); } while (0)
#define atomic_is_lock_free(OBJ) \
(sizeof(*(OBJ)) <= sizeof(long))
#define atomic_store(OBJ, VAL) \
do { *(OBJ) = (VAL); __sync_synchronize(); } while (0)
#define atomic_store_explicit(OBJ, VAL, MO) \
atomic_store((OBJ), (VAL))
#define atomic_load(OBJ) \
({ __sync_synchronize(); *(OBJ); })
#define atomic_load_explicit(OBJ, MO) \
atomic_load(OBJ)
#define atomic_exchange(OBJ, DES) \
({ \
typeof(OBJ) obj = (OBJ); \
typeof(*obj) des = (DES); \
typeof(*obj) expval; \
typeof(*obj) oldval = atomic_load(obj); \
do { \
expval = oldval; \
oldval = __sync_val_compare_and_swap( \
obj, expval, des); \
} while (oldval != expval); \
oldval; \
})
#define atomic_exchange_explicit(OBJ, DES, MO) \
atomic_exchange((OBJ), (DES))
#define atomic_compare_exchange_strong(OBJ, EXP, DES) \
({ \
typeof(OBJ) obj = (OBJ); \
typeof(EXP) exp = (EXP); \
typeof(*obj) expval = *exp; \
typeof(*obj) oldval = __sync_val_compare_and_swap( \
obj, expval, (DES)); \
*exp = oldval; \
oldval == expval; \
})
#define atomic_compare_exchange_strong_explicit(OBJ, EXP, DES, MO) \
atomic_compare_exchange_strong((OBJ), (EXP), (DES))
#define atomic_compare_exchange_weak(OBJ, EXP, DES) \
atomic_compare_exchange_strong((OBJ), (EXP), (DES))
#define atomic_compare_exchange_weak_explicit(OBJ, EXP, DES, MO) \
atomic_compare_exchange_weak((OBJ), (EXP), (DES))
#define atomic_fetch_add(OBJ, VAL) \
__sync_fetch_and_add((OBJ), (VAL))
#define atomic_fetch_add_explicit(OBJ, VAL, MO) \
atomic_fetch_add((OBJ), (VAL))
#define atomic_fetch_sub(OBJ, VAL) \
__sync_fetch_and_sub((OBJ), (VAL))
#define atomic_fetch_sub_explicit(OBJ, VAL, MO) \
atomic_fetch_sub((OBJ), (VAL))
#define atomic_fetch_or(OBJ, VAL) \
__sync_fetch_and_or((OBJ), (VAL))
#define atomic_fetch_or_explicit(OBJ, VAL, MO) \
atomic_fetch_or((OBJ), (VAL))
#define atomic_fetch_xor(OBJ, VAL) \
__sync_fetch_and_xor((OBJ), (VAL))
#define atomic_fetch_xor_explicit(OBJ, VAL, MO) \
atomic_fetch_xor((OBJ), (VAL))
#define atomic_fetch_and(OBJ, VAL) \
__sync_fetch_and_and((OBJ), (VAL))
#define atomic_fetch_and_explicit(OBJ, VAL, MO) \
atomic_fetch_and((OBJ), (VAL))
#define atomic_thread_fence(MO) \
__sync_synchronize()
#define atomic_signal_fence(MO) \
__sync_synchronize()
#ifdef __cplusplus
}
#endif
#endif /* __METAL_GCC_ATOMIC__H__ */
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file gcc/compiler.h
* @brief GCC specific primitives for libmetal.
*/
#ifndef __METAL_GCC_COMPILER__H__
#define __METAL_GCC_COMPILER__H__
#ifdef __cplusplus
extern "C" {
#endif
#define restrict __restrict__
#define metal_align(n) __attribute__((aligned(n)))
#define metal_weak __attribute__((weak))
#ifdef __cplusplus
}
#endif
#endif /* __METAL_GCC_COMPILER__H__ */
/*
* Copyright (c) 2018, ST Microelectronics. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file iar/compiler.h
* @brief IAR specific primitives for libmetal.
*/
#ifndef __METAL_IAR_COMPILER__H__
#define __METAL_IAR_COMPILER__H__
#ifdef __cplusplus
extern "C" {
#endif
#define restrict __restrict__
#define metal_align(n) __attribute__((aligned(n)))
#define metal_weak __attribute__((weak))
#ifdef __cplusplus
}
#endif
#endif /* __METAL_IAR_COMPILER__H__ */
/*
* * Copyright (c) 2019 STMicroelectronics. All rights reserved.
* *
* * Copyright (c) 1982, 1986, 1989, 1993
* * The Regents of the University of California. All rights reserved.
* * Copyright (c) 1982, 1986, 1989, 1993
* * The Regents of the University of California. All rights reserved.
* * (c) UNIX System Laboratories, Inc.
* * All or some portions of this file are derived from material licensed
* * to the University of California by American Telephone and Telegraph
* * Co. or Unix System Laboratories, Inc. and are reproduced herein with
* * the permission of UNIX System Laboratories, Inc.
*
* * SPDX-License-Identifier: BSD-3-Clause
* */
#ifndef __METAL_ERRNO__H__
#error "Include metal/errno.h instead of metal/iar/errno.h"
#endif
#ifndef _ERRNO_H_
#ifdef __cplusplus
extern "C" {
#endif
#define _ERRNO_H_
#ifndef EPERM
#define EPERM 1 /* Not owner */
#endif
#ifndef ENOENT
#define ENOENT 2 /* No such file or directory */
#endif
#ifndef ESRCH
#define ESRCH 3 /* No such process */
#endif
#ifndef EINTR
#define EINTR 4 /* Interrupted system call */
#endif
#ifndef EIO
#define EIO 5 /* I/O error */
#endif
#ifndef ENXIO
#define ENXIO 6 /* No such device or address */
#endif
#ifndef E2BIG
#define E2BIG 7 /* Arg list too long */
#endif
#ifndef ENOEXEC
#define ENOEXEC 8 /* Exec format error */
#endif
#ifndef EBADF
#define EBADF 9 /* Bad file number */
#endif
#ifndef ECHILD
#define ECHILD 10 /* No children */
#endif
#ifndef EAGAIN
#define EAGAIN 11 /* No more processes */
#endif
#ifndef ENOMEM
#define ENOMEM 12 /* Not enough space */
#endif
#ifndef EACCES
#define EACCES 13 /* Permission denied */
#endif
#ifndef EFAULT
#define EFAULT 14 /* Bad address */
#endif
#ifndef EBUSY
#define EBUSY 16 /* Device or resource busy */
#endif
#ifndef EEXIST
#define EEXIST 17 /* File exists */
#endif
#ifndef EXDEV
#define EXDEV 18 /* Cross-device link */
#endif
#ifndef ENODEV
#define ENODEV 19 /* No such device */
#endif
#ifndef ENOTDIR
#define ENOTDIR 20 /* Not a directory */
#endif
#ifndef EISDIR
#define EISDIR 21 /* Is a directory */
#endif
#ifndef EINVAL
#define EINVAL 22 /* Invalid argument */
#endif
#ifndef ENFILE
#define ENFILE 23 /* Too many open files in system */
#endif
#ifndef EMFILE
#define EMFILE 24 /* File descriptor value too large */
#endif
#ifndef ENOTTY
#define ENOTTY 25 /* Not a character device */
#endif
#ifndef ETXTBSY
#define ETXTBSY 26 /* Text file busy */
#endif
#ifndef EFBIG
#define EFBIG 27 /* File too large */
#endif
#ifndef ENOSPC
#define ENOSPC 28 /* No space left on device */
#endif
#ifndef ESPIPE
#define ESPIPE 29 /* Illegal seek */
#endif
#ifndef EROFS
#define EROFS 30 /* Read-only file system */
#endif
#ifndef EMLINK
#define EMLINK 31 /* Too many links */
#endif
#ifndef EPIPE
#define EPIPE 32 /* Broken pipe */
#endif
#ifndef EDOM
#define EDOM 33 /* Mathematics argument out of domain of function */
#endif
#ifndef ERANGE
#define ERANGE 34 /* Result too large */
#endif
#ifndef ENOMSG
#define ENOMSG 35 /* No message of desired type */
#endif
#ifndef EIDRM
#define EIDRM 36 /* Identifier removed */
#endif
#ifndef EDEADLK
#define EDEADLK 45 /* Deadlock */
#endif
#ifndef ENOLCK
#define ENOLCK 46 /* No lock */
#endif
#ifndef ENOSTR
#define ENOSTR 60 /* Not a stream */
#endif
#ifndef ENODATA
#define ENODATA 61 /* No data (for no delay io) */
#endif
#ifndef ETIME
#define ETIME 62 /* Stream ioctl timeout */
#endif
#ifndef ENOSR
#define ENOSR 63 /* No stream resources */
#endif
#ifndef ENOLINK
#define ENOLINK 67 /* Virtual circuit is gone */
#endif
#ifndef EPROTO
#define EPROTO 71 /* Protocol error */
#endif
#ifndef EMULTIHOP
#define EMULTIHOP 74 /* Multihop attempted */
#endif
#ifndef EBADMSG
#define EBADMSG 77 /* Bad message */
#endif
#ifndef EFTYPE
#define EFTYPE 79 /* Inappropriate file type or format */
#endif
#ifndef ENOSYS
#define ENOSYS 88 /* Function not implemented */
#endif
#ifndef ENOTEMPTY
#define ENOTEMPTY 90 /* Directory not empty */
#endif
#ifndef ENAMETOOLONG
#define ENAMETOOLONG 91 /* File or path name too long */
#endif
#ifndef ELOOP
#define ELOOP 92 /* Too many symbolic links */
#endif
#ifndef EOPNOTSUPP
#define EOPNOTSUPP 95 /* Operation not supported on socket */
#endif
#ifndef EPFNOSUPPORT
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#endif
#ifndef ECONNRESET
#define ECONNRESET 104 /* Connection reset by peer */
#endif
#ifndef ENOBUFS
#define ENOBUFS 105 /* No buffer space available */
#endif
#ifndef EAFNOSUPPORT
#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */
#endif
#ifndef EPROTOTYPE
#define EPROTOTYPE 107 /* Protocol wrong type for socket */
#endif
#ifndef ENOTSOCK
#define ENOTSOCK 108 /* Socket operation on non-socket */
#endif
#ifndef ENOPROTOOPT
#define ENOPROTOOPT 109 /* Protocol not available */
#endif
#ifndef ECONNREFUSED
#define ECONNREFUSED 111 /* Connection refused */
#endif
#ifndef EADDRINUSE
#define EADDRINUSE 112 /* Address already in use */
#endif
#ifndef ECONNABORTED
#define ECONNABORTED 113 /* Software caused connection abort */
#endif
#ifndef ENETUNREACH
#define ENETUNREACH 114 /* Network is unreachable */
#endif
#ifndef ENETDOWN
#define ENETDOWN 115 /* Network interface is not configured */
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT 116 /* Connection timed out */
#endif
#ifndef EHOSTDOWN
#define EHOSTDOWN 117 /* Host is down */
#endif
#ifndef EHOSTUNREACH
#define EHOSTUNREACH 118 /* Host is unreachable */
#endif
#ifndef EINPROGRESS
#define EINPROGRESS 119 /* Connection already in progress */
#endif
#ifndef EALREADY
#define EALREADY 120 /* Socket already connected */
#endif
#ifndef EDESTADDRREQ
#define EDESTADDRREQ 121 /* Destination address required */
#endif
#ifndef EMSGSIZE
#define EMSGSIZE 122 /* Message too long */
#endif
#ifndef EPROTONOSUPPORT
#define EPROTONOSUPPORT 123 /* Unknown protocol */
#endif
#ifndef EADDRNOTAVAIL
#define EADDRNOTAVAIL 125 /* Address not available */
#endif
#ifndef ENETRESET
#define ENETRESET 126 /* Connection aborted by network */
#endif
#ifndef EISCONN
#define EISCONN 127 /* Socket is already connected */
#endif
#ifndef ENOTCONN
#define ENOTCONN 128 /* Socket is not connected */
#endif
#ifndef ETOOMANYREFS
#define ETOOMANYREFS 129
#endif
#ifndef EDQUOT
#define EDQUOT 132
#endif
#ifndef ESTALE
#define ESTALE 133
#endif
#ifndef ENOTSUP
#define ENOTSUP 134 /* Not supported */
#endif
#ifndef EILSEQ
#define EILSEQ 138 /* Illegal byte sequence */
#endif
#ifndef EOVERFLOW
#define EOVERFLOW 139 /* Value too large for defined data type */
#endif
#ifndef ECANCELED
#define ECANCELED 140 /* Operation canceled */
#endif
#ifndef ENOTRECOVERABLE
#define ENOTRECOVERABLE 141 /* State not recoverable */
#endif
#ifndef EOWNERDEAD
#define EOWNERDEAD 142 /* Previous owner died */
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN /* Operation would block */
#endif
#define __ELASTERROR 2000 /* Users can add values starting here */
#ifdef __cplusplus
}
#endif
#endif /* _ERRNO_H */
/*
* * Copyright (c) 2019 STMicroelectronics. All rights reserved.
* *
* * Copyright (c) 1982, 1986, 1989, 1993
* * The Regents of the University of California. All rights reserved.
* * Copyright (c) 1982, 1986, 1989, 1993
* * The Regents of the University of California. All rights reserved.
* * (c) UNIX System Laboratories, Inc.
* * All or some portions of this file are derived from material licensed
* * to the University of California by American Telephone and Telegraph
* * Co. or Unix System Laboratories, Inc. and are reproduced herein with
* * the permission of UNIX System Laboratories, Inc.
*
* * SPDX-License-Identifier: BSD-3-Clause
* */
#ifndef __METAL_ERRNO__H__
#error "Include metal/errno.h instead of metal/mdk-arm/errno.h"
#endif
#ifndef _ERRNO_H_
#ifdef __cplusplus
extern "C" {
#endif
#define _ERRNO_H_
#define EPERM 1 /* Not owner */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Arg list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No children */
#define EAGAIN 11 /* No more processes */
#ifdef ENOMEM
#undef ENOMEM
#endif
#define ENOMEM 12 /* Not enough space */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#ifdef EINVAL
#undef EINVAL
#endif
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* Too many open files in system */
#define EMFILE 24 /* File descriptor value too large */
#define ENOTTY 25 /* Not a character device */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#ifdef EDOM
#undef EDOM
#endif
#define EDOM 33 /* Mathematics argument out of domain of function */
#ifdef ERANGE
#undef ERANGE
#endif
#define ERANGE 34 /* Result too large */
#define ENOMSG 35 /* No message of desired type */
#define EIDRM 36 /* Identifier removed */
#define EDEADLK 45 /* Deadlock */
#define ENOLCK 46 /* No lock */
#define ENOSTR 60 /* Not a stream */
#define ENODATA 61 /* No data (for no delay io) */
#define ETIME 62 /* Stream ioctl timeout */
#define ENOSR 63 /* No stream resources */
#define ENOLINK 67 /* Virtual circuit is gone */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 74 /* Multihop attempted */
#define EBADMSG 77 /* Bad message */
#define EFTYPE 79 /* Inappropriate file type or format */
#define ENOSYS 88 /* Function not implemented */
#define ENOTEMPTY 90 /* Directory not empty */
#define ENAMETOOLONG 91 /* File or path name too long */
#define ELOOP 92 /* Too many symbolic links */
#define EOPNOTSUPP 95 /* Operation not supported on socket */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EAFNOSUPPORT 106 /* Address family not supported by protocol family */
#define EPROTOTYPE 107 /* Protocol wrong type for socket */
#define ENOTSOCK 108 /* Socket operation on non-socket */
#define ENOPROTOOPT 109 /* Protocol not available */
#define ECONNREFUSED 111 /* Connection refused */
#define EADDRINUSE 112 /* Address already in use */
#define ECONNABORTED 113 /* Software caused connection abort */
#define ENETUNREACH 114 /* Network is unreachable */
#define ENETDOWN 115 /* Network interface is not configured */
#define ETIMEDOUT 116 /* Connection timed out */
#define EHOSTDOWN 117 /* Host is down */
#define EHOSTUNREACH 118 /* Host is unreachable */
#define EINPROGRESS 119 /* Connection already in progress */
#define EALREADY 120 /* Socket already connected */
#define EDESTADDRREQ 121 /* Destination address required */
#define EMSGSIZE 122 /* Message too long */
#define EPROTONOSUPPORT 123 /* Unknown protocol */
#define EADDRNOTAVAIL 125 /* Address not available */
#define ENETRESET 126 /* Connection aborted by network */
#define EISCONN 127 /* Socket is already connected */
#define ENOTCONN 128 /* Socket is not connected */
#define ETOOMANYREFS 129
#define EDQUOT 132
#define ESTALE 133
#define ENOTSUP 134 /* Not supported */
#ifdef EILSEQ
#undef EILSEQ
#endif
#define EILSEQ 138 /* Illegal byte sequence */
#define EOVERFLOW 139 /* Value too large for defined data type */
#define ECANCELED 140 /* Operation canceled */
#define ENOTRECOVERABLE 141 /* State not recoverable */
#define EOWNERDEAD 142 /* Previous owner died */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define __ELASTERROR 2000 /* Users can add values starting here */
#ifdef __cplusplus
}
#endif
#endif /* _ERRNO_H */
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file condition.h
* @brief Condition variable for libmetal.
*/
#ifndef __METAL_CONDITION__H__
#define __METAL_CONDITION__H__
#include <metal/mutex.h>
#include <metal/utilities.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup condition Condition Variable Interfaces
* @{ */
/** Opaque libmetal condition variable data structure. */
struct metal_condition;
/**
* @brief Initialize a libmetal condition variable.
* @param[in] cv condition variable to initialize.
*/
static inline void metal_condition_init(struct metal_condition *cv);
/**
* @brief Notify one waiter.
* Before calling this function, the caller
* should have acquired the mutex.
* @param[in] cv condition variable
* @return zero on no errors, non-zero on errors
* @see metal_condition_wait, metal_condition_broadcast
*/
static inline int metal_condition_signal(struct metal_condition *cv);
/**
* @brief Notify all waiters.
* Before calling this function, the caller
* should have acquired the mutex.
* @param[in] cv condition variable
* @return zero on no errors, non-zero on errors
* @see metal_condition_wait, metal_condition_signal
*/
static inline int metal_condition_broadcast(struct metal_condition *cv);
/**
* @brief Block until the condition variable is notified.
* Before calling this function, the caller should
* have acquired the mutex.
* @param[in] cv condition variable
* @param[in] m mutex
* @return 0 on success, non-zero on failure.
* @see metal_condition_signal
*/
int metal_condition_wait(struct metal_condition *cv, metal_mutex_t *m);
#include <metal/system/generic/condition.h>
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* __METAL_CONDITION__H__ */
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file config.h
* @brief Generated configuration settings for libmetal.
*/
#ifndef __METAL_CONFIG__H__
#define __METAL_CONFIG__H__
#ifdef __cplusplus
extern "C" {
#endif
/** Library major version number. */
#define METAL_VER_MAJOR 0
/** Library minor version number. */
#define METAL_VER_MINOR 1
/** Library patch level. */
#define METAL_VER_PATCH 0
/** Library version string. */
#define METAL_VER "0.1.0"
/** System type (linux, generic, ...). */
#define METAL_SYSTEM "generic"
#define METAL_SYSTEM_GENERIC
/** Processor type (arm, x86_64, ...). */
#define METAL_PROCESSOR "arm"
#define METAL_PROCESSOR_ARM
/** Machine type (zynq, zynqmp, ...). */
#define METAL_MACHINE "cortexm"
#define METAL_MACHINE_CORTEXM
#define HAVE_STDATOMIC_H
/* #undef HAVE_FUTEX_H */
#ifdef __cplusplus
}
#endif
#endif /* __METAL_CONFIG__H__ */
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file cpu.h
* @brief CPU primitives for libmetal.
*/
#ifndef __METAL_CPU__H__
#define __METAL_CPU__H__
# include <metal/processor/arm/cpu.h>
#endif /* __METAL_CPU__H__ */
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file device.h
* @brief Bus abstraction for libmetal.
*/
#ifndef __METAL_BUS__H__
#define __METAL_BUS__H__
#include <stdint.h>
#include <metal/io.h>
#include <metal/list.h>
#include <metal/dma.h>
#include <metal/sys.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup device Bus Abstraction
* @{ */
#ifndef METAL_MAX_DEVICE_REGIONS
#define METAL_MAX_DEVICE_REGIONS 32
#endif
struct metal_bus;
struct metal_device;
/** Bus operations. */
struct metal_bus_ops {
void (*bus_close)(struct metal_bus *bus);
int (*dev_open)(struct metal_bus *bus,
const char *dev_name,
struct metal_device **device);
void (*dev_close)(struct metal_bus *bus,
struct metal_device *device);
void (*dev_irq_ack)(struct metal_bus *bus,
struct metal_device *device,
int irq);
int (*dev_dma_map)(struct metal_bus *bus,
struct metal_device *device,
uint32_t dir,
struct metal_sg *sg_in,
int nents_in,
struct metal_sg *sg_out);
void (*dev_dma_unmap)(struct metal_bus *bus,
struct metal_device *device,
uint32_t dir,
struct metal_sg *sg,
int nents);
};
/** Libmetal bus structure. */
struct metal_bus {
const char *name;
struct metal_bus_ops ops;
struct metal_list devices;
struct metal_list node;
};
/** Libmetal generic bus. */
extern struct metal_bus metal_generic_bus;
/** Libmetal device structure. */
struct metal_device {
const char *name; /**< Device name */
struct metal_bus *bus; /**< Bus that contains device */
unsigned num_regions; /**< Number of I/O regions in
device */
struct metal_io_region regions[METAL_MAX_DEVICE_REGIONS]; /**< Array of
I/O regions in device*/
struct metal_list node; /**< Node on bus' list of devices */
int irq_num; /**< Number of IRQs per device */
void *irq_info; /**< IRQ ID */
};
/**
* @brief Register a libmetal bus.
* @param[in] bus Pre-initialized bus structure.
* @return 0 on success, or -errno on failure.
*/
extern int metal_bus_register(struct metal_bus *bus);
/**
* @brief Unregister a libmetal bus.
* @param[in] bus Pre-registered bus structure.
* @return 0 on success, or -errno on failure.
*/
extern int metal_bus_unregister(struct metal_bus *bus);
/**
* @brief Find a libmetal bus by name.
* @param[in] name Bus name.
* @param[out] bus Returned bus handle.
* @return 0 on success, or -errno on failure.
*/
extern int metal_bus_find(const char *name, struct metal_bus **bus);
/**
* @brief Statically register a generic libmetal device.
*
* In non-Linux systems, devices are always required to be statically
* registered at application initialization.
* In Linux system, devices can be dynamically opened via sysfs or libfdt based
* enumeration at runtime.
* This interface is used for static registration of devices. Subsequent calls
* to metal_device_open() look up in this list of pre-registered devices on the
* "generic" bus.
* "generic" bus is used on non-Linux system to group the memory mapped devices.
*
* @param[in] device Generic device.
* @return 0 on success, or -errno on failure.
*/
extern int metal_register_generic_device(struct metal_device *device);
/**
* @brief Open a libmetal device by name.
* @param[in] bus_name Bus name.
* @param[in] dev_name Device name.
* @param[out] device Returned device handle.
* @return 0 on success, or -errno on failure.
*/
extern int metal_device_open(const char *bus_name, const char *dev_name,
struct metal_device **device);
/**
* @brief Close a libmetal device.
* @param[in] device Device handle.
*/
extern void metal_device_close(struct metal_device *device);
/**
* @brief Get an I/O region accessor for a device region.
*
* @param[in] device Device handle.
* @param[in] index Region index.
* @return I/O accessor handle, or NULL on failure.
*/
static inline struct metal_io_region *
metal_device_io_region(struct metal_device *device, unsigned index)
{
return (index < device->num_regions
? &device->regions[index]
: NULL);
}
/** @} */
#ifdef METAL_INTERNAL
extern int metal_generic_dev_sys_open(struct metal_device *dev);
extern int metal_generic_dev_open(struct metal_bus *bus, const char *dev_name,
struct metal_device **device);
extern int metal_generic_dev_dma_map(struct metal_bus *bus,
struct metal_device *device,
uint32_t dir,
struct metal_sg *sg_in,
int nents_in,
struct metal_sg *sg_out);
extern void metal_generic_dev_dma_unmap(struct metal_bus *bus,
struct metal_device *device,
uint32_t dir,
struct metal_sg *sg,
int nents);
#endif /* METAL_INTERNAL */
#ifdef __cplusplus
}
#endif
#endif /* __METAL_BUS__H__ */
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file dma.h
* @brief DMA primitives for libmetal.
*/
#ifndef __METAL_DMA__H__
#define __METAL_DMA__H__
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup dma DMA Interfaces
* @{ */
#include <stdint.h>
#include <metal/sys.h>
#define METAL_DMA_DEV_R 1 /**< DMA direction, device read */
#define METAL_DMA_DEV_W 2 /**< DMA direction, device write */
#define METAL_DMA_DEV_WR 3 /**< DMA direction, device read/write */
/**
* @brief scatter/gather list element structure
*/
struct metal_sg {
void *virt; /**< CPU virtual address */
struct metal_io_region *io; /**< IO region */
int len; /**< length */
};
struct metal_device;
/**
* @brief Map memory for DMA transaction.
* After the memory is DMA mapped, the memory should be
* accessed by the DMA device but not the CPU.
*
* @param[in] dev DMA device
* @param[in] dir DMA direction
* @param[in] sg_in sg list of memory to map
* @param[in] nents_in number of sg list entries of memory to map
* @param[out] sg_out sg list of mapped memory
* @return number of mapped sg entries, -error on failure.
*/
int metal_dma_map(struct metal_device *dev,
uint32_t dir,
struct metal_sg *sg_in,
int nents_in,
struct metal_sg *sg_out);
/**
* @brief Unmap DMA memory
* After the memory is DMA unmapped, the memory should
* be accessed by the CPU but not the DMA device.
*
* @param[in] dev DMA device
* @param[in] dir DMA direction
* @param[in] sg sg list of mapped DMA memory
* @param[in] nents number of sg list entries of DMA memory
*/
void metal_dma_unmap(struct metal_device *dev,
uint32_t dir,
struct metal_sg *sg,
int nents);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* __METAL_DMA__H__ */
/*
* * Copyright (c) 2019 STMicrolectonics , Xilinx Inc. and Contributors. All rights reserved.
* *
* * SPDX-License-Identifier: BSD-3-Clause
* */
/*
* * @file metal/errno.h
* * @brief error specific primitives for libmetal.
* */
#ifndef __METAL_ERRNO__H__
#define __METAL_ERRNO__H__
#if defined (__CC_ARM)
# include <metal/compiler/mdk-arm/errno.h>
#elif defined (__ICCARM__)
# include <metal/compiler/iar/errno.h>
#else
#include <errno.h>
#endif
#endif /* __METAL_ERRNO__H__ */
/*
* Copyright (c) 2015 - 2017, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file io.h
* @brief I/O access primitives for libmetal.
*/
#ifndef __METAL_IO__H__
#define __METAL_IO__H__
#include <limits.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <metal/assert.h>
#include <metal/compiler.h>
#include <metal/atomic.h>
#include <metal/sys.h>
#include <metal/cpu.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup io IO Interfaces
* @{ */
#ifdef __MICROBLAZE__
#define NO_ATOMIC_64_SUPPORT
#endif
struct metal_io_region;
/** Generic I/O operations. */
struct metal_io_ops {
uint64_t (*read)(struct metal_io_region *io,
unsigned long offset,
memory_order order,
int width);
void (*write)(struct metal_io_region *io,
unsigned long offset,
uint64_t value,
memory_order order,
int width);
int (*block_read)(struct metal_io_region *io,
unsigned long offset,
void *restrict dst,
memory_order order,
int len);
int (*block_write)(struct metal_io_region *io,
unsigned long offset,
const void *restrict src,
memory_order order,
int len);
void (*block_set)(struct metal_io_region *io,
unsigned long offset,
unsigned char value,
memory_order order,
int len);
void (*close)(struct metal_io_region *io);
};
/** Libmetal I/O region structure. */
struct metal_io_region {
void *virt; /**< base virtual address */
const metal_phys_addr_t *physmap; /**< table of base physical address
of each of the pages in the I/O
region */
size_t size; /**< size of the I/O region */
unsigned long page_shift; /**< page shift of I/O region */
metal_phys_addr_t page_mask; /**< page mask of I/O region */
unsigned int mem_flags; /**< memory attribute of the
I/O region */
struct metal_io_ops ops; /**< I/O region operations */
};
/**
* @brief Open a libmetal I/O region.
*
* @param[in, out] io I/O region handle.
* @param[in] virt Virtual address of region.
* @param[in] physmap Array of physical addresses per page.
* @param[in] size Size of region.
* @param[in] page_shift Log2 of page size (-1 for single page).
* @param[in] mem_flags Memory flags
* @param[in] ops ops
*/
void
metal_io_init(struct metal_io_region *io, void *virt,
const metal_phys_addr_t *physmap, size_t size,
unsigned page_shift, unsigned int mem_flags,
const struct metal_io_ops *ops);
/**
* @brief Close a libmetal shared memory segment.
* @param[in] io I/O region handle.
*/
static inline void metal_io_finish(struct metal_io_region *io)
{
if (io->ops.close)
(*io->ops.close)(io);
memset(io, 0, sizeof(*io));
}
/**
* @brief Get size of I/O region.
*
* @param[in] io I/O region handle.
* @return Size of I/O region.
*/
static inline size_t metal_io_region_size(struct metal_io_region *io)
{
return io->size;
}
/**
* @brief Get virtual address for a given offset into the I/O region.
* @param[in] io I/O region handle.
* @param[in] offset Offset into shared memory segment.
* @return NULL if offset is out of range, or pointer to offset.
*/
static inline void *
metal_io_virt(struct metal_io_region *io, unsigned long offset)
{
return (io->virt != METAL_BAD_VA && offset <= io->size
? (uint8_t *)io->virt + offset
: NULL);
}
/**
* @brief Convert a virtual address to offset within I/O region.
* @param[in] io I/O region handle.
* @param[in] virt Virtual address within segment.
* @return METAL_BAD_OFFSET if out of range, or offset.
*/
static inline unsigned long
metal_io_virt_to_offset(struct metal_io_region *io, void *virt)
{
size_t offset = (uint8_t *)virt - (uint8_t *)io->virt;
return (offset < io->size ? offset : METAL_BAD_OFFSET);
}
/**
* @brief Get physical address for a given offset into the I/O region.
* @param[in] io I/O region handle.
* @param[in] offset Offset into shared memory segment.
* @return METAL_BAD_PHYS if offset is out of range, or physical address
* of offset.
*/
static inline metal_phys_addr_t
metal_io_phys(struct metal_io_region *io, unsigned long offset)
{
unsigned long page = (io->page_shift >=
sizeof(offset) * CHAR_BIT ?
0 : offset >> io->page_shift);
return (io->physmap != NULL && offset <= io->size
? io->physmap[page] + (offset & io->page_mask)
: METAL_BAD_PHYS);
}
/**
* @brief Convert a physical address to offset within I/O region.
* @param[in] io I/O region handle.
* @param[in] phys Physical address within segment.
* @return METAL_BAD_OFFSET if out of range, or offset.
*/
static inline unsigned long
metal_io_phys_to_offset(struct metal_io_region *io, metal_phys_addr_t phys)
{
unsigned long offset =
(io->page_mask == (metal_phys_addr_t)(-1) ?
phys - io->physmap[0] : phys & io->page_mask);
do {
if (metal_io_phys(io, offset) == phys)
return offset;
offset += io->page_mask + 1;
} while (offset < io->size);
return METAL_BAD_OFFSET;
}
/**
* @brief Convert a physical address to virtual address.
* @param[in] io Shared memory segment handle.
* @param[in] phys Physical address within segment.
* @return NULL if out of range, or corresponding virtual address.
*/
static inline void *
metal_io_phys_to_virt(struct metal_io_region *io, metal_phys_addr_t phys)
{
return metal_io_virt(io, metal_io_phys_to_offset(io, phys));
}
/**
* @brief Convert a virtual address to physical address.
* @param[in] io Shared memory segment handle.
* @param[in] virt Virtual address within segment.
* @return METAL_BAD_PHYS if out of range, or corresponding
* physical address.
*/
static inline metal_phys_addr_t
metal_io_virt_to_phys(struct metal_io_region *io, void *virt)
{
return metal_io_phys(io, metal_io_virt_to_offset(io, virt));
}
/**
* @brief Read a value from an I/O region.
* @param[in] io I/O region handle.
* @param[in] offset Offset into I/O region.
* @param[in] order Memory ordering.
* @param[in] width Width in bytes of datatype to read. This must be 1, 2,
* 4, or 8, and a compile time constant for this function
* to inline cleanly.
* @return Value.
*/
static inline uint64_t
metal_io_read(struct metal_io_region *io, unsigned long offset,
memory_order order, int width)
{
void *ptr = metal_io_virt(io, offset);
if (io->ops.read)
return (*io->ops.read)(io, offset, order, width);
else if (ptr && sizeof(atomic_uchar) == width)
return atomic_load_explicit((atomic_uchar *)ptr, order);
else if (ptr && sizeof(atomic_ushort) == width)
return atomic_load_explicit((atomic_ushort *)ptr, order);
else if (ptr && sizeof(atomic_uint) == width)
return atomic_load_explicit((atomic_uint *)ptr, order);
else if (ptr && sizeof(atomic_ulong) == width)
return atomic_load_explicit((atomic_ulong *)ptr, order);
#ifndef NO_ATOMIC_64_SUPPORT
else if (ptr && sizeof(atomic_ullong) == width)
return atomic_load_explicit((atomic_ullong *)ptr, order);
#endif
metal_assert(0);
return 0; /* quiet compiler */
}
/**
* @brief Write a value into an I/O region.
* @param[in] io I/O region handle.
* @param[in] offset Offset into I/O region.
* @param[in] value Value to write.
* @param[in] order Memory ordering.
* @param[in] width Width in bytes of datatype to read. This must be 1, 2,
* 4, or 8, and a compile time constant for this function
* to inline cleanly.
*/
static inline void
metal_io_write(struct metal_io_region *io, unsigned long offset,
uint64_t value, memory_order order, int width)
{
void *ptr = metal_io_virt(io, offset);
if (io->ops.write)
(*io->ops.write)(io, offset, value, order, width);
else if (ptr && sizeof(atomic_uchar) == width)
atomic_store_explicit((atomic_uchar *)ptr, value, order);
else if (ptr && sizeof(atomic_ushort) == width)
atomic_store_explicit((atomic_ushort *)ptr, value, order);
else if (ptr && sizeof(atomic_uint) == width)
atomic_store_explicit((atomic_uint *)ptr, value, order);
else if (ptr && sizeof(atomic_ulong) == width)
atomic_store_explicit((atomic_ulong *)ptr, value, order);
#ifndef NO_ATOMIC_64_SUPPORT
else if (ptr && sizeof(atomic_ullong) == width)
atomic_store_explicit((atomic_ullong *)ptr, value, order);
#endif
else
metal_assert (0);
}
#define metal_io_read8_explicit(_io, _ofs, _order) \
metal_io_read((_io), (_ofs), (_order), 1)
#define metal_io_read8(_io, _ofs) \
metal_io_read((_io), (_ofs), memory_order_seq_cst, 1)
#define metal_io_write8_explicit(_io, _ofs, _val, _order) \
metal_io_write((_io), (_ofs), (_val), (_order), 1)
#define metal_io_write8(_io, _ofs, _val) \
metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 1)
#define metal_io_read16_explicit(_io, _ofs, _order) \
metal_io_read((_io), (_ofs), (_order), 2)
#define metal_io_read16(_io, _ofs) \
metal_io_read((_io), (_ofs), memory_order_seq_cst, 2)
#define metal_io_write16_explicit(_io, _ofs, _val, _order) \
metal_io_write((_io), (_ofs), (_val), (_order), 2)
#define metal_io_write16(_io, _ofs, _val) \
metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 2)
#define metal_io_read32_explicit(_io, _ofs, _order) \
metal_io_read((_io), (_ofs), (_order), 4)
#define metal_io_read32(_io, _ofs) \
metal_io_read((_io), (_ofs), memory_order_seq_cst, 4)
#define metal_io_write32_explicit(_io, _ofs, _val, _order) \
metal_io_write((_io), (_ofs), (_val), (_order), 4)
#define metal_io_write32(_io, _ofs, _val) \
metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 4)
#define metal_io_read64_explicit(_io, _ofs, _order) \
metal_io_read((_io), (_ofs), (_order), 8)
#define metal_io_read64(_io, _ofs) \
metal_io_read((_io), (_ofs), memory_order_seq_cst, 8)
#define metal_io_write64_explicit(_io, _ofs, _val, _order) \
metal_io_write((_io), (_ofs), (_val), (_order), 8)
#define metal_io_write64(_io, _ofs, _val) \
metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 8)
/**
* @brief Read a block from an I/O region.
* @param[in] io I/O region handle.
* @param[in] offset Offset into I/O region.
* @param[in] dst destination to store the read data.
* @param[in] len length in bytes to read.
* @return On success, number of bytes read. On failure, negative value
*/
int metal_io_block_read(struct metal_io_region *io, unsigned long offset,
void *restrict dst, int len);
/**
* @brief Write a block into an I/O region.
* @param[in] io I/O region handle.
* @param[in] offset Offset into I/O region.
* @param[in] src source to write.
* @param[in] len length in bytes to write.
* @return On success, number of bytes written. On failure, negative value
*/
int metal_io_block_write(struct metal_io_region *io, unsigned long offset,
const void *restrict src, int len);
/**
* @brief fill a block of an I/O region.
* @param[in] io I/O region handle.
* @param[in] offset Offset into I/O region.
* @param[in] value value to fill into the block
* @param[in] len length in bytes to fill.
* @return On success, number of bytes filled. On failure, negative value
*/
int metal_io_block_set(struct metal_io_region *io, unsigned long offset,
unsigned char value, int len);
#include <metal/system/generic/io.h>
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* __METAL_IO__H__ */
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file irq.h
* @brief Interrupt handling primitives for libmetal.
*/
#ifndef __METAL_IRQ__H__
#define __METAL_IRQ__H__
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup irq Interrupt Handling Interfaces
* @{ */
#include <stdlib.h>
/** IRQ handled status */
#define METAL_IRQ_NOT_HANDLED 0
#define METAL_IRQ_HANDLED 1
/**
* @brief type of interrupt handler
* @param[in] irq interrupt id
* @param[in] priv private data
* @return irq handled status
*/
typedef int (*metal_irq_handler) (int irq, void *priv);
struct metal_device;
/**
* @brief Register interrupt handler for driver ID/device.
*
* @param[in] irq interrupt id
* @param[in] irq_handler interrupt handler
* @param[in] dev metal device this irq belongs to (can be NULL).
* @param[in] drv_id driver id is a unique interrupt handler identifier.
* It can also be used for driver data.
* @return 0 for success, non-zero on failure
*/
int metal_irq_register(int irq,
metal_irq_handler irq_handler,
struct metal_device *dev,
void *drv_id);
/**
* @brief Unregister interrupt handler for driver ID and/or device.
*
* If interrupt handler (hd), driver ID (drv_id) and device (dev)
* are NULL, unregister all handlers for this interrupt.
*
* If interrupt handler (hd), device (dev) or driver ID (drv_id),
* are not NULL, unregister handlers matching non NULL criterias.
* e.g: when call is made with drv_id and dev non NULL,
* all handlers matching both are unregistered.
*
* If interrupt is not found, or other criterias not matching,
* return -ENOENT
*
* @param[in] irq interrupt id
* @param[in] irq_handler interrupt handler
* @param[in] dev metal device this irq belongs to
* @param[in] drv_id driver id. It can be used for driver data.
* @return 0 for success, non-zero on failure
*/
int metal_irq_unregister(int irq,
metal_irq_handler irq_handler,
struct metal_device *dev,
void *drv_id);
/**
* @brief disable interrupts
* @return interrupts state
*/
unsigned int metal_irq_save_disable(void);
/**
* @brief restore interrupts to their previous state
* @param[in] flags previous interrupts state
*/
void metal_irq_restore_enable(unsigned int flags);
/**
* @brief metal_irq_enable
*
* Enables the given interrupt
*
* @param vector - interrupt vector number
*/
void metal_irq_enable(unsigned int vector);
/**
* @brief metal_irq_disable
*
* Disables the given interrupt
*
* @param vector - interrupt vector number
*/
void metal_irq_disable(unsigned int vector);
#include <metal/system/generic/irq.h>
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* __METAL_IRQ__H__ */
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file list.h
* @brief List primitives for libmetal.
*/
#ifndef __METAL_LIST__H__
#define __METAL_LIST__H__
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup list List Primitives
* @{ */
struct metal_list {
struct metal_list *next, *prev;
};
/*
* METAL_INIT_LIST - used for initializing an list elmenet in a static struct
* or global
*/
#define METAL_INIT_LIST(name) { .next = &name, .prev = &name }
/*
* METAL_DECLARE_LIST - used for defining and initializing a global or
* static singleton list
*/
#define METAL_DECLARE_LIST(name) \
struct metal_list name = METAL_INIT_LIST(name)
static inline void metal_list_init(struct metal_list *list)
{
list->next = list->prev = list;
}
static inline void metal_list_add_before(struct metal_list *node,
struct metal_list *new_node)
{
new_node->prev = node->prev;
new_node->next = node;
new_node->next->prev = new_node;
new_node->prev->next = new_node;
}
static inline void metal_list_add_after(struct metal_list *node,
struct metal_list *new_node)
{
new_node->prev = node;
new_node->next = node->next;
new_node->next->prev = new_node;
new_node->prev->next = new_node;
}
static inline void metal_list_add_head(struct metal_list *list,
struct metal_list *node)
{
metal_list_add_after(list, node);
}
static inline void metal_list_add_tail(struct metal_list *list,
struct metal_list *node)
{
metal_list_add_before(list, node);
}
static inline int metal_list_is_empty(struct metal_list *list)
{
return list->next == list;
}
static inline void metal_list_del(struct metal_list *node)
{
node->next->prev = node->prev;
node->prev->next = node->next;
node->next = node->prev = node;
}
static inline struct metal_list *metal_list_first(struct metal_list *list)
{
return metal_list_is_empty(list) ? NULL : list->next;
}
#define metal_list_for_each(list, node) \
for ((node) = (list)->next; \
(node) != (list); \
(node) = (node)->next)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* __METAL_LIST__H__ */
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file log.h
* @brief Logging support for libmetal.
*/
#ifndef __METAL_METAL_LOG__H__
#define __METAL_METAL_LOG__H__
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup logging Library Logging Interfaces
* @{ */
/** Log message priority levels for libmetal. */
enum metal_log_level {
METAL_LOG_EMERGENCY, /**< system is unusable. */
METAL_LOG_ALERT, /**< action must be taken immediately. */
METAL_LOG_CRITICAL, /**< critical conditions. */
METAL_LOG_ERROR, /**< error conditions. */
METAL_LOG_WARNING, /**< warning conditions. */
METAL_LOG_NOTICE, /**< normal but significant condition. */
METAL_LOG_INFO, /**< informational messages. */
METAL_LOG_DEBUG, /**< debug-level messages. */
};
/** Log message handler type. */
typedef void (*metal_log_handler)(enum metal_log_level level,
const char *format, ...);
/**
* @brief Set libmetal log handler.
* @param[in] handler log message handler.
* @return 0 on success, or -errno on failure.
*/
extern void metal_set_log_handler(metal_log_handler handler);
/**
* @brief Get the current libmetal log handler.
* @return Current log handler.
*/
extern metal_log_handler metal_get_log_handler(void);
/**
* @brief Set the level for libmetal logging.
* @param[in] level log message level.
*/
extern void metal_set_log_level(enum metal_log_level level);
/**
* @brief Get the current level for libmetal logging.
* @return Current log level.
*/
extern enum metal_log_level metal_get_log_level(void);
/**
* @brief Default libmetal log handler. This handler prints libmetal log
* mesages to stderr.
* @param[in] level log message level.
* @param[in] format log message format string.
* @return 0 on success, or -errno on failure.
*/
extern void metal_default_log_handler(enum metal_log_level level,
const char *format, ...);
/**
* Emit a log message if the log level permits.
*
* @param level Log level.
* @param ... Format string and arguments.
*/
#define metal_log(level, ...) \
((level <= _metal.common.log_level && _metal.common.log_handler) \
? (void)_metal.common.log_handler(level, __VA_ARGS__) \
: (void)0)
/** @} */
#ifdef __cplusplus
}
#endif
#include <metal/system/generic/log.h>
#endif /* __METAL_METAL_LOG__H__ */
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file arm/atomic.h
* @brief ARM specific atomic primitives for libmetal.
*/
#ifndef __METAL_ARM_ATOMIC__H__
#define __METAL_ARM_ATOMIC__H__
#endif /* __METAL_ARM_ATOMIC__H__ */
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册