Sync inav to Gitea
Make sure docs are updated / settings_md (push) Canceled after 0s
Build firmware / test (push) Canceled after 0s
Build firmware / build-SITL-Windows (push) Canceled after 0s
Build firmware / build-SITL-Mac (push) Canceled after 0s
Build firmware / build-SITL-Linux (push) Canceled after 0s
Build firmware / build-SITL-Linux-arm64 (push) Canceled after 0s
Build firmware / upload-artifacts (push) Canceled after 0s
Build firmware / build-single-target (push) Canceled after 0s
Build firmware / build (9) (push) Canceled after 0s
Build firmware / build (8) (push) Canceled after 0s
Build firmware / build (7) (push) Canceled after 0s
Build firmware / build (6) (push) Canceled after 0s
Build firmware / build (5) (push) Canceled after 0s
Build firmware / build (4) (push) Canceled after 0s
Build firmware / build (3) (push) Canceled after 0s
Build firmware / build (2) (push) Canceled after 0s
Build firmware / build (14) (push) Canceled after 0s
Build firmware / build (13) (push) Canceled after 0s
Build firmware / build (12) (push) Canceled after 0s
Build firmware / build (11) (push) Canceled after 0s
Build firmware / build (10) (push) Canceled after 0s
Build firmware / build (1) (push) Canceled after 0s
Build firmware / build (0) (push) Canceled after 0s
Build firmware / detect (push) Canceled after 0s
Build pre-release / build (push) Canceled after 0s
Build pre-release / Release (push) Canceled after 0s

This commit is contained in:
2026-08-03 16:37:40 +08:00
commit dac37fd077
14095 changed files with 5603119 additions and 0 deletions
@@ -0,0 +1,76 @@
collector_create (PROJECT_LIB_TESTS "${CMAKE_CURRENT_SOURCE_DIR}")
add_subdirectory (system)
collect (PROJECT_LIB_HEADERS metal-test.h)
collect (PROJECT_LIB_TESTS version.c)
collect (PROJECT_LIB_TESTS metal-test.c)
collector_list (_hdirs PROJECT_INC_DIRS)
include_directories (${_hdirs} ${CMAKE_CURRENT_SOURCE_DIR})
collector_list (_ldirs PROJECT_LIB_DIRS)
link_directories (${_ldirs})
collector_list (_deps PROJECT_LIB_DEPS)
collector_list (_srcs PROJECT_LIB_TESTS)
if (WITH_ZEPHYR)
set (_tfiles "")
foreach (f ${_srcs})
list(APPEND _tfiles "${CMAKE_CURRENT_SOURCE_DIR}/${f}")
endforeach(f)
target_sources(app PRIVATE ${_tfiles})
target_include_directories (app PRIVATE ${_hdirs} ${CMAKE_CURRENT_SOURCE_DIR})
set (_eldflags "")
foreach (d ${_ldirs})
list (APPEND _eldflags "-L${d}")
endforeach(d)
add_dependencies(app metal)
list (APPEND _deps -lmetal)
target_link_libraries(app LINK_INTERFACE_LIBRARIES "${_eldflags}" ${_deps})
target_compile_options (app PRIVATE -DNOT_HAVE_STRERROR)
else (WITH_ZEPHYR)
if(WITH_SHARED_LIB)
set (_lib ${PROJECT_NAME}-shared)
add_executable (test-${_lib} ${_srcs})
target_link_libraries (test-${_lib} ${_deps} ${_lib})
install (TARGETS test-${_lib} RUNTIME DESTINATION bin)
if (PROJECT_EC_FLAGS)
string(REPLACE " " ";" _ec_flgs ${PROJECT_EC_FLAGS})
target_compile_options (test-${_lib} PUBLIC ${_ec_flgs})
endif (PROJECT_EC_FLAGS)
add_dependencies (test-${_lib} ${PROJECT_NAME}-shared)
if (WITH_TESTS_EXEC)
add_test (test-${_lib} test-${_lib})
endif (WITH_TESTS_EXEC)
endif (WITH_SHARED_LIB)
if (WITH_STATIC_LIB)
get_property (_linker_options GLOBAL PROPERTY TEST_LINKER_OPTIONS)
set (_lib ${PROJECT_NAME}-static)
add_executable (test-${_lib} ${_srcs})
target_link_libraries (test-${_lib} -Wl,-Map=test-${_lib}.map ${_linker_options} -Wl,--start-group ${_lib} ${_deps} -Wl,--end-group)
install (TARGETS test-${_lib} RUNTIME DESTINATION bin)
if (PROJECT_EC_FLAGS)
string(REPLACE " " ";" _ec_flgs ${PROJECT_EC_FLAGS})
target_compile_options (test-${_lib} PUBLIC ${_ec_flgs})
endif (PROJECT_EC_FLAGS)
add_dependencies (test-${_lib} ${PROJECT_NAME}-static)
if (WITH_TESTS_EXEC)
add_test (test-${_lib} test-${_lib})
endif (WITH_TESTS_EXEC)
endif (WITH_STATIC_LIB)
collector_list (_headers PROJECT_HDR_TESTS)
foreach (INCLUDE ${_headers})
string (REGEX REPLACE "[^a-zA-Z0-9]+" "-" _f ${INCLUDE})
configure_file (metal-header-template.c ${_f}.c)
list (APPEND _flist "${CMAKE_CURRENT_BINARY_DIR}/${_f}")
endforeach (INCLUDE)
add_library (metal-headers STATIC ${_flist})
endif (WITH_ZEPHYR)
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,11 @@
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* Template file used to ensure that each <metal/...> header can be included
* without independently without prior inclusion of dependencies.
*/
#include <@INCLUDE@>
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <metal/errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "metal-test.h"
#include <metal/compiler.h>
#include <metal/sys.h>
#include <metal/utilities.h>
static METAL_DECLARE_LIST(test_cases);
/*
* Not every enviornment has strerror() implemented.
*/
#ifdef NOT_HAVE_STRERROR
char metal_weak *strerror(int errnum)
{
static char errstr[33];
int i, j;
if (errnum < 0)
return NULL;
i = 0;
while (errnum) {
int digit = errnum % 10;
errstr[i++] = '0' + (char)digit;
errnum /= 10;
}
errstr[i] = '\0';
j = i - 1;
for (i = 0; i < j; i++, j--) {
char *tmp = &errstr[i];
errstr[i] = errstr[j];
errstr[j] = *tmp;
}
return errstr;
}
#endif
void metal_add_test_case(struct metal_test_case *test_case)
{
metal_list_add_tail(&test_cases, &test_case->node);
}
int metal_tests_run(struct metal_init_params *params)
{
struct metal_init_params dparams = METAL_INIT_DEFAULTS;
struct metal_test_case *test_case;
struct metal_list *node;
int error, errors = 0;
const char *dots = "..................................";
const char *pad;
if (!params)
params = &dparams;
params->log_level = METAL_LOG_DEBUG;
error = metal_init(params);
if (error)
return error;
metal_list_for_each(&test_cases, node) {
test_case = metal_container_of(node, struct metal_test_case,
node);
pad = dots + strlen(test_case->name);
metal_log(METAL_LOG_INFO,"running [%s]\n", test_case->name);
error = test_case->test();
metal_log(METAL_LOG_INFO,"result [%s]%s %s%s%s\n",
test_case->name, pad,
error ? "fail" : "pass",
error ? " - error: " : "",
error ? strerror(-error) : "");
if (error)
errors++;
}
metal_finish();
return errors;
}
@@ -0,0 +1,96 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file metal-test.h
* @brief Top level include internal to libmetal tests.
*/
#ifndef __METAL_TEST__H__
#define __METAL_TEST__H__
#ifdef __cplusplus
extern "C" {
#endif
#include <metal/sys.h>
#include <metal/list.h>
typedef int (*test_func_t)(void);
typedef void *(*metal_thread_t)(void *);
struct metal_test_case {
struct metal_list node;
const char *name;
test_func_t test;
};
extern void metal_add_test_case(struct metal_test_case *test_case);
#define METAL_ADD_TEST(func) \
__attribute__ ((constructor)) static void metal_test_##func() { \
static struct metal_test_case metal_test_##func = { \
.name = #func, \
.test = func, \
}; \
metal_add_test_case(&metal_test_##func); \
}
/**
* @brief run all tests cases
*
* @param[in] metal init parameters
*
* @return non-zero on error
*/
int metal_tests_run(struct metal_init_params *params);
/**
* @brief run child threads and wait until all they finish.
* if tids1 is zero, that is not required to store
* threads ids for the caller, it will not return
* until all the threads finishes.
* @param[in] threads how many threads to run
* @param[in] child routine which the threads will run
* @param[in] arg argument passed to the child threads
*
* @return zero on no errors, non-zero on errors
*/
extern int metal_run(int threads, metal_thread_t child, void *arg);
/**
* @brief run child threads and return without waiting
* for all the threads to finish.
* @param[in] threads how many threads to run
* @param[in] child routine which the threads will run
* @param[in] arg argument passed to the child threads
* @param[in] tids pointers to store the threads ids.
* the caller is required to make sure the tids is
* big enough to store all the child threads ids.
* @param[out] threads_out number of threads created
*
* @return zero on no errors, non-zero on errors
*/
extern int metal_run_noblock(int threads, metal_thread_t child,
void *arg, void *tids, int *threads_out);
/**
* @brief do not return until all the specified child threads
* finish.
* @param[in] threads how many threads to wait
* @param[in] tids pointers to the threads ids.
*
*/
extern void metal_finish_threads(int threads, void *tids);
#ifdef __cplusplus
}
#endif
#endif /* __METAL_TEST__H__ */
@@ -0,0 +1,3 @@
add_subdirectory (${PROJECT_SYSTEM})
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,13 @@
collect (PROJECT_LIB_TESTS main.c)
collect (PROJECT_LIB_TESTS threads.c)
collect (PROJECT_LIB_TESTS alloc.c)
collect (PROJECT_LIB_TESTS irq.c)
collect (PROJECT_LIB_TESTS mutex.c)
collect (PROJECT_LIB_TESTS atomic.c)
collect (PROJECT_LIB_TESTS sleep.c)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
add_subdirectory(${PROJECT_MACHINE})
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <metal/errno.h>
#include <string.h>
#include "FreeRTOS.h"
#include "task.h"
#include "metal-test.h"
#include <metal/alloc.h>
#include <metal/log.h>
#include <metal/sys.h>
static const int test_count = 10;
static void *alloc_thread(void *arg)
{
int i;
void *ptr;
void *rv = 0;
(void)arg;
for (i = 0; i < test_count; i++) {
/* expecting the implementation to be thread safe */
ptr = metal_allocate_memory(256 /*10*i*/);
if (!ptr) {
metal_log(METAL_LOG_DEBUG, "failed to allocate memmory\n");
rv = (void *)-ENOMEM;
break;
}
metal_free_memory(ptr);
}
return rv;
}
static int alloc(void)
{
const int threads = 10;
int rc;
rc = metal_run(threads, alloc_thread, NULL);
return rc;
}
METAL_ADD_TEST(alloc);
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include <metal/errno.h>
#include "metal-test.h"
#include <metal/atomic.h>
#include <metal/log.h>
#include <metal/sys.h>
static const int atomic_test_count = 1000;
static void *atomic_thread(void *arg)
{
atomic_int *c = arg;
int i;
for (i = 0; i < atomic_test_count; i++)
atomic_fetch_add(c, 1);
return NULL;
}
static int atomic(void)
{
const int threads = 10;
atomic_int counter = ATOMIC_VAR_INIT(0);
int value, error;
error = metal_run(threads, atomic_thread, &counter);
if (!error) {
value = atomic_load(&counter);
value -= atomic_test_count * threads;
if (value) {
metal_log(METAL_LOG_DEBUG, "counter mismatch, delta = %d\n",
value);
error = -EINVAL;
}
}
return error;
}
METAL_ADD_TEST(atomic);
@@ -0,0 +1,218 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include <metal/errno.h>
/* We need to find the internal MAX_IRQS limit */
/* Could be retrieved from platform specific files in the future */
#define METAL_INTERNAL
#include "metal-test.h"
#include <metal/irq.h>
#include <metal/log.h>
#include <metal/sys.h>
#include <metal/list.h>
#include <metal/utilities.h>
int irq_handler(int irq, void *priv)
{
(void)irq;
(void)priv;
return 0;
}
static int irq(void)
{
int rc = 0, flags_1, flags_2;
char *err_msg="";
enum metal_log_level mll= metal_get_log_level();
/* Do not show LOG_ERROR or LOG_DEBUG for expected fail case */
metal_set_log_level(METAL_LOG_CRITICAL);
rc = metal_irq_register(1, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 1 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(2, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 2 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(2, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 2 fail drv_id 2\n";
goto out;
}
rc = metal_irq_register(3, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 3 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(4, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 4 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(4, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 4 fail drv_id 2\n";
goto out;
}
rc = metal_irq_register(1, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 1 fail drv_id 2\n";
goto out;
}
rc = metal_irq_unregister(1, 0, 0, (void *)0);
if (rc) {
err_msg = "unregister irq 1 failed \n";
goto out;
}
rc = metal_irq_unregister(1, 0, 0, (void *)0);
if (!rc) {
err_msg = "unregister irq 1 fail expected\n";
goto out;
}
rc = metal_irq_unregister(2, 0, 0, (void *)2);
if (rc) {
err_msg = "unregister irq 2 drv_id 2 failed \n";
goto out;
}
rc = metal_irq_unregister(2, 0, 0, (void *)2);
if (!rc) {
err_msg = "unregister irq 2 drv_id 2 fail expected\n";
goto out;
}
rc = metal_irq_register(2, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 2 fail drv_id 2\n";
goto out;
}
rc = metal_irq_unregister(2, 0, 0, (void *)1);
if (rc) {
err_msg = "unregister irq 2 drv_id 1 failed \n";
goto out;
}
rc = metal_irq_unregister(2, 0, 0, (void *)2);
if (rc) {
err_msg = "unregister irq 2 drv_id 2 failed \n";
goto out;
}
rc = metal_irq_register(3, irq_handler, 0, (void *)1);
if (!rc) {
err_msg = "register irq 3 drv_id 1 overwrite fail expected\n";
goto out;
}
rc = metal_irq_register(3, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 3 fail drv_id 2\n";
goto out;
}
rc = metal_irq_unregister(3, irq_handler+1, 0, (void *)0);
if (!rc) {
err_msg = "unregister irq 3 match handler fail expected\n";
goto out;
}
rc = metal_irq_unregister(3, irq_handler, 0, (void *)0);
if (rc) {
err_msg = "unregister irq 3 match handler failed \n";
goto out;
}
rc = metal_irq_unregister(4, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "unregister irq 4 match handler and drv_id 2 failed \n";
goto out;
}
rc = metal_irq_unregister(4, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "unregister irq 4 match handler and drv_id 1 failed \n";
goto out;
}
rc = metal_irq_register(5, irq_handler, (void *)10, (void *)1);
if (rc) {
err_msg = "register irq 5 fail dev 10 drv_id 1\n";
goto out;
}
rc = metal_irq_register(5, irq_handler, (void *)20, (void *)2);
if (rc) {
err_msg = "register irq 5 fail dev 20 drv_id 2\n";
goto out;
}
rc = metal_irq_register(5, irq_handler, (void *)10, (void *)3);
if (rc) {
err_msg = "register irq 5 fail dev 10 drv_id 3\n";
goto out;
}
rc = metal_irq_register(5, irq_handler, 0, (void *)4);
if (rc) {
err_msg = "register irq 5 fail drv_id 4\n";
goto out;
}
rc = metal_irq_register(5, irq_handler, (void *)10, (void *)5);
if (rc) {
err_msg = "register irq 5 fail dev 10 drv_id 5\n";
goto out;
}
rc = metal_irq_unregister(5, irq_handler, (void *)10, (void *)3);
if (rc) {
err_msg = "unregister irq 5 match handle, dev 10 and drv_id 3 failed \n";
goto out;
}
rc = metal_irq_unregister(5, 0, 0, (void *)4);
if (rc) {
err_msg = "unregister irq 5 drv_id 4 failed \n";
goto out;
}
rc = metal_irq_unregister(5, 0, (void *)10, 0);
if (rc) {
err_msg = "unregister irq 5 dev 10 failed \n";
goto out;
}
rc = metal_irq_unregister(5, 0, (void *)20, (void *)2);
if (rc) {
err_msg = "unregister irq 5 match dev 20 and drv_id 2 failed \n";
goto out;
}
rc = metal_irq_register(-1, irq_handler, 0, (void *)1);
if (!rc) {
err_msg = "register irq -1 should have failed\n";
goto out;
}
/* global interrupt disable/enable normal behavior */
flags_1=metal_irq_save_disable();
metal_irq_restore_enable(flags_1);
/* global interrupt less common */
flags_1=metal_irq_save_disable();
flags_2=metal_irq_save_disable();
metal_irq_restore_enable(flags_2);
metal_irq_restore_enable(flags_1);
rc = 0;
out:
metal_set_log_level(mll);
if ((err_msg[0] != '\0') && (!rc))
rc = -EINVAL;
if (rc) metal_log(METAL_LOG_ERROR, "%s", err_msg);
return rc;
}
METAL_ADD_TEST(irq);
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "metal-test.h"
#include "FreeRTOS.h"
#include "task.h"
#define MAIN_THREAD_STACK_SZ 512
static void run_tests(void *param)
{
(void)param;
(void)metal_tests_run(NULL);
vTaskDelete(NULL);
}
int main(void)
{
BaseType_t stat;
stat = xTaskCreate(run_tests, "run_tests", MAIN_THREAD_STACK_SZ,
NULL, 2, NULL);
if (stat != pdPASS) {
metal_log(METAL_LOG_ERROR, "failed to create run_tests thread\n");
} else {
/* Start running FreeRTOS tasks */
vTaskStartScheduler();
}
/* Will not get here, unless a call is made to vTaskEndScheduler() */
while (1) {
__asm__("wfi\n\t");
}
/* suppress compilation warnings*/
return 0;
}
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <unistd.h>
#include "metal-test.h"
#include <metal/log.h>
#include <metal/sys.h>
#include <metal/mutex.h>
static const int mutex_test_count = 1000;
static void *mutex_thread(void *arg)
{
metal_mutex_t *l = arg;
int i;
for (i = 0; i < mutex_test_count; i++) {
metal_mutex_acquire(l);
usleep(1);
metal_mutex_release(l);
}
return NULL;
}
static int mutex(void)
{
metal_mutex_t lock;
const int threads = 10;
int rc;
metal_mutex_init(&lock);
rc = metal_run(threads, mutex_thread, &lock);
metal_mutex_deinit(&lock);
return rc;
}
METAL_ADD_TEST(mutex);
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <metal/errno.h>
#include <string.h>
#include "FreeRTOS.h"
#include "task.h"
#include "metal-test.h"
#include <metal/time.h>
#include <metal/sleep.h>
#include <metal/log.h>
#include <metal/sys.h>
static int sleep(void)
{
int rc;
unsigned int usec = 3;
unsigned long long tstart, tend, tdelayed;
tstart = metal_get_timestamp();
metal_sleep_usec((usec/portTICK_PERIOD_MS));
tend = metal_get_timestamp();
tdelayed = tend - tstart;
if (tdelayed > (usec/portTICK_PERIOD_MS))
rc = -1;
else
rc = 0;
return rc;
}
METAL_ADD_TEST(sleep);
@@ -0,0 +1,98 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <metal/errno.h>
#include "FreeRTOS.h"
#include "task.h"
#include <metal/sys.h>
#include <metal/utilities.h>
#include "metal-test.h"
#define TEST_THREAD_STACK_SIZE 128
typedef struct {
metal_thread_t thread_func;
void *arg;
} thread_wrap_arg_t;
static void thread_wrapper(void *arg)
{
thread_wrap_arg_t *wrap_p = (thread_wrap_arg_t *)arg;
(void)wrap_p->thread_func(wrap_p->arg);
vPortFree(wrap_p);
vTaskDelete(NULL);
}
int metal_run(int threads, metal_thread_t child, void *arg)
{
TaskHandle_t tids[threads];
int error, ts_created;
error = metal_run_noblock(threads, child, arg, (void *)tids, &ts_created);
metal_finish_threads(ts_created, (void *)tids);
return error;
}
int metal_run_noblock(int threads, metal_thread_t child,
void *arg, void *tids, int *threads_out)
{
int i;
TaskHandle_t *tid_p = (TaskHandle_t *)tids;
BaseType_t stat = pdPASS;
char tn[15];
thread_wrap_arg_t *wrap_p;
if (!tids) {
metal_log(METAL_LOG_ERROR, "invalid argument, tids is NULL.\n");
return -EINVAL;
}
for (i = 0; i < threads; i++) {
snprintf(tn, metal_dim(tn), "%d", i);
wrap_p = pvPortMalloc(sizeof(thread_wrap_arg_t));
if (!wrap_p) {
metal_log(METAL_LOG_ERROR, "failed to allocate wrapper %d\n", i);
break;
}
wrap_p->thread_func = child;
wrap_p->arg = arg;
stat = xTaskCreate(thread_wrapper, tn, TEST_THREAD_STACK_SIZE,
wrap_p, 2, &tid_p[i]);
if (stat != pdPASS) {
metal_log(METAL_LOG_ERROR, "failed to create thread %d\n", i);
vPortFree(wrap_p);
break;
}
}
*threads_out = i;
return pdPASS == stat ? 0 : -ENOMEM;
}
void metal_finish_threads(int threads, void *tids)
{
int i;
TaskHandle_t *tid_p = (TaskHandle_t *)tids;
if (!tids) {
metal_log(METAL_LOG_ERROR, "invalid argument, tids is NULL.\n");
return;
}
for (i = 0; i < threads; i++) {
eTaskState ts;
do {
taskYIELD();
ts=eTaskGetState(tid_p[i]);
} while (ts != eDeleted);
}
}
@@ -0,0 +1,18 @@
set (_test_lib_external "xil")
collect (PROJECT_LIB_DEPS ${_test_lib_external})
collect (PROJECT_LIB_DEPS "c")
collect (PROJECT_LIB_DEPS "m")
find_library (_ext_lib_path ${_test_lib_external})
if (NOT _ext_lib_path)
message ( "external library ${_test_lib_external} not found" )
message ( "hint: you may need to pass -DCMAKE_LIBRARY_PATH=<path>" )
message ( FATAL_ERROR "library ${_test_lib_external} is required to build the tests" )
endif (NOT _ext_lib_path)
get_filename_component (_ext_lib_path ${_ext_lib_path} DIRECTORY)
collect (PROJECT_LIB_DIRS ${_ext_lib_path})
set_property (GLOBAL PROPERTY TEST_LINKER_OPTIONS "-Wl,--gc-sections -Wl,-build-id=none -specs=${CMAKE_CURRENT_SOURCE_DIR}/Xilinx.spec -T\"${CMAKE_CURRENT_SOURCE_DIR}/lscript.ld\" -Wl,--start-group,-lxil,-lfreertos,-lgcc,-lc,--end-group")
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,2 @@
*startfile:
crti%O%s crtbegin%O%s
@@ -0,0 +1,304 @@
/******************************************************************************
*
* Copyright (C) 2017 Xilinx, Inc. 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.
*
******************************************************************************/
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x6000;
_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024;
_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;
/* Define Memories in the system */
MEMORY
{
ps7_ddr_0_S_AXI_BASEADDR : ORIGIN = 0x00100000, LENGTH = 0x08000000
ps7_ram_0_S_AXI_BASEADDR : ORIGIN = 0x00000000, LENGTH = 0x00030000
ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0000, LENGTH = 0x0000FE00
}
/* Specify the default entry point to the program */
ENTRY(_vector_table)
/* Define the sections, and where they are mapped in memory */
SECTIONS
{
.text : {
*(.vectors)
*(.boot)
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
*(.plt)
*(.gnu_warning)
*(.gcc_execpt_table)
*(.glue_7)
*(.glue_7t)
*(.vfp11_veneer)
*(.ARM.extab)
*(.gnu.linkonce.armextab.*)
} > ps7_ddr_0_S_AXI_BASEADDR
.init : {
KEEP (*(.init))
} > ps7_ddr_0_S_AXI_BASEADDR
.fini : {
KEEP (*(.fini))
} > ps7_ddr_0_S_AXI_BASEADDR
.rodata : {
__rodata_start = .;
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.rodata1 : {
__rodata1_start = .;
*(.rodata1)
*(.rodata1.*)
__rodata1_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.sdata2 : {
__sdata2_start = .;
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
__sdata2_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.sbss2 : {
__sbss2_start = .;
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
__sbss2_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.data : {
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.jcr)
*(.got)
*(.got.plt)
__data_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.data1 : {
__data1_start = .;
*(.data1)
*(.data1.*)
__data1_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.got : {
*(.got)
} > ps7_ddr_0_S_AXI_BASEADDR
.ctors : {
__CTOR_LIST__ = .;
___CTORS_LIST___ = .;
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
___CTORS_END___ = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.dtors : {
__DTOR_LIST__ = .;
___DTORS_LIST___ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
___DTORS_END___ = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.fixup : {
__fixup_start = .;
*(.fixup)
__fixup_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.eh_frame : {
*(.eh_frame)
} > ps7_ddr_0_S_AXI_BASEADDR
.eh_framehdr : {
__eh_framehdr_start = .;
*(.eh_framehdr)
__eh_framehdr_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.gcc_except_table : {
*(.gcc_except_table)
} > ps7_ddr_0_S_AXI_BASEADDR
.mmu_tbl (ALIGN(16384)) : {
__mmu_tbl_start = .;
*(.mmu_tbl)
__mmu_tbl_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
*(.gnu.linkonce.armexidix.*.*)
__exidx_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.preinit_array : {
__preinit_array_start = .;
KEEP (*(SORT(.preinit_array.*)))
KEEP (*(.preinit_array))
__preinit_array_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.init_array : {
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.fini_array : {
__fini_array_start = .;
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array))
__fini_array_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.ARM.attributes : {
__ARM.attributes_start = .;
*(.ARM.attributes)
__ARM.attributes_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.sdata : {
__sdata_start = .;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
__sdata_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.sbss (NOLOAD) : {
__sbss_start = .;
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
__sbss_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.tdata : {
__tdata_start = .;
*(.tdata)
*(.tdata.*)
*(.gnu.linkonce.td.*)
__tdata_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.tbss : {
__tbss_start = .;
*(.tbss)
*(.tbss.*)
*(.gnu.linkonce.tb.*)
__tbss_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.bss (NOLOAD) : {
__bss_start = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
__bss_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
/* Generate Stack and Heap definitions */
.heap (NOLOAD) : {
. = ALIGN(16);
_heap = .;
HeapBase = .;
_heap_start = .;
. += _HEAP_SIZE;
_heap_end = .;
HeapLimit = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.stack (NOLOAD) : {
. = ALIGN(16);
_stack_end = .;
. += _STACK_SIZE;
_stack = .;
__stack = _stack;
. = ALIGN(16);
_irq_stack_end = .;
. += _IRQ_STACK_SIZE;
__irq_stack = .;
_supervisor_stack_end = .;
. += _SUPERVISOR_STACK_SIZE;
. = ALIGN(16);
__supervisor_stack = .;
_abort_stack_end = .;
. += _ABORT_STACK_SIZE;
. = ALIGN(16);
__abort_stack = .;
_fiq_stack_end = .;
. += _FIQ_STACK_SIZE;
. = ALIGN(16);
__fiq_stack = .;
_undef_stack_end = .;
. += _UNDEF_STACK_SIZE;
. = ALIGN(16);
__undef_stack = .;
} > ps7_ddr_0_S_AXI_BASEADDR
_end = .;
}
@@ -0,0 +1,19 @@
set (_test_lib_external "xil")
collect (PROJECT_LIB_DEPS ${_test_lib_external})
collect (PROJECT_LIB_DEPS "c")
collect (PROJECT_LIB_DEPS "m")
find_library (_ext_lib_path ${_test_lib_external})
if (NOT _ext_lib_path)
message ( "external library ${_test_lib_external} not found" )
message ( "hint: you may need to pass -DCMAKE_LIBRARY_PATH=<path>" )
message ( FATAL_ERROR "library ${_test_lib_external} is required to build the tests" )
endif (NOT _ext_lib_path)
get_filename_component (_ext_lib_path ${_ext_lib_path} DIRECTORY)
collect (PROJECT_LIB_DIRS ${_ext_lib_path})
set_property (GLOBAL PROPERTY TEST_LINKER_OPTIONS "-Wl,--gc-sections -T\"${CMAKE_CURRENT_SOURCE_DIR}/lscript.ld\" -Wl,--start-group,-lxil,-lfreertos,-lgcc,-lc,--end-group")
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,339 @@
/******************************************************************************
*
* Copyright (C) 2017 Xilinx, Inc. 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.
*
******************************************************************************/
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x6000;
_EL0_STACK_SIZE = DEFINED(_EL0_STACK_SIZE) ? _EL0_STACK_SIZE : 1024;
_EL1_STACK_SIZE = DEFINED(_EL1_STACK_SIZE) ? _EL1_STACK_SIZE : 2048;
_EL2_STACK_SIZE = DEFINED(_EL2_STACK_SIZE) ? _EL2_STACK_SIZE : 1024;
/* Define Memories in the system */
MEMORY
{
psu_ddr_0_MEM_0 : ORIGIN = 0x0, LENGTH = 0x80000000
psu_ddr_1_MEM_0 : ORIGIN = 0x800000000, LENGTH = 0x80000000
psu_ocm_ram_0_MEM_0 : ORIGIN = 0xFFFC0000, LENGTH = 0x40000
psu_qspi_linear_0_MEM_0 : ORIGIN = 0xC0000000, LENGTH = 0x20000000
}
/* Specify the default entry point to the program */
ENTRY(_vector_table)
/* Define the sections, and where they are mapped in memory */
SECTIONS
{
.text : {
KEEP (*(.vectors))
*(.boot)
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
*(.plt)
*(.gnu_warning)
*(.gcc_execpt_table)
*(.glue_7)
*(.glue_7t)
*(.ARM.extab)
*(.gnu.linkonce.armextab.*)
} > psu_ddr_0_MEM_0
.init (ALIGN(64)) : {
KEEP (*(.init))
} > psu_ddr_0_MEM_0
.fini (ALIGN(64)) : {
KEEP (*(.fini))
} > psu_ddr_0_MEM_0
.interp : {
KEEP (*(.interp))
} > psu_ddr_0_MEM_0
.note-ABI-tag : {
KEEP (*(.note-ABI-tag))
} > psu_ddr_0_MEM_0
.rodata : {
. = ALIGN(64);
__rodata_start = .;
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > psu_ddr_0_MEM_0
.rodata1 : {
. = ALIGN(64);
__rodata1_start = .;
*(.rodata1)
*(.rodata1.*)
__rodata1_end = .;
} > psu_ddr_0_MEM_0
.sdata2 : {
. = ALIGN(64);
__sdata2_start = .;
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
__sdata2_end = .;
} > psu_ddr_0_MEM_0
.sbss2 : {
. = ALIGN(64);
__sbss2_start = .;
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
__sbss2_end = .;
} > psu_ddr_0_MEM_0
.data : {
. = ALIGN(64);
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.jcr)
*(.got)
*(.got.plt)
__data_end = .;
} > psu_ddr_0_MEM_0
.data1 : {
. = ALIGN(64);
__data1_start = .;
*(.data1)
*(.data1.*)
__data1_end = .;
} > psu_ddr_0_MEM_0
.got : {
*(.got)
} > psu_ddr_0_MEM_0
.got1 : {
*(.got1)
} > psu_ddr_0_MEM_0
.got2 : {
*(.got2)
} > psu_ddr_0_MEM_0
.ctors : {
. = ALIGN(64);
__CTOR_LIST__ = .;
___CTORS_LIST___ = .;
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
___CTORS_END___ = .;
} > psu_ddr_0_MEM_0
.dtors : {
. = ALIGN(64);
__DTOR_LIST__ = .;
___DTORS_LIST___ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
___DTORS_END___ = .;
} > psu_ddr_0_MEM_0
.fixup : {
__fixup_start = .;
*(.fixup)
__fixup_end = .;
} > psu_ddr_0_MEM_0
.eh_frame : {
*(.eh_frame)
} > psu_ddr_0_MEM_0
.eh_framehdr : {
__eh_framehdr_start = .;
*(.eh_framehdr)
__eh_framehdr_end = .;
} > psu_ddr_0_MEM_0
.gcc_except_table : {
*(.gcc_except_table)
} > psu_ddr_0_MEM_0
.mmu_tbl0 (ALIGN(4096)) : {
__mmu_tbl0_start = .;
*(.mmu_tbl0)
__mmu_tbl0_end = .;
} > psu_ddr_0_MEM_0
.mmu_tbl1 (ALIGN(4096)) : {
__mmu_tbl1_start = .;
*(.mmu_tbl1)
__mmu_tbl1_end = .;
} > psu_ddr_0_MEM_0
.mmu_tbl2 (ALIGN(4096)) : {
__mmu_tbl2_start = .;
*(.mmu_tbl2)
__mmu_tbl2_end = .;
} > psu_ddr_0_MEM_0
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
*(.gnu.linkonce.armexidix.*.*)
__exidx_end = .;
} > psu_ddr_0_MEM_0
.preinit_array : {
. = ALIGN(64);
__preinit_array_start = .;
KEEP (*(SORT(.preinit_array.*)))
KEEP (*(.preinit_array))
__preinit_array_end = .;
} > psu_ddr_0_MEM_0
.init_array : {
. = ALIGN(64);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > psu_ddr_0_MEM_0
.fini_array : {
. = ALIGN(64);
__fini_array_start = .;
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array))
__fini_array_end = .;
} > psu_ddr_0_MEM_0
.ARM.attributes : {
__ARM.attributes_start = .;
*(.ARM.attributes)
__ARM.attributes_end = .;
} > psu_ddr_0_MEM_0
.sdata : {
. = ALIGN(64);
__sdata_start = .;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
__sdata_end = .;
} > psu_ddr_0_MEM_0
.sbss (NOLOAD) : {
. = ALIGN(64);
__sbss_start = .;
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
. = ALIGN(64);
__sbss_end = .;
} > psu_ddr_0_MEM_0
.tdata : {
. = ALIGN(64);
__tdata_start = .;
*(.tdata)
*(.tdata.*)
*(.gnu.linkonce.td.*)
__tdata_end = .;
} > psu_ddr_0_MEM_0
.tbss : {
. = ALIGN(64);
__tbss_start = .;
*(.tbss)
*(.tbss.*)
*(.gnu.linkonce.tb.*)
__tbss_end = .;
} > psu_ddr_0_MEM_0
.bss (NOLOAD) : {
. = ALIGN(64);
__bss_start__ = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(64);
__bss_end__ = .;
} > psu_ddr_0_MEM_0
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
/* Generate Stack and Heap definitions */
.heap (NOLOAD) : {
. = ALIGN(64);
_heap = .;
HeapBase = .;
_heap_start = .;
. += _HEAP_SIZE;
_heap_end = .;
HeapLimit = .;
} > psu_ddr_0_MEM_0
.stack (NOLOAD) : {
. = ALIGN(64);
_el3_stack_end = .;
. += _STACK_SIZE;
__el3_stack = .;
_el2_stack_end = .;
. += _EL2_STACK_SIZE;
. = ALIGN(64);
__el2_stack = .;
_el1_stack_end = .;
. += _EL1_STACK_SIZE;
. = ALIGN(64);
__el1_stack = .;
_el0_stack_end = .;
. += _EL0_STACK_SIZE;
. = ALIGN(64);
__el0_stack = .;
} > psu_ddr_0_MEM_0
_end = .;
}
@@ -0,0 +1,18 @@
set (_test_lib_external "xil")
collect (PROJECT_LIB_DEPS ${_test_lib_external})
collect (PROJECT_LIB_DEPS "c")
collect (PROJECT_LIB_DEPS "m")
find_library (_ext_lib_path ${_test_lib_external})
if (NOT _ext_lib_path)
message ( "external library ${_test_lib_external} not found" )
message ( "hint: you may need to pass -DCMAKE_LIBRARY_PATH=<path>" )
message ( FATAL_ERROR "library ${_test_lib_external} is required to build the tests" )
endif (NOT _ext_lib_path)
get_filename_component (_ext_lib_path ${_ext_lib_path} DIRECTORY)
collect (PROJECT_LIB_DIRS ${_ext_lib_path})
set_property (GLOBAL PROPERTY TEST_LINKER_OPTIONS "-Wl,--gc-sections -T\"${CMAKE_CURRENT_SOURCE_DIR}/lscript.ld\" -Wl,--start-group,-lxil,-lfreertos,-lgcc,-lc,--end-group")
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,317 @@
/******************************************************************************
*
* Copyright (C) 2017 Xilinx, Inc. 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.
*
******************************************************************************/
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x6000;
_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024;
_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;
/* Define Memories in the system */
MEMORY
{
psu_r5_atcm_MEM_0 : ORIGIN = 0x0, LENGTH = 0x10000
psu_r5_btcm_MEM_0 : ORIGIN = 0x20000, LENGTH = 0x10000
psu_r5_ddr_0_MEM_0 : ORIGIN = 0x3ed00000, LENGTH = 0x80000
}
/* Specify the default entry point to the program */
ENTRY(_boot)
/* Define the sections, and where they are mapped in memory */
SECTIONS
{
.vectors : {
KEEP (*(.vectors))
*(.boot)
} > psu_r5_atcm_MEM_0
.text : {
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
*(.plt)
*(.gnu_warning)
*(.gcc_execpt_table)
*(.glue_7)
*(.glue_7t)
*(.vfp11_veneer)
*(.ARM.extab)
*(.gnu.linkonce.armextab.*)
} > psu_r5_ddr_0_MEM_0
.init : {
KEEP (*(.init))
} > psu_r5_ddr_0_MEM_0
.fini : {
KEEP (*(.fini))
} > psu_r5_ddr_0_MEM_0
.interp : {
KEEP (*(.interp))
} > psu_r5_ddr_0_MEM_0
.note-ABI-tag : {
KEEP (*(.note-ABI-tag))
} > psu_r5_ddr_0_MEM_0
.rodata : {
__rodata_start = .;
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > psu_r5_ddr_0_MEM_0
.rodata1 : {
__rodata1_start = .;
*(.rodata1)
*(.rodata1.*)
__rodata1_end = .;
} > psu_r5_ddr_0_MEM_0
.sdata2 : {
__sdata2_start = .;
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
__sdata2_end = .;
} > psu_r5_ddr_0_MEM_0
.sbss2 : {
__sbss2_start = .;
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
__sbss2_end = .;
} > psu_r5_ddr_0_MEM_0
.data : {
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.jcr)
*(.got)
*(.got.plt)
__data_end = .;
} > psu_r5_ddr_0_MEM_0
.data1 : {
__data1_start = .;
*(.data1)
*(.data1.*)
__data1_end = .;
} > psu_r5_ddr_0_MEM_0
.got : {
*(.got)
} > psu_r5_ddr_0_MEM_0
.ctors : {
__CTOR_LIST__ = .;
___CTORS_LIST___ = .;
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
___CTORS_END___ = .;
} > psu_r5_ddr_0_MEM_0
.dtors : {
__DTOR_LIST__ = .;
___DTORS_LIST___ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
___DTORS_END___ = .;
} > psu_r5_ddr_0_MEM_0
.fixup : {
__fixup_start = .;
*(.fixup)
__fixup_end = .;
} > psu_r5_ddr_0_MEM_0
.eh_frame : {
*(.eh_frame)
} > psu_r5_ddr_0_MEM_0
.eh_framehdr : {
__eh_framehdr_start = .;
*(.eh_framehdr)
__eh_framehdr_end = .;
} > psu_r5_ddr_0_MEM_0
.gcc_except_table : {
*(.gcc_except_table)
} > psu_r5_ddr_0_MEM_0
.mmu_tbl (ALIGN(16384)) : {
__mmu_tbl_start = .;
*(.mmu_tbl)
__mmu_tbl_end = .;
} > psu_r5_ddr_0_MEM_0
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
*(.gnu.linkonce.armexidix.*.*)
__exidx_end = .;
} > psu_r5_ddr_0_MEM_0
.preinit_array : {
__preinit_array_start = .;
KEEP (*(SORT(.preinit_array.*)))
KEEP (*(.preinit_array))
__preinit_array_end = .;
} > psu_r5_ddr_0_MEM_0
.init_array : {
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > psu_r5_ddr_0_MEM_0
.fini_array : {
__fini_array_start = .;
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array))
__fini_array_end = .;
} > psu_r5_ddr_0_MEM_0
.ARM.attributes : {
__ARM.attributes_start = .;
*(.ARM.attributes)
__ARM.attributes_end = .;
} > psu_r5_ddr_0_MEM_0
.sdata : {
__sdata_start = .;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
__sdata_end = .;
} > psu_r5_ddr_0_MEM_0
.sbss (NOLOAD) : {
__sbss_start = .;
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
__sbss_end = .;
} > psu_r5_ddr_0_MEM_0
.tdata : {
__tdata_start = .;
*(.tdata)
*(.tdata.*)
*(.gnu.linkonce.td.*)
__tdata_end = .;
} > psu_r5_ddr_0_MEM_0
.tbss : {
__tbss_start = .;
*(.tbss)
*(.tbss.*)
*(.gnu.linkonce.tb.*)
__tbss_end = .;
} > psu_r5_ddr_0_MEM_0
.bss (NOLOAD) : {
. = ALIGN(4);
__bss_start__ = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > psu_r5_ddr_0_MEM_0
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
/* Generate Stack and Heap definitions */
.heap (NOLOAD) : {
. = ALIGN(16);
_heap = .;
HeapBase = .;
_heap_start = .;
. += _HEAP_SIZE;
_heap_end = .;
HeapLimit = .;
} > psu_r5_btcm_MEM_0
.stack (NOLOAD) : {
. = ALIGN(16);
_stack_end = .;
. += _STACK_SIZE;
_stack = .;
__stack = _stack;
. = ALIGN(16);
_irq_stack_end = .;
. += _IRQ_STACK_SIZE;
__irq_stack = .;
_supervisor_stack_end = .;
. += _SUPERVISOR_STACK_SIZE;
. = ALIGN(16);
__supervisor_stack = .;
_abort_stack_end = .;
. += _ABORT_STACK_SIZE;
. = ALIGN(16);
__abort_stack = .;
_fiq_stack_end = .;
. += _FIQ_STACK_SIZE;
. = ALIGN(16);
__fiq_stack = .;
_undef_stack_end = .;
. += _UNDEF_STACK_SIZE;
. = ALIGN(16);
__undef_stack = .;
} > psu_r5_btcm_MEM_0
_end = .;
}
@@ -0,0 +1,11 @@
collect (PROJECT_LIB_TESTS main.c)
collect (PROJECT_LIB_TESTS alloc.c)
collect (PROJECT_LIB_TESTS irq.c)
collect (PROJECT_LIB_TESTS mutex.c)
collect (PROJECT_LIB_TESTS atomic.c)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
add_subdirectory(${PROJECT_MACHINE})
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include "metal-test.h"
#include <metal/alloc.h>
#include <metal/log.h>
#include <metal/sys.h>
static int alloc(void)
{
void *ptr;
ptr = metal_allocate_memory(1000);
if (!ptr) {
metal_log(METAL_LOG_DEBUG, "failed to allocate memmory\n");
return errno;
}
metal_free_memory(ptr);
return 0;
}
METAL_ADD_TEST(alloc);
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include <metal-test.h>
#include <metal/atomic.h>
#include <metal/log.h>
#include <metal/sys.h>
static const int atomic_test_count = 1000;
static int atomic(void)
{
atomic_int counter = ATOMIC_VAR_INIT(0);
int value, error=0, i;
for (i = 0; i < atomic_test_count; i++) {
atomic_fetch_add(&counter, 1);
}
value = atomic_load(&counter);
value -= atomic_test_count;
if (value) {
metal_log(METAL_LOG_DEBUG, "counter mismatch, delta = %d\n", value);
error = -1;
}
return error;
}
METAL_ADD_TEST(atomic);
@@ -0,0 +1,218 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include <metal/errno.h>
/* We need to find the internal MAX_IRQS limit */
/* Could be retrieved from platform specific files in the future */
#define METAL_INTERNAL
#include "metal-test.h"
#include <metal/irq.h>
#include <metal/log.h>
#include <metal/sys.h>
#include <metal/list.h>
#include <metal/utilities.h>
int irq_handler(int irq, void *priv)
{
(void)irq;
(void)priv;
return 0;
}
static int irq(void)
{
int rc = 0, flags_1, flags_2;
char *err_msg="";
enum metal_log_level mll= metal_get_log_level();
/* Do not show LOG_ERROR or LOG_DEBUG for expected fail case */
metal_set_log_level(METAL_LOG_CRITICAL);
rc = metal_irq_register(1, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 1 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(2, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 2 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(2, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 2 fail drv_id 2\n";
goto out;
}
rc = metal_irq_register(3, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 3 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(4, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 4 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(4, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 4 fail drv_id 2\n";
goto out;
}
rc = metal_irq_register(1, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 1 fail drv_id 2\n";
goto out;
}
rc = metal_irq_unregister(1, 0, 0, (void *)0);
if (rc) {
err_msg = "unregister irq 1 failed \n";
goto out;
}
rc = metal_irq_unregister(1, 0, 0, (void *)0);
if (!rc) {
err_msg = "unregister irq 1 fail expected\n";
goto out;
}
rc = metal_irq_unregister(2, 0, 0, (void *)2);
if (rc) {
err_msg = "unregister irq 2 drv_id 2 failed \n";
goto out;
}
rc = metal_irq_unregister(2, 0, 0, (void *)2);
if (!rc) {
err_msg = "unregister irq 2 drv_id 2 fail expected\n";
goto out;
}
rc = metal_irq_register(2, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 2 fail drv_id 2\n";
goto out;
}
rc = metal_irq_unregister(2, 0, 0, (void *)1);
if (rc) {
err_msg = "unregister irq 2 drv_id 1 failed \n";
goto out;
}
rc = metal_irq_unregister(2, 0, 0, (void *)2);
if (rc) {
err_msg = "unregister irq 2 drv_id 2 failed \n";
goto out;
}
rc = metal_irq_register(3, irq_handler, 0, (void *)1);
if (!rc) {
err_msg = "register irq 3 drv_id 1 overwrite fail expected\n";
goto out;
}
rc = metal_irq_register(3, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 3 fail drv_id 2\n";
goto out;
}
rc = metal_irq_unregister(3, irq_handler+1, 0, (void *)0);
if (!rc) {
err_msg = "unregister irq 3 match handler fail expected\n";
goto out;
}
rc = metal_irq_unregister(3, irq_handler, 0, (void *)0);
if (rc) {
err_msg = "unregister irq 3 match handler failed \n";
goto out;
}
rc = metal_irq_unregister(4, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "unregister irq 4 match handler and drv_id 2 failed \n";
goto out;
}
rc = metal_irq_unregister(4, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "unregister irq 4 match handler and drv_id 1 failed \n";
goto out;
}
rc = metal_irq_register(5, irq_handler, (void *)10, (void *)1);
if (rc) {
err_msg = "register irq 5 fail dev 10 drv_id 1\n";
goto out;
}
rc = metal_irq_register(5, irq_handler, (void *)20, (void *)2);
if (rc) {
err_msg = "register irq 5 fail dev 20 drv_id 2\n";
goto out;
}
rc = metal_irq_register(5, irq_handler, (void *)10, (void *)3);
if (rc) {
err_msg = "register irq 5 fail dev 10 drv_id 3\n";
goto out;
}
rc = metal_irq_register(5, irq_handler, 0, (void *)4);
if (rc) {
err_msg = "register irq 5 fail drv_id 4\n";
goto out;
}
rc = metal_irq_register(5, irq_handler, (void *)10, (void *)5);
if (rc) {
err_msg = "register irq 5 fail dev 10 drv_id 5\n";
goto out;
}
rc = metal_irq_unregister(5, irq_handler, (void *)10, (void *)3);
if (rc) {
err_msg = "unregister irq 5 match handle, dev 10 and drv_id 3 failed \n";
goto out;
}
rc = metal_irq_unregister(5, 0, 0, (void *)4);
if (rc) {
err_msg = "unregister irq 5 drv_id 4 failed \n";
goto out;
}
rc = metal_irq_unregister(5, 0, (void *)10, 0);
if (rc) {
err_msg = "unregister irq 5 dev 10 failed \n";
goto out;
}
rc = metal_irq_unregister(5, 0, (void *)20, (void *)2);
if (rc) {
err_msg = "unregister irq 5 match dev 20 and drv_id 2 failed \n";
goto out;
}
rc = metal_irq_register(-1, irq_handler, 0, (void *)1);
if (!rc) {
err_msg = "register irq -1 should have failed\n";
goto out;
}
/* global interrupt disable/enable normal behavior */
flags_1=metal_irq_save_disable();
metal_irq_restore_enable(flags_1);
/* global interrupt less common */
flags_1=metal_irq_save_disable();
flags_2=metal_irq_save_disable();
metal_irq_restore_enable(flags_2);
metal_irq_restore_enable(flags_1);
rc = 0;
out:
metal_set_log_level(mll);
if ((err_msg[0] != '\0') && (!rc))
rc = -EINVAL;
if (rc) metal_log(METAL_LOG_ERROR, "%s", err_msg);
return rc;
}
METAL_ADD_TEST(irq);
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "metal-test.h"
extern int init_system(void);
extern void metal_generic_default_poll(void);
int main(void)
{
(void)init_system();
(void)metal_tests_run(NULL);
while (1)
metal_generic_default_poll();
/* will not return, but quiet the compiler */
return 0;
}
@@ -0,0 +1,21 @@
collect (PROJECT_LIB_TESTS helper.c)
collect (PROJECT_LIB_TESTS platform.c)
set (_test_lib_external "xil")
collect (PROJECT_LIB_DEPS ${_test_lib_external})
collect (PROJECT_LIB_DEPS "c")
collect (PROJECT_LIB_DEPS "m")
find_library (_ext_lib_path ${_test_lib_external})
if (NOT _ext_lib_path)
message ( "external library ${_test_lib_external} not found" )
message ( "hint: you may need to pass -DCMAKE_LIBRARY_PATH=<path>" )
message ( FATAL_ERROR "library ${_test_lib_external} is required to build the tests" )
endif (NOT _ext_lib_path)
get_filename_component (_ext_lib_path ${_ext_lib_path} DIRECTORY)
collect (PROJECT_LIB_DIRS ${_ext_lib_path})
set_property (GLOBAL PROPERTY TEST_LINKER_OPTIONS "-Wl,--gc-sections -T\"${CMAKE_CURRENT_SOURCE_DIR}/lscript.ld\"")
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,15 @@
/*
* Copyright (c) 2017 Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "platform.h"
/* Main hw machinery initialization entry point, called from main()*/
/* return 0 on success */
int init_system(void)
{
init_platform();
return 0;
}
@@ -0,0 +1,229 @@
/*
* Copyright (c) 2017 Xilinx, Inc. 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 the <ORGANIZATION> 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.
*/
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000;
/* Define Memories in the system */
MEMORY
{
microblaze_0_local_memory_ilmb_bram_if_cntlr_Mem_microblaze_0_local_memory_dlmb_bram_if_cntlr_Mem : ORIGIN = 0x50, LENGTH = 0x1FB0
ddr3_sdram_memaddr : ORIGIN = 0x80000000, LENGTH = 0x40000000
linear_flash_MEM0_BASEADDR_MEM0 : ORIGIN = 0x60000000, LENGTH = 0x8000000
}
/* Specify the default entry point to the program */
ENTRY(_start)
/* Define the sections, and where they are mapped in memory */
SECTIONS
{
.vectors.reset 0x0 : {
KEEP (*(.vectors.reset))
}
.vectors.sw_exception 0x8 : {
KEEP (*(.vectors.sw_exception))
}
.vectors.interrupt 0x10 : {
KEEP (*(.vectors.interrupt))
}
.vectors.hw_exception 0x20 : {
KEEP (*(.vectors.hw_exception))
}
.text : {
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
} > ddr3_sdram_memaddr
.init : {
KEEP (*(.init))
} > ddr3_sdram_memaddr
.fini : {
KEEP (*(.fini))
} > ddr3_sdram_memaddr
.ctors : {
__CTOR_LIST__ = .;
___CTORS_LIST___ = .;
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
___CTORS_END___ = .;
} > ddr3_sdram_memaddr
.dtors : {
__DTOR_LIST__ = .;
___DTORS_LIST___ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
PROVIDE(__DTOR_END__ = .);
PROVIDE(___DTORS_END___ = .);
} > ddr3_sdram_memaddr
.rodata : {
__rodata_start = .;
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > ddr3_sdram_memaddr
.sdata2 : {
. = ALIGN(8);
__sdata2_start = .;
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
. = ALIGN(8);
__sdata2_end = .;
} > ddr3_sdram_memaddr
.sbss2 : {
__sbss2_start = .;
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
__sbss2_end = .;
} > ddr3_sdram_memaddr
.data : {
. = ALIGN(4);
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
__data_end = .;
} > ddr3_sdram_memaddr
.got : {
*(.got)
} > ddr3_sdram_memaddr
.got1 : {
*(.got1)
} > ddr3_sdram_memaddr
.got2 : {
*(.got2)
} > ddr3_sdram_memaddr
.eh_frame : {
*(.eh_frame)
} > ddr3_sdram_memaddr
.jcr : {
*(.jcr)
} > ddr3_sdram_memaddr
.gcc_except_table : {
*(.gcc_except_table)
} > ddr3_sdram_memaddr
.sdata : {
. = ALIGN(8);
__sdata_start = .;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
__sdata_end = .;
} > ddr3_sdram_memaddr
.sbss (NOLOAD) : {
. = ALIGN(4);
__sbss_start = .;
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
. = ALIGN(8);
__sbss_end = .;
} > ddr3_sdram_memaddr
.tdata : {
__tdata_start = .;
*(.tdata)
*(.tdata.*)
*(.gnu.linkonce.td.*)
__tdata_end = .;
} > ddr3_sdram_memaddr
.tbss : {
__tbss_start = .;
*(.tbss)
*(.tbss.*)
*(.gnu.linkonce.tb.*)
__tbss_end = .;
} > ddr3_sdram_memaddr
.bss (NOLOAD) : {
. = ALIGN(4);
__bss_start = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > ddr3_sdram_memaddr
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
/* Generate Stack and Heap definitions */
.heap (NOLOAD) : {
. = ALIGN(8);
_heap = .;
_heap_start = .;
. += _HEAP_SIZE;
_heap_end = .;
} > ddr3_sdram_memaddr
.stack (NOLOAD) : {
_stack_end = .;
. += _STACK_SIZE;
. = ALIGN(8);
_stack = .;
__stack = _stack;
} > ddr3_sdram_memaddr
_end = .;
}
@@ -0,0 +1,62 @@
/******************************************************************************
*
* Copyright (C) 2017 Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "xparameters.h"
#include "xil_cache.h"
#ifdef STDOUT_IS_16550
#include "xuartns550_l.h"
#define UART_BAUD 115200
#endif
void
enable_caches()
{
#ifdef XPAR_MICROBLAZE_USE_ICACHE
Xil_ICacheEnable();
#endif
#ifdef XPAR_MICROBLAZE_USE_DCACHE
Xil_DCacheEnable();
#endif
}
void
disable_caches()
{
#ifdef __MICROBLAZE__
#ifdef XPAR_MICROBLAZE_USE_DCACHE
Xil_DCacheDisable();
#endif
#ifdef XPAR_MICROBLAZE_USE_ICACHE
Xil_ICacheDisable();
#endif
#endif
}
void
init_uart()
{
#ifdef STDOUT_IS_16550
XUartNs550_SetBaud(STDOUT_BASEADDR, XPAR_XUARTNS550_CLOCK_HZ, UART_BAUD);
XUartNs550_SetLineControlReg(STDOUT_BASEADDR, XUN_LCR_8_DATA_BITS);
#endif
/* Bootrom/BSP configures PS7/PSU UART to 115200 bps */
}
void
init_platform()
{
enable_caches();
init_uart();
}
void
cleanup_platform()
{
disable_caches();
}
@@ -0,0 +1,15 @@
/******************************************************************************
*
* Copyright (C) 2017 Xilinx, Inc. All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __PLATFORM_H_
#define __PLATFORM_H_
void init_platform();
void cleanup_platform();
#endif
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <metal-test.h>
#include <metal/mutex.h>
static const int mutex_test_count = 1000;
static int mutex(void)
{
metal_mutex_t lock;
int i;
metal_mutex_init(&lock);
for (i = 0; i < mutex_test_count; i++) {
metal_mutex_acquire(&lock);
metal_mutex_release(&lock);
}
return 0;
}
METAL_ADD_TEST(mutex);
@@ -0,0 +1,20 @@
collect (PROJECT_LIB_TESTS helper.c)
set (_test_lib_external "xil")
collect (PROJECT_LIB_DEPS ${_test_lib_external})
collect (PROJECT_LIB_DEPS "c")
collect (PROJECT_LIB_DEPS "m")
find_library (_ext_lib_path ${_test_lib_external})
if (NOT _ext_lib_path)
message ( "external library ${_test_lib_external} not found" )
message ( "hint: you may need to pass -DCMAKE_LIBRARY_PATH=<path>" )
message ( FATAL_ERROR "library ${_test_lib_external} is required to build the tests" )
endif (NOT _ext_lib_path)
get_filename_component (_ext_lib_path ${_ext_lib_path} DIRECTORY)
collect (PROJECT_LIB_DIRS ${_ext_lib_path})
set_property (GLOBAL PROPERTY TEST_LINKER_OPTIONS "-Wl,--gc-sections -Wl,-build-id=none -specs=${CMAKE_CURRENT_SOURCE_DIR}/Xilinx.spec -T\"${CMAKE_CURRENT_SOURCE_DIR}/lscript.ld\"")
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,2 @@
*startfile:
crti%O%s crtbegin%O%s
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2014, Mentor Graphics Corporation
* All rights reserved.
*
* Copyright (c) 2016 Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "xscugic.h"
#define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID
static XScuGic xInterruptController;
/* Interrupt Controller setup */
static int app_gic_initialize(void)
{
u32 Status;
XScuGic_Config *IntcConfig; /* The configuration parameters of the interrupt controller */
Xil_ExceptionDisable();
/*
* Initialize the interrupt controller driver
*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(&xInterruptController, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Register the interrupt handler to the hardware interrupt handling
* logic in the ARM processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
&xInterruptController);
Xil_ExceptionEnable();
return 0;
}
/* Main hw machinery initialization entry point, called from main()*/
/* return 0 on success */
int init_system(void)
{
/* configure the global interrupt controller */
app_gic_initialize();
return 0;
}
@@ -0,0 +1,290 @@
/*******************************************************************/
/* */
/* This file is automatically generated by linker script generator.*/
/* */
/* Version: */
/* */
/* Copyright (c) 2010 Xilinx, Inc. All rights reserved. */
/* */
/* Description : Cortex-A9 Linker Script */
/* */
/*******************************************************************/
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x4000;
_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 4096;
_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;
/* Define Memories in the system */
MEMORY
{
ps7_ddr_0_S_AXI_BASEADDR : ORIGIN = 0x00100000, LENGTH = 0x08000000
ps7_ram_0_S_AXI_BASEADDR : ORIGIN = 0x00000000, LENGTH = 0x00030000
ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0000, LENGTH = 0x0000FE00
}
/* Specify the default entry point to the program */
ENTRY(_vector_table)
/* Define the sections, and where they are mapped in memory */
SECTIONS
{
.text : {
_binary_firmware1_start = 0;
_binary_firmware1_end = 0;
_binary_firmware2_start = 0;
_binary_firmware2_end = 0;
*(.vectors)
*(.boot)
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
*(.plt)
*(.gnu_warning)
*(.gcc_execpt_table)
*(.glue_7)
*(.glue_7t)
*(.vfp11_veneer)
*(.ARM.extab)
*(.gnu.linkonce.armextab.*)
} > ps7_ddr_0_S_AXI_BASEADDR
.init : {
KEEP (*(.init))
} > ps7_ddr_0_S_AXI_BASEADDR
.fini : {
KEEP (*(.fini))
} > ps7_ddr_0_S_AXI_BASEADDR
.rodata : {
__rodata_start = .;
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.rodata1 : {
__rodata1_start = .;
*(.rodata1)
*(.rodata1.*)
__rodata1_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.sdata2 : {
__sdata2_start = .;
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
__sdata2_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.sbss2 : {
__sbss2_start = .;
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
__sbss2_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.data : {
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.jcr)
*(.got)
*(.got.plt)
__data_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.data1 : {
__data1_start = .;
*(.data1)
*(.data1.*)
__data1_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.got : {
*(.got)
} > ps7_ddr_0_S_AXI_BASEADDR
.ctors : {
__CTOR_LIST__ = .;
___CTORS_LIST___ = .;
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
___CTORS_END___ = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.dtors : {
__DTOR_LIST__ = .;
___DTORS_LIST___ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
___DTORS_END___ = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.fixup : {
__fixup_start = .;
*(.fixup)
__fixup_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.eh_frame : {
*(.eh_frame)
} > ps7_ddr_0_S_AXI_BASEADDR
.eh_framehdr : {
__eh_framehdr_start = .;
*(.eh_framehdr)
__eh_framehdr_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.gcc_except_table : {
*(.gcc_except_table)
} > ps7_ddr_0_S_AXI_BASEADDR
.mmu_tbl (ALIGN(16384)) : {
__mmu_tbl_start = .;
*(.mmu_tbl)
__mmu_tbl_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
*(.gnu.linkonce.armexidix.*.*)
__exidx_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.preinit_array : {
__preinit_array_start = .;
KEEP (*(SORT(.preinit_array.*)))
KEEP (*(.preinit_array))
__preinit_array_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.init_array : {
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.fini_array : {
__fini_array_start = .;
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array))
__fini_array_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.ARM.attributes : {
__ARM.attributes_start = .;
*(.ARM.attributes)
__ARM.attributes_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.sdata : {
__sdata_start = .;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
__sdata_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.sbss (NOLOAD) : {
__sbss_start = .;
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
__sbss_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.tdata : {
__tdata_start = .;
*(.tdata)
*(.tdata.*)
*(.gnu.linkonce.td.*)
__tdata_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.tbss : {
__tbss_start = .;
*(.tbss)
*(.tbss.*)
*(.gnu.linkonce.tb.*)
__tbss_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.bss (NOLOAD) : {
__bss_start = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
__bss_end = .;
} > ps7_ddr_0_S_AXI_BASEADDR
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
/* Generate Stack and Heap definitions */
.heap (NOLOAD) : {
. = ALIGN(16);
_heap = .;
HeapBase = .;
_heap_start = .;
. += _HEAP_SIZE;
_heap_end = .;
HeapLimit = .;
} > ps7_ddr_0_S_AXI_BASEADDR
.stack (NOLOAD) : {
. = ALIGN(16);
_stack_end = .;
. += _STACK_SIZE;
_stack = .;
__stack = _stack;
. = ALIGN(16);
_irq_stack_end = .;
. += _IRQ_STACK_SIZE;
__irq_stack = .;
_supervisor_stack_end = .;
. += _SUPERVISOR_STACK_SIZE;
. = ALIGN(16);
__supervisor_stack = .;
_abort_stack_end = .;
. += _ABORT_STACK_SIZE;
. = ALIGN(16);
__abort_stack = .;
_fiq_stack_end = .;
. += _FIQ_STACK_SIZE;
. = ALIGN(16);
__fiq_stack = .;
_undef_stack_end = .;
. += _UNDEF_STACK_SIZE;
. = ALIGN(16);
__undef_stack = .;
} > ps7_ddr_0_S_AXI_BASEADDR
_end = .;
}
@@ -0,0 +1,20 @@
collect (PROJECT_LIB_TESTS helper.c)
set (_test_lib_external "xil")
collect (PROJECT_LIB_DEPS ${_test_lib_external})
collect (PROJECT_LIB_DEPS "c")
collect (PROJECT_LIB_DEPS "m")
find_library (_ext_lib_path ${_test_lib_external})
if (NOT _ext_lib_path)
message ( "external library ${_test_lib_external} not found" )
message ( "hint: you may need to pass -DCMAKE_LIBRARY_PATH=<path>" )
message ( FATAL_ERROR "library ${_test_lib_external} is required to build the tests" )
endif (NOT _ext_lib_path)
get_filename_component (_ext_lib_path ${_ext_lib_path} DIRECTORY)
collect (PROJECT_LIB_DIRS ${_ext_lib_path})
set_property (GLOBAL PROPERTY TEST_LINKER_OPTIONS "-Wl,--gc-sections -T\"${CMAKE_CURRENT_SOURCE_DIR}/lscript.ld\"")
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2014, Mentor Graphics Corporation
* All rights reserved.
*
* Copyright (c) 2016 Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "xscugic.h"
#define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID
static XScuGic xInterruptController;
/* Interrupt Controller setup */
static int app_gic_initialize(void)
{
u32 Status;
XScuGic_Config *IntcConfig; /* The configuration parameters of the interrupt controller */
Xil_ExceptionDisable();
/*
* Initialize the interrupt controller driver
*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(&xInterruptController, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Register the interrupt handler to the hardware interrupt handling
* logic in the ARM processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,&xInterruptController);
Xil_ExceptionEnable();
return 0;
}
/* Main hw machinery initialization entry point, called from main()*/
/* return 0 on success */
int init_system(void)
{
/* configure the global interrupt controller */
app_gic_initialize();
return 0;
}
@@ -0,0 +1,319 @@
/*******************************************************************/
/* */
/* This file is automatically generated by linker script generator.*/
/* */
/* Version: */
/* */
/* Copyright (c) 2010-2016 Xilinx, Inc. All rights reserved. */
/* */
/* Description : Cortex-A53 Linker Script */
/* */
/*******************************************************************/
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000;
_EL0_STACK_SIZE = DEFINED(_EL0_STACK_SIZE) ? _EL0_STACK_SIZE : 1024;
_EL1_STACK_SIZE = DEFINED(_EL1_STACK_SIZE) ? _EL1_STACK_SIZE : 2048;
_EL2_STACK_SIZE = DEFINED(_EL2_STACK_SIZE) ? _EL2_STACK_SIZE : 1024;
/* Define Memories in the system */
MEMORY
{
psu_ddr_0_MEM_0 : ORIGIN = 0x0, LENGTH = 0x80000000
psu_ddr_1_MEM_0 : ORIGIN = 0x800000000, LENGTH = 0x80000000
psu_ocm_ram_0_MEM_0 : ORIGIN = 0xFFFC0000, LENGTH = 0x40000
psu_qspi_linear_0_MEM_0 : ORIGIN = 0xC0000000, LENGTH = 0x20000000
}
/* Specify the default entry point to the program */
ENTRY(_vector_table)
/* Define the sections, and where they are mapped in memory */
SECTIONS
{
.text : {
KEEP (*(.vectors))
*(.boot)
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
*(.plt)
*(.gnu_warning)
*(.gcc_execpt_table)
*(.glue_7)
*(.glue_7t)
*(.ARM.extab)
*(.gnu.linkonce.armextab.*)
} > psu_ddr_0_MEM_0
.init (ALIGN(64)) : {
KEEP (*(.init))
} > psu_ddr_0_MEM_0
.fini (ALIGN(64)) : {
KEEP (*(.fini))
} > psu_ddr_0_MEM_0
.interp : {
KEEP (*(.interp))
} > psu_ddr_0_MEM_0
.note-ABI-tag : {
KEEP (*(.note-ABI-tag))
} > psu_ddr_0_MEM_0
.rodata : {
. = ALIGN(64);
__rodata_start = .;
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > psu_ddr_0_MEM_0
.rodata1 : {
. = ALIGN(64);
__rodata1_start = .;
*(.rodata1)
*(.rodata1.*)
__rodata1_end = .;
} > psu_ddr_0_MEM_0
.sdata2 : {
. = ALIGN(64);
__sdata2_start = .;
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
__sdata2_end = .;
} > psu_ddr_0_MEM_0
.sbss2 : {
. = ALIGN(64);
__sbss2_start = .;
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
__sbss2_end = .;
} > psu_ddr_0_MEM_0
.data : {
. = ALIGN(64);
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.jcr)
*(.got)
*(.got.plt)
__data_end = .;
} > psu_ddr_0_MEM_0
.data1 : {
. = ALIGN(64);
__data1_start = .;
*(.data1)
*(.data1.*)
__data1_end = .;
} > psu_ddr_0_MEM_0
.got : {
*(.got)
} > psu_ddr_0_MEM_0
.got1 : {
*(.got1)
} > psu_ddr_0_MEM_0
.got2 : {
*(.got2)
} > psu_ddr_0_MEM_0
.ctors : {
. = ALIGN(64);
__CTOR_LIST__ = .;
___CTORS_LIST___ = .;
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
___CTORS_END___ = .;
} > psu_ddr_0_MEM_0
.dtors : {
. = ALIGN(64);
__DTOR_LIST__ = .;
___DTORS_LIST___ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
___DTORS_END___ = .;
} > psu_ddr_0_MEM_0
.fixup : {
__fixup_start = .;
*(.fixup)
__fixup_end = .;
} > psu_ddr_0_MEM_0
.eh_frame : {
*(.eh_frame)
} > psu_ddr_0_MEM_0
.eh_framehdr : {
__eh_framehdr_start = .;
*(.eh_framehdr)
__eh_framehdr_end = .;
} > psu_ddr_0_MEM_0
.gcc_except_table : {
*(.gcc_except_table)
} > psu_ddr_0_MEM_0
.mmu_tbl0 (ALIGN(4096)) : {
__mmu_tbl0_start = .;
*(.mmu_tbl0)
__mmu_tbl0_end = .;
} > psu_ddr_0_MEM_0
.mmu_tbl1 (ALIGN(4096)) : {
__mmu_tbl1_start = .;
*(.mmu_tbl1)
__mmu_tbl1_end = .;
} > psu_ddr_0_MEM_0
.mmu_tbl2 (ALIGN(4096)) : {
__mmu_tbl2_start = .;
*(.mmu_tbl2)
__mmu_tbl2_end = .;
} > psu_ddr_0_MEM_0
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
*(.gnu.linkonce.armexidix.*.*)
__exidx_end = .;
} > psu_ddr_0_MEM_0
.preinit_array : {
. = ALIGN(64);
__preinit_array_start = .;
KEEP (*(SORT(.preinit_array.*)))
KEEP (*(.preinit_array))
__preinit_array_end = .;
} > psu_ddr_0_MEM_0
.init_array : {
. = ALIGN(64);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > psu_ddr_0_MEM_0
.fini_array : {
. = ALIGN(64);
__fini_array_start = .;
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array))
__fini_array_end = .;
} > psu_ddr_0_MEM_0
.ARM.attributes : {
__ARM.attributes_start = .;
*(.ARM.attributes)
__ARM.attributes_end = .;
} > psu_ddr_0_MEM_0
.sdata : {
. = ALIGN(64);
__sdata_start = .;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
__sdata_end = .;
} > psu_ddr_0_MEM_0
.sbss (NOLOAD) : {
. = ALIGN(64);
__sbss_start = .;
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
. = ALIGN(64);
__sbss_end = .;
} > psu_ddr_0_MEM_0
.tdata : {
. = ALIGN(64);
__tdata_start = .;
*(.tdata)
*(.tdata.*)
*(.gnu.linkonce.td.*)
__tdata_end = .;
} > psu_ddr_0_MEM_0
.tbss : {
. = ALIGN(64);
__tbss_start = .;
*(.tbss)
*(.tbss.*)
*(.gnu.linkonce.tb.*)
__tbss_end = .;
} > psu_ddr_0_MEM_0
.bss (NOLOAD) : {
. = ALIGN(64);
__bss_start__ = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(64);
__bss_end__ = .;
} > psu_ddr_0_MEM_0
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
/* Generate Stack and Heap definitions */
.heap (NOLOAD) : {
. = ALIGN(64);
_heap = .;
HeapBase = .;
_heap_start = .;
. += _HEAP_SIZE;
_heap_end = .;
HeapLimit = .;
} > psu_ddr_0_MEM_0
.stack (NOLOAD) : {
. = ALIGN(64);
_el3_stack_end = .;
. += _STACK_SIZE;
__el3_stack = .;
_el2_stack_end = .;
. += _EL2_STACK_SIZE;
. = ALIGN(64);
__el2_stack = .;
_el1_stack_end = .;
. += _EL1_STACK_SIZE;
. = ALIGN(64);
__el1_stack = .;
_el0_stack_end = .;
. += _EL0_STACK_SIZE;
. = ALIGN(64);
__el0_stack = .;
} > psu_ddr_0_MEM_0
_end = .;
}
@@ -0,0 +1,20 @@
collect (PROJECT_LIB_TESTS helper.c)
set (_test_lib_external "xil")
collect (PROJECT_LIB_DEPS ${_test_lib_external})
collect (PROJECT_LIB_DEPS "c")
collect (PROJECT_LIB_DEPS "m")
find_library (_ext_lib_path ${_test_lib_external})
if (NOT _ext_lib_path)
message ( "external library ${_test_lib_external} not found" )
message ( "hint: you may need to pass -DCMAKE_LIBRARY_PATH=<path>" )
message ( FATAL_ERROR "library ${_test_lib_external} is required to build the tests" )
endif (NOT _ext_lib_path)
get_filename_component (_ext_lib_path ${_ext_lib_path} DIRECTORY)
collect (PROJECT_LIB_DIRS ${_ext_lib_path})
set_property (GLOBAL PROPERTY TEST_LINKER_OPTIONS "-Wl,--gc-sections -T\"${CMAKE_CURRENT_SOURCE_DIR}/lscript.ld\"")
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2014, Mentor Graphics Corporation
* All rights reserved.
*
* Copyright (c) 2016 Xilinx, Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "xscugic.h"
#define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID
static XScuGic xInterruptController;
/* Interrupt Controller setup */
static int app_gic_initialize(void)
{
u32 Status;
XScuGic_Config *IntcConfig; /* The configuration parameters of the interrupt controller */
Xil_ExceptionDisable();
/*
* Initialize the interrupt controller driver
*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(&xInterruptController, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Register the interrupt handler to the hardware interrupt handling
* logic in the ARM processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,&xInterruptController);
Xil_ExceptionEnable();
return 0;
}
/* Main hw machinery initialization entry point, called from main()*/
/* return 0 on success */
int init_system(void)
{
/* configure the global interrupt controller */
app_gic_initialize();
return 0;
}
@@ -0,0 +1,316 @@
/******************************************************************************
*
* Copyright (C) 2017 Xilinx, Inc. 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.
*
******************************************************************************/
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x4000;
_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024;
_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;
/* Define Memories in the system */
MEMORY
{
psu_r5_atcm_MEM_0 : ORIGIN = 0x0, LENGTH = 0x10000
psu_r5_btcm_MEM_0 : ORIGIN = 0x20000, LENGTH = 0x10000
}
/* Specify the default entry point to the program */
ENTRY(_boot)
/* Define the sections, and where they are mapped in memory */
SECTIONS
{
.vectors : {
KEEP (*(.vectors))
*(.boot)
} > psu_r5_atcm_MEM_0
.text : {
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
*(.plt)
*(.gnu_warning)
*(.gcc_execpt_table)
*(.glue_7)
*(.glue_7t)
*(.vfp11_veneer)
*(.ARM.extab)
*(.gnu.linkonce.armextab.*)
} > psu_r5_atcm_MEM_0
.init : {
KEEP (*(.init))
} > psu_r5_atcm_MEM_0
.fini : {
KEEP (*(.fini))
} > psu_r5_atcm_MEM_0
.interp : {
KEEP (*(.interp))
} > psu_r5_atcm_MEM_0
.note-ABI-tag : {
KEEP (*(.note-ABI-tag))
} > psu_r5_btcm_MEM_0
.rodata : {
__rodata_start = .;
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > psu_r5_btcm_MEM_0
.rodata1 : {
__rodata1_start = .;
*(.rodata1)
*(.rodata1.*)
__rodata1_end = .;
} > psu_r5_btcm_MEM_0
.sdata2 : {
__sdata2_start = .;
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
__sdata2_end = .;
} > psu_r5_btcm_MEM_0
.sbss2 : {
__sbss2_start = .;
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
__sbss2_end = .;
} > psu_r5_btcm_MEM_0
.data : {
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.jcr)
*(.got)
*(.got.plt)
__data_end = .;
} > psu_r5_btcm_MEM_0
.data1 : {
__data1_start = .;
*(.data1)
*(.data1.*)
__data1_end = .;
} > psu_r5_btcm_MEM_0
.got : {
*(.got)
} > psu_r5_btcm_MEM_0
.ctors : {
__CTOR_LIST__ = .;
___CTORS_LIST___ = .;
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__CTOR_END__ = .;
___CTORS_END___ = .;
} > psu_r5_btcm_MEM_0
.dtors : {
__DTOR_LIST__ = .;
___DTORS_LIST___ = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
__DTOR_END__ = .;
___DTORS_END___ = .;
} > psu_r5_btcm_MEM_0
.fixup : {
__fixup_start = .;
*(.fixup)
__fixup_end = .;
} > psu_r5_btcm_MEM_0
.eh_frame : {
*(.eh_frame)
} > psu_r5_btcm_MEM_0
.eh_framehdr : {
__eh_framehdr_start = .;
*(.eh_framehdr)
__eh_framehdr_end = .;
} > psu_r5_btcm_MEM_0
.gcc_except_table : {
*(.gcc_except_table)
} > psu_r5_btcm_MEM_0
.mmu_tbl (ALIGN(16384)) : {
__mmu_tbl_start = .;
*(.mmu_tbl)
__mmu_tbl_end = .;
} > psu_r5_btcm_MEM_0
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
*(.gnu.linkonce.armexidix.*.*)
__exidx_end = .;
} > psu_r5_btcm_MEM_0
.preinit_array : {
__preinit_array_start = .;
KEEP (*(SORT(.preinit_array.*)))
KEEP (*(.preinit_array))
__preinit_array_end = .;
} > psu_r5_btcm_MEM_0
.init_array : {
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > psu_r5_btcm_MEM_0
.fini_array : {
__fini_array_start = .;
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array))
__fini_array_end = .;
} > psu_r5_btcm_MEM_0
.ARM.attributes : {
__ARM.attributes_start = .;
*(.ARM.attributes)
__ARM.attributes_end = .;
} > psu_r5_btcm_MEM_0
.sdata : {
__sdata_start = .;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
__sdata_end = .;
} > psu_r5_btcm_MEM_0
.sbss (NOLOAD) : {
__sbss_start = .;
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
__sbss_end = .;
} > psu_r5_btcm_MEM_0
.tdata : {
__tdata_start = .;
*(.tdata)
*(.tdata.*)
*(.gnu.linkonce.td.*)
__tdata_end = .;
} > psu_r5_btcm_MEM_0
.tbss : {
__tbss_start = .;
*(.tbss)
*(.tbss.*)
*(.gnu.linkonce.tb.*)
__tbss_end = .;
} > psu_r5_btcm_MEM_0
.bss (NOLOAD) : {
. = ALIGN(4);
__bss_start__ = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > psu_r5_btcm_MEM_0
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );
_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
/* Generate Stack and Heap definitions */
.heap (NOLOAD) : {
. = ALIGN(16);
_heap = .;
HeapBase = .;
_heap_start = .;
. += _HEAP_SIZE;
_heap_end = .;
HeapLimit = .;
} > psu_r5_btcm_MEM_0
.stack (NOLOAD) : {
. = ALIGN(16);
_stack_end = .;
. += _STACK_SIZE;
_stack = .;
__stack = _stack;
. = ALIGN(16);
_irq_stack_end = .;
. += _IRQ_STACK_SIZE;
__irq_stack = .;
_supervisor_stack_end = .;
. += _SUPERVISOR_STACK_SIZE;
. = ALIGN(16);
__supervisor_stack = .;
_abort_stack_end = .;
. += _ABORT_STACK_SIZE;
. = ALIGN(16);
__abort_stack = .;
_fiq_stack_end = .;
. += _FIQ_STACK_SIZE;
. = ALIGN(16);
__fiq_stack = .;
_undef_stack_end = .;
. += _UNDEF_STACK_SIZE;
. = ALIGN(16);
__undef_stack = .;
} > psu_r5_btcm_MEM_0
_end = .;
}
@@ -0,0 +1,15 @@
collect (PROJECT_LIB_TESTS main.c)
collect (PROJECT_LIB_TESTS atomic.c)
collect (PROJECT_LIB_TESTS mutex.c)
collect (PROJECT_LIB_TESTS shmem.c)
collect (PROJECT_LIB_TESTS condition.c)
collect (PROJECT_LIB_TESTS threads.c)
collect (PROJECT_LIB_TESTS spinlock.c)
collect (PROJECT_LIB_TESTS alloc.c)
collect (PROJECT_LIB_TESTS irq.c)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
add_subdirectory(${PROJECT_MACHINE})
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include "metal-test.h"
#include <metal/alloc.h>
#include <metal/log.h>
#include <metal/sys.h>
static int alloc(void)
{
void *ptr;
ptr = metal_allocate_memory(1000);
if (!ptr) {
metal_log(METAL_LOG_DEBUG, "failed to allocate memmory\n");
return errno;
}
metal_free_memory(ptr);
return 0;
}
METAL_ADD_TEST(alloc);
@@ -0,0 +1,47 @@
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <pthread.h>
#include <stdlib.h>
#include "metal-test.h"
#include <metal/atomic.h>
#include <metal/log.h>
#include <metal/sys.h>
static const int atomic_test_count = 1000;
static void *atomic_thread(void *arg)
{
atomic_int *c = arg;
int i;
for (i = 0; i < atomic_test_count; i++)
atomic_fetch_add(c, 1);
return NULL;
}
static int atomic(void)
{
const int threads = 10;
atomic_int counter = ATOMIC_VAR_INIT(0);
int value, error;
error = metal_run(threads, atomic_thread, &counter);
if (!error) {
value = atomic_load(&counter);
value -= atomic_test_count * threads;
if (value) {
metal_log(METAL_LOG_DEBUG, "counter mismatch, delta = %d\n",
value);
error = -EINVAL;
}
}
return error;
}
METAL_ADD_TEST(atomic);
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <pthread.h>
#include "metal-test.h"
#include <metal/log.h>
#include <metal/sys.h>
#include <metal/mutex.h>
#include <metal/condition.h>
#define COUNTER_MAX 10
#define THREADS 10
METAL_MUTEX_DEFINE(lock);
static struct metal_condition nempty_condv = METAL_CONDITION_INIT;
static struct metal_condition nfull_condv = METAL_CONDITION_INIT;
static unsigned int counter;
static void *consumer_thread(void *arg)
{
(void)arg;
metal_mutex_acquire(&lock);
while (!counter)
metal_condition_wait(&nempty_condv, &lock);
counter--;
metal_condition_signal(&nfull_condv);
metal_mutex_release(&lock);
return NULL;
}
static void *producer_thread(void *arg)
{
(void)arg;
metal_mutex_acquire(&lock);
while (counter == COUNTER_MAX)
metal_condition_wait(&nfull_condv, &lock);
counter++;
metal_condition_signal(&nempty_condv);
metal_mutex_release(&lock);
return NULL;
}
static int condition(void)
{
int ret;
int ts_created;
pthread_t tids[THREADS];
/** TC1 consumer threads go first */
/** create 10 consumer threads first */
ret = metal_run_noblock(THREADS, consumer_thread, NULL, tids,
&ts_created);
if (ret < 0) {
metal_log(METAL_LOG_ERROR, "Failed to create consumer thread: %d.\n",
ret);
goto out;
}
/** create 10 producer threads next */
ret = metal_run(THREADS, producer_thread, NULL);
if (ret < 0) {
metal_log(METAL_LOG_ERROR, "Failed to create producer thread: %d.\n",
ret);
goto out;
}
/** wait for consumer threads to finish */
metal_finish_threads(THREADS, (void *)tids);
/** TC2 producer threads go first */
/** create 10 producer threads first */
ret = metal_run_noblock(THREADS, producer_thread, NULL, tids,
&ts_created);
if (ret < 0) {
metal_log(METAL_LOG_ERROR, "Failed to create consumer thread: %d.\n",
ret);
goto out;
}
/** create 10 consumer threads next */
ret = metal_run(THREADS, consumer_thread, NULL);
if (ret < 0) {
metal_log(METAL_LOG_ERROR, "Failed to create producer thread: %d.\n",
ret);
goto out;
}
out:
/** wait for producer threads to finish */
metal_finish_threads(THREADS, (void *)tids);
return ret;
}
METAL_ADD_TEST(condition);
@@ -0,0 +1,213 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include <metal/errno.h>
#include <sys/eventfd.h>
/* We need to find the internal MAX_IRQS limit */
/* Could be retrieved from platform specific files in the future */
#define METAL_INTERNAL
#include "metal-test.h"
#include <metal/irq.h>
#include <metal/log.h>
#include <metal/sys.h>
#include <metal/list.h>
#include <metal/utilities.h>
int irq_handler(int irq, void *priv)
{
(void)irq;
(void)priv;
return 0;
}
static int irq(void)
{
int rc = 0;
char *err_msg="";
enum metal_log_level mll= metal_get_log_level();
int i, tst_irq[6];
/* Do not show LOG_ERROR or LOG_DEBUG for expected fail case */
metal_set_log_level(METAL_LOG_CRITICAL);
for (i=1; i < 6; i++) {
/* we only want to test the lib API, so create 'virtual' IRQs */
tst_irq[i] = eventfd(0,0);
metal_log(METAL_LOG_DEBUG, "%s: irq %d associated with fd %d\n", __func__, i, tst_irq[i]);
}
rc = metal_irq_register(tst_irq[1], irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 1 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(tst_irq[2], irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 2 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(tst_irq[2], irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 2 fail drv_id 2\n";
goto out;
}
rc = metal_irq_register(tst_irq[3], irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 3 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(tst_irq[4], irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 4 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(tst_irq[4], irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 4 fail drv_id 2\n";
goto out;
}
rc = metal_irq_register(tst_irq[1], irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 1 fail drv_id 2\n";
goto out;
}
rc = metal_irq_unregister(tst_irq[1], 0, 0, (void *)0);
if (rc) {
err_msg = "unregister irq 1 failed \n";
goto out;
}
rc = metal_irq_unregister(tst_irq[1], 0, 0, (void *)0);
if (!rc) {
err_msg = "unregister irq 1 success but fail expected\n";
goto out;
}
rc = metal_irq_unregister(tst_irq[2], 0, 0, (void *)2);
if (rc) {
err_msg = "unregister irq 2 drv_id 2 failed \n";
goto out;
}
rc = metal_irq_unregister(tst_irq[2], 0, 0, (void *)2);
if (!rc) {
err_msg = "unregister irq 2 drv_id 2 success but fail expected\n";
goto out;
}
rc = metal_irq_register(tst_irq[2], irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 2 fail drv_id 2\n";
goto out;
}
rc = metal_irq_unregister(tst_irq[2], 0, 0, (void *)1);
if (rc) {
err_msg = "unregister irq 2 drv_id 1 failed \n";
goto out;
}
rc = metal_irq_unregister(tst_irq[2], 0, 0, (void *)2);
if (rc) {
err_msg = "unregister irq 2 drv_id 2 failed \n";
goto out;
}
rc = metal_irq_register(tst_irq[3], irq_handler, 0, (void *)1);
if (!rc) {
err_msg = "register irq 3 drv_id 1 overwrite fail expected\n";
goto out;
}
rc = metal_irq_register(tst_irq[3], irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 3 fail drv_id 2\n";
goto out;
}
rc = metal_irq_unregister(tst_irq[3], irq_handler+1, 0, (void *)0);
if (!rc) {
err_msg = "unregister irq 3 match handler success but fail expected\n";
goto out;
}
rc = metal_irq_unregister(tst_irq[3], irq_handler, 0, (void *)0);
if (rc) {
err_msg = "unregister irq 3 match handler failed \n";
goto out;
}
rc = metal_irq_unregister(tst_irq[4], irq_handler, 0, (void *)2);
if (rc) {
err_msg = "unregister irq 4 match handler and drv_id 2 failed \n";
goto out;
}
rc = metal_irq_unregister(tst_irq[4], irq_handler, 0, (void *)1);
if (rc) {
err_msg = "unregister irq 4 match handler and drv_id 1 failed \n";
goto out;
}
rc = metal_irq_register(tst_irq[5], irq_handler, (void *)10, (void *)1);
if (rc) {
err_msg = "register irq 5 fail dev 10 drv_id 1\n";
goto out;
}
rc = metal_irq_register(tst_irq[5], irq_handler, (void *)20, (void *)2);
if (rc) {
err_msg = "register irq 5 fail dev 20 drv_id 2\n";
goto out;
}
rc = metal_irq_register(tst_irq[5], irq_handler, (void *)10, (void *)3);
if (rc) {
err_msg = "register irq 5 fail dev 10 drv_id 3\n";
goto out;
}
rc = metal_irq_register(tst_irq[5], irq_handler, 0, (void *)4);
if (rc) {
err_msg = "register irq 5 fail drv_id 4\n";
goto out;
}
rc = metal_irq_register(tst_irq[5], irq_handler, (void *)10, (void *)5);
if (rc) {
err_msg = "register irq 5 fail dev 10 drv_id 5\n";
goto out;
}
rc = metal_irq_unregister(tst_irq[5], irq_handler, (void *)10, (void *)3);
if (rc) {
err_msg = "unregister irq 5 match handle, dev 10 and drv_id 3 failed \n";
goto out;
}
rc = metal_irq_unregister(tst_irq[5], 0, 0, (void *)4);
if (rc) {
err_msg = "unregister irq 5 drv_id 4 failed \n";
goto out;
}
rc = metal_irq_unregister(tst_irq[5], 0, (void *)10, 0);
if (rc) {
err_msg = "unregister irq 5 dev 10 failed \n";
goto out;
}
rc = metal_irq_unregister(tst_irq[5], 0, (void *)20, (void *)2);
if (rc) {
err_msg = "unregister irq 5 match dev 20 and drv_id 2 failed \n";
goto out;
}
rc = 0;
out:
for (i=1; i < 6; i++) {
close(tst_irq[i]);
}
metal_set_log_level(mll);
if ((err_msg[0] != '\0') && (!rc))
rc = -EINVAL;
if (rc) metal_log(METAL_LOG_ERROR, "%s", err_msg);
return rc;
}
METAL_ADD_TEST(irq);
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "metal-test.h"
int main(void)
{
int status;
status = metal_tests_run(NULL);
return status;
}
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <pthread.h>
#include "metal-test.h"
#include <metal/log.h>
#include <metal/sys.h>
#include <metal/mutex.h>
static const int mutex_test_count = 1000;
static void *mutex_thread(void *arg)
{
metal_mutex_t *l = arg;
int i;
for (i = 0; i < mutex_test_count; i++) {
metal_mutex_acquire(l);
usleep(1);
metal_mutex_release(l);
}
return NULL;
}
static int mutex(void)
{
metal_mutex_t lock;
const int threads = 10;
int rc;
metal_mutex_init(&lock);
rc = metal_run(threads, mutex_thread, &lock);
metal_mutex_deinit(&lock);
return rc;
}
METAL_ADD_TEST(mutex);
@@ -0,0 +1,59 @@
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "metal-test.h"
#include <metal/log.h>
#include <metal/mutex.h>
#include <metal/shmem.h>
#include <metal/sys.h>
#include <metal/atomic.h>
static atomic_int nb_err = ATOMIC_VAR_INIT(0);
static const int shmem_threads = 10;
static void *shmem_child(void *arg)
{
const char *name = arg;
struct {
metal_mutex_t mutex;
int counter;
} *virt;
struct metal_io_region *io;
unsigned long phys;
size_t size = 2 * 1024 * 1024;
int error;
error = metal_shmem_open(name, size, &io);
if (error) {
metal_log(METAL_LOG_ERROR, "Failed shmem_open: %d.\n", error);
atomic_fetch_add(&nb_err, 1);
return NULL;
}
virt = metal_io_virt(io, 0);
phys = metal_io_phys(io, 0);
if (phys != METAL_BAD_OFFSET) {
if (virt != metal_io_phys_to_virt(io, phys)) {
atomic_fetch_add(&nb_err, 1);
metal_log(METAL_LOG_ERROR, "Failed virt != phys.\n");
}
if (phys != metal_io_virt_to_phys(io, virt)) {
atomic_fetch_add(&nb_err, 1);
metal_log(METAL_LOG_ERROR, "Failed phys != virt.\n");
}
}
metal_io_finish(io);
return NULL;
}
static int shmem(void)
{
return atomic_load(&nb_err) || metal_run(shmem_threads, shmem_child, "/foo");
}
METAL_ADD_TEST(shmem);
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <pthread.h>
#include "metal-test.h"
#include <metal/log.h>
#include <metal/sys.h>
#include <metal/spinlock.h>
static const int spinlock_test_count = 1000;
static unsigned int total = 0;
static void *spinlock_thread(void *arg)
{
struct metal_spinlock *l = arg;
int i;
for (i = 0; i < spinlock_test_count; i++) {
metal_spinlock_acquire(l);
total++;
metal_spinlock_release(l);
}
return NULL;
}
static int spinlock(void)
{
struct metal_spinlock lock = METAL_SPINLOCK_INIT;
const int threads = 10;
int value, error;
error = metal_run(threads, spinlock_thread, &lock);
if (!error) {
value = total;
value -= spinlock_test_count * threads;
if (value) {
metal_log(METAL_LOG_DEBUG, "counter mismatch, delta = %d\n",
value);
error = -EINVAL;
}
}
return error;
}
METAL_ADD_TEST(spinlock);
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <metal/sys.h>
#include <metal/utilities.h>
#include "metal-test.h"
int metal_run(int threads, metal_thread_t child, void *arg)
{
pthread_t tids[threads];
int error, ts_created;
error = metal_run_noblock(threads, child, arg, tids, &ts_created);
metal_finish_threads(ts_created, (void *)tids);
return error;
}
int metal_run_noblock(int threads, metal_thread_t child,
void *arg, void *tids, int *threads_out)
{
int error, i;
pthread_t *tid_p = (pthread_t *)tids;
if (!tids) {
metal_log(METAL_LOG_ERROR, "invalid arguement, tids is NULL.\n");
return -EINVAL;
}
error = 0;
for (i = 0; i < threads; i++) {
error = -pthread_create(&tid_p[i], NULL, child, arg);
if (error) {
metal_log(METAL_LOG_ERROR, "failed to create thread - %s\n",
strerror(error));
break;
}
}
*threads_out = i;
return error;
}
void metal_finish_threads(int threads, void *tids)
{
int i;
pthread_t *tid_p = (pthread_t *)tids;
if (!tids) {
metal_log(METAL_LOG_ERROR, "invalid argument, tids is NULL.\n");
return;
}
for (i = 0; i < threads; i++)
(void)pthread_join(tid_p[i], NULL);
}
@@ -0,0 +1,3 @@
collect (PROJECT_LIB_TESTS device.c)
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,36 @@
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <unistd.h>
#include "metal-test.h"
#include <metal/device.h>
static int device(void)
{
struct metal_device *device;
struct metal_io_region *io;
uint32_t idcode;
int error;
error = metal_device_open("platform", "f8000000.slcr", &device);
if (error)
return error;
io = metal_device_io_region(device, 0);
if (!io) {
metal_device_close(device);
return -ENODEV;
}
idcode = metal_io_read32(io, 0x530);
metal_log(METAL_LOG_DEBUG, "Read id code %x\n", idcode);
metal_device_close(device);
return 0;
}
METAL_ADD_TEST(device);
@@ -0,0 +1,11 @@
collect (PROJECT_LIB_TESTS main.c)
collect (PROJECT_LIB_TESTS alloc.c)
collect (PROJECT_LIB_TESTS irq.c)
collect (PROJECT_LIB_TESTS mutex.c)
collect (PROJECT_LIB_TESTS atomic.c)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
add_subdirectory(${PROJECT_MACHINE})
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
# vim: expandtab:ts=2:sw=2:smartindent
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include <metal/alloc.h>
#include <metal/log.h>
#include <metal/sys.h>
#include <misc/printk.h>
#include "metal-test-internal.h"
static int alloc(void)
{
void *ptr;
ptr = metal_allocate_memory(1000);
if (!ptr) {
metal_log(METAL_LOG_DEBUG, "failed to allocate memmory\n");
return errno;
}
metal_free_memory(ptr);
return 0;
}
METAL_ADD_TEST(alloc);
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include <metal/atomic.h>
#include <metal/log.h>
#include <metal/sys.h>
#include "metal-test-internal.h"
static const int atomic_test_count = 1000;
static int atomic(void)
{
atomic_int counter = ATOMIC_VAR_INIT(0);
int value, error=0, i;
for (i = 0; i < atomic_test_count; i++) {
atomic_fetch_add(&counter, 1);
}
value = atomic_load(&counter);
value -= atomic_test_count;
if (value) {
metal_log(METAL_LOG_DEBUG, "counter mismatch, delta = %d\n", value);
error = -1;
}
return error;
}
METAL_ADD_TEST(atomic);
@@ -0,0 +1,224 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include <metal/errno.h>
/* We need to find the internal MAX_IRQS limit */
/* Could be retrieved from platform specific files in the future */
#define METAL_INTERNAL
#include <metal/irq.h>
#include <metal/log.h>
#include <metal/sys.h>
#include <metal/list.h>
#include <metal/utilities.h>
#include "metal-test-internal.h"
int irq_handler(int irq, void *priv)
{
(void)irq;
(void)priv;
return 0;
}
int irq_handler_1(int irq, void *priv)
{
(void)irq;
(void)priv;
return 0;
}
static int irq(void)
{
int rc = 0, flags_1, flags_2;
char *err_msg="";
enum metal_log_level mll= metal_get_log_level();
/* Do not show LOG_ERROR or LOG_DEBUG for expected fail case */
metal_set_log_level(METAL_LOG_CRITICAL);
rc = metal_irq_register(1, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 1 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(2, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 2 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(2, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 2 fail drv_id 2\n";
goto out;
}
rc = metal_irq_register(3, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 3 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(4, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "register irq 4 fail drv_id 1\n";
goto out;
}
rc = metal_irq_register(4, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 4 fail drv_id 2\n";
goto out;
}
rc = metal_irq_register(1, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 1 fail drv_id 2\n";
goto out;
}
rc = metal_irq_unregister(1, 0, 0, (void *)0);
if (rc) {
err_msg = "unregister irq 1 failed \n";
goto out;
}
rc = metal_irq_unregister(1, 0, 0, (void *)0);
if (!rc) {
err_msg = "unregister irq 1 fail expected\n";
goto out;
}
rc = metal_irq_unregister(2, 0, 0, (void *)2);
if (rc) {
err_msg = "unregister irq 2 drv_id 2 failed \n";
goto out;
}
rc = metal_irq_unregister(2, 0, 0, (void *)2);
if (!rc) {
err_msg = "unregister irq 2 drv_id 2 fail expected\n";
goto out;
}
rc = metal_irq_register(2, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 2 fail drv_id 2\n";
goto out;
}
rc = metal_irq_unregister(2, 0, 0, (void *)1);
if (rc) {
err_msg = "unregister irq 2 drv_id 1 failed \n";
goto out;
}
rc = metal_irq_unregister(2, 0, 0, (void *)2);
if (rc) {
err_msg = "unregister irq 2 drv_id 2 failed \n";
goto out;
}
rc = metal_irq_register(3, irq_handler, 0, (void *)1);
if (!rc) {
err_msg = "register irq 3 drv_id 1 overwrite fail expected\n";
goto out;
}
rc = metal_irq_register(3, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "register irq 3 fail drv_id 2\n";
goto out;
}
rc = metal_irq_unregister(3, irq_handler_1, 0, (void *)0);
if (!rc) {
err_msg = "unregister irq 3 match handler fail expected\n";
goto out;
}
rc = metal_irq_unregister(3, irq_handler, 0, (void *)0);
if (rc) {
err_msg = "unregister irq 3 match handler failed \n";
goto out;
}
rc = metal_irq_unregister(4, irq_handler, 0, (void *)2);
if (rc) {
err_msg = "unregister irq 4 match handler and drv_id 2 failed \n";
goto out;
}
rc = metal_irq_unregister(4, irq_handler, 0, (void *)1);
if (rc) {
err_msg = "unregister irq 4 match handler and drv_id 1 failed \n";
goto out;
}
rc = metal_irq_register(5, irq_handler, (void *)10, (void *)1);
if (rc) {
err_msg = "register irq 5 fail dev 10 drv_id 1\n";
goto out;
}
rc = metal_irq_register(5, irq_handler, (void *)20, (void *)2);
if (rc) {
err_msg = "register irq 5 fail dev 20 drv_id 2\n";
goto out;
}
rc = metal_irq_register(5, irq_handler, (void *)10, (void *)3);
if (rc) {
err_msg = "register irq 5 fail dev 10 drv_id 3\n";
goto out;
}
rc = metal_irq_register(5, irq_handler, 0, (void *)4);
if (rc) {
err_msg = "register irq 5 fail drv_id 4\n";
goto out;
}
rc = metal_irq_register(5, irq_handler, (void *)10, (void *)5);
if (rc) {
err_msg = "register irq 5 fail dev 10 drv_id 5\n";
goto out;
}
rc = metal_irq_unregister(5, irq_handler, (void *)10, (void *)3);
if (rc) {
err_msg = "unregister irq 5 match handle, dev 10 and drv_id 3 failed \n";
goto out;
}
rc = metal_irq_unregister(5, 0, 0, (void *)4);
if (rc) {
err_msg = "unregister irq 5 drv_id 4 failed \n";
goto out;
}
rc = metal_irq_unregister(5, 0, (void *)10, 0);
if (rc) {
err_msg = "unregister irq 5 dev 10 failed \n";
goto out;
}
rc = metal_irq_unregister(5, 0, (void *)20, (void *)2);
if (rc) {
err_msg = "unregister irq 5 match dev 20 and drv_id 2 failed \n";
goto out;
}
rc = metal_irq_register(-1, irq_handler, 0, (void *)1);
if (!rc) {
err_msg = "register irq -1 should have failed\n";
goto out;
}
/* global interrupt disable/enable normal behavior */
flags_1=metal_irq_save_disable();
metal_irq_restore_enable(flags_1);
/* global interrupt less common */
flags_1=metal_irq_save_disable();
flags_2=metal_irq_save_disable();
metal_irq_restore_enable(flags_2);
metal_irq_restore_enable(flags_1);
rc = 0;
out:
metal_set_log_level(mll);
if ((err_msg[0] != '\0') && (!rc))
rc = -EINVAL;
if (rc) metal_log(METAL_LOG_ERROR, "%s", err_msg);
return rc;
}
METAL_ADD_TEST(irq);
@@ -0,0 +1,84 @@
/*
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "metal-test-internal.h"
#include <kernel.h>
#include <metal/log.h>
#include <misc/printk.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#define BLK_SIZE_MIN 128
#define BLK_SIZE_MAX 1024
#define BLK_NUM_MIN 64
#define BLK_NUM_MAX 16
#define BLK_ALIGN BLK_SIZE_MIN
K_MEM_POOL_DEFINE(kmpool, BLK_SIZE_MIN, BLK_SIZE_MAX, BLK_NUM_MAX, BLK_ALIGN);
struct k_mem_block block[BLK_NUM_MIN];
extern int init_system(void);
extern void metal_generic_default_poll(void);
extern void metal_test_add_alloc();
extern void metal_test_add_atomic();
extern void metal_test_add_irq();
extern void metal_test_add_mutex();
extern void *metal_zephyr_allocate_memory(unsigned int size)
{
int i;
struct k_mem_block *blk;
for (i = 0; i < sizeof(block)/sizeof(block[0]); i++) {
blk = &block[i];
if (!blk->data) {
if (k_mem_pool_alloc(&kmpool, blk,size, K_NO_WAIT))
printk("Failed to alloc 0x%x memory.\n", size);
return blk->data;
}
}
printk("Failed to alloc 0x%x memory, no free blocks.\n", size);
return NULL;
}
extern void metal_zephyr_free_memory(void *ptr)
{
int i;
struct k_mem_block *blk;
for (i = 0; i < sizeof(block)/sizeof(block[0]); i++) {
blk = &block[i];
if (blk->data == ptr) {
k_mem_pool_free(blk);
blk->data = NULL;
return;
}
}
printk("Failed to free %p, no block matches.\n", ptr);
}
void metal_test_add_functions()
{
metal_test_add_alloc();
metal_test_add_atomic();
metal_test_add_irq();
metal_test_add_mutex();
}
int main(void)
{
metal_test_add_functions();
(void)metal_tests_run(NULL);
while (1)
metal_generic_default_poll();
/* will not return, but quiet the compiler */
return 0;
}
@@ -0,0 +1,35 @@
/*
* Copyright (c) 2017, Linaro Limited. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* @file system/zephyr/metal-test-internal.h
* @brief Zephyr include internal to libmetal tests.
*/
#ifndef __METAL_TEST_ZEPHYR_INTERNAL__H__
#define __METAL_TEST_ZEPHYR_INTERNAL__H__
#ifdef __cplusplus
extern "C" {
#endif
#include "metal-test.h"
#undef METAL_ADD_TEST
#define METAL_ADD_TEST(func) \
void metal_test_add_##func() { \
static struct metal_test_case metal_test_##func = { \
.name = #func, \
.test = func, \
}; \
metal_add_test_case(&metal_test_##func); \
}
#ifdef __cplusplus
}
#endif
#endif /* __METAL_TEST_ZEPHYR_INTERNAL__H__ */
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "metal-test-internal.h"
#include <metal/mutex.h>
static const int mutex_test_count = 1000;
static int mutex(void)
{
metal_mutex_t lock;
int i;
metal_mutex_init(&lock);
for (i = 0; i < mutex_test_count; i++) {
metal_mutex_acquire(&lock);
metal_mutex_release(&lock);
}
return 0;
}
METAL_ADD_TEST(mutex);
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <string.h>
#include "metal-test.h"
#include <metal/config.h>
#include <metal/version.h>
static int version(void)
{
char ver_def[16], ver_dyn[16];
snprintf(ver_def, sizeof(ver_def), "%d.%d.%d",
METAL_VER_MAJOR,
METAL_VER_MINOR,
METAL_VER_PATCH);
snprintf(ver_dyn, sizeof(ver_dyn), "%d.%d.%d",
metal_ver_major(), metal_ver_minor(), metal_ver_patch());
return (strcmp(ver_def, METAL_VER) +
strcmp(ver_dyn, metal_ver()));
}
METAL_ADD_TEST(version);