Merge branch 'master' of https://github.com/RT-Thread/rt-thread into fix_bug_of_dataqueue
This commit is contained in:
commit
77f0814992
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* 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"
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* 2019-04-23 WillianChan Fix GPIO serial number disorder
|
||||
* 2020-06-16 thread-liu add STM32MP1
|
||||
* 2020-09-01 thread-liu add GPIOZ
|
||||
* 2020-09-18 geniusgogo optimization design pin-index algorithm
|
||||
*/
|
||||
|
||||
#include <board.h>
|
||||
|
@ -16,225 +17,53 @@
|
|||
|
||||
#ifdef RT_USING_PIN
|
||||
|
||||
static const struct pin_index pins[] =
|
||||
{
|
||||
#if defined(GPIOA)
|
||||
__STM32_PIN(0 , A, 0 ),
|
||||
__STM32_PIN(1 , A, 1 ),
|
||||
__STM32_PIN(2 , A, 2 ),
|
||||
__STM32_PIN(3 , A, 3 ),
|
||||
__STM32_PIN(4 , A, 4 ),
|
||||
__STM32_PIN(5 , A, 5 ),
|
||||
__STM32_PIN(6 , A, 6 ),
|
||||
__STM32_PIN(7 , A, 7 ),
|
||||
__STM32_PIN(8 , A, 8 ),
|
||||
__STM32_PIN(9 , A, 9 ),
|
||||
__STM32_PIN(10, A, 10),
|
||||
__STM32_PIN(11, A, 11),
|
||||
__STM32_PIN(12, A, 12),
|
||||
__STM32_PIN(13, A, 13),
|
||||
__STM32_PIN(14, A, 14),
|
||||
__STM32_PIN(15, A, 15),
|
||||
#if defined(GPIOB)
|
||||
__STM32_PIN(16, B, 0),
|
||||
__STM32_PIN(17, B, 1),
|
||||
__STM32_PIN(18, B, 2),
|
||||
__STM32_PIN(19, B, 3),
|
||||
__STM32_PIN(20, B, 4),
|
||||
__STM32_PIN(21, B, 5),
|
||||
__STM32_PIN(22, B, 6),
|
||||
__STM32_PIN(23, B, 7),
|
||||
__STM32_PIN(24, B, 8),
|
||||
__STM32_PIN(25, B, 9),
|
||||
__STM32_PIN(26, B, 10),
|
||||
__STM32_PIN(27, B, 11),
|
||||
__STM32_PIN(28, B, 12),
|
||||
__STM32_PIN(29, B, 13),
|
||||
__STM32_PIN(30, B, 14),
|
||||
__STM32_PIN(31, B, 15),
|
||||
#if defined(GPIOC)
|
||||
__STM32_PIN(32, C, 0),
|
||||
__STM32_PIN(33, C, 1),
|
||||
__STM32_PIN(34, C, 2),
|
||||
__STM32_PIN(35, C, 3),
|
||||
__STM32_PIN(36, C, 4),
|
||||
__STM32_PIN(37, C, 5),
|
||||
__STM32_PIN(38, C, 6),
|
||||
__STM32_PIN(39, C, 7),
|
||||
__STM32_PIN(40, C, 8),
|
||||
__STM32_PIN(41, C, 9),
|
||||
__STM32_PIN(42, C, 10),
|
||||
__STM32_PIN(43, C, 11),
|
||||
__STM32_PIN(44, C, 12),
|
||||
__STM32_PIN(45, C, 13),
|
||||
__STM32_PIN(46, C, 14),
|
||||
__STM32_PIN(47, C, 15),
|
||||
#if defined(GPIOD)
|
||||
__STM32_PIN(48, D, 0),
|
||||
__STM32_PIN(49, D, 1),
|
||||
__STM32_PIN(50, D, 2),
|
||||
__STM32_PIN(51, D, 3),
|
||||
__STM32_PIN(52, D, 4),
|
||||
__STM32_PIN(53, D, 5),
|
||||
__STM32_PIN(54, D, 6),
|
||||
__STM32_PIN(55, D, 7),
|
||||
__STM32_PIN(56, D, 8),
|
||||
__STM32_PIN(57, D, 9),
|
||||
__STM32_PIN(58, D, 10),
|
||||
__STM32_PIN(59, D, 11),
|
||||
__STM32_PIN(60, D, 12),
|
||||
__STM32_PIN(61, D, 13),
|
||||
__STM32_PIN(62, D, 14),
|
||||
__STM32_PIN(63, D, 15),
|
||||
#if defined(GPIOE)
|
||||
__STM32_PIN(64, E, 0),
|
||||
__STM32_PIN(65, E, 1),
|
||||
__STM32_PIN(66, E, 2),
|
||||
__STM32_PIN(67, E, 3),
|
||||
__STM32_PIN(68, E, 4),
|
||||
__STM32_PIN(69, E, 5),
|
||||
__STM32_PIN(70, E, 6),
|
||||
__STM32_PIN(71, E, 7),
|
||||
__STM32_PIN(72, E, 8),
|
||||
__STM32_PIN(73, E, 9),
|
||||
__STM32_PIN(74, E, 10),
|
||||
__STM32_PIN(75, E, 11),
|
||||
__STM32_PIN(76, E, 12),
|
||||
__STM32_PIN(77, E, 13),
|
||||
__STM32_PIN(78, E, 14),
|
||||
__STM32_PIN(79, E, 15),
|
||||
#if defined(GPIOF)
|
||||
__STM32_PIN(80, F, 0),
|
||||
__STM32_PIN(81, F, 1),
|
||||
__STM32_PIN(82, F, 2),
|
||||
__STM32_PIN(83, F, 3),
|
||||
__STM32_PIN(84, F, 4),
|
||||
__STM32_PIN(85, F, 5),
|
||||
__STM32_PIN(86, F, 6),
|
||||
__STM32_PIN(87, F, 7),
|
||||
__STM32_PIN(88, F, 8),
|
||||
__STM32_PIN(89, F, 9),
|
||||
__STM32_PIN(90, F, 10),
|
||||
__STM32_PIN(91, F, 11),
|
||||
__STM32_PIN(92, F, 12),
|
||||
__STM32_PIN(93, F, 13),
|
||||
__STM32_PIN(94, F, 14),
|
||||
__STM32_PIN(95, F, 15),
|
||||
#if defined(GPIOG)
|
||||
__STM32_PIN(96, G, 0),
|
||||
__STM32_PIN(97, G, 1),
|
||||
__STM32_PIN(98, G, 2),
|
||||
__STM32_PIN(99, G, 3),
|
||||
__STM32_PIN(100, G, 4),
|
||||
__STM32_PIN(101, G, 5),
|
||||
__STM32_PIN(102, G, 6),
|
||||
__STM32_PIN(103, G, 7),
|
||||
__STM32_PIN(104, G, 8),
|
||||
__STM32_PIN(105, G, 9),
|
||||
__STM32_PIN(106, G, 10),
|
||||
__STM32_PIN(107, G, 11),
|
||||
__STM32_PIN(108, G, 12),
|
||||
__STM32_PIN(109, G, 13),
|
||||
__STM32_PIN(110, G, 14),
|
||||
__STM32_PIN(111, G, 15),
|
||||
#if defined(GPIOH)
|
||||
__STM32_PIN(112, H, 0),
|
||||
__STM32_PIN(113, H, 1),
|
||||
__STM32_PIN(114, H, 2),
|
||||
__STM32_PIN(115, H, 3),
|
||||
__STM32_PIN(116, H, 4),
|
||||
__STM32_PIN(117, H, 5),
|
||||
__STM32_PIN(118, H, 6),
|
||||
__STM32_PIN(119, H, 7),
|
||||
__STM32_PIN(120, H, 8),
|
||||
__STM32_PIN(121, H, 9),
|
||||
__STM32_PIN(122, H, 10),
|
||||
__STM32_PIN(123, H, 11),
|
||||
__STM32_PIN(124, H, 12),
|
||||
__STM32_PIN(125, H, 13),
|
||||
__STM32_PIN(126, H, 14),
|
||||
__STM32_PIN(127, H, 15),
|
||||
#if defined(GPIOI)
|
||||
__STM32_PIN(128, I, 0),
|
||||
__STM32_PIN(129, I, 1),
|
||||
__STM32_PIN(130, I, 2),
|
||||
__STM32_PIN(131, I, 3),
|
||||
__STM32_PIN(132, I, 4),
|
||||
__STM32_PIN(133, I, 5),
|
||||
__STM32_PIN(134, I, 6),
|
||||
__STM32_PIN(135, I, 7),
|
||||
__STM32_PIN(136, I, 8),
|
||||
__STM32_PIN(137, I, 9),
|
||||
__STM32_PIN(138, I, 10),
|
||||
__STM32_PIN(139, I, 11),
|
||||
__STM32_PIN(140, I, 12),
|
||||
__STM32_PIN(141, I, 13),
|
||||
__STM32_PIN(142, I, 14),
|
||||
__STM32_PIN(143, I, 15),
|
||||
#if defined(GPIOJ)
|
||||
__STM32_PIN(144, J, 0),
|
||||
__STM32_PIN(145, J, 1),
|
||||
__STM32_PIN(146, J, 2),
|
||||
__STM32_PIN(147, J, 3),
|
||||
__STM32_PIN(148, J, 4),
|
||||
__STM32_PIN(149, J, 5),
|
||||
__STM32_PIN(150, J, 6),
|
||||
__STM32_PIN(151, J, 7),
|
||||
__STM32_PIN(152, J, 8),
|
||||
__STM32_PIN(153, J, 9),
|
||||
__STM32_PIN(154, J, 10),
|
||||
__STM32_PIN(155, J, 11),
|
||||
__STM32_PIN(156, J, 12),
|
||||
__STM32_PIN(157, J, 13),
|
||||
__STM32_PIN(158, J, 14),
|
||||
__STM32_PIN(159, J, 15),
|
||||
#if defined(GPIOK)
|
||||
__STM32_PIN(160, K, 0),
|
||||
__STM32_PIN(161, K, 1),
|
||||
__STM32_PIN(162, K, 2),
|
||||
__STM32_PIN(163, K, 3),
|
||||
__STM32_PIN(164, K, 4),
|
||||
__STM32_PIN(165, K, 5),
|
||||
__STM32_PIN(166, K, 6),
|
||||
__STM32_PIN(167, K, 7),
|
||||
__STM32_PIN(168, K, 8),
|
||||
__STM32_PIN(169, K, 9),
|
||||
__STM32_PIN(170, K, 10),
|
||||
__STM32_PIN(171, K, 11),
|
||||
__STM32_PIN(172, K, 12),
|
||||
__STM32_PIN(173, K, 13),
|
||||
__STM32_PIN(174, K, 14),
|
||||
__STM32_PIN(175, K, 15),
|
||||
#define PIN_NUM(port, no) (((((port) & 0xFu) << 4) | ((no) & 0xFu)))
|
||||
#define PIN_PORT(pin) ((uint8_t)(((pin) >> 4) & 0xFu))
|
||||
#define PIN_NO(pin) ((uint8_t)((pin) & 0xFu))
|
||||
|
||||
#if defined(SOC_SERIES_STM32MP1)
|
||||
#if defined(GPIOZ)
|
||||
__STM32_PIN(176, Z, 0),
|
||||
__STM32_PIN(177, Z, 1),
|
||||
__STM32_PIN(178, Z, 2),
|
||||
__STM32_PIN(179, Z, 3),
|
||||
__STM32_PIN(180, Z, 4),
|
||||
__STM32_PIN(181, Z, 5),
|
||||
__STM32_PIN(182, Z, 6),
|
||||
__STM32_PIN(183, Z, 7),
|
||||
__STM32_PIN(184, Z, 8),
|
||||
__STM32_PIN(185, Z, 9),
|
||||
__STM32_PIN(186, Z, 10),
|
||||
__STM32_PIN(187, Z, 11),
|
||||
__STM32_PIN(188, Z, 12),
|
||||
__STM32_PIN(189, Z, 13),
|
||||
__STM32_PIN(190, Z, 14),
|
||||
__STM32_PIN(191, Z, 15),
|
||||
#endif /* defined(GPIOZ) */
|
||||
#endif /* defined(GPIOK) */
|
||||
#endif /* defined(GPIOJ) */
|
||||
#endif /* defined(GPIOI) */
|
||||
#endif /* defined(GPIOH) */
|
||||
#endif /* defined(GPIOG) */
|
||||
#endif /* defined(GPIOF) */
|
||||
#endif /* defined(GPIOE) */
|
||||
#endif /* defined(GPIOD) */
|
||||
#endif /* defined(GPIOC) */
|
||||
#endif /* defined(GPIOB) */
|
||||
#endif /* defined(GPIOA) */
|
||||
};
|
||||
#define gpioz_port_base (175) /* PIN_STPORT_MAX * 16 - 16 */
|
||||
#define PIN_STPORT(pin) ((pin > gpioz_port_base) ? ((GPIO_TypeDef *)(GPIOZ_BASE )) : ((GPIO_TypeDef *)(GPIOA_BASE + (0x1000u * PIN_PORT(pin)))))
|
||||
#else
|
||||
#define PIN_STPORT(pin) ((GPIO_TypeDef *)(GPIOA_BASE + (0x1000u * PIN_PORT(pin)))))
|
||||
#endif /* GPIOZ */
|
||||
#else
|
||||
#define PIN_STPORT(pin) ((GPIO_TypeDef *)(GPIOA_BASE + (0x400u * PIN_PORT(pin))))
|
||||
#endif /* SOC_SERIES_STM32MP1 */
|
||||
|
||||
#define PIN_STPIN(pin) ((uint16_t)(1u << PIN_NO(pin)))
|
||||
|
||||
#if defined(GPIOZ)
|
||||
#define __STM32_PORT_MAX 12u
|
||||
#elif defined(GPIOK)
|
||||
#define __STM32_PORT_MAX 11u
|
||||
#elif defined(GPIOJ)
|
||||
#define __STM32_PORT_MAX 10u
|
||||
#elif defined(GPIOI)
|
||||
#define __STM32_PORT_MAX 9u
|
||||
#elif defined(GPIOH)
|
||||
#define __STM32_PORT_MAX 8u
|
||||
#elif defined(GPIOG)
|
||||
#define __STM32_PORT_MAX 7u
|
||||
#elif defined(GPIOF)
|
||||
#define __STM32_PORT_MAX 6u
|
||||
#elif defined(GPIOE)
|
||||
#define __STM32_PORT_MAX 5u
|
||||
#elif defined(GPIOD)
|
||||
#define __STM32_PORT_MAX 4u
|
||||
#elif defined(GPIOC)
|
||||
#define __STM32_PORT_MAX 3u
|
||||
#elif defined(GPIOB)
|
||||
#define __STM32_PORT_MAX 2u
|
||||
#elif defined(GPIOA)
|
||||
#define __STM32_PORT_MAX 1u
|
||||
#else
|
||||
#define __STM32_PORT_MAX 0u
|
||||
#error Unsupported STM32 GPIO peripheral.
|
||||
#endif
|
||||
|
||||
#define PIN_STPORT_MAX __STM32_PORT_MAX
|
||||
|
||||
static const struct pin_irq_map pin_irq_map[] =
|
||||
{
|
||||
|
@ -311,33 +140,15 @@ static struct rt_pin_irq_hdr pin_irq_hdr_tab[] =
|
|||
{-1, 0, RT_NULL, RT_NULL},
|
||||
{-1, 0, RT_NULL, RT_NULL},
|
||||
};
|
||||
static uint32_t pin_irq_enable_mask=0;
|
||||
static uint32_t pin_irq_enable_mask = 0;
|
||||
|
||||
#define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
|
||||
static const struct pin_index *get_pin(uint8_t pin)
|
||||
{
|
||||
const struct pin_index *index;
|
||||
|
||||
if (pin < ITEM_NUM(pins))
|
||||
{
|
||||
index = &pins[pin];
|
||||
if (index->index == -1)
|
||||
index = RT_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = RT_NULL;
|
||||
}
|
||||
|
||||
return index;
|
||||
};
|
||||
|
||||
static rt_base_t stm32_pin_get(const char *name)
|
||||
{
|
||||
rt_base_t pin = 0;
|
||||
int hw_port_num, hw_pin_num = 0;
|
||||
int i, name_len = 1;
|
||||
int mul = 1;
|
||||
int i, name_len;
|
||||
|
||||
name_len = rt_strlen(name);
|
||||
|
||||
|
@ -359,68 +170,58 @@ static rt_base_t stm32_pin_get(const char *name)
|
|||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
for (i = name_len - 1; i > 2; i--)
|
||||
for (i = 3; i < name_len; i++)
|
||||
{
|
||||
hw_pin_num += ((int)(name[i] - '0') * mul);
|
||||
mul = mul * 10;
|
||||
hw_pin_num *= 10;
|
||||
hw_pin_num += name[i] - '0';
|
||||
}
|
||||
|
||||
pin = 16 * hw_port_num + hw_pin_num;
|
||||
pin = PIN_NUM(hw_port_num, hw_pin_num);
|
||||
|
||||
if (pin < ITEM_NUM(pins))
|
||||
{
|
||||
return pin;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void stm32_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value)
|
||||
{
|
||||
const struct pin_index *index;
|
||||
GPIO_TypeDef *gpio_port;
|
||||
uint16_t gpio_pin;
|
||||
|
||||
index = get_pin(pin);
|
||||
if (index == RT_NULL)
|
||||
if (PIN_PORT(pin) < PIN_STPORT_MAX)
|
||||
{
|
||||
return;
|
||||
}
|
||||
gpio_port = PIN_STPORT(pin);
|
||||
gpio_pin = PIN_STPIN(pin);
|
||||
|
||||
HAL_GPIO_WritePin(index->gpio, index->pin, (GPIO_PinState)value);
|
||||
HAL_GPIO_WritePin(gpio_port, gpio_pin, (GPIO_PinState)value);
|
||||
}
|
||||
}
|
||||
|
||||
static int stm32_pin_read(rt_device_t dev, rt_base_t pin)
|
||||
{
|
||||
int value;
|
||||
const struct pin_index *index;
|
||||
GPIO_TypeDef *gpio_port;
|
||||
uint16_t gpio_pin;
|
||||
int value = PIN_LOW;
|
||||
|
||||
value = PIN_LOW;
|
||||
|
||||
index = get_pin(pin);
|
||||
if (index == RT_NULL)
|
||||
if (PIN_PORT(pin) < PIN_STPORT_MAX)
|
||||
{
|
||||
return value;
|
||||
gpio_port = PIN_STPORT(pin);
|
||||
gpio_pin = PIN_STPIN(pin);
|
||||
value = HAL_GPIO_ReadPin(gpio_port, gpio_pin);
|
||||
}
|
||||
|
||||
value = HAL_GPIO_ReadPin(index->gpio, index->pin);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void stm32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode)
|
||||
{
|
||||
const struct pin_index *index;
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
||||
index = get_pin(pin);
|
||||
if (index == RT_NULL)
|
||||
if (PIN_PORT(pin) >= PIN_STPORT_MAX)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Configure GPIO_InitStructure */
|
||||
GPIO_InitStruct.Pin = index->pin;
|
||||
GPIO_InitStruct.Pin = PIN_STPIN(pin);
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
|
@ -456,7 +257,7 @@ static void stm32_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode)
|
|||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
}
|
||||
|
||||
HAL_GPIO_Init(index->gpio, &GPIO_InitStruct);
|
||||
HAL_GPIO_Init(PIN_STPORT(pin), &GPIO_InitStruct);
|
||||
}
|
||||
|
||||
rt_inline rt_int32_t bit2bitno(rt_uint32_t bit)
|
||||
|
@ -485,16 +286,15 @@ rt_inline const struct pin_irq_map *get_pin_irq_map(uint32_t pinbit)
|
|||
static rt_err_t stm32_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
|
||||
rt_uint32_t mode, void (*hdr)(void *args), void *args)
|
||||
{
|
||||
const struct pin_index *index;
|
||||
rt_base_t level;
|
||||
rt_int32_t irqindex = -1;
|
||||
|
||||
index = get_pin(pin);
|
||||
if (index == RT_NULL)
|
||||
if (PIN_PORT(pin) >= PIN_STPORT_MAX)
|
||||
{
|
||||
return RT_ENOSYS;
|
||||
return -RT_ENOSYS;
|
||||
}
|
||||
irqindex = bit2bitno(index->pin);
|
||||
|
||||
irqindex = bit2bitno(PIN_STPIN(pin));
|
||||
if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map))
|
||||
{
|
||||
return RT_ENOSYS;
|
||||
|
@ -525,16 +325,15 @@ static rt_err_t stm32_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
|
|||
|
||||
static rt_err_t stm32_pin_dettach_irq(struct rt_device *device, rt_int32_t pin)
|
||||
{
|
||||
const struct pin_index *index;
|
||||
rt_base_t level;
|
||||
rt_int32_t irqindex = -1;
|
||||
|
||||
index = get_pin(pin);
|
||||
if (index == RT_NULL)
|
||||
if (PIN_PORT(pin) >= PIN_STPORT_MAX)
|
||||
{
|
||||
return RT_ENOSYS;
|
||||
return -RT_ENOSYS;
|
||||
}
|
||||
irqindex = bit2bitno(index->pin);
|
||||
|
||||
irqindex = bit2bitno(PIN_STPIN(pin));
|
||||
if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map))
|
||||
{
|
||||
return RT_ENOSYS;
|
||||
|
@ -558,21 +357,19 @@ static rt_err_t stm32_pin_dettach_irq(struct rt_device *device, rt_int32_t pin)
|
|||
static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
|
||||
rt_uint32_t enabled)
|
||||
{
|
||||
const struct pin_index *index;
|
||||
const struct pin_irq_map *irqmap;
|
||||
rt_base_t level;
|
||||
rt_int32_t irqindex = -1;
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
||||
index = get_pin(pin);
|
||||
if (index == RT_NULL)
|
||||
if (PIN_PORT(pin) >= PIN_STPORT_MAX)
|
||||
{
|
||||
return RT_ENOSYS;
|
||||
return -RT_ENOSYS;
|
||||
}
|
||||
|
||||
if (enabled == PIN_IRQ_ENABLE)
|
||||
{
|
||||
irqindex = bit2bitno(index->pin);
|
||||
irqindex = bit2bitno(PIN_STPIN(pin));
|
||||
if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map))
|
||||
{
|
||||
return RT_ENOSYS;
|
||||
|
@ -589,7 +386,7 @@ static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
|
|||
irqmap = &pin_irq_map[irqindex];
|
||||
|
||||
/* Configure GPIO_InitStructure */
|
||||
GPIO_InitStruct.Pin = index->pin;
|
||||
GPIO_InitStruct.Pin = PIN_STPIN(pin);
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
switch (pin_irq_hdr_tab[irqindex].mode)
|
||||
{
|
||||
|
@ -606,7 +403,7 @@ static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
|
|||
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
|
||||
break;
|
||||
}
|
||||
HAL_GPIO_Init(index->gpio, &GPIO_InitStruct);
|
||||
HAL_GPIO_Init(PIN_STPORT(pin), &GPIO_InitStruct);
|
||||
|
||||
HAL_NVIC_SetPriority(irqmap->irqno, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(irqmap->irqno);
|
||||
|
@ -616,7 +413,7 @@ static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
|
|||
}
|
||||
else if (enabled == PIN_IRQ_DISABLE)
|
||||
{
|
||||
irqmap = get_pin_irq_map(index->pin);
|
||||
irqmap = get_pin_irq_map(PIN_STPIN(pin));
|
||||
if (irqmap == RT_NULL)
|
||||
{
|
||||
return RT_ENOSYS;
|
||||
|
@ -624,28 +421,28 @@ static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
|
|||
|
||||
level = rt_hw_interrupt_disable();
|
||||
|
||||
HAL_GPIO_DeInit(index->gpio, index->pin);
|
||||
HAL_GPIO_DeInit(PIN_STPORT(pin), PIN_STPIN(pin));
|
||||
|
||||
pin_irq_enable_mask &= ~irqmap->pinbit;
|
||||
#if defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0)
|
||||
if (( irqmap->pinbit>=GPIO_PIN_0 )&&( irqmap->pinbit<=GPIO_PIN_1 ))
|
||||
if ((irqmap->pinbit >= GPIO_PIN_0) && (irqmap->pinbit <= GPIO_PIN_1))
|
||||
{
|
||||
if(!(pin_irq_enable_mask&(GPIO_PIN_0|GPIO_PIN_1)))
|
||||
if (!(pin_irq_enable_mask & (GPIO_PIN_0 | GPIO_PIN_1)))
|
||||
{
|
||||
HAL_NVIC_DisableIRQ(irqmap->irqno);
|
||||
}
|
||||
}
|
||||
else if (( irqmap->pinbit>=GPIO_PIN_2 )&&( irqmap->pinbit<=GPIO_PIN_3 ))
|
||||
else if ((irqmap->pinbit >= GPIO_PIN_2) && (irqmap->pinbit <= GPIO_PIN_3))
|
||||
{
|
||||
if(!(pin_irq_enable_mask&(GPIO_PIN_2|GPIO_PIN_3)))
|
||||
if (!(pin_irq_enable_mask & (GPIO_PIN_2 | GPIO_PIN_3)))
|
||||
{
|
||||
HAL_NVIC_DisableIRQ(irqmap->irqno);
|
||||
}
|
||||
}
|
||||
else if (( irqmap->pinbit>=GPIO_PIN_4 )&&( irqmap->pinbit<=GPIO_PIN_15 ))
|
||||
else if ((irqmap->pinbit >= GPIO_PIN_4) && (irqmap->pinbit <= GPIO_PIN_15))
|
||||
{
|
||||
if(!(pin_irq_enable_mask&(GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|
|
||||
GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15)))
|
||||
if (!(pin_irq_enable_mask & (GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 |
|
||||
GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15)))
|
||||
{
|
||||
HAL_NVIC_DisableIRQ(irqmap->irqno);
|
||||
}
|
||||
|
@ -655,16 +452,16 @@ static rt_err_t stm32_pin_irq_enable(struct rt_device *device, rt_base_t pin,
|
|||
HAL_NVIC_DisableIRQ(irqmap->irqno);
|
||||
}
|
||||
#else
|
||||
if (( irqmap->pinbit>=GPIO_PIN_5 )&&( irqmap->pinbit<=GPIO_PIN_9 ))
|
||||
if ((irqmap->pinbit >= GPIO_PIN_5) && (irqmap->pinbit <= GPIO_PIN_9))
|
||||
{
|
||||
if(!(pin_irq_enable_mask&(GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9)))
|
||||
if (!(pin_irq_enable_mask & (GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9)))
|
||||
{
|
||||
HAL_NVIC_DisableIRQ(irqmap->irqno);
|
||||
}
|
||||
}
|
||||
else if (( irqmap->pinbit>=GPIO_PIN_10 )&&( irqmap->pinbit<=GPIO_PIN_15 ))
|
||||
else if ((irqmap->pinbit >= GPIO_PIN_10) && (irqmap->pinbit <= GPIO_PIN_15))
|
||||
{
|
||||
if(!(pin_irq_enable_mask&(GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15)))
|
||||
if (!(pin_irq_enable_mask & (GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15)))
|
||||
{
|
||||
HAL_NVIC_DisableIRQ(irqmap->irqno);
|
||||
}
|
||||
|
@ -754,97 +551,113 @@ void EXTI4_15_IRQHandler(void)
|
|||
}
|
||||
|
||||
#elif defined(SOC_STM32MP157A)
|
||||
void EXTI0_IRQHandler(void) {
|
||||
void EXTI0_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI1_IRQHandler(void) {
|
||||
void EXTI1_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI2_IRQHandler(void) {
|
||||
void EXTI2_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI3_IRQHandler(void) {
|
||||
void EXTI3_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI4_IRQHandler(void) {
|
||||
void EXTI4_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI5_IRQHandler(void) {
|
||||
void EXTI5_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI6_IRQHandler(void) {
|
||||
void EXTI6_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI7_IRQHandler(void) {
|
||||
void EXTI7_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI8_IRQHandler(void) {
|
||||
void EXTI8_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI9_IRQHandler(void) {
|
||||
void EXTI9_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI10_IRQHandler(void) {
|
||||
void EXTI10_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_10);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI11_IRQHandler(void) {
|
||||
void EXTI11_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI12_IRQHandler(void) {
|
||||
void EXTI12_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI13_IRQHandler(void) {
|
||||
void EXTI13_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI14_IRQHandler(void) {
|
||||
void EXTI14_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void EXTI15_IRQHandler(void) {
|
||||
void EXTI15_IRQHandler(void)
|
||||
{
|
||||
rt_interrupt_enter();
|
||||
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15);
|
||||
rt_interrupt_leave();
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -38,7 +38,7 @@ 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 | |
|
||||
|
@ -52,7 +52,7 @@ Each peripheral supporting condition for this BSP is as follows:
|
|||
| SPI | YES | |
|
||||
| TIM | YES | |
|
||||
| LPTIM | YES | |
|
||||
| I2C | YES | Software & Hardware |
|
||||
| I2C | YES | Software |
|
||||
| ADC | YES | |
|
||||
| DAC | YES | |
|
||||
| WWDG | YES | |
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* File Name : IPCC.h
|
||||
* Description : This file provides code for the configuration
|
||||
* of the IPCC instances.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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****/
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file mbox_ipcc.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header for mbox_ipcc.c module
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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_ */
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file openamp.h
|
||||
* @brief Header for openamp applications
|
||||
* @author MCD Application Team
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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****/
|
|
@ -0,0 +1,242 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file openamp_conf.h
|
||||
* @author MCD Application Team
|
||||
* @brief Configuration file for OpenAMP MW
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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****/
|
|
@ -0,0 +1,134 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file log.h
|
||||
* @author MCD Application Team
|
||||
* @brief logging services
|
||||
******************************************************************************
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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****/
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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_ */
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @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>© 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****/
|
|
@ -0,0 +1,176 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file openamp.c
|
||||
* @author MCD Application Team
|
||||
* @brief Code for openamp applications
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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****/
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @file log.c
|
||||
* @author MCD Application Team
|
||||
* @brief Ressource table
|
||||
*
|
||||
* This file provides services for logging
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© 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****/
|
|
@ -0,0 +1,174 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* @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>© 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.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 = 16;
|
||||
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
|
||||
*/
|
||||
|
|
|
@ -23,22 +23,24 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#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
|
||||
|
||||
|
|
|
@ -1,28 +1,44 @@
|
|||
/*###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};
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
/*
|
||||
* 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
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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__ */
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,289 @@
|
|||
/*
|
||||
* * 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 */
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* * 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 */
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* * 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__ */
|
||||
|
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file mutex.h
|
||||
* @brief Mutex primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_MUTEX__H__
|
||||
#define __METAL_MUTEX__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup mutex Mutex Interfaces
|
||||
* @{ */
|
||||
|
||||
#include <metal/system/generic/mutex.h>
|
||||
|
||||
/**
|
||||
* @brief Initialize a libmetal mutex.
|
||||
* @param[in] mutex Mutex to initialize.
|
||||
*/
|
||||
static inline void metal_mutex_init(metal_mutex_t *mutex)
|
||||
{
|
||||
__metal_mutex_init(mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitialize a libmetal mutex.
|
||||
* @param[in] mutex Mutex to deinitialize.
|
||||
*/
|
||||
static inline void metal_mutex_deinit(metal_mutex_t *mutex)
|
||||
{
|
||||
__metal_mutex_deinit(mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to acquire a mutex
|
||||
* @param[in] mutex Mutex to mutex.
|
||||
* @return 0 on failure to acquire, non-zero on success.
|
||||
*/
|
||||
static inline int metal_mutex_try_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
return __metal_mutex_try_acquire(mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Acquire a mutex
|
||||
* @param[in] mutex Mutex to mutex.
|
||||
*/
|
||||
static inline void metal_mutex_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
__metal_mutex_acquire(mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release a previously acquired mutex.
|
||||
* @param[in] mutex Mutex to mutex.
|
||||
* @see metal_mutex_try_acquire, metal_mutex_acquire
|
||||
*/
|
||||
static inline void metal_mutex_release(metal_mutex_t *mutex)
|
||||
{
|
||||
__metal_mutex_release(mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checked if a mutex has been acquired.
|
||||
* @param[in] mutex mutex to check.
|
||||
* @see metal_mutex_try_acquire, metal_mutex_acquire
|
||||
*/
|
||||
static inline int metal_mutex_is_acquired(metal_mutex_t *mutex)
|
||||
{
|
||||
return __metal_mutex_is_acquired(mutex);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_MUTEX__H__ */
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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__ */
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file cpu.h
|
||||
* @brief CPU specific primatives
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ARM_CPU__H__
|
||||
#define __METAL_ARM_CPU__H__
|
||||
|
||||
#define metal_cpu_yield()
|
||||
|
||||
#endif /* __METAL_ARM_CPU__H__ */
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file shmem.h
|
||||
* @brief Shared memory primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SHMEM__H__
|
||||
#define __METAL_SHMEM__H__
|
||||
|
||||
#include <metal/io.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup shmem Shared Memory Interfaces
|
||||
* @{ */
|
||||
|
||||
/** Generic shared memory data structure. */
|
||||
struct metal_generic_shmem {
|
||||
const char *name;
|
||||
struct metal_io_region io;
|
||||
struct metal_list node;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Open a libmetal shared memory segment.
|
||||
*
|
||||
* Open a shared memory segment.
|
||||
*
|
||||
* @param[in] name Name of segment to open.
|
||||
* @param[in] size Size of segment.
|
||||
* @param[out] io I/O region handle, if successful.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*
|
||||
* @see metal_shmem_create
|
||||
*/
|
||||
extern int metal_shmem_open(const char *name, size_t size,
|
||||
struct metal_io_region **io);
|
||||
|
||||
/**
|
||||
* @brief Statically register a generic shared memory region.
|
||||
*
|
||||
* Shared memory regions may be statically registered at application
|
||||
* initialization, or may be dynamically opened. This interface is used for
|
||||
* static registration of regions. Subsequent calls to metal_shmem_open() look
|
||||
* up in this list of pre-registered regions.
|
||||
*
|
||||
* @param[in] shmem Generic shmem structure.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
extern int metal_shmem_register_generic(struct metal_generic_shmem *shmem);
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief Open a statically registered shmem segment.
|
||||
*
|
||||
* This interface is meant for internal libmetal use within system specific
|
||||
* shmem implementations.
|
||||
*
|
||||
* @param[in] name Name of segment to open.
|
||||
* @param[in] size Size of segment.
|
||||
* @param[out] io I/O region handle, if successful.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
int metal_shmem_open_generic(const char *name, size_t size,
|
||||
struct metal_io_region **result);
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_SHMEM__H__ */
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file sleep.h
|
||||
* @brief Sleep primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SLEEP__H__
|
||||
#define __METAL_SLEEP__H__
|
||||
|
||||
#include <metal/system/generic/sleep.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup sleep Sleep Interfaces
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
* @brief delay in microseconds
|
||||
* delay the next execution in the calling thread
|
||||
* fo usec microseconds.
|
||||
*
|
||||
* @param[in] usec microsecond intervals
|
||||
* @return 0 on success, non-zero for failures
|
||||
*/
|
||||
static inline int metal_sleep_usec(unsigned int usec)
|
||||
{
|
||||
return __metal_sleep_usec(usec);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_SLEEP__H__ */
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file spinlock.h
|
||||
* @brief Spinlock primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SPINLOCK__H__
|
||||
#define __METAL_SPINLOCK__H__
|
||||
|
||||
#include <metal/atomic.h>
|
||||
#include <metal/cpu.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup spinlock Spinlock Interfaces
|
||||
* @{ */
|
||||
struct metal_spinlock {
|
||||
union{
|
||||
atomic_int v;
|
||||
atomic_flag w;
|
||||
};
|
||||
};
|
||||
|
||||
/** Static metal spinlock initialization. */
|
||||
#define METAL_SPINLOCK_INIT {ATOMIC_VAR_INIT(0)}
|
||||
|
||||
/**
|
||||
* @brief Initialize a libmetal spinlock.
|
||||
* @param[in] slock Spinlock to initialize.
|
||||
*/
|
||||
static inline void metal_spinlock_init(struct metal_spinlock *slock)
|
||||
{
|
||||
atomic_store(&slock->v, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Acquire a spinlock.
|
||||
* @param[in] slock Spinlock to acquire.
|
||||
* @see metal_spinlock_release
|
||||
*/
|
||||
static inline void metal_spinlock_acquire(struct metal_spinlock *slock)
|
||||
{
|
||||
while (atomic_flag_test_and_set(&slock->w)) {
|
||||
metal_cpu_yield();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release a previously acquired spinlock.
|
||||
* @param[in] slock Spinlock to release.
|
||||
* @see metal_spinlock_acquire
|
||||
*/
|
||||
static inline void metal_spinlock_release(struct metal_spinlock *slock)
|
||||
{
|
||||
atomic_flag_clear(&slock->w);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_SPINLOCK__H__ */
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file sys.h
|
||||
* @brief System primitives for libmetal.
|
||||
* @brief Top level include internal to libmetal library code.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SYS__H__
|
||||
#define __METAL_SYS__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <metal/log.h>
|
||||
#include <metal/list.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup system Top Level Interfaces
|
||||
* @{ */
|
||||
|
||||
/** Physical address type. */
|
||||
typedef unsigned long metal_phys_addr_t;
|
||||
|
||||
/** Interrupt request number. */
|
||||
typedef int metal_irq_t;
|
||||
|
||||
/** Bad offset into shared memory or I/O region. */
|
||||
#define METAL_BAD_OFFSET ((unsigned long)-1)
|
||||
|
||||
/** Bad physical address value. */
|
||||
#define METAL_BAD_PHYS ((metal_phys_addr_t)-1)
|
||||
|
||||
/** Bad virtual address value. */
|
||||
#define METAL_BAD_VA ((void *)-1)
|
||||
|
||||
/** Bad IRQ. */
|
||||
#define METAL_BAD_IRQ ((metal_irq_t)-1)
|
||||
|
||||
/**
|
||||
* Initialization configuration for libmetal.
|
||||
*/
|
||||
struct metal_init_params {
|
||||
|
||||
/** log message handler (defaults to stderr). */
|
||||
metal_log_handler log_handler;
|
||||
|
||||
/** default log message level (defaults to emergency). */
|
||||
enum metal_log_level log_level;
|
||||
};
|
||||
|
||||
/**
|
||||
* System independent runtime state for libmetal. This is part of a system
|
||||
* specific singleton data structure (@see _metal).
|
||||
*/
|
||||
struct metal_common_state {
|
||||
/** Current log level. */
|
||||
enum metal_log_level log_level;
|
||||
|
||||
/** Current log handler (null for none). */
|
||||
metal_log_handler log_handler;
|
||||
|
||||
/** List of registered buses. */
|
||||
struct metal_list bus_list;
|
||||
|
||||
/** Generic statically defined shared memory segments. */
|
||||
struct metal_list generic_shmem_list;
|
||||
|
||||
/** Generic statically defined devices. */
|
||||
struct metal_list generic_device_list;
|
||||
};
|
||||
|
||||
struct metal_state;
|
||||
|
||||
#include <metal/system/generic/sys.h>
|
||||
|
||||
#ifndef METAL_INIT_DEFAULTS
|
||||
#define METAL_INIT_DEFAULTS \
|
||||
{ \
|
||||
.log_handler = metal_default_log_handler, \
|
||||
.log_level = METAL_LOG_INFO, \
|
||||
}
|
||||
#endif
|
||||
|
||||
/** System specific runtime data. */
|
||||
extern struct metal_state _metal;
|
||||
|
||||
/**
|
||||
* @brief Initialize libmetal.
|
||||
*
|
||||
* Initialize the libmetal library.
|
||||
*
|
||||
* @param[in] params Initialization params (@see metal_init_params).
|
||||
*
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*
|
||||
* @see metal_finish
|
||||
*/
|
||||
extern int metal_init(const struct metal_init_params *params);
|
||||
|
||||
/**
|
||||
* @brief Shutdown libmetal.
|
||||
*
|
||||
* Shutdown the libmetal library, and release all reserved resources.
|
||||
*
|
||||
* @see metal_init
|
||||
*/
|
||||
extern void metal_finish(void);
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief libmetal system initialization.
|
||||
*
|
||||
* This function initializes libmetal on Linux or Generic platforms. This
|
||||
* involves obtaining necessary pieces of system information (sysfs mount path,
|
||||
* page size, etc.).
|
||||
*
|
||||
* @param[in] params Initialization parameters (@see metal_init_params).
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
extern int metal_sys_init(const struct metal_init_params *params);
|
||||
|
||||
/**
|
||||
* @brief libmetal system shutdown.
|
||||
*
|
||||
* This function shuts down and releases resources held by libmetal Linux or
|
||||
* Generic platform layers.
|
||||
*
|
||||
* @see metal_sys_init
|
||||
*/
|
||||
extern void metal_sys_finish(void);
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_SYS__H__ */
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/alloc.c
|
||||
* @brief generic libmetal memory allocattion definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ALLOC__H__
|
||||
#error "Include metal/alloc.h instead of metal/generic/alloc.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_ALLOC__H__
|
||||
#define __METAL_GENERIC_ALLOC__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void *metal_allocate_memory(unsigned int size)
|
||||
{
|
||||
return (malloc(size));
|
||||
}
|
||||
|
||||
static inline void metal_free_memory(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_ALLOC__H__ */
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file assert.h
|
||||
* @brief Generic assertion support.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ASSERT__H__
|
||||
#error "Include metal/assert.h instead of metal/generic/assert.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_ASSERT__H__
|
||||
#define __METAL_GENERIC_ASSERT__H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/**
|
||||
* @brief Assertion macro for bare-metal applications.
|
||||
* @param cond Condition to evaluate.
|
||||
*/
|
||||
#define metal_sys_assert(cond) assert(cond)
|
||||
|
||||
#endif /* __METAL_GENERIC_ASSERT__H__ */
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/cache.h
|
||||
* @brief generic cache operation primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CACHE__H__
|
||||
#error "Include metal/cache.h instead of metal/generic/cache.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_CACHE__H__
|
||||
#define __METAL_GENERIC_CACHE__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void metal_machine_cache_flush(void *addr, unsigned int len);
|
||||
extern void metal_machine_cache_invalidate(void *addr, unsigned int len);
|
||||
|
||||
static inline void __metal_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
metal_machine_cache_flush(addr, len);
|
||||
}
|
||||
|
||||
static inline void __metal_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
metal_machine_cache_invalidate(addr, len);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_CACHE__H__ */
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/condition.h
|
||||
* @brief Generic condition variable primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CONDITION__H__
|
||||
#error "Include metal/condition.h instead of metal/generic/condition.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_CONDITION__H__
|
||||
#define __METAL_GENERIC_CONDITION__H__
|
||||
|
||||
#if defined (__CC_ARM)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <metal/atomic.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <metal/errno.h>
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct metal_condition {
|
||||
metal_mutex_t *m; /**< mutex.
|
||||
The condition variable is attached to
|
||||
this mutex when it is waiting.
|
||||
It is also used to check correctness
|
||||
in case there are multiple waiters. */
|
||||
|
||||
atomic_int v; /**< condition variable value. */
|
||||
};
|
||||
|
||||
/** Static metal condition variable initialization. */
|
||||
#define METAL_CONDITION_INIT { NULL, ATOMIC_VAR_INIT(0) }
|
||||
|
||||
static inline void metal_condition_init(struct metal_condition *cv)
|
||||
{
|
||||
cv->m = NULL;
|
||||
atomic_init(&cv->v, 0);
|
||||
}
|
||||
|
||||
static inline int metal_condition_signal(struct metal_condition *cv)
|
||||
{
|
||||
if (!cv)
|
||||
return -EINVAL;
|
||||
|
||||
/** wake up waiters if there are any. */
|
||||
atomic_fetch_add(&cv->v, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int metal_condition_broadcast(struct metal_condition *cv)
|
||||
{
|
||||
return metal_condition_signal(cv);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_CONDITION__H__ */
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Xilinx nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/mp1_m4/sys.h
|
||||
* @brief generic mp1_m4 system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_GENERIC_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/generic/cortexm/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_MP1_M4_SYS__H__
|
||||
#define __METAL_GENERIC_MP1_M4_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(MAX_IRQS)
|
||||
#define MAX_IRQS 8 /**< maximum number of irqs */
|
||||
#endif
|
||||
|
||||
static inline void sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
(void)vector;
|
||||
}
|
||||
|
||||
static inline void sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
(void)vector;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_MP1_M4_SYS__H__ */
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/io.h
|
||||
* @brief Generic specific io definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IO__H__
|
||||
#error "Include metal/io.h instead of metal/generic/io.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_IO__H__
|
||||
#define __METAL_GENERIC_IO__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief memory mapping for an I/O region
|
||||
*/
|
||||
void metal_sys_io_mem_map(struct metal_io_region *io);
|
||||
|
||||
/**
|
||||
* @brief memory mapping
|
||||
*/
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_IO__H__ */
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/irq.c
|
||||
* @brief Generic libmetal irq definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IRQ__H__
|
||||
#error "Include metal/irq.h instead of metal/generic/irq.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_IRQ__H__
|
||||
#define __METAL_GENERIC_IRQ__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief default interrupt handler
|
||||
* @param[in] vector interrupt vector
|
||||
*/
|
||||
void metal_irq_isr(unsigned int vector);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_IRQ__H__ */
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Linaro nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/log.h
|
||||
* @brief Generic libmetal log handler definition.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_METAL_LOG__H__
|
||||
#error "Include metal/log.h instead of metal/generic/log.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_LOG__H__
|
||||
#define __METAL_GENERIC_LOG__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_LOG__H__ */
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/mutex.h
|
||||
* @brief Generic mutex primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_MUTEX__H__
|
||||
#error "Include metal/mutex.h instead of metal/generic/mutex.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_MUTEX__H__
|
||||
#define __METAL_GENERIC_MUTEX__H__
|
||||
|
||||
#include <metal/atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
union{
|
||||
atomic_int v;
|
||||
atomic_flag w;
|
||||
};
|
||||
} metal_mutex_t;
|
||||
|
||||
/*
|
||||
* METAL_MUTEX_INIT - used for initializing an mutex elmenet in a static struct
|
||||
* or global
|
||||
*/
|
||||
#define METAL_MUTEX_INIT(m) { ATOMIC_VAR_INIT(0) }
|
||||
/*
|
||||
* METAL_MUTEX_DEFINE - used for defining and initializing a global or
|
||||
* static singleton mutex
|
||||
*/
|
||||
#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m)
|
||||
|
||||
static inline void __metal_mutex_init(metal_mutex_t *mutex)
|
||||
{
|
||||
atomic_store(&mutex->v, 0);
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_deinit(metal_mutex_t *mutex)
|
||||
{
|
||||
(void)mutex;
|
||||
}
|
||||
|
||||
static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
return 1 - atomic_flag_test_and_set(&mutex->w);
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
while (atomic_flag_test_and_set(&mutex->w)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_release(metal_mutex_t *mutex)
|
||||
{
|
||||
atomic_flag_clear(&mutex->w);
|
||||
}
|
||||
|
||||
static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex)
|
||||
{
|
||||
return atomic_load(&mutex->v);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_MUTEX__H__ */
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/sleep.h
|
||||
* @brief Generic sleep primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SLEEP__H__
|
||||
#error "Include metal/sleep.h instead of metal/generic/sleep.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_SLEEP__H__
|
||||
#define __METAL_GENERIC_SLEEP__H__
|
||||
|
||||
#include <metal/utilities.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline int __metal_sleep_usec(unsigned int usec)
|
||||
{
|
||||
metal_unused(usec);
|
||||
/* Fix me */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_SLEEP__H__ */
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/sys.h
|
||||
* @brief Generic system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/generic/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_SYS__H__
|
||||
#define __METAL_GENERIC_SYS__H__
|
||||
|
||||
#include <metal/errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "./cortexm/sys.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef METAL_MAX_DEVICE_REGIONS
|
||||
#define METAL_MAX_DEVICE_REGIONS 1
|
||||
#endif
|
||||
|
||||
/** Structure of generic libmetal runtime state. */
|
||||
struct metal_state {
|
||||
|
||||
/** Common (system independent) data. */
|
||||
struct metal_common_state common;
|
||||
};
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief restore interrupts to state before disable_global_interrupt()
|
||||
*/
|
||||
void sys_irq_restore_enable(unsigned int flags);
|
||||
|
||||
/**
|
||||
* @brief disable all interrupts
|
||||
*/
|
||||
unsigned int sys_irq_save_disable(void);
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_SYS__H__ */
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file time.h
|
||||
* @brief Time primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_TIME__H__
|
||||
#define __METAL_TIME__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup time TIME Interfaces
|
||||
* @{ */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <metal/sys.h>
|
||||
|
||||
/**
|
||||
* @brief get timestamp
|
||||
* This function returns the timestampe as unsigned long long
|
||||
* value.
|
||||
*
|
||||
* @return timestamp
|
||||
*/
|
||||
unsigned long long metal_get_timestamp(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_TIME__H__ */
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file utilities.h
|
||||
* @brief Utility routines for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_UTILITIES__H__
|
||||
#define __METAL_UTILITIES__H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <metal/assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup utilities Simple Utilities
|
||||
* @{ */
|
||||
|
||||
/** Marker for unused function arguments/variables. */
|
||||
#define metal_unused(x) do { (x) = (x); } while (0)
|
||||
|
||||
/** Figure out number of elements in an array. */
|
||||
#define metal_dim(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
/** Minimum of two numbers (warning: multiple evaluation!). */
|
||||
#define metal_min(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
/** Maximum of two numbers (warning: multiple evaluation!). */
|
||||
#define metal_max(x, y) ((x) > (y) ? (x) : (y))
|
||||
|
||||
/** Sign of a number [-1, 0, or 1] (warning: multiple evaluation!). */
|
||||
#define metal_sign(x) ((x) < 0 ? -1 : ((x) > 0 ? 1 : 0))
|
||||
|
||||
/** Align 'size' down to a multiple of 'align' (must be a power of two). */
|
||||
#define metal_align_down(size, align) \
|
||||
((size) & ~((align) - 1))
|
||||
|
||||
/** Align 'size' up to a multiple of 'align' (must be a power of two). */
|
||||
#define metal_align_up(size, align) \
|
||||
metal_align_down((size) + (align) - 1, align)
|
||||
|
||||
/** Divide (and round down). */
|
||||
#define metal_div_round_down(num, den) \
|
||||
((num) / (den))
|
||||
|
||||
/** Divide (and round up). */
|
||||
#define metal_div_round_up(num, den) \
|
||||
metal_div_round_down((num) + (den) - 1, (den))
|
||||
|
||||
/** Align 'ptr' down to a multiple of 'align' (must be a power of two). */
|
||||
#define metal_ptr_align_down(ptr, align) \
|
||||
(void *)(metal_align_down((uintptr_t)(ptr), (uintptr_t)(align)))
|
||||
|
||||
/** Align 'ptr' up to a multiple of 'align' (must be a power of two). */
|
||||
#define metal_ptr_align_up(ptr, align) \
|
||||
(void *)(metal_align_up((uintptr_t)(ptr), (uintptr_t)(align)))
|
||||
|
||||
/** Compute offset of a field within a structure. */
|
||||
#define metal_offset_of(structure, member) \
|
||||
((uintptr_t) &(((structure *) 0)->member))
|
||||
|
||||
/** Compute pointer to a structure given a pointer to one of its fields. */
|
||||
#define metal_container_of(ptr, structure, member) \
|
||||
(void *)((uintptr_t)(ptr) - metal_offset_of(structure, member))
|
||||
|
||||
#define METAL_BITS_PER_ULONG (8 * sizeof(unsigned long))
|
||||
|
||||
#define metal_bit(bit) (1UL << (bit))
|
||||
|
||||
#define metal_bitmap_longs(x) metal_div_round_up((x), METAL_BITS_PER_ULONG)
|
||||
|
||||
static inline void metal_bitmap_set_bit(unsigned long *bitmap, int bit)
|
||||
{
|
||||
bitmap[bit / METAL_BITS_PER_ULONG] |=
|
||||
metal_bit(bit & (METAL_BITS_PER_ULONG - 1));
|
||||
}
|
||||
|
||||
static inline int metal_bitmap_is_bit_set(unsigned long *bitmap, int bit)
|
||||
{
|
||||
return bitmap[bit / METAL_BITS_PER_ULONG] &
|
||||
metal_bit(bit & (METAL_BITS_PER_ULONG - 1));
|
||||
}
|
||||
|
||||
static inline void metal_bitmap_clear_bit(unsigned long *bitmap, int bit)
|
||||
{
|
||||
bitmap[bit / METAL_BITS_PER_ULONG] &=
|
||||
~metal_bit(bit & (METAL_BITS_PER_ULONG - 1));
|
||||
}
|
||||
|
||||
static inline int metal_bitmap_is_bit_clear(unsigned long *bitmap, int bit)
|
||||
{
|
||||
return !metal_bitmap_is_bit_set(bitmap, bit);
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
metal_bitmap_next_set_bit(unsigned long *bitmap, unsigned int start,
|
||||
unsigned int max)
|
||||
{
|
||||
unsigned int bit;
|
||||
for (bit = start;
|
||||
bit < max && !metal_bitmap_is_bit_set(bitmap, bit);
|
||||
bit ++)
|
||||
;
|
||||
return bit;
|
||||
}
|
||||
|
||||
#define metal_bitmap_for_each_set_bit(bitmap, bit, max) \
|
||||
for ((bit) = metal_bitmap_next_set_bit((bitmap), 0, (max)); \
|
||||
(bit) < (max); \
|
||||
(bit) = metal_bitmap_next_set_bit((bitmap), (bit), (max)))
|
||||
|
||||
static inline unsigned int
|
||||
metal_bitmap_next_clear_bit(unsigned long *bitmap, unsigned int start,
|
||||
unsigned int max)
|
||||
{
|
||||
unsigned int bit;
|
||||
for (bit = start;
|
||||
bit < max && !metal_bitmap_is_bit_clear(bitmap, bit);
|
||||
bit ++)
|
||||
;
|
||||
return bit;
|
||||
}
|
||||
|
||||
#define metal_bitmap_for_each_clear_bit(bitmap, bit, max) \
|
||||
for ((bit) = metal_bitmap_next_clear_bit((bitmap), 0, (max)); \
|
||||
(bit) < (max); \
|
||||
(bit) = metal_bitmap_next_clear_bit((bitmap), (bit), (max)))
|
||||
|
||||
static inline unsigned long metal_log2(unsigned long in)
|
||||
{
|
||||
unsigned long result;
|
||||
|
||||
metal_assert((in & (in - 1)) == 0);
|
||||
|
||||
for (result = 0; (1UL << result) < in; result ++)
|
||||
;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_UTILITIES__H__ */
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file version.h
|
||||
* @brief Library version information for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_VERSION__H__
|
||||
#define __METAL_VERSION__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup versions Library Version Interfaces
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
* @brief Library major version number.
|
||||
*
|
||||
* Return the major version number of the library linked into the application.
|
||||
* This is required to match the value of METAL_VER_MAJOR, which is the major
|
||||
* version of the library that the application was compiled against.
|
||||
*
|
||||
* @return Library major version number.
|
||||
* @see METAL_VER_MAJOR
|
||||
*/
|
||||
extern int metal_ver_major(void);
|
||||
|
||||
/**
|
||||
* @brief Library minor version number.
|
||||
*
|
||||
* Return the minor version number of the library linked into the application.
|
||||
* This could differ from the value of METAL_VER_MINOR, which is the minor
|
||||
* version of the library that the application was compiled against.
|
||||
*
|
||||
* @return Library minor version number.
|
||||
* @see METAL_VER_MINOR
|
||||
*/
|
||||
extern int metal_ver_minor(void);
|
||||
|
||||
/**
|
||||
* @brief Library patch level.
|
||||
*
|
||||
* Return the patch level of the library linked into the application. This
|
||||
* could differ from the value of METAL_VER_PATCH, which is the patch level of
|
||||
* the library that the application was compiled against.
|
||||
*
|
||||
* @return Library patch level.
|
||||
* @see METAL_VER_PATCH
|
||||
*/
|
||||
extern int metal_ver_patch(void);
|
||||
|
||||
/**
|
||||
* @brief Library version string.
|
||||
*
|
||||
* Return the version string of the library linked into the application. This
|
||||
* could differ from the value of METAL_VER, which is the version string of
|
||||
* the library that the application was compiled against.
|
||||
*
|
||||
* @return Library version string.
|
||||
* @see METAL_VER
|
||||
*/
|
||||
extern const char *metal_ver(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_VERSION__H__ */
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <metal/sys.h>
|
||||
|
||||
int metal_init(const struct metal_init_params *params)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
memset(&_metal, 0, sizeof(_metal));
|
||||
|
||||
_metal.common.log_handler = params->log_handler;
|
||||
_metal.common.log_level = params->log_level;
|
||||
|
||||
metal_list_init(&_metal.common.bus_list);
|
||||
metal_list_init(&_metal.common.generic_shmem_list);
|
||||
metal_list_init(&_metal.common.generic_device_list);
|
||||
|
||||
error = metal_sys_init(params);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void metal_finish(void)
|
||||
{
|
||||
metal_sys_finish();
|
||||
memset(&_metal, 0, sizeof(_metal));
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <metal/errno.h>
|
||||
#include <limits.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
|
||||
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)
|
||||
{
|
||||
const struct metal_io_ops nops = {NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
|
||||
io->virt = virt;
|
||||
io->physmap = physmap;
|
||||
io->size = size;
|
||||
io->page_shift = page_shift;
|
||||
if (page_shift >= sizeof(io->page_mask) * CHAR_BIT)
|
||||
/* avoid overflow */
|
||||
io->page_mask = -1UL;
|
||||
else
|
||||
io->page_mask = (1UL << page_shift) - 1UL;
|
||||
io->mem_flags = mem_flags;
|
||||
io->ops = ops ? *ops : nops;
|
||||
metal_sys_io_mem_map(io);
|
||||
}
|
||||
|
||||
int metal_io_block_read(struct metal_io_region *io, unsigned long offset,
|
||||
void *restrict dst, int len)
|
||||
{
|
||||
unsigned char *ptr = metal_io_virt(io, offset);
|
||||
unsigned char *dest = dst;
|
||||
int retlen;
|
||||
|
||||
if (offset > io->size)
|
||||
return -ERANGE;
|
||||
if ((offset + len) > io->size)
|
||||
len = io->size - offset;
|
||||
retlen = len;
|
||||
if (io->ops.block_read) {
|
||||
retlen = (*io->ops.block_read)(
|
||||
io, offset, dst, memory_order_seq_cst, len);
|
||||
} else {
|
||||
atomic_thread_fence(memory_order_seq_cst);
|
||||
while ( len && (
|
||||
((uintptr_t)dest % sizeof(int)) ||
|
||||
((uintptr_t)ptr % sizeof(int)))) {
|
||||
*(unsigned char *)dest =
|
||||
*(const unsigned char *)ptr;
|
||||
dest++;
|
||||
ptr++;
|
||||
len--;
|
||||
}
|
||||
for (; len >= (int)sizeof(int); dest += sizeof(int),
|
||||
ptr += sizeof(int),
|
||||
len -= sizeof(int))
|
||||
*(unsigned int *)dest = *(const unsigned int *)ptr;
|
||||
for (; len != 0; dest++, ptr++, len--)
|
||||
*(unsigned char *)dest =
|
||||
*(const unsigned char *)ptr;
|
||||
}
|
||||
return retlen;
|
||||
}
|
||||
|
||||
int metal_io_block_write(struct metal_io_region *io, unsigned long offset,
|
||||
const void *restrict src, int len)
|
||||
{
|
||||
unsigned char *ptr = metal_io_virt(io, offset);
|
||||
const unsigned char *source = src;
|
||||
int retlen;
|
||||
|
||||
if (offset > io->size)
|
||||
return -ERANGE;
|
||||
if ((offset + len) > io->size)
|
||||
len = io->size - offset;
|
||||
retlen = len;
|
||||
if (io->ops.block_write) {
|
||||
retlen = (*io->ops.block_write)(
|
||||
io, offset, src, memory_order_seq_cst, len);
|
||||
} else {
|
||||
while ( len && (
|
||||
((uintptr_t)ptr % sizeof(int)) ||
|
||||
((uintptr_t)source % sizeof(int)))) {
|
||||
*(unsigned char *)ptr =
|
||||
*(const unsigned char *)source;
|
||||
ptr++;
|
||||
source++;
|
||||
len--;
|
||||
}
|
||||
for (; len >= (int)sizeof(int); ptr += sizeof(int),
|
||||
source += sizeof(int),
|
||||
len -= sizeof(int))
|
||||
*(unsigned int *)ptr = *(const unsigned int *)source;
|
||||
for (; len != 0; ptr++, source++, len--)
|
||||
*(unsigned char *)ptr =
|
||||
*(const unsigned char *)source;
|
||||
atomic_thread_fence(memory_order_seq_cst);
|
||||
}
|
||||
return retlen;
|
||||
}
|
||||
|
||||
int metal_io_block_set(struct metal_io_region *io, unsigned long offset,
|
||||
unsigned char value, int len)
|
||||
{
|
||||
unsigned char *ptr = metal_io_virt(io, offset);
|
||||
int retlen = len;
|
||||
|
||||
if (offset > io->size)
|
||||
return -ERANGE;
|
||||
if ((offset + len) > io->size)
|
||||
len = io->size - offset;
|
||||
retlen = len;
|
||||
if (io->ops.block_set) {
|
||||
(*io->ops.block_set)(
|
||||
io, offset, value, memory_order_seq_cst, len);
|
||||
} else {
|
||||
unsigned int cint = value;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 1; i < sizeof(int); i++)
|
||||
cint |= ((unsigned int)value << (8 * i));
|
||||
|
||||
for (; len && ((uintptr_t)ptr % sizeof(int)); ptr++, len--)
|
||||
*(unsigned char *)ptr = (unsigned char) value;
|
||||
for (; len >= (int)sizeof(int); ptr += sizeof(int),
|
||||
len -= sizeof(int))
|
||||
*(unsigned int *)ptr = cint;
|
||||
for (; len != 0; ptr++, len--)
|
||||
*(unsigned char *)ptr = (unsigned char) value;
|
||||
atomic_thread_fence(memory_order_seq_cst);
|
||||
}
|
||||
return retlen;
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <metal/log.h>
|
||||
#include <metal/sys.h>
|
||||
|
||||
void metal_default_log_handler(enum metal_log_level level,
|
||||
const char *format, ...)
|
||||
{
|
||||
#ifdef DEFAULT_LOGGER_ON
|
||||
char msg[1024];
|
||||
va_list args;
|
||||
static const char *level_strs[] = {
|
||||
"metal: emergency: ",
|
||||
"metal: alert: ",
|
||||
"metal: critical: ",
|
||||
"metal: error: ",
|
||||
"metal: warning: ",
|
||||
"metal: notice: ",
|
||||
"metal: info: ",
|
||||
"metal: debug: ",
|
||||
};
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(msg, sizeof(msg), format, args);
|
||||
va_end(args);
|
||||
|
||||
if (level <= METAL_LOG_EMERGENCY || level > METAL_LOG_DEBUG)
|
||||
level = METAL_LOG_EMERGENCY;
|
||||
|
||||
fprintf(stderr, "%s%s", level_strs[level], msg);
|
||||
#else
|
||||
(void)level;
|
||||
(void)format;
|
||||
#endif
|
||||
}
|
||||
|
||||
void metal_set_log_handler(metal_log_handler handler)
|
||||
{
|
||||
_metal.common.log_handler = handler;
|
||||
}
|
||||
|
||||
metal_log_handler metal_get_log_handler(void)
|
||||
{
|
||||
return _metal.common.log_handler;
|
||||
}
|
||||
|
||||
void metal_set_log_level(enum metal_log_level level)
|
||||
{
|
||||
_metal.common.log_level = level;
|
||||
}
|
||||
|
||||
enum metal_log_level metal_get_log_level(void)
|
||||
{
|
||||
return _metal.common.log_level;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/shmem.c
|
||||
* @brief Generic libmetal shared memory handling.
|
||||
*/
|
||||
|
||||
#include <metal/errno.h>
|
||||
#include <metal/assert.h>
|
||||
#include <metal/shmem.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
int metal_shmem_register_generic(struct metal_generic_shmem *shmem)
|
||||
{
|
||||
/* Make sure that we can be found. */
|
||||
metal_assert(shmem->name && strlen(shmem->name) != 0);
|
||||
|
||||
/* Statically registered shmem regions cannot have a destructor. */
|
||||
metal_assert(!shmem->io.ops.close);
|
||||
|
||||
metal_list_add_tail(&_metal.common.generic_shmem_list,
|
||||
&shmem->node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_shmem_open_generic(const char *name, size_t size,
|
||||
struct metal_io_region **result)
|
||||
{
|
||||
struct metal_generic_shmem *shmem;
|
||||
struct metal_list *node;
|
||||
|
||||
metal_list_for_each(&_metal.common.generic_shmem_list, node) {
|
||||
shmem = metal_container_of(node, struct metal_generic_shmem, node);
|
||||
if (strcmp(shmem->name, name) != 0)
|
||||
continue;
|
||||
if (size > metal_io_region_size(&shmem->io))
|
||||
continue;
|
||||
*result = &shmem->io;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <metal/errno.h>
|
||||
#include <metal/assert.h>
|
||||
#include <metal/device.h>
|
||||
#include <metal/list.h>
|
||||
#include <metal/log.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/dma.h>
|
||||
#include <metal/cache.h>
|
||||
|
||||
int metal_bus_register(struct metal_bus *bus)
|
||||
{
|
||||
if (!bus || !bus->name || !strlen(bus->name))
|
||||
return -EINVAL;
|
||||
if (metal_bus_find(bus->name, NULL) == 0)
|
||||
return -EEXIST;
|
||||
metal_list_init(&bus->devices);
|
||||
metal_list_add_tail(&_metal.common.bus_list, &bus->node);
|
||||
metal_log(METAL_LOG_DEBUG, "registered %s bus\n", bus->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_bus_unregister(struct metal_bus *bus)
|
||||
{
|
||||
metal_list_del(&bus->node);
|
||||
if (bus->ops.bus_close)
|
||||
bus->ops.bus_close(bus);
|
||||
metal_log(METAL_LOG_DEBUG, "unregistered %s bus\n", bus->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_bus_find(const char *name, struct metal_bus **result)
|
||||
{
|
||||
struct metal_list *node;
|
||||
struct metal_bus *bus;
|
||||
|
||||
metal_list_for_each(&_metal.common.bus_list, node) {
|
||||
bus = metal_container_of(node, struct metal_bus, node);
|
||||
if (strcmp(bus->name, name) != 0)
|
||||
continue;
|
||||
if (result)
|
||||
*result = bus;
|
||||
return 0;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int metal_device_open(const char *bus_name, const char *dev_name,
|
||||
struct metal_device **device)
|
||||
{
|
||||
struct metal_bus *bus;
|
||||
int error;
|
||||
|
||||
if (!bus_name || !strlen(bus_name) ||
|
||||
!dev_name || !strlen(dev_name) ||
|
||||
!device)
|
||||
return -EINVAL;
|
||||
|
||||
error = metal_bus_find(bus_name, &bus);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!bus->ops.dev_open)
|
||||
return -ENODEV;
|
||||
|
||||
error = (*bus->ops.dev_open)(bus, dev_name, device);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_device_close(struct metal_device *device)
|
||||
{
|
||||
metal_assert(device && device->bus);
|
||||
if (device->bus->ops.dev_close)
|
||||
device->bus->ops.dev_close(device->bus, device);
|
||||
}
|
||||
|
||||
int metal_register_generic_device(struct metal_device *device)
|
||||
{
|
||||
if (!device->name || !strlen(device->name) ||
|
||||
device->num_regions > METAL_MAX_DEVICE_REGIONS)
|
||||
return -EINVAL;
|
||||
|
||||
device->bus = &metal_generic_bus;
|
||||
metal_list_add_tail(&_metal.common.generic_device_list,
|
||||
&device->node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_generic_dev_open(struct metal_bus *bus, const char *dev_name,
|
||||
struct metal_device **device)
|
||||
{
|
||||
struct metal_list *node;
|
||||
struct metal_device *dev;
|
||||
|
||||
(void)bus;
|
||||
|
||||
metal_list_for_each(&_metal.common.generic_device_list, node) {
|
||||
dev = metal_container_of(node, struct metal_device, node);
|
||||
if (strcmp(dev->name, dev_name) != 0)
|
||||
continue;
|
||||
*device = dev;
|
||||
return metal_generic_dev_sys_open(dev);
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
(void)bus;
|
||||
(void)device;
|
||||
int i;
|
||||
|
||||
if (sg_out != sg_in)
|
||||
memcpy(sg_out, sg_in, nents_in*(sizeof(struct metal_sg)));
|
||||
for (i = 0; i < nents_in; i++) {
|
||||
if (dir == METAL_DMA_DEV_W) {
|
||||
metal_cache_flush(sg_out[i].virt, sg_out[i].len);
|
||||
}
|
||||
metal_cache_invalidate(sg_out[i].virt, sg_out[i].len);
|
||||
}
|
||||
|
||||
return nents_in;
|
||||
}
|
||||
|
||||
void metal_generic_dev_dma_unmap(struct metal_bus *bus,
|
||||
struct metal_device *device,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg,
|
||||
int nents)
|
||||
{
|
||||
(void)bus;
|
||||
(void)device;
|
||||
(void)dir;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nents; i++) {
|
||||
metal_cache_invalidate(sg[i].virt, sg[i].len);
|
||||
}
|
||||
}
|
||||
|
||||
struct metal_bus metal_weak metal_generic_bus = {
|
||||
.name = "generic",
|
||||
.ops = {
|
||||
.bus_close = NULL,
|
||||
.dev_open = metal_generic_dev_open,
|
||||
.dev_close = NULL,
|
||||
.dev_irq_ack = NULL,
|
||||
.dev_dma_map = metal_generic_dev_dma_map,
|
||||
.dev_dma_unmap = metal_generic_dev_dma_unmap,
|
||||
},
|
||||
};
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/alloc.c
|
||||
* @brief generic libmetal memory allocattion definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ALLOC__H__
|
||||
#error "Include metal/alloc.h instead of metal/generic/alloc.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_ALLOC__H__
|
||||
#define __METAL_GENERIC_ALLOC__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void *metal_allocate_memory(unsigned int size)
|
||||
{
|
||||
return (malloc(size));
|
||||
}
|
||||
|
||||
static inline void metal_free_memory(void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_ALLOC__H__ */
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file assert.h
|
||||
* @brief Generic assertion support.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ASSERT__H__
|
||||
#error "Include metal/assert.h instead of metal/generic/assert.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_ASSERT__H__
|
||||
#define __METAL_GENERIC_ASSERT__H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/**
|
||||
* @brief Assertion macro for bare-metal applications.
|
||||
* @param cond Condition to evaluate.
|
||||
*/
|
||||
#define metal_sys_assert(cond) assert(cond)
|
||||
|
||||
#endif /* __METAL_GENERIC_ASSERT__H__ */
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/cache.h
|
||||
* @brief generic cache operation primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CACHE__H__
|
||||
#error "Include metal/cache.h instead of metal/generic/cache.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_CACHE__H__
|
||||
#define __METAL_GENERIC_CACHE__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void metal_machine_cache_flush(void *addr, unsigned int len);
|
||||
extern void metal_machine_cache_invalidate(void *addr, unsigned int len);
|
||||
|
||||
static inline void __metal_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
metal_machine_cache_flush(addr, len);
|
||||
}
|
||||
|
||||
static inline void __metal_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
metal_machine_cache_invalidate(addr, len);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_CACHE__H__ */
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/condition.c
|
||||
* @brief Generic libmetal condition variable handling.
|
||||
*/
|
||||
|
||||
#include <metal/condition.h>
|
||||
#include <metal/irq.h>
|
||||
|
||||
extern void metal_generic_default_poll(void);
|
||||
|
||||
int metal_condition_wait(struct metal_condition *cv,
|
||||
metal_mutex_t *m)
|
||||
{
|
||||
metal_mutex_t *tmpm = 0;
|
||||
int v;
|
||||
unsigned int flags;
|
||||
|
||||
/* Check if the mutex has been acquired */
|
||||
if (!cv || !m || !metal_mutex_is_acquired(m))
|
||||
return -EINVAL;
|
||||
|
||||
if (!atomic_compare_exchange_strong(&cv->m->v, &tmpm->v, m->v)) {
|
||||
if (m != tmpm)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
v = atomic_load(&cv->v);
|
||||
|
||||
/* Release the mutex first. */
|
||||
metal_mutex_release(m);
|
||||
do {
|
||||
flags = metal_irq_save_disable();
|
||||
if (atomic_load(&cv->v) != v) {
|
||||
metal_irq_restore_enable(flags);
|
||||
break;
|
||||
}
|
||||
metal_generic_default_poll();
|
||||
metal_irq_restore_enable(flags);
|
||||
} while(1);
|
||||
/* Acquire the mutex again. */
|
||||
metal_mutex_acquire(m);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/condition.h
|
||||
* @brief Generic condition variable primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CONDITION__H__
|
||||
#error "Include metal/condition.h instead of metal/generic/condition.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_CONDITION__H__
|
||||
#define __METAL_GENERIC_CONDITION__H__
|
||||
|
||||
#include <unistd.h>
|
||||
#include <metal/atomic.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include <metal/errno.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct metal_condition {
|
||||
metal_mutex_t *m; /**< mutex.
|
||||
The condition variable is attached to
|
||||
this mutex when it is waiting.
|
||||
It is also used to check correctness
|
||||
in case there are multiple waiters. */
|
||||
|
||||
atomic_int v; /**< condition variable value. */
|
||||
};
|
||||
|
||||
/** Static metal condition variable initialization. */
|
||||
#define METAL_CONDITION_INIT { NULL, ATOMIC_VAR_INIT(0) }
|
||||
|
||||
static inline void metal_condition_init(struct metal_condition *cv)
|
||||
{
|
||||
cv->m = NULL;
|
||||
atomic_init(&cv->v, 0);
|
||||
}
|
||||
|
||||
static inline int metal_condition_signal(struct metal_condition *cv)
|
||||
{
|
||||
if (!cv)
|
||||
return -EINVAL;
|
||||
|
||||
/** wake up waiters if there are any. */
|
||||
atomic_fetch_add(&cv->v, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int metal_condition_broadcast(struct metal_condition *cv)
|
||||
{
|
||||
return metal_condition_signal(cv);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_CONDITION__H__ */
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Xilinx nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
|
||||
#include "metal/io.h"
|
||||
#include "metal/sys.h"
|
||||
|
||||
void sys_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int sys_irq_save_disable(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
(void)addr;
|
||||
(void)len;
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
(void)addr;
|
||||
(void)len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief poll function until some event happens
|
||||
*/
|
||||
void __attribute__((weak)) metal_generic_default_poll(void)
|
||||
{
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
(void)va;
|
||||
(void)pa;
|
||||
(void)size;
|
||||
(void)flags;
|
||||
|
||||
return va;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Xilinx nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/mp1_m4/sys.h
|
||||
* @brief generic mp1_m4 system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_GENERIC_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/generic/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_MP1_M4_SYS__H__
|
||||
#define __METAL_GENERIC_MP1_M4_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(MAX_IRQS)
|
||||
#define MAX_IRQS 8 /**< maximum number of irqs */
|
||||
#endif
|
||||
|
||||
static inline void sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
(void)vector;
|
||||
}
|
||||
|
||||
static inline void sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
(void)vector;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_MP1_M4_SYS__H__ */
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/device.c
|
||||
* @brief Generic libmetal device operations.
|
||||
*/
|
||||
|
||||
#include <metal/device.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
int metal_generic_dev_sys_open(struct metal_device *dev)
|
||||
{
|
||||
struct metal_io_region *io;
|
||||
unsigned i;
|
||||
|
||||
/* map I/O memory regions */
|
||||
for (i = 0; i < dev->num_regions; i++) {
|
||||
io = &dev->regions[i];
|
||||
if (!io->size)
|
||||
break;
|
||||
metal_sys_io_mem_map(io);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/init.c
|
||||
* @brief Generic libmetal initialization.
|
||||
*/
|
||||
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/device.h>
|
||||
|
||||
struct metal_state _metal;
|
||||
|
||||
int metal_sys_init(const struct metal_init_params *params)
|
||||
{
|
||||
metal_unused(params);
|
||||
metal_bus_register(&metal_generic_bus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_sys_finish(void)
|
||||
{
|
||||
metal_bus_unregister(&metal_generic_bus);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/io.c
|
||||
* @brief Generic libmetal io operations
|
||||
*/
|
||||
|
||||
#include <metal/io.h>
|
||||
|
||||
void metal_sys_io_mem_map(struct metal_io_region *io)
|
||||
{
|
||||
unsigned long p;
|
||||
size_t psize;
|
||||
size_t *va;
|
||||
|
||||
va = (size_t *)io->virt;
|
||||
psize = io->size;
|
||||
if (psize) {
|
||||
if (psize >> io->page_shift)
|
||||
psize = (size_t)1 << io->page_shift;
|
||||
for (p = 0; p <= (io->size >> io->page_shift); p++) {
|
||||
metal_machine_io_mem_map(va, io->physmap[p],
|
||||
psize, io->mem_flags);
|
||||
va += psize;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,279 @@
|
|||
/*
|
||||
* Copyright (c) 2016 - 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/irq.c
|
||||
* @brief generic libmetal irq definitions.
|
||||
*/
|
||||
|
||||
#include <metal/errno.h>
|
||||
#include <metal/irq.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/log.h>
|
||||
#include <metal/mutex.h>
|
||||
#include <metal/list.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/alloc.h>
|
||||
|
||||
/** IRQ handlers descriptor structure */
|
||||
struct metal_irq_hddesc {
|
||||
metal_irq_handler hd; /**< irq handler */
|
||||
void *drv_id; /**< id to identify the driver
|
||||
of the irq handler */
|
||||
struct metal_device *dev; /**< device identifier */
|
||||
struct metal_list node; /**< node on irq handlers list */
|
||||
};
|
||||
|
||||
/** IRQ descriptor structure */
|
||||
struct metal_irq_desc {
|
||||
int irq; /**< interrupt number */
|
||||
struct metal_list hdls; /**< interrupt handlers */
|
||||
struct metal_list node; /**< node on irqs list */
|
||||
};
|
||||
|
||||
/** IRQ state structure */
|
||||
struct metal_irqs_state {
|
||||
struct metal_list irqs; /**< interrupt descriptors */
|
||||
metal_mutex_t irq_lock; /**< access lock */
|
||||
};
|
||||
|
||||
static struct metal_irqs_state _irqs = {
|
||||
.irqs = METAL_INIT_LIST(_irqs.irqs),
|
||||
.irq_lock = METAL_MUTEX_INIT(_irqs.irq_lock),
|
||||
};
|
||||
|
||||
int metal_irq_register(int irq,
|
||||
metal_irq_handler hd,
|
||||
struct metal_device *dev,
|
||||
void *drv_id)
|
||||
{
|
||||
struct metal_irq_desc *irq_p = NULL;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
struct metal_list *node;
|
||||
unsigned int irq_flags_save;
|
||||
|
||||
if (irq < 0) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d need to be a positive number\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((drv_id == NULL) || (hd == NULL)) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d need drv_id and hd.\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Search for irq in list */
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if (irq_p->irq == irq) {
|
||||
struct metal_list *h_node;
|
||||
|
||||
/* Check if drv_id already exist */
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
/* if drv_id already exist reject */
|
||||
if ((hdl_p->drv_id == drv_id) &&
|
||||
((dev == NULL) || (hdl_p->dev == dev))) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d already registered."
|
||||
"Will not register again.\n",
|
||||
__func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* irq found and drv_id not used, get out of metal_list_for_each */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Either need to add handler to an existing list or to a new one */
|
||||
hdl_p = metal_allocate_memory(sizeof(struct metal_irq_hddesc));
|
||||
if (hdl_p == NULL) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d cannot allocate mem for drv_id %d.\n",
|
||||
__func__, irq, drv_id);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
hdl_p->hd = hd;
|
||||
hdl_p->drv_id = drv_id;
|
||||
hdl_p->dev = dev;
|
||||
|
||||
/* interrupt already registered, add handler to existing list*/
|
||||
if ((irq_p != NULL) && (irq_p->irq == irq)) {
|
||||
irq_flags_save = metal_irq_save_disable();
|
||||
metal_list_add_tail(&irq_p->hdls, &hdl_p->node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success, irq %d add drv_id %p \n",
|
||||
__func__, irq, drv_id);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* interrupt was not already registered, add */
|
||||
irq_p = metal_allocate_memory(sizeof(struct metal_irq_desc));
|
||||
if (irq_p == NULL) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d cannot allocate mem.\n",
|
||||
__func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
irq_p->irq = irq;
|
||||
metal_list_init(&irq_p->hdls);
|
||||
metal_list_add_tail(&irq_p->hdls, &hdl_p->node);
|
||||
|
||||
irq_flags_save = metal_irq_save_disable();
|
||||
metal_list_add_tail(&_irqs.irqs, &irq_p->node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success, added irq %d\n", __func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* helper function for metal_irq_unregister() */
|
||||
static void metal_irq_delete_node(struct metal_list *node, void *p_to_free)
|
||||
{
|
||||
unsigned int irq_flags_save;
|
||||
|
||||
irq_flags_save=metal_irq_save_disable();
|
||||
metal_list_del(node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
metal_free_memory(p_to_free);
|
||||
}
|
||||
|
||||
int metal_irq_unregister(int irq,
|
||||
metal_irq_handler hd,
|
||||
struct metal_device *dev,
|
||||
void *drv_id)
|
||||
{
|
||||
struct metal_irq_desc *irq_p;
|
||||
struct metal_list *node;
|
||||
|
||||
if (irq < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d need to be a positive number\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Search for irq in list */
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if (irq_p->irq == irq) {
|
||||
struct metal_list *h_node, *h_prenode;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
unsigned int delete_count = 0;
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: found irq %d\n",
|
||||
__func__, irq);
|
||||
|
||||
/* Search through handlers */
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
if (((hd == NULL) || (hdl_p->hd == hd)) &&
|
||||
((drv_id == NULL) || (hdl_p->drv_id == drv_id)) &&
|
||||
((dev == NULL) || (hdl_p->dev == dev))) {
|
||||
metal_log(METAL_LOG_DEBUG,
|
||||
"%s: unregister hd=%p drv_id=%p dev=%p\n",
|
||||
__func__, hdl_p->hd, hdl_p->drv_id, hdl_p->dev);
|
||||
h_prenode = h_node->prev;
|
||||
metal_irq_delete_node(h_node, hdl_p);
|
||||
h_node = h_prenode;
|
||||
delete_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* we did not find any handler to delete */
|
||||
if (!delete_count) {
|
||||
metal_log(METAL_LOG_DEBUG, "%s: No matching entry\n",
|
||||
__func__);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOENT;
|
||||
|
||||
}
|
||||
|
||||
/* if interrupt handlers list is empty, unregister interrupt */
|
||||
if (metal_list_is_empty(&irq_p->hdls)) {
|
||||
metal_log(METAL_LOG_DEBUG,
|
||||
"%s: handlers list empty, unregister interrupt\n",
|
||||
__func__);
|
||||
metal_irq_delete_node(node, irq_p);
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success\n", __func__);
|
||||
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: No matching IRQ entry\n", __func__);
|
||||
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
unsigned int metal_irq_save_disable(void)
|
||||
{
|
||||
return sys_irq_save_disable();
|
||||
}
|
||||
|
||||
void metal_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
sys_irq_restore_enable(flags);
|
||||
}
|
||||
|
||||
void metal_irq_enable(unsigned int vector)
|
||||
{
|
||||
sys_irq_enable(vector);
|
||||
}
|
||||
|
||||
void metal_irq_disable(unsigned int vector)
|
||||
{
|
||||
sys_irq_disable(vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief default handler
|
||||
*/
|
||||
void metal_irq_isr(unsigned int vector)
|
||||
{
|
||||
struct metal_list *node;
|
||||
struct metal_irq_desc *irq_p;
|
||||
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if ((unsigned int)irq_p->irq == vector) {
|
||||
struct metal_list *h_node;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
(hdl_p->hd)(vector, hdl_p->drv_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/irq.c
|
||||
* @brief Generic libmetal irq definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IRQ__H__
|
||||
#error "Include metal/irq.h instead of metal/generic/irq.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_IRQ__H__
|
||||
#define __METAL_GENERIC_IRQ__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief default interrupt handler
|
||||
* @param[in] vector interrupt vector
|
||||
*/
|
||||
void metal_irq_isr(unsigned int vector);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_IRQ__H__ */
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/shmem.c
|
||||
* @brief Generic libmetal shared memory handling.
|
||||
*/
|
||||
|
||||
#include <metal/shmem.h>
|
||||
|
||||
int metal_shmem_open(const char *name, size_t size,
|
||||
struct metal_io_region **io)
|
||||
{
|
||||
return metal_shmem_open_generic(name, size, io);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/time.c
|
||||
* @brief Generic libmetal time handling.
|
||||
*/
|
||||
|
||||
#include <metal/time.h>
|
||||
|
||||
unsigned long long metal_get_timestamp(void)
|
||||
{
|
||||
/* TODO: Implement timestamp for generic system */
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/io.h
|
||||
* @brief Generic specific io definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IO__H__
|
||||
#error "Include metal/io.h instead of metal/generic/io.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_IO__H__
|
||||
#define __METAL_GENERIC_IO__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief memory mapping for an I/O region
|
||||
*/
|
||||
void metal_sys_io_mem_map(struct metal_io_region *io);
|
||||
|
||||
/**
|
||||
* @brief memory mapping
|
||||
*/
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_IO__H__ */
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Linaro nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/log.h
|
||||
* @brief Generic libmetal log handler definition.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_METAL_LOG__H__
|
||||
#error "Include metal/log.h instead of metal/generic/log.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_LOG__H__
|
||||
#define __METAL_GENERIC_LOG__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_LOG__H__ */
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/mutex.h
|
||||
* @brief Generic mutex primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_MUTEX__H__
|
||||
#error "Include metal/mutex.h instead of metal/generic/mutex.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_MUTEX__H__
|
||||
#define __METAL_GENERIC_MUTEX__H__
|
||||
|
||||
#include <metal/atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
union{
|
||||
atomic_int v;
|
||||
atomic_flag w;
|
||||
};
|
||||
} metal_mutex_t;
|
||||
|
||||
/*
|
||||
* METAL_MUTEX_INIT - used for initializing an mutex elmenet in a static struct
|
||||
* or global
|
||||
*/
|
||||
#define METAL_MUTEX_INIT(m) { ATOMIC_VAR_INIT(0) }
|
||||
/*
|
||||
* METAL_MUTEX_DEFINE - used for defining and initializing a global or
|
||||
* static singleton mutex
|
||||
*/
|
||||
#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m)
|
||||
|
||||
static inline void __metal_mutex_init(metal_mutex_t *mutex)
|
||||
{
|
||||
atomic_store(&mutex->v, 0);
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_deinit(metal_mutex_t *mutex)
|
||||
{
|
||||
(void)mutex;
|
||||
}
|
||||
|
||||
static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
return 1 - atomic_flag_test_and_set(&mutex->w);
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
while (atomic_flag_test_and_set(&mutex->w)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_release(metal_mutex_t *mutex)
|
||||
{
|
||||
atomic_flag_clear(&mutex->w);
|
||||
}
|
||||
|
||||
static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex)
|
||||
{
|
||||
return atomic_load(&mutex->v);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_MUTEX__H__ */
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/sleep.h
|
||||
* @brief Generic sleep primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SLEEP__H__
|
||||
#error "Include metal/sleep.h instead of metal/generic/sleep.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_SLEEP__H__
|
||||
#define __METAL_GENERIC_SLEEP__H__
|
||||
|
||||
#include <metal/utilities.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline int __metal_sleep_usec(unsigned int usec)
|
||||
{
|
||||
metal_unused(usec);
|
||||
/* Fix me */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_SLEEP__H__ */
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/sys.h
|
||||
* @brief Generic system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/generic/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_GENERIC_SYS__H__
|
||||
#define __METAL_GENERIC_SYS__H__
|
||||
|
||||
#include <metal/errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "./@PROJECT_MACHINE@/sys.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef METAL_MAX_DEVICE_REGIONS
|
||||
#define METAL_MAX_DEVICE_REGIONS 1
|
||||
#endif
|
||||
|
||||
/** Structure of generic libmetal runtime state. */
|
||||
struct metal_state {
|
||||
|
||||
/** Common (system independent) data. */
|
||||
struct metal_common_state common;
|
||||
};
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief restore interrupts to state before disable_global_interrupt()
|
||||
*/
|
||||
void sys_irq_restore_enable(unsigned int flags);
|
||||
|
||||
/**
|
||||
* @brief disable all interrupts
|
||||
*/
|
||||
unsigned int sys_irq_save_disable(void);
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GENERIC_SYS__H__ */
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <metal/config.h>
|
||||
|
||||
int metal_ver_major(void)
|
||||
{
|
||||
return METAL_VER_MAJOR;
|
||||
}
|
||||
|
||||
int metal_ver_minor(void)
|
||||
{
|
||||
return METAL_VER_MINOR;
|
||||
}
|
||||
|
||||
int metal_ver_patch(void)
|
||||
{
|
||||
return METAL_VER_PATCH;
|
||||
}
|
||||
|
||||
const char *metal_ver(void)
|
||||
{
|
||||
return METAL_VER;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
#ifndef _COMPILER_H_
|
||||
#define _COMPILER_H_
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* FILE NAME
|
||||
*
|
||||
* compiler.h
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file defines compiler-specific macros.
|
||||
*
|
||||
***************************************************************************/
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* IAR ARM build tools */
|
||||
#if defined(__ICCARM__)
|
||||
|
||||
#ifndef OPENAMP_PACKED_BEGIN
|
||||
#define OPENAMP_PACKED_BEGIN __packed
|
||||
#endif
|
||||
|
||||
#ifndef OPENAMP_PACKED_END
|
||||
#define OPENAMP_PACKED_END
|
||||
#endif
|
||||
|
||||
/* GNUC */
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
#ifndef OPENAMP_PACKED_BEGIN
|
||||
#define OPENAMP_PACKED_BEGIN
|
||||
#endif
|
||||
|
||||
#ifndef OPENAMP_PACKED_END
|
||||
#define OPENAMP_PACKED_END __attribute__((__packed__))
|
||||
#endif
|
||||
|
||||
/* ARM GCC */
|
||||
#elif defined(__CC_ARM)
|
||||
|
||||
#ifndef OPENAMP_PACKED_BEGIN
|
||||
#define OPENAMP_PACKED_BEGIN _Pragma("pack(1U)")
|
||||
#endif
|
||||
|
||||
#ifndef OPENAMP_PACKED_END
|
||||
#define OPENAMP_PACKED_END _Pragma("pack()")
|
||||
#endif
|
||||
|
||||
#else
|
||||
/*
|
||||
* There is no default definition here to avoid wrong structures packing in case
|
||||
* of not supported compiler
|
||||
*/
|
||||
#error Please implement the structure packing macros for your compiler here!
|
||||
#endif
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _COMPILER_H_ */
|
|
@ -0,0 +1,428 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef ELF_LOADER_H_
|
||||
#define ELF_LOADER_H_
|
||||
|
||||
#include <openamp/remoteproc.h>
|
||||
#include <openamp/remoteproc_loader.h>
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* ELF32 base types - 32-bit. */
|
||||
typedef uint32_t Elf32_Addr;
|
||||
typedef uint16_t Elf32_Half;
|
||||
typedef uint32_t Elf32_Off;
|
||||
typedef int32_t Elf32_Sword;
|
||||
typedef uint32_t Elf32_Word;
|
||||
|
||||
/* ELF64 base types - 64-bit. */
|
||||
typedef uint64_t Elf64_Addr;
|
||||
typedef uint16_t Elf64_Half;
|
||||
typedef uint64_t Elf64_Off;
|
||||
typedef int32_t Elf64_Sword;
|
||||
typedef uint32_t Elf64_Word;
|
||||
typedef uint64_t Elf64_Xword;
|
||||
typedef int64_t Elf64_Sxword;
|
||||
|
||||
/* Size of ELF identifier field in the ELF file header. */
|
||||
#define EI_NIDENT 16
|
||||
|
||||
/* ELF32 file header */
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf32_Half e_type;
|
||||
Elf32_Half e_machine;
|
||||
Elf32_Word e_version;
|
||||
Elf32_Addr e_entry;
|
||||
Elf32_Off e_phoff;
|
||||
Elf32_Off e_shoff;
|
||||
Elf32_Word e_flags;
|
||||
Elf32_Half e_ehsize;
|
||||
Elf32_Half e_phentsize;
|
||||
Elf32_Half e_phnum;
|
||||
Elf32_Half e_shentsize;
|
||||
Elf32_Half e_shnum;
|
||||
Elf32_Half e_shstrndx;
|
||||
} Elf32_Ehdr;
|
||||
|
||||
/* ELF64 file header */
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf64_Half e_type;
|
||||
Elf64_Half e_machine;
|
||||
Elf64_Word e_version;
|
||||
Elf64_Addr e_entry;
|
||||
Elf64_Off e_phoff;
|
||||
Elf64_Off e_shoff;
|
||||
Elf64_Word e_flags;
|
||||
Elf64_Half e_ehsize;
|
||||
Elf64_Half e_phentsize;
|
||||
Elf64_Half e_phnum;
|
||||
Elf64_Half e_shentsize;
|
||||
Elf64_Half e_shnum;
|
||||
Elf64_Half e_shstrndx;
|
||||
} Elf64_Ehdr;
|
||||
|
||||
/* e_ident */
|
||||
#define ET_NONE 0
|
||||
#define ET_REL 1 /* Re-locatable file */
|
||||
#define ET_EXEC 2 /* Executable file */
|
||||
#define ET_DYN 3 /* Shared object file */
|
||||
#define ET_CORE 4 /* Core file */
|
||||
#define ET_LOOS 0xfe00 /* Operating system-specific */
|
||||
#define ET_HIOS 0xfeff /* Operating system-specific */
|
||||
#define ET_LOPROC 0xff00 /* remote_proc-specific */
|
||||
#define ET_HIPROC 0xffff /* remote_proc-specific */
|
||||
|
||||
/* e_machine */
|
||||
#define EM_ARM 40 /* ARM/Thumb Architecture */
|
||||
|
||||
/* e_version */
|
||||
#define EV_CURRENT 1 /* Current version */
|
||||
|
||||
/* e_ident[] Identification Indexes */
|
||||
#define EI_MAG0 0 /* File identification */
|
||||
#define EI_MAG1 1 /* File identification */
|
||||
#define EI_MAG2 2 /* File identification */
|
||||
#define EI_MAG3 3 /* File identification */
|
||||
#define EI_CLASS 4 /* File class */
|
||||
#define EI_DATA 5 /* Data encoding */
|
||||
#define EI_VERSION 6 /* File version */
|
||||
#define EI_OSABI 7 /* Operating system/ABI identification */
|
||||
#define EI_ABIVERSION 8 /* ABI version */
|
||||
#define EI_PAD 9 /* Start of padding bytes */
|
||||
#define EI_NIDENT 16 /* Size of e_ident[] */
|
||||
|
||||
/*
|
||||
* EI_MAG0 to EI_MAG3 - A file's first 4 bytes hold amagic number, identifying
|
||||
* the file as an ELF object file
|
||||
*/
|
||||
#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */
|
||||
#define ELFMAG1 'E' /* e_ident[EI_MAG1] */
|
||||
#define ELFMAG2 'L' /* e_ident[EI_MAG2] */
|
||||
#define ELFMAG3 'F' /* e_ident[EI_MAG3] */
|
||||
#define ELFMAG "\177ELF"
|
||||
#define SELFMAG 4
|
||||
|
||||
/*
|
||||
* EI_CLASS - The next byte, e_ident[EI_CLASS], identifies the file's class, or
|
||||
* capacity.
|
||||
*/
|
||||
#define ELFCLASSNONE 0 /* Invalid class */
|
||||
#define ELFCLASS32 1 /* 32-bit objects */
|
||||
#define ELFCLASS64 2 /* 64-bit objects */
|
||||
|
||||
/*
|
||||
* EI_DATA - Byte e_ident[EI_DATA] specifies the data encoding of the
|
||||
* remote_proc-specific data in the object file. The following encodings are
|
||||
* currently defined.
|
||||
*/
|
||||
#define ELFDATANONE 0 /* Invalid data encoding */
|
||||
#define ELFDATA2LSB 1 /* See Data encodings, below */
|
||||
#define ELFDATA2MSB 2 /* See Data encodings, below */
|
||||
|
||||
/* EI_OSABI - We do not define an OS specific ABI */
|
||||
#define ELFOSABI_NONE 0
|
||||
|
||||
/* ELF32 program header */
|
||||
typedef struct elf32_phdr{
|
||||
Elf32_Word p_type;
|
||||
Elf32_Off p_offset;
|
||||
Elf32_Addr p_vaddr;
|
||||
Elf32_Addr p_paddr;
|
||||
Elf32_Word p_filesz;
|
||||
Elf32_Word p_memsz;
|
||||
Elf32_Word p_flags;
|
||||
Elf32_Word p_align;
|
||||
} Elf32_Phdr;
|
||||
|
||||
/* ELF64 program header */
|
||||
typedef struct elf64_phdr {
|
||||
Elf64_Word p_type;
|
||||
Elf64_Word p_flags;
|
||||
Elf64_Off p_offset;
|
||||
Elf64_Addr p_vaddr;
|
||||
Elf64_Addr p_paddr;
|
||||
Elf64_Xword p_filesz;
|
||||
Elf64_Xword p_memsz;
|
||||
Elf64_Xword p_align;
|
||||
} Elf64_Phdr;
|
||||
|
||||
/* segment types */
|
||||
#define PT_NULL 0
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define PT_NOTE 4
|
||||
#define PT_SHLIB 5
|
||||
#define PT_PHDR 6
|
||||
#define PT_TLS 7 /* Thread local storage segment */
|
||||
#define PT_LOOS 0x60000000 /* OS-specific */
|
||||
#define PT_HIOS 0x6fffffff /* OS-specific */
|
||||
#define PT_LOPROC 0x70000000
|
||||
#define PT_HIPROC 0x7fffffff
|
||||
|
||||
/* ELF32 section header. */
|
||||
typedef struct {
|
||||
Elf32_Word sh_name;
|
||||
Elf32_Word sh_type;
|
||||
Elf32_Word sh_flags;
|
||||
Elf32_Addr sh_addr;
|
||||
Elf32_Off sh_offset;
|
||||
Elf32_Word sh_size;
|
||||
Elf32_Word sh_link;
|
||||
Elf32_Word sh_info;
|
||||
Elf32_Word sh_addralign;
|
||||
Elf32_Word sh_entsize;
|
||||
} Elf32_Shdr;
|
||||
|
||||
/* ELF64 section header. */
|
||||
typedef struct {
|
||||
Elf64_Word sh_name;
|
||||
Elf64_Word sh_type;
|
||||
Elf64_Xword sh_flags;
|
||||
Elf64_Addr sh_addr;
|
||||
Elf64_Off sh_offset;
|
||||
Elf64_Xword sh_size;
|
||||
Elf64_Word sh_link;
|
||||
Elf64_Word sh_info;
|
||||
Elf64_Xword sh_addralign;
|
||||
Elf64_Xword sh_entsize;
|
||||
} Elf64_Shdr;
|
||||
|
||||
/* sh_type */
|
||||
#define SHT_NULL 0
|
||||
#define SHT_PROGBITS 1
|
||||
#define SHT_SYMTAB 2
|
||||
#define SHT_STRTAB 3
|
||||
#define SHT_RELA 4
|
||||
#define SHT_HASH 5
|
||||
#define SHT_DYNAMIC 6
|
||||
#define SHT_NOTE 7
|
||||
#define SHT_NOBITS 8
|
||||
#define SHT_REL 9
|
||||
#define SHT_SHLIB 10
|
||||
#define SHT_DYNSYM 11
|
||||
#define SHT_INIT_ARRAY 14
|
||||
#define SHT_FINI_ARRAY 15
|
||||
#define SHT_PREINIT_ARRAY 16
|
||||
#define SHT_GROUP 17
|
||||
#define SHT_SYMTAB_SHNDX 18
|
||||
#define SHT_LOOS 0x60000000
|
||||
#define SHT_HIOS 0x6fffffff
|
||||
#define SHT_LOPROC 0x70000000
|
||||
#define SHT_HIPROC 0x7fffffff
|
||||
#define SHT_LOUSER 0x80000000
|
||||
#define SHT_HIUSER 0xffffffff
|
||||
|
||||
/* sh_flags */
|
||||
#define SHF_WRITE 0x1
|
||||
#define SHF_ALLOC 0x2
|
||||
#define SHF_EXECINSTR 0x4
|
||||
#define SHF_MASKPROC 0xf0000000
|
||||
|
||||
/* Relocation entry (without addend) */
|
||||
typedef struct {
|
||||
Elf32_Addr r_offset;
|
||||
Elf32_Word r_info;
|
||||
|
||||
} Elf32_Rel;
|
||||
|
||||
typedef struct {
|
||||
Elf64_Addr r_offset;
|
||||
Elf64_Xword r_info;
|
||||
|
||||
} Elf64_Rel;
|
||||
|
||||
/* Relocation entry with addend */
|
||||
typedef struct {
|
||||
Elf32_Addr r_offset;
|
||||
Elf32_Word r_info;
|
||||
Elf32_Sword r_addend;
|
||||
|
||||
} Elf32_Rela;
|
||||
|
||||
typedef struct elf64_rela {
|
||||
Elf64_Addr r_offset;
|
||||
Elf64_Xword r_info;
|
||||
Elf64_Sxword r_addend;
|
||||
} Elf64_Rela;
|
||||
|
||||
/* Macros to extract information from 'r_info' field of relocation entries */
|
||||
#define ELF32_R_SYM(i) ((i) >> 8)
|
||||
#define ELF32_R_TYPE(i) ((unsigned char)(i))
|
||||
#define ELF64_R_SYM(i) ((i) >> 32)
|
||||
#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
|
||||
|
||||
/* Symbol table entry */
|
||||
typedef struct {
|
||||
Elf32_Word st_name;
|
||||
Elf32_Addr st_value;
|
||||
Elf32_Word st_size;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
Elf32_Half st_shndx;
|
||||
|
||||
} Elf32_Sym;
|
||||
|
||||
typedef struct elf64_sym {
|
||||
Elf64_Word st_name;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
Elf64_Half st_shndx;
|
||||
Elf64_Addr st_value;
|
||||
Elf64_Xword st_size;
|
||||
} Elf64_Sym;
|
||||
|
||||
/* ARM specific dynamic relocation codes */
|
||||
#define R_ARM_GLOB_DAT 21 /* 0x15 */
|
||||
#define R_ARM_JUMP_SLOT 22 /* 0x16 */
|
||||
#define R_ARM_RELATIVE 23 /* 0x17 */
|
||||
#define R_ARM_ABS32 2 /* 0x02 */
|
||||
|
||||
/* ELF decoding information */
|
||||
struct elf32_info {
|
||||
Elf32_Ehdr ehdr;
|
||||
unsigned int load_state;
|
||||
Elf32_Phdr *phdrs;
|
||||
Elf32_Shdr *shdrs;
|
||||
void *shstrtab;
|
||||
};
|
||||
|
||||
struct elf64_info {
|
||||
Elf64_Ehdr ehdr;
|
||||
unsigned int load_state;
|
||||
Elf64_Phdr *phdrs;
|
||||
Elf64_Shdr *shdrs;
|
||||
void *shstrtab;
|
||||
};
|
||||
|
||||
#define ELF_STATE_INIT 0x0UL
|
||||
#define ELF_STATE_WAIT_FOR_PHDRS 0x100UL
|
||||
#define ELF_STATE_WAIT_FOR_SHDRS 0x200UL
|
||||
#define ELF_STATE_WAIT_FOR_SHSTRTAB 0x400UL
|
||||
#define ELF_STATE_HDRS_COMPLETE 0x800UL
|
||||
#define ELF_STATE_MASK 0xFF00UL
|
||||
#define ELF_NEXT_SEGMENT_MASK 0x00FFUL
|
||||
|
||||
extern struct loader_ops elf_ops;
|
||||
|
||||
/**
|
||||
* elf_identify - check if it is an ELF file
|
||||
*
|
||||
* It will check if the input image header is an ELF header.
|
||||
*
|
||||
* @img_data: firmware private data which will be passed to user defined loader
|
||||
* operations
|
||||
* @len: firmware header length
|
||||
*
|
||||
* return 0 for success or negative value for failure.
|
||||
*/
|
||||
int elf_identify(const void *img_data, size_t len);
|
||||
|
||||
/**
|
||||
* elf_load_header - Load ELF headers
|
||||
*
|
||||
* It will get the ELF header, the program header, and the section header.
|
||||
*
|
||||
* @img_data: image data
|
||||
* @offset: input image data offset to the start of image file
|
||||
* @len: input image data length
|
||||
* @img_info: pointer to store image information data
|
||||
* @last_load_state: last state return by this function
|
||||
* @noffset: pointer to next offset required by loading ELF header
|
||||
* @nlen: pointer to next data length required by loading ELF header
|
||||
*
|
||||
* return ELF loading header state, or negative value for failure
|
||||
*/
|
||||
int elf_load_header(const void *img_data, size_t offset, size_t len,
|
||||
void **img_info, int last_load_state,
|
||||
size_t *noffset, size_t *nlen);
|
||||
|
||||
/**
|
||||
* elf_load - load ELF data
|
||||
*
|
||||
* It will parse the ELF image and return the target device address,
|
||||
* offset to the start of the ELF image of the data to load and the
|
||||
* length of the data to load.
|
||||
*
|
||||
* @rproc: pointer to remoteproc instance
|
||||
* @img_data: image data which will passed to the function.
|
||||
* it can be NULL, if image data doesn't need to be handled
|
||||
* by the load function. E.g. binary data which was
|
||||
* loaded to the target memory.
|
||||
* @offset: last loaded image data offset to the start of image file
|
||||
* @len: last loaded image data length
|
||||
* @img_info: pointer to store image information data
|
||||
* @last_load_state: the returned state of the last function call.
|
||||
* @da: target device address, if the data to load is not for target memory
|
||||
* the da will be set to ANY.
|
||||
* @noffset: pointer to next offset required by loading ELF header
|
||||
* @nlen: pointer to next data length required by loading ELF header
|
||||
* @padding: value to pad it is possible that a size of a segment in memory
|
||||
* is larger than what it is in the ELF image. e.g. a segment
|
||||
* can have stack section .bss. It doesn't need to copy image file
|
||||
* space, in this case, it will be packed with 0.
|
||||
* @nmemsize: pointer to next data target memory size. The size of a segment
|
||||
* in the target memory can be larger than the its size in the
|
||||
* image file.
|
||||
*
|
||||
* return 0 for success, otherwise negative value for failure
|
||||
*/
|
||||
int elf_load(struct remoteproc *rproc, const void *img_data,
|
||||
size_t offset, size_t len,
|
||||
void **img_info, int last_load_state,
|
||||
metal_phys_addr_t *da,
|
||||
size_t *noffset, size_t *nlen,
|
||||
unsigned char *padding, size_t *nmemsize);
|
||||
|
||||
/**
|
||||
* elf_release - Release ELF image information
|
||||
*
|
||||
* It will release ELF image information data.
|
||||
*
|
||||
* @img_info: pointer to ELF image information
|
||||
*/
|
||||
void elf_release(void *img_info);
|
||||
|
||||
/**
|
||||
* elf_get_entry - Get entry point
|
||||
*
|
||||
* It will return entry point specified in the ELF file.
|
||||
*
|
||||
* @img_info: pointer to ELF image information
|
||||
*
|
||||
* return entry address
|
||||
*/
|
||||
metal_phys_addr_t elf_get_entry(void *img_info);
|
||||
|
||||
/**
|
||||
* elf_locate_rsc_table - locate the resource table information
|
||||
*
|
||||
* It will return the length of the resource table, and the device address of
|
||||
* the resource table.
|
||||
*
|
||||
* @img_info: pointer to ELF image information
|
||||
* @da: pointer to the device address
|
||||
* @offset: pointer to the offset to in the ELF image of the resource
|
||||
* table section.
|
||||
* @size: pointer to the size of the resource table section.
|
||||
*
|
||||
* return 0 if successfully locate the resource table, negative value for
|
||||
* failure.
|
||||
*/
|
||||
int elf_locate_rsc_table(void *img_info, metal_phys_addr_t *da,
|
||||
size_t *offset, size_t *size);
|
||||
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ELF_LOADER_H_ */
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef OPEN_AMP_H_
|
||||
#define OPEN_AMP_H_
|
||||
|
||||
#include <openamp/rpmsg.h>
|
||||
#include <openamp/rpmsg_virtio.h>
|
||||
#include <openamp/remoteproc.h>
|
||||
#include <openamp/remoteproc_virtio.h>
|
||||
|
||||
|
||||
#endif /* OPEN_AMP_H_ */
|
|
@ -0,0 +1,871 @@
|
|||
/*
|
||||
* Remoteproc Framework
|
||||
*
|
||||
* Copyright(c) 2018 Xilinx Ltd.
|
||||
* Copyright(c) 2011 Texas Instruments, Inc.
|
||||
* Copyright(c) 2011 Google, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef REMOTEPROC_H
|
||||
#define REMOTEPROC_H
|
||||
|
||||
#include <metal/io.h>
|
||||
#include <metal/mutex.h>
|
||||
#include <openamp/compiler.h>
|
||||
|
||||
#if defined __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RSC_NOTIFY_ID_ANY 0xFFFFFFFFUL
|
||||
|
||||
/**
|
||||
* struct resource_table - firmware resource table header
|
||||
* @ver: version number
|
||||
* @num: number of resource entries
|
||||
* @reserved: reserved (must be zero)
|
||||
* @offset: array of offsets pointing at the various resource entries
|
||||
*
|
||||
* A resource table is essentially a list of system resources required
|
||||
* by the remote remote_proc. It may also include configuration entries.
|
||||
* If needed, the remote remote_proc firmware should contain this table
|
||||
* as a dedicated ".resource_table" ELF section.
|
||||
*
|
||||
* Some resources entries are mere announcements, where the host is informed
|
||||
* of specific remoteproc configuration. Other entries require the host to
|
||||
* do something (e.g. allocate a system resource). Sometimes a negotiation
|
||||
* is expected, where the firmware requests a resource, and once allocated,
|
||||
* the host should provide back its details (e.g. address of an allocated
|
||||
* memory region).
|
||||
*
|
||||
* The header of the resource table, as expressed by this structure,
|
||||
* contains a version number (should we need to change this format in the
|
||||
* future), the number of available resource entries, and their offsets
|
||||
* in the table.
|
||||
*
|
||||
* Immediately following this header are the resource entries themselves,
|
||||
* each of which begins with a resource entry header (as described below).
|
||||
*/
|
||||
OPENAMP_PACKED_BEGIN
|
||||
struct resource_table {
|
||||
uint32_t ver;
|
||||
uint32_t num;
|
||||
uint32_t reserved[2];
|
||||
uint32_t offset[0];
|
||||
} OPENAMP_PACKED_END;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_hdr - firmware resource entry header
|
||||
* @type: resource type
|
||||
* @data: resource data
|
||||
*
|
||||
* Every resource entry begins with a 'struct fw_rsc_hdr' header providing
|
||||
* its @type. The content of the entry itself will immediately follow
|
||||
* this header, and it should be parsed according to the resource type.
|
||||
*/
|
||||
OPENAMP_PACKED_BEGIN
|
||||
struct fw_rsc_hdr {
|
||||
uint32_t type;
|
||||
uint8_t data[0];
|
||||
} OPENAMP_PACKED_END;
|
||||
|
||||
/**
|
||||
* enum fw_resource_type - types of resource entries
|
||||
*
|
||||
* @RSC_CARVEOUT: request for allocation of a physically contiguous
|
||||
* memory region.
|
||||
* @RSC_DEVMEM: request to iommu_map a memory-based peripheral.
|
||||
* @RSC_TRACE: announces the availability of a trace buffer into which
|
||||
* the remote remote_proc will be writing logs.
|
||||
* @RSC_VDEV: declare support for a virtio device, and serve as its
|
||||
* virtio header.
|
||||
* @RSC_VENDOR_START: start of the vendor specific resource types range
|
||||
* @RSC_VENDOR_END : end of the vendor specific resource types range
|
||||
* @RSC_LAST: just keep this one at the end
|
||||
*
|
||||
* For more details regarding a specific resource type, please see its
|
||||
* dedicated structure below.
|
||||
*
|
||||
* Please note that these values are used as indices to the rproc_handle_rsc
|
||||
* lookup table, so please keep them sane. Moreover, @RSC_LAST is used to
|
||||
* check the validity of an index before the lookup table is accessed, so
|
||||
* please update it as needed.
|
||||
*/
|
||||
enum fw_resource_type {
|
||||
RSC_CARVEOUT = 0,
|
||||
RSC_DEVMEM = 1,
|
||||
RSC_TRACE = 2,
|
||||
RSC_VDEV = 3,
|
||||
RSC_RPROC_MEM = 4,
|
||||
RSC_FW_CHKSUM = 5,
|
||||
RSC_LAST = 6,
|
||||
RSC_VENDOR_START = 128,
|
||||
RSC_VENDOR_END = 512,
|
||||
};
|
||||
|
||||
#define FW_RSC_ADDR_ANY (0xFFFFFFFFFFFFFFFF)
|
||||
#define FW_RSC_U32_ADDR_ANY (0xFFFFFFFF)
|
||||
|
||||
/**
|
||||
* struct fw_rsc_carveout - physically contiguous memory request
|
||||
* @da: device address
|
||||
* @pa: physical address
|
||||
* @len: length (in bytes)
|
||||
* @flags: iommu protection flags
|
||||
* @reserved: reserved (must be zero)
|
||||
* @name: human-readable name of the requested memory region
|
||||
*
|
||||
* This resource entry requests the host to allocate a physically contiguous
|
||||
* memory region.
|
||||
*
|
||||
* These request entries should precede other firmware resource entries,
|
||||
* as other entries might request placing other data objects inside
|
||||
* these memory regions (e.g. data/code segments, trace resource entries, ...).
|
||||
*
|
||||
* Allocating memory this way helps utilizing the reserved physical memory
|
||||
* (e.g. CMA) more efficiently, and also minimizes the number of TLB entries
|
||||
* needed to map it (in case @rproc is using an IOMMU). Reducing the TLB
|
||||
* pressure is important; it may have a substantial impact on performance.
|
||||
*
|
||||
* If the firmware is compiled with static addresses, then @da should specify
|
||||
* the expected device address of this memory region. If @da is set to
|
||||
* FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then
|
||||
* overwrite @da with the dynamically allocated address.
|
||||
*
|
||||
* We will always use @da to negotiate the device addresses, even if it
|
||||
* isn't using an iommu. In that case, though, it will obviously contain
|
||||
* physical addresses.
|
||||
*
|
||||
* Some remote remote_procs needs to know the allocated physical address
|
||||
* even if they do use an iommu. This is needed, e.g., if they control
|
||||
* hardware accelerators which access the physical memory directly (this
|
||||
* is the case with OMAP4 for instance). In that case, the host will
|
||||
* overwrite @pa with the dynamically allocated physical address.
|
||||
* Generally we don't want to expose physical addresses if we don't have to
|
||||
* (remote remote_procs are generally _not_ trusted), so we might want to
|
||||
* change this to happen _only_ when explicitly required by the hardware.
|
||||
*
|
||||
* @flags is used to provide IOMMU protection flags, and @name should
|
||||
* (optionally) contain a human readable name of this carveout region
|
||||
* (mainly for debugging purposes).
|
||||
*/
|
||||
OPENAMP_PACKED_BEGIN
|
||||
struct fw_rsc_carveout {
|
||||
uint32_t type;
|
||||
uint32_t da;
|
||||
uint32_t pa;
|
||||
uint32_t len;
|
||||
uint32_t flags;
|
||||
uint32_t reserved;
|
||||
uint8_t name[32];
|
||||
} OPENAMP_PACKED_END;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_devmem - iommu mapping request
|
||||
* @da: device address
|
||||
* @pa: physical address
|
||||
* @len: length (in bytes)
|
||||
* @flags: iommu protection flags
|
||||
* @reserved: reserved (must be zero)
|
||||
* @name: human-readable name of the requested region to be mapped
|
||||
*
|
||||
* This resource entry requests the host to iommu map a physically contiguous
|
||||
* memory region. This is needed in case the remote remote_proc requires
|
||||
* access to certain memory-based peripherals; _never_ use it to access
|
||||
* regular memory.
|
||||
*
|
||||
* This is obviously only needed if the remote remote_proc is accessing memory
|
||||
* via an iommu.
|
||||
*
|
||||
* @da should specify the required device address, @pa should specify
|
||||
* the physical address we want to map, @len should specify the size of
|
||||
* the mapping and @flags is the IOMMU protection flags. As always, @name may
|
||||
* (optionally) contain a human readable name of this mapping (mainly for
|
||||
* debugging purposes).
|
||||
*
|
||||
* Note: at this point we just "trust" those devmem entries to contain valid
|
||||
* physical addresses, but this isn't safe and will be changed: eventually we
|
||||
* want remoteproc implementations to provide us ranges of physical addresses
|
||||
* the firmware is allowed to request, and not allow firmwares to request
|
||||
* access to physical addresses that are outside those ranges.
|
||||
*/
|
||||
OPENAMP_PACKED_BEGIN
|
||||
struct fw_rsc_devmem {
|
||||
uint32_t type;
|
||||
uint32_t da;
|
||||
uint32_t pa;
|
||||
uint32_t len;
|
||||
uint32_t flags;
|
||||
uint32_t reserved;
|
||||
uint8_t name[32];
|
||||
} OPENAMP_PACKED_END;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_trace - trace buffer declaration
|
||||
* @da: device address
|
||||
* @len: length (in bytes)
|
||||
* @reserved: reserved (must be zero)
|
||||
* @name: human-readable name of the trace buffer
|
||||
*
|
||||
* This resource entry provides the host information about a trace buffer
|
||||
* into which the remote remote_proc will write log messages.
|
||||
*
|
||||
* @da specifies the device address of the buffer, @len specifies
|
||||
* its size, and @name may contain a human readable name of the trace buffer.
|
||||
*
|
||||
* After booting the remote remote_proc, the trace buffers are exposed to the
|
||||
* user via debugfs entries (called trace0, trace1, etc..).
|
||||
*/
|
||||
OPENAMP_PACKED_BEGIN
|
||||
struct fw_rsc_trace {
|
||||
uint32_t type;
|
||||
uint32_t da;
|
||||
uint32_t len;
|
||||
uint32_t reserved;
|
||||
uint8_t name[32];
|
||||
} OPENAMP_PACKED_END;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_vdev_vring - vring descriptor entry
|
||||
* @da: device address
|
||||
* @align: the alignment between the consumer and producer parts of the vring
|
||||
* @num: num of buffers supported by this vring (must be power of two)
|
||||
* @notifyid is a unique rproc-wide notify index for this vring. This notify
|
||||
* index is used when kicking a remote remote_proc, to let it know that this
|
||||
* vring is triggered.
|
||||
* @reserved: reserved (must be zero)
|
||||
*
|
||||
* This descriptor is not a resource entry by itself; it is part of the
|
||||
* vdev resource type (see below).
|
||||
*
|
||||
* Note that @da should either contain the device address where
|
||||
* the remote remote_proc is expecting the vring, or indicate that
|
||||
* dynamically allocation of the vring's device address is supported.
|
||||
*/
|
||||
OPENAMP_PACKED_BEGIN
|
||||
struct fw_rsc_vdev_vring {
|
||||
uint32_t da;
|
||||
uint32_t align;
|
||||
uint32_t num;
|
||||
uint32_t notifyid;
|
||||
uint32_t reserved;
|
||||
} OPENAMP_PACKED_END;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_vdev - virtio device header
|
||||
* @id: virtio device id (as in virtio_ids.h)
|
||||
* @notifyid is a unique rproc-wide notify index for this vdev. This notify
|
||||
* index is used when kicking a remote remote_proc, to let it know that the
|
||||
* status/features of this vdev have changes.
|
||||
* @dfeatures specifies the virtio device features supported by the firmware
|
||||
* @gfeatures is a place holder used by the host to write back the
|
||||
* negotiated features that are supported by both sides.
|
||||
* @config_len is the size of the virtio config space of this vdev. The config
|
||||
* space lies in the resource table immediate after this vdev header.
|
||||
* @status is a place holder where the host will indicate its virtio progress.
|
||||
* @num_of_vrings indicates how many vrings are described in this vdev header
|
||||
* @reserved: reserved (must be zero)
|
||||
* @vring is an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'.
|
||||
*
|
||||
* This resource is a virtio device header: it provides information about
|
||||
* the vdev, and is then used by the host and its peer remote remote_procs
|
||||
* to negotiate and share certain virtio properties.
|
||||
*
|
||||
* By providing this resource entry, the firmware essentially asks remoteproc
|
||||
* to statically allocate a vdev upon registration of the rproc (dynamic vdev
|
||||
* allocation is not yet supported).
|
||||
*
|
||||
* Note: unlike virtualization systems, the term 'host' here means
|
||||
* the Linux side which is running remoteproc to control the remote
|
||||
* remote_procs. We use the name 'gfeatures' to comply with virtio's terms,
|
||||
* though there isn't really any virtualized guest OS here: it's the host
|
||||
* which is responsible for negotiating the final features.
|
||||
* Yeah, it's a bit confusing.
|
||||
*
|
||||
* Note: immediately following this structure is the virtio config space for
|
||||
* this vdev (which is specific to the vdev; for more info, read the virtio
|
||||
* spec). the size of the config space is specified by @config_len.
|
||||
*/
|
||||
OPENAMP_PACKED_BEGIN
|
||||
struct fw_rsc_vdev {
|
||||
uint32_t type;
|
||||
uint32_t id;
|
||||
uint32_t notifyid;
|
||||
uint32_t dfeatures;
|
||||
uint32_t gfeatures;
|
||||
uint32_t config_len;
|
||||
uint8_t status;
|
||||
uint8_t num_of_vrings;
|
||||
uint8_t reserved[2];
|
||||
struct fw_rsc_vdev_vring vring[0];
|
||||
} OPENAMP_PACKED_END;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_vendor - remote processor vendor specific resource
|
||||
* @len: length of the resource
|
||||
*
|
||||
* This resource entry tells the host the vendor specific resource
|
||||
* required by the remote.
|
||||
*
|
||||
* These request entries should precede other shared resource entries
|
||||
* such as vdevs, vrings.
|
||||
*/
|
||||
OPENAMP_PACKED_BEGIN
|
||||
struct fw_rsc_vendor {
|
||||
uint32_t type;
|
||||
uint32_t len;
|
||||
} OPENAMP_PACKED_END;
|
||||
|
||||
/**
|
||||
* struct fw_rsc_rproc_mem - remote processor memory
|
||||
* @da: device address
|
||||
* @pa: physical address
|
||||
* @len: length (in bytes)
|
||||
* @reserved: reserved (must be zero)
|
||||
*
|
||||
* This resource entry tells the host to the remote processor
|
||||
* memory that the host can be used as shared memory.
|
||||
*
|
||||
* These request entries should precede other shared resource entries
|
||||
* such as vdevs, vrings.
|
||||
*/
|
||||
OPENAMP_PACKED_BEGIN
|
||||
struct fw_rsc_rproc_mem {
|
||||
uint32_t type;
|
||||
uint32_t da;
|
||||
uint32_t pa;
|
||||
uint32_t len;
|
||||
uint32_t reserved;
|
||||
} OPENAMP_PACKED_END;
|
||||
|
||||
/*
|
||||
* struct fw_rsc_fw_chksum - firmware checksum
|
||||
* @algo: algorithm to generate the cheksum
|
||||
* @chksum: checksum of the firmware loadable sections.
|
||||
*
|
||||
* This resource entry provides checksum for the firmware loadable sections.
|
||||
* It is used to check if the remote already runs with the expected firmware to
|
||||
* decide if it needs to start the remote if the remote is already running.
|
||||
*/
|
||||
OPENAMP_PACKED_BEGIN
|
||||
struct fw_rsc_fw_chksum {
|
||||
uint32_t type;
|
||||
uint8_t algo[16];
|
||||
uint8_t chksum[64];
|
||||
} OPENAMP_PACKED_END;
|
||||
|
||||
struct loader_ops;
|
||||
struct image_store_ops;
|
||||
struct remoteproc_ops;
|
||||
|
||||
/**
|
||||
* struct remoteproc_mem
|
||||
*
|
||||
* This structure presents the memory used by the remote processor
|
||||
*
|
||||
* @da: device memory
|
||||
* @pa: physical memory
|
||||
* @size: size of the memory
|
||||
* @io: pointer to the I/O region
|
||||
* @node: list node
|
||||
*/
|
||||
struct remoteproc_mem {
|
||||
metal_phys_addr_t da;
|
||||
metal_phys_addr_t pa;
|
||||
size_t size;
|
||||
char name[32];
|
||||
struct metal_io_region *io;
|
||||
struct metal_list node;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct remoteproc
|
||||
*
|
||||
* This structure is maintained by the remoteproc to represent the remote
|
||||
* processor instance. This structure acts as a prime parameter to use
|
||||
* the remoteproc APIs.
|
||||
*
|
||||
* @bootadd: boot address
|
||||
* @loader: executable loader
|
||||
* @lock: mutext lock
|
||||
* @ops: remoteproc operations
|
||||
* @rsc_table: pointer to resource table
|
||||
* @rsc_len: length of resource table
|
||||
* @rsc_io: metal I/O region of resource table
|
||||
* @mems: remoteproc memories
|
||||
* @vdevs: remoteproc virtio devices
|
||||
* @bitmap: bitmap for notify IDs for remoteproc subdevices
|
||||
* @state: remote processor state
|
||||
* @priv: private data
|
||||
*/
|
||||
struct remoteproc {
|
||||
metal_mutex_t lock;
|
||||
void *rsc_table;
|
||||
size_t rsc_len;
|
||||
struct metal_io_region *rsc_io;
|
||||
struct metal_list mems;
|
||||
struct metal_list vdevs;
|
||||
unsigned long bitmap;
|
||||
struct remoteproc_ops *ops;
|
||||
metal_phys_addr_t bootaddr;
|
||||
struct loader_ops *loader;
|
||||
unsigned int state;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct remoteproc_ops
|
||||
*
|
||||
* remoteproc operations needs to be implemented by each remoteproc driver
|
||||
*
|
||||
* @init: initialize the remoteproc instance
|
||||
* @remove: remove the remoteproc instance
|
||||
* @mmap: memory mapped the mempory with physical address or destination
|
||||
* address as input.
|
||||
* @handle_rsc: handle the vendor specific resource
|
||||
* @config: configure the remoteproc to make it ready to load and run
|
||||
* executable
|
||||
* @start: kick the remoteproc to run application
|
||||
* @stop: stop the remoteproc from running application, the resource such as
|
||||
* memory may not be off.
|
||||
* @shutdown: shutdown the remoteproc and release its resources.
|
||||
* @notify: notify the remote
|
||||
*/
|
||||
struct remoteproc_ops {
|
||||
struct remoteproc *(*init)(struct remoteproc *rproc,
|
||||
struct remoteproc_ops *ops, void *arg);
|
||||
void (*remove)(struct remoteproc *rproc);
|
||||
void *(*mmap)(struct remoteproc *rproc,
|
||||
metal_phys_addr_t *pa, metal_phys_addr_t *da,
|
||||
size_t size, unsigned int attribute,
|
||||
struct metal_io_region **io);
|
||||
int (*handle_rsc)(struct remoteproc *rproc, void *rsc, size_t len);
|
||||
int (*config)(struct remoteproc *rproc, void *data);
|
||||
int (*start)(struct remoteproc *rproc);
|
||||
int (*stop)(struct remoteproc *rproc);
|
||||
int (*shutdown)(struct remoteproc *rproc);
|
||||
int (*notify)(struct remoteproc *rproc, uint32_t id);
|
||||
};
|
||||
|
||||
/* Remoteproc error codes */
|
||||
#define RPROC_EBASE 0
|
||||
#define RPROC_ENOMEM (RPROC_EBASE + 1)
|
||||
#define RPROC_EINVAL (RPROC_EBASE + 2)
|
||||
#define RPROC_ENODEV (RPROC_EBASE + 3)
|
||||
#define RPROC_EAGAIN (RPROC_EBASE + 4)
|
||||
#define RPROC_ERR_RSC_TAB_TRUNC (RPROC_EBASE + 5)
|
||||
#define RPROC_ERR_RSC_TAB_VER (RPROC_EBASE + 6)
|
||||
#define RPROC_ERR_RSC_TAB_RSVD (RPROC_EBASE + 7)
|
||||
#define RPROC_ERR_RSC_TAB_VDEV_NRINGS (RPROC_EBASE + 9)
|
||||
#define RPROC_ERR_RSC_TAB_NP (RPROC_EBASE + 10)
|
||||
#define RPROC_ERR_RSC_TAB_NS (RPROC_EBASE + 11)
|
||||
#define RPROC_ERR_LOADER_STATE (RPROC_EBASE + 12)
|
||||
#define RPROC_EMAX (RPROC_EBASE + 16)
|
||||
#define RPROC_EPTR (void *)(-1)
|
||||
#define RPROC_EOF (void *)(-1)
|
||||
|
||||
static inline long RPROC_PTR_ERR(const void *ptr)
|
||||
{
|
||||
return (long)ptr;
|
||||
}
|
||||
|
||||
static inline int RPROC_IS_ERR(const void *ptr)
|
||||
{
|
||||
if ((unsigned long)ptr >= (unsigned long)(-RPROC_EMAX))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void *RPROC_ERR_PTR(long error)
|
||||
{
|
||||
return (void *)error;
|
||||
}
|
||||
|
||||
/**
|
||||
* enum rproc_state - remote processor states
|
||||
* @RPROC_OFFLINE: remote is offline
|
||||
* @RPROC_READY: remote is ready to start
|
||||
* @RPROC_RUNNING: remote is up and running
|
||||
* @RPROC_SUSPENDED: remote is suspended
|
||||
* @RPROC_ERROR: remote has error; need to recover
|
||||
* @RPROC_STOPPED: remote is stopped
|
||||
* @RPROC_LAST: just keep this one at the end
|
||||
*/
|
||||
enum remoteproc_state {
|
||||
RPROC_OFFLINE = 0,
|
||||
RPROC_CONFIGURED = 1,
|
||||
RPROC_READY = 2,
|
||||
RPROC_RUNNING = 3,
|
||||
RPROC_SUSPENDED = 4,
|
||||
RPROC_ERROR = 5,
|
||||
RPROC_STOPPED = 6,
|
||||
RPROC_LAST = 7,
|
||||
};
|
||||
|
||||
/**
|
||||
* remoteproc_init
|
||||
*
|
||||
* Initializes remoteproc resource.
|
||||
*
|
||||
* @rproc - pointer to remoteproc instance
|
||||
* @ops - pointer to remoteproc operations
|
||||
* @priv - pointer to private data
|
||||
*
|
||||
* @returns created remoteproc pointer
|
||||
*/
|
||||
struct remoteproc *remoteproc_init(struct remoteproc *rproc,
|
||||
struct remoteproc_ops *ops, void *priv);
|
||||
|
||||
/**
|
||||
* remoteproc_remove
|
||||
*
|
||||
* Remove remoteproc resource
|
||||
*
|
||||
* @rproc - pointer to remoteproc instance
|
||||
*
|
||||
* returns 0 for success, negative value for failure
|
||||
*/
|
||||
int remoteproc_remove(struct remoteproc *rproc);
|
||||
|
||||
/**
|
||||
* remoteproc_init_mem
|
||||
*
|
||||
* Initialize remoteproc memory
|
||||
*
|
||||
* @mem - pointer to remoteproc memory
|
||||
* @char - memory name
|
||||
* @pa - physcial address
|
||||
* @da - device address
|
||||
* @size - memory size
|
||||
* @io - pointer to the I/O region
|
||||
*/
|
||||
static inline void
|
||||
remoteproc_init_mem(struct remoteproc_mem *mem, const char *name,
|
||||
metal_phys_addr_t pa, metal_phys_addr_t da,
|
||||
size_t size, struct metal_io_region *io)
|
||||
{
|
||||
if (!mem)
|
||||
return;
|
||||
if (name)
|
||||
strncpy(mem->name, name, sizeof(mem->name));
|
||||
else
|
||||
mem->name[0] = 0;
|
||||
mem->pa = pa;
|
||||
mem->da = da;
|
||||
mem->io = io;
|
||||
mem->size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_add_mem
|
||||
*
|
||||
* Add remoteproc memory
|
||||
*
|
||||
* @rproc - pointer to remoteproc
|
||||
* @mem - pointer to remoteproc memory
|
||||
*/
|
||||
static inline void
|
||||
remoteproc_add_mem(struct remoteproc *rproc, struct remoteproc_mem *mem)
|
||||
{
|
||||
if (!rproc || !mem)
|
||||
return;
|
||||
metal_list_add_tail(&rproc->mems, &mem->node);
|
||||
}
|
||||
|
||||
/**
|
||||
* remoteproc_get_io_with_name
|
||||
*
|
||||
* get remoteproc memory I/O region with name
|
||||
*
|
||||
* @rproc - pointer to the remote processor
|
||||
* @name - name of the shared memory
|
||||
* @io - pointer to the pointer of the I/O region
|
||||
*
|
||||
* returns metal I/O region pointer, NULL for failure
|
||||
*/
|
||||
struct metal_io_region *
|
||||
remoteproc_get_io_with_name(struct remoteproc *rproc,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* remoteproc_get_io_with_pa
|
||||
*
|
||||
* get remoteproc memory I/O region with physical address
|
||||
*
|
||||
* @rproc - pointer to the remote processor
|
||||
* @pa - physical address
|
||||
*
|
||||
* returns metal I/O region pointer, NULL for failure
|
||||
*/
|
||||
struct metal_io_region *
|
||||
remoteproc_get_io_with_pa(struct remoteproc *rproc,
|
||||
metal_phys_addr_t pa);
|
||||
|
||||
/**
|
||||
* remoteproc_get_io_with_da
|
||||
*
|
||||
* get remoteproc memory I/O region with device address
|
||||
*
|
||||
* @rproc - pointer to the remote processor
|
||||
* @da - device address
|
||||
* @offset - I/O region offset of the device address
|
||||
*
|
||||
* returns metal I/O region pointer, NULL for failure
|
||||
*/
|
||||
struct metal_io_region *
|
||||
remoteproc_get_io_with_da(struct remoteproc *rproc,
|
||||
metal_phys_addr_t da,
|
||||
unsigned long *offset);
|
||||
|
||||
/**
|
||||
* remoteproc_get_io_with_va
|
||||
*
|
||||
* get remoteproc memory I/O region with virtual address
|
||||
*
|
||||
* @rproc - pointer to the remote processor
|
||||
* @va - virtual address
|
||||
*
|
||||
* returns metal I/O region pointer, NULL for failure
|
||||
*/
|
||||
struct metal_io_region *
|
||||
remoteproc_get_io_with_va(struct remoteproc *rproc,
|
||||
void *va);
|
||||
|
||||
/**
|
||||
* remoteproc_mmap
|
||||
*
|
||||
* remoteproc mmap memory
|
||||
*
|
||||
* @rproc - pointer to the remote processor
|
||||
* @pa - physical address pointer
|
||||
* @da - device address pointer
|
||||
* @size - size of the memory
|
||||
* @attribute - memory attribute
|
||||
* @io - pointer to the I/O region
|
||||
*
|
||||
* returns pointer to the memory
|
||||
*/
|
||||
void *remoteproc_mmap(struct remoteproc *rproc,
|
||||
metal_phys_addr_t *pa, metal_phys_addr_t *da,
|
||||
size_t size, unsigned int attribute,
|
||||
struct metal_io_region **io);
|
||||
|
||||
/**
|
||||
* remoteproc_parse_rsc_table
|
||||
*
|
||||
* Parse resource table of remoteproc
|
||||
*
|
||||
* @rproc - pointer to remoteproc instance
|
||||
* @rsc_table - pointer to resource table
|
||||
* @rsc_size - resource table size
|
||||
*
|
||||
* returns 0 for success and negative value for errors
|
||||
*/
|
||||
int remoteproc_parse_rsc_table(struct remoteproc *rproc,
|
||||
struct resource_table *rsc_table,
|
||||
size_t rsc_size);
|
||||
|
||||
/**
|
||||
* remoteproc_set_rsc_table
|
||||
*
|
||||
* Parse and set resource table of remoteproc
|
||||
*
|
||||
* @rproc - pointer to remoteproc instance
|
||||
* @rsc_table - pointer to resource table
|
||||
* @rsc_size - resource table size
|
||||
*
|
||||
* returns 0 for success and negative value for errors
|
||||
*/
|
||||
int remoteproc_set_rsc_table(struct remoteproc *rproc,
|
||||
struct resource_table *rsc_table,
|
||||
size_t rsc_size);
|
||||
|
||||
/**
|
||||
* remoteproc_config
|
||||
*
|
||||
* This function configures the remote processor to get it
|
||||
* ready to load and run executable.
|
||||
*
|
||||
* @rproc - pointer to remoteproc instance to start
|
||||
* @data - configuration data
|
||||
*
|
||||
* returns 0 for success and negative value for errors
|
||||
*/
|
||||
int remoteproc_config(struct remoteproc *rproc, void *data);
|
||||
|
||||
/**
|
||||
* remoteproc_start
|
||||
*
|
||||
* This function starts the remote processor.
|
||||
* It assumes the firmware is already loaded,
|
||||
*
|
||||
* @rproc - pointer to remoteproc instance to start
|
||||
*
|
||||
* returns 0 for success and negative value for errors
|
||||
*/
|
||||
int remoteproc_start(struct remoteproc *rproc);
|
||||
|
||||
/**
|
||||
* remoteproc_stop
|
||||
*
|
||||
* This function stops the remote processor but it
|
||||
* will not release its resource.
|
||||
*
|
||||
* @rproc - pointer to remoteproc instance
|
||||
*
|
||||
* returns 0 for success and negative value for errors
|
||||
*/
|
||||
int remoteproc_stop(struct remoteproc *rproc);
|
||||
|
||||
/**
|
||||
* remoteproc_shutdown
|
||||
*
|
||||
* This function shutdown the remote processor and
|
||||
* release its resources.
|
||||
*
|
||||
* @rproc - pointer to remoteproc instance
|
||||
*
|
||||
* returns 0 for success and negative value for errors
|
||||
*/
|
||||
int remoteproc_shutdown(struct remoteproc *rproc);
|
||||
|
||||
/**
|
||||
* remoteproc_load
|
||||
*
|
||||
* load executable, it expects the user application defines how to
|
||||
* open the executable file and how to get data from the executable file
|
||||
* and how to load data to the target memory.
|
||||
*
|
||||
* @rproc: pointer to the remoteproc instance
|
||||
* @path: optional path to the image file
|
||||
* @store: pointer to user defined image store argument
|
||||
* @store_ops: pointer to image store operations
|
||||
* @image_info: pointer to memory which stores image information used
|
||||
* by remoteproc loader
|
||||
*
|
||||
* return 0 for success and negative value for failure
|
||||
*/
|
||||
int remoteproc_load(struct remoteproc *rproc, const char *path,
|
||||
void *store, struct image_store_ops *store_ops,
|
||||
void **img_info);
|
||||
|
||||
/**
|
||||
* remoteproc_load_noblock
|
||||
*
|
||||
* load executable, it expects the caller has loaded image data to local
|
||||
* memory and passed to the this function. If the function needs more
|
||||
* image data it will return the next expected image data offset and
|
||||
* the next expected image data length. If the function requires the
|
||||
* caller to download image data to the target memory, it will also
|
||||
* return the target physical address besides the offset and length.
|
||||
* This function can be used to load firmware in stream mode. In this
|
||||
* mode, you cannot do seek to the executable file. If the executable
|
||||
* is ELF, it cannot get the resource table section before it loads
|
||||
* the full ELF file. Furthermore, application usually don't store
|
||||
* the data which is loaded to local memory in streaming mode, and
|
||||
* thus, in this mode, it will load the binrary to the target memory
|
||||
* before it gets the resource table. And thus, when calling this funciton
|
||||
* don't put the target exectuable memory in the resource table, as
|
||||
* this function will parse the resource table after it loads the binary
|
||||
* to target memory.
|
||||
*
|
||||
* @rproc: pointer to the remoteproc instance
|
||||
* @img_data: pointer to image data for remoteproc loader to parse
|
||||
* @offset: image data offset to the beginning of the image file
|
||||
* @len: image data length
|
||||
* @image_info: pointer to memory which stores image information used
|
||||
* by remoteproc loader
|
||||
* @pa: pointer to the target memory physical address. If the next expected
|
||||
* data doesn't need to load to the target memory, the function will
|
||||
* set it to ANY.
|
||||
* @io: pointer to the target memory physical address. If the next expected
|
||||
* data doesn't need to load to the target memory, the function will
|
||||
* set it to ANY.
|
||||
* @noffset: pointer to the next image data offset to the beginning of
|
||||
* the image file needs to load to local or to the target
|
||||
* memory.
|
||||
* @nlen: pointer to the next image data length needs to load to local
|
||||
* or to the target memory.
|
||||
* @nmlen: pointer to the memory size. It is only used when the next
|
||||
* expected data is going to be loaded to the target memory. E.g.
|
||||
* in ELF, it is possible that loadable segment in memory is
|
||||
* larger that the segment data in the ELF file. In this case,
|
||||
* application will need to pad the rest of the memory with
|
||||
* padding.
|
||||
* @padding: pointer to the padding value. It is only used when the next
|
||||
* expected data is going to be loaded to the target memory.
|
||||
* and the target memory size is larger than the segment data in
|
||||
* the executable file.
|
||||
*
|
||||
* return 0 for success and negative value for failure
|
||||
*/
|
||||
int remoteproc_load_noblock(struct remoteproc *rproc,
|
||||
const void *img_data, size_t offset, size_t len,
|
||||
void **img_info,
|
||||
metal_phys_addr_t *pa, struct metal_io_region **io,
|
||||
size_t *noffset, size_t *nlen,
|
||||
size_t *nmlen, unsigned char *padding);
|
||||
|
||||
/**
|
||||
* remoteproc_allocate_id
|
||||
*
|
||||
* allocate notifyid for resource
|
||||
*
|
||||
* @rproc - pointer to the remoteproc instance
|
||||
* @start - start of the id range
|
||||
* @end - end of the id range
|
||||
*
|
||||
* return allocated notify id
|
||||
*/
|
||||
unsigned int remoteproc_allocate_id(struct remoteproc *rproc,
|
||||
unsigned int start,
|
||||
unsigned int end);
|
||||
|
||||
/* remoteproc_create_virtio
|
||||
*
|
||||
* create virtio device, it returns pointer to the created virtio device.
|
||||
*
|
||||
* @rproc: pointer to the remoteproc instance
|
||||
* @vdev_id: virtio device ID
|
||||
* @role: virtio device role
|
||||
* @rst_cb: virtio device reset callback
|
||||
*
|
||||
* return pointer to the created virtio device, NULL for failure.
|
||||
*/
|
||||
struct virtio_device *
|
||||
remoteproc_create_virtio(struct remoteproc *rproc,
|
||||
int vdev_id, unsigned int role,
|
||||
void (*rst_cb)(struct virtio_device *vdev));
|
||||
|
||||
/* remoteproc_remove_virtio
|
||||
*
|
||||
* Remove virtio device
|
||||
*
|
||||
* @rproc: pointer to the remoteproc instance
|
||||
* @vdev: pointer to the virtio device
|
||||
*
|
||||
*/
|
||||
void remoteproc_remove_virtio(struct remoteproc *rproc,
|
||||
struct virtio_device *vdev);
|
||||
|
||||
/* remoteproc_get_notification
|
||||
*
|
||||
* remoteproc is got notified, it will check its subdevices
|
||||
* for the notification
|
||||
*
|
||||
* @rproc - pointer to the remoteproc instance
|
||||
* @notifyid - notificatin id
|
||||
*
|
||||
* return 0 for succeed, negative value for failure
|
||||
*/
|
||||
int remoteproc_get_notification(struct remoteproc *rproc,
|
||||
uint32_t notifyid);
|
||||
#if defined __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* REMOTEPROC_H_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue