sw_apps: openamp echo test is modified to support freertos

Signed-off-by: Kinjal Pravinbhai Patel <patelki@xilinx.com>
Acked-for-series: Anirudha Sarangi   <anirudh@xilinx.com>
This commit is contained in:
Kinjal Pravinbhai Patel 2015-08-26 17:01:54 +05:30 committed by Nava kishore Manne
parent 0d7905e608
commit 9e44967224
10 changed files with 738 additions and 62 deletions

View file

@ -46,8 +46,8 @@ proc check_standalone_os {} {
}
set os [lindex $oslist 0];
if { $os != "standalone" } {
error "This application is supported only on the Standalone Board Support Package.";
if { ( $os != "standalone" ) && ( $os != "freertos821_xilinx" ) } {
error "This application is supported only on the Standalone Board Support Package and freertos821.";
}
}
@ -90,7 +90,21 @@ proc check_stdout_hw {} {
}
proc swapp_generate {} {
return;
set oslist [get_os];
if { [llength $oslist] != 1 } {
return 0;
}
set os [lindex $oslist 0];
if { $os != "standalone" } {
set ld_file "lscript.ld"
set ld_file_new "lscript_freertos.ld"
file rename -force $ld_file_new $ld_file
file delete -force $ld_file_new
} else {
set ld_file "lscript_freertos.ld"
file delete -force $ld_file
}
return;
}
proc swapp_get_linker_constraints {} {

View file

@ -30,21 +30,25 @@
*/
#include <stdio.h>
#include <string.h>
#include "xparameters.h"
#include "xil_exception.h"
#include "xscugic.h"
#include "xil_cache.h"
#include "xil_mmu.h"
#include "xil_mpu.h"
#include "baremetal.h"
#include "env.h"
XScuGic InterruptController;
#include "platform.h"
#ifdef USE_FREERTOS
extern XScuGic xInterruptController;
#else
XScuGic xInterruptController;
#endif
extern struct isr_info isr_table[ISR_COUNT];
extern struct XOpenAMPInstPtr OpenAMPInstPtr;
unsigned int xInsideISR;
int zynqMP_r5_gic_initialize() {
#ifndef USE_FREERTOS
u32 Status;
Xil_ExceptionDisable();
XScuGic_Config *IntcConfig; /* The configuration parameters of the interrupt controller */
/*
@ -55,7 +59,7 @@ int zynqMP_r5_gic_initialize() {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(&InterruptController, IntcConfig,
Status = XScuGic_CfgInitialize(&xInterruptController, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
@ -66,26 +70,54 @@ int zynqMP_r5_gic_initialize() {
* logic in the ARM processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
(Xil_ExceptionHandler) zynqMP_r5_irq_isr,
&InterruptController);
XScuGic_InterruptHandler,&xInterruptController);
Xil_ExceptionEnable();
#endif
OpenAMPInstPtr.IntrID=VRING1_IPI_INTR_VECT;
XScuGic_Connect(&xInterruptController, VRING1_IPI_INTR_VECT,
(Xil_ExceptionHandler)zynqMP_r5_irq_isr,
&OpenAMPInstPtr);
return 0;
}
extern void bm_env_isr(int vector);
void zynqMP_r5_irq_isr() {
void zynqMP_r5_irq_isr(void *OpenAMPInst) {
unsigned int raw_irq;
int irq_vector;
raw_irq = (unsigned int)XScuGic_CPUReadReg(&InterruptController,XSCUGIC_INT_ACK_OFFSET);
irq_vector = (int) (raw_irq & XSCUGIC_ACK_INTID_MASK);
struct XOpenAMPInstPtr *OpenAMPInstance;
int idx;
struct isr_info *info;
OpenAMPInstance = (struct XOpenAMPInstPtr *)OpenAMPInst;
xInsideISR=1;
bm_env_isr(irq_vector);
for(idx = 0; idx < ISR_COUNT; idx++)
{
info = &isr_table[idx];
if(info->vector == OpenAMPInstance->IntrID)
{
unsigned long ipi_base_addr = *((unsigned long *)info->data);
OpenAMPInstance->IPI_Status = (unsigned int)Xil_In32(ipi_base_addr + IPI_ISR_OFFSET);
Xil_Out32((ipi_base_addr + IPI_ISR_OFFSET), OpenAMPInstance->IPI_Status);
break;
}
}
env_release_sync_lock(OpenAMPInstance->lock);
xInsideISR=0;
}
XScuGic_CPUWriteReg(&InterruptController,XSCUGIC_EOI_OFFSET, raw_irq);
void process_communication(struct XOpenAMPInstPtr OpenAMPInstance) {
int idx;
struct isr_info *info;
for(idx = 0; idx < ISR_COUNT; idx++)
{
info = &isr_table[idx];
if(info->vector == OpenAMPInstance.IntrID)
{
info->isr(info->vector , info->data, OpenAMPInstance.IPI_Status);
break;
}
}
}
/*
@ -160,9 +192,8 @@ void ipi_unregister_handler(unsigned long ipi_base_addr, unsigned int intr_mask)
memset(&(ipi_handler_table[ipi_hd_i]), 0, sizeof(struct ipi_handler_info));
}
void ipi_isr(int vect_id, void *data, unsigned int inr_status) {
void ipi_isr(int vect_id, void *data, unsigned int ipi_intr_status) {
unsigned long ipi_base_addr = *((unsigned long *)data);
unsigned int ipi_intr_status = (unsigned int)Xil_In32(ipi_base_addr + IPI_ISR_OFFSET);
int i = 0;
do {
Xil_Out32((ipi_base_addr + IPI_ISR_OFFSET), ipi_intr_status);
@ -236,12 +267,18 @@ unsigned int old_value = 0;
void restore_global_interrupts() {
#ifdef USE_FREERTOS
taskENABLE_INTERRUPTS();
#else
ARM_AR_INT_BITS_SET(old_value);
#endif
}
void disable_global_interrupts() {
#ifdef USE_FREERTOS
taskDISABLE_INTERRUPTS();
#else
unsigned int value = 0;
ARM_AR_INT_BITS_GET(&value);
@ -253,7 +290,7 @@ void disable_global_interrupts() {
old_value = value;
}
#endif
}
/*==================================================================*/

View file

@ -32,10 +32,30 @@
#ifndef _BAREMETAL_H
#define _BAREMETAL_H
#include "amp_os.h"
#include "xil_types.h"
#include "xparameters.h"
#include "xil_cache.h"
#include "xreg_cortexr5.h"
#ifdef USE_FREERTOS
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
#endif
#include "xpqueue.h"
struct XOpenAMPInstPtr{
unsigned int IntrID;
unsigned int IPI_Status;
void *lock;
#ifdef USE_FREERTOS
QueueHandle_t send_queue;
#else
pq_queue_t *send_queue;
#endif
};
#define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID
@ -97,5 +117,6 @@ void platform_cache_disable();
void platform_map_mem_region(unsigned int va,unsigned int pa, unsigned int size, unsigned int flags);
unsigned long platform_vatopa(void *addr);
void *platform_patova(unsigned long addr);
void process_communication(struct XOpenAMPInstPtr OpenAMPInstance);
#endif /* _BAREMETAL_H */

View file

@ -81,49 +81,159 @@
#include "baremetal.h"
#include "xil_cache.h"
#include "xil_mmu.h"
#include "xstatus.h"
#include "xreg_cortexr5.h"
#include "xil_exception.h"
#define SHUTDOWN_MSG 0xEF56A55A
#ifdef USE_FREERTOS
#define DELAY_200MSEC 200/portTICK_PERIOD_MS
#endif
/* Internal functions */
static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl);
static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl);
static void rpmsg_read_cb(struct rpmsg_channel *, void *, int, void *, unsigned long);
static void init_system();
static void communication_task();
static void echo_test();
/* Globals */
/* Static variables */
static struct rpmsg_channel *app_rp_chnl;
static struct rpmsg_endpoint *rp_ept;
static struct remote_proc *proc = NULL;
static struct rsc_table_info rsc_info;
#ifdef USE_FREERTOS
static queue_data send_data, echo_data;
static TimerHandle_t stop_scheduler;
#else
static queue_data *send_data, *echo_data;
#endif
static queue_data recv_echo_data;
#ifdef USE_FREERTOS
static TaskHandle_t comm_task;
static TaskHandle_t echo_tst;
static QueueSetHandle_t comm_queueset;
static QueueHandle_t echo_queue;
#else
static pq_queue_t *echo_queue;
#endif
/* Globals */
extern const struct remote_resource_table resources;
struct XOpenAMPInstPtr OpenAMPInstPtr;
/* Application entry point */
int main() {
int status = 0;
Xil_ExceptionDisable();
/* Initialize HW system components */
init_system();
#ifdef USE_FREERTOS
BaseType_t stat;
rsc_info.rsc_tab = (struct resource_table *)&resources;
rsc_info.size = sizeof(resources);
/* Create the tasks */
stat = xTaskCreate(communication_task, ( const char * ) "HW2",
1024, NULL,2,&comm_task);
if(stat != pdPASS)
return -1;
/* Initialize RPMSG framework */
status = remoteproc_resource_init(&rsc_info, rpmsg_channel_created, rpmsg_channel_deleted, rpmsg_read_cb,
&proc);
stat = xTaskCreate(echo_test, ( const char * ) "HW2",
1024, NULL, 1, &echo_tst );
if(stat != pdPASS)
return -1;
if (status < 0) {
return -1;
}
/*Create Queues*/
echo_queue = xQueueCreate( 1, sizeof( queue_data ) );
OpenAMPInstPtr.send_queue = xQueueCreate( 1, sizeof( queue_data ) );
env_create_sync_lock(&OpenAMPInstPtr.lock,LOCKED);
/* Start the tasks and timer running. */
vTaskStartScheduler();
while(1);
while(1) {
__asm__ ( "\
wfi\n\t" \
);
};
#else
return 0;
/*Create Queues*/
echo_queue = pq_create_queue();
OpenAMPInstPtr.send_queue = pq_create_queue();
communication_task();
#endif
return 0;
}
void communication_task(){
int status;
rsc_info.rsc_tab = (struct resource_table *)&resources;
rsc_info.size = sizeof(resources);
zynqMP_r5_gic_initialize();
/* Initialize RPMSG framework */
status = remoteproc_resource_init(&rsc_info, rpmsg_channel_created, rpmsg_channel_deleted,
rpmsg_read_cb ,&proc);
if (status < 0) {
return;
}
#ifdef USE_FREERTOS
comm_queueset = xQueueCreateSet( 2 );
xQueueAddToSet( OpenAMPInstPtr.send_queue, comm_queueset);
xQueueAddToSet( OpenAMPInstPtr.lock, comm_queueset);
#else
env_create_sync_lock(&OpenAMPInstPtr.lock,LOCKED);
#endif
env_enable_interrupt(VRING1_IPI_INTR_VECT,0,0);
while (1) {
#ifdef USE_FREERTOS
QueueSetMemberHandle_t xActivatedMember;
xActivatedMember = xQueueSelectFromSet( comm_queueset, portMAX_DELAY);
if( xActivatedMember == OpenAMPInstPtr.lock ) {
env_acquire_sync_lock(OpenAMPInstPtr.lock);
process_communication(OpenAMPInstPtr);
}
if (xActivatedMember == OpenAMPInstPtr.send_queue) {
xQueueReceive( OpenAMPInstPtr.send_queue, &send_data, 0 );
rpmsg_send(app_rp_chnl, send_data.data, send_data.length);
}
#else
env_acquire_sync_lock(OpenAMPInstPtr.lock);
process_communication(OpenAMPInstPtr);
echo_test();
/* Wait for the result data on queue */
if(pq_qlength(OpenAMPInstPtr.send_queue) > 0) {
send_data = pq_dequeue(OpenAMPInstPtr.send_queue);
/* Send the result of matrix multiplication back to master. */
rpmsg_send(app_rp_chnl, send_data->data, send_data->length);
}
#endif
}
}
void echo_test(){
#ifdef USE_FREERTOS
for( ;; ){
/* Wait to receive data for matrix multiplication */
if( xQueueReceive( echo_queue, &echo_data, portMAX_DELAY )){
/*
* The data can be processed here and send back
* Since it is simple echo test, the data is sent without
* processing
*/
xQueueSend( OpenAMPInstPtr.send_queue, &echo_data, portMAX_DELAY );
}
}
#else
/* check whether data is received for matrix multiplication */
if(pq_qlength(echo_queue) > 0){
echo_data = pq_dequeue(echo_queue);
/*
* The data can be processed here and send back
* Since it is simple echo test, the data is sent without
* processing
*/
pq_enqueue(OpenAMPInstPtr.send_queue, echo_data);
}
#endif
}
static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {
@ -132,23 +242,33 @@ static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {
RPMSG_ADDR_ANY);
}
static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {
#ifdef USE_FREERTOS
static void StopSchedulerTmrCallBack(TimerHandle_t timer)
{
vTaskEndScheduler();
}
#endif
static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {
}
static void rpmsg_read_cb(struct rpmsg_channel *rp_chnl, void *data, int len,
void * priv, unsigned long src) {
if ((*(int *) data) == SHUTDOWN_MSG) {
remoteproc_resource_deinit(proc);
#ifdef USE_FREERTOS
int TempTimerId;
stop_scheduler = xTimerCreate("TMR", DELAY_200MSEC, pdFALSE, (void *)&TempTimerId, StopSchedulerTmrCallBack);
xTimerStart(stop_scheduler, 0);
#endif
} else {
/* Send data back to master*/
rpmsg_send(rp_chnl, data, len);
/* copy the received data and send to matrix mul task over queue */
recv_echo_data.data = data;
recv_echo_data.length = len;
#ifdef USE_FREERTOS
xQueueSend( echo_queue, &recv_echo_data, portMAX_DELAY );
#else
pq_enqueue(echo_queue, &recv_echo_data);
#endif
}
}
static void init_system() {
/* Initilaize GIC */
zynqMP_r5_gic_initialize();
}

View file

@ -294,7 +294,7 @@ _SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
. += _HEAP_SIZE;
_heap_end = .;
HeapLimit = .;
} > ps8_ocm_ram_1_S_AXI_BASEADDR
} > ps8_ddr_S_AXI_BASEADDR
.stack (NOLOAD) : {
. = ALIGN(16);
@ -322,7 +322,7 @@ _SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
. += _UNDEF_STACK_SIZE;
. = ALIGN(16);
__undef_stack = .;
} > ps8_ocm_ram_1_S_AXI_BASEADDR
} > ps8_ddr_S_AXI_BASEADDR
_end = .;
}

View file

@ -0,0 +1,328 @@
/******************************************************************************
*
* Copyright (C) 2015 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x1000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x500;
_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
{
ps8_bbram_0_S_AXI_BASEADDR : ORIGIN = 0xFFCC4000, LENGTH = 0x00001000
ps8_csu_ram_0_S_AXI_BASEADDR : ORIGIN = 0xFFC40000, LENGTH = 0x00008000
ps8_ddr_S_AXI_BASEADDR : ORIGIN = 0x3ED00000, LENGTH = 0x00040000
ps8_ocm_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0000, LENGTH = 0x00010000
ps8_r5_tcm_ram_0_S_AXI_BASEADDR : ORIGIN = 0x00000050, LENGTH = 0x0001FFB1
}
/* Specify the default entry point to the program */
/* ENTRY(_boot) */
ENTRY(_vector_table)
/* Define the sections, and where they are mapped in memory */
SECTIONS
{
.vectors : {
*(.vectors)
} > ps8_ocm_ram_1_S_AXI_BASEADDR
_binary_firmware1_start = 0;
_binary_firmware1_end = 0;
_binary_firmware2_start = 0;
_binary_firmware2_end = 0;
.text : {
*(.boot)
*(.text)
*(.text.*)
*(.gnu.linkonce.t.*)
*(.plt)
*(.gnu_warning)
*(.gcc_execpt_table)
*(.glue_7)
*(.glue_7t)
*(.vfp11_veneer)
*(.ARM.extab)
*(.gnu.linkonce.armextab.*)
} > ps8_ddr_S_AXI_BASEADDR
.init : {
KEEP (*(.init))
} > ps8_ddr_S_AXI_BASEADDR
.fini : {
KEEP (*(.fini))
} > ps8_ddr_S_AXI_BASEADDR
.interp : {
KEEP (*(.interp))
} > ps8_ddr_S_AXI_BASEADDR
.note-ABI-tag : {
KEEP (*(.note-ABI-tag))
} > ps8_ddr_S_AXI_BASEADDR
.rodata : {
__rodata_start = .;
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.rodata1 : {
__rodata1_start = .;
*(.rodata1)
*(.rodata1.*)
__rodata1_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.sdata2 : {
__sdata2_start = .;
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
__sdata2_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.sbss2 : {
__sbss2_start = .;
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
__sbss2_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.data : {
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.jcr)
*(.got)
*(.got.plt)
__data_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.data1 : {
__data1_start = .;
*(.data1)
*(.data1.*)
__data1_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.got : {
*(.got)
} > ps8_ddr_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___ = .;
} > ps8_ddr_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___ = .;
} > ps8_ddr_S_AXI_BASEADDR
.fixup : {
__fixup_start = .;
*(.fixup)
__fixup_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.eh_frame : {
*(.eh_frame)
} > ps8_ddr_S_AXI_BASEADDR
.eh_framehdr : {
__eh_framehdr_start = .;
*(.eh_framehdr)
__eh_framehdr_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.gcc_except_table : {
*(.gcc_except_table)
} > ps8_ddr_S_AXI_BASEADDR
.mmu_tbl (ALIGN(16384)) : {
__mmu_tbl_start = .;
*(.mmu_tbl)
__mmu_tbl_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
*(.gnu.linkonce.armexidix.*.*)
__exidx_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.preinit_array : {
__preinit_array_start = .;
KEEP (*(SORT(.preinit_array.*)))
KEEP (*(.preinit_array))
__preinit_array_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.init_array : {
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.fini_array : {
__fini_array_start = .;
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array))
__fini_array_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.ARM.attributes : {
__ARM.attributes_start = .;
*(.ARM.attributes)
__ARM.attributes_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.sdata : {
__sdata_start = .;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
__sdata_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.sbss (NOLOAD) : {
__sbss_start = .;
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
__sbss_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.tdata : {
__tdata_start = .;
*(.tdata)
*(.tdata.*)
*(.gnu.linkonce.td.*)
__tdata_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.tbss : {
__tbss_start = .;
*(.tbss)
*(.tbss.*)
*(.gnu.linkonce.tb.*)
__tbss_end = .;
} > ps8_ddr_S_AXI_BASEADDR
.bss (NOLOAD) : {
. = ALIGN(4);
__bss_start__ = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > ps8_ddr_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 = .;
} > ps8_ddr_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 = .;
} > ps8_ddr_S_AXI_BASEADDR
_end = .;
}

View file

@ -76,9 +76,10 @@ int _enable_interrupt(struct proc_vring *vring_hw) {
/* Register ISR*/
env_register_isr(vring_hw->intr_info.vect_id, &(chn_ipi_info->ipi_base_addr), ipi_isr);
/* Enable IPI interrupt */
env_enable_interrupt(vring_hw->intr_info.vect_id,
/* FIXME: enabled interrupt in application */
/*env_enable_interrupt(vring_hw->intr_info.vect_id,
vring_hw->intr_info.priority,
vring_hw->intr_info.trigger_type);
vring_hw->intr_info.trigger_type);*/
return 0;
}
@ -95,6 +96,7 @@ void _notify(int cpu_id, struct proc_intr *intr_info) {
if (chn_ipi_info == NULL)
return;
platform_dcache_all_flush();
env_wmb();
/* Trigger IPI */
ipi_trigger(chn_ipi_info->ipi_base_addr, chn_ipi_info->ipi_chn_mask);
}

View file

@ -44,9 +44,8 @@ struct remote_resource_table {
unsigned int reserved[2];
unsigned int offset[NO_RESOURCE_ENTRIES];
/* text carve out entry */
struct fw_rsc_carveout ddr_cout;
struct fw_rsc_carveout ocm_1_cout;
struct fw_rsc_carveout ddr_cout;
/* rpmsg vdev entry */
struct fw_rsc_vdev rpmsg_vdev;
struct fw_rsc_vdev_vring rpmsg_vring0;

View file

@ -0,0 +1,93 @@
/******************************************************************************
*
* Copyright (C) 2007 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
#include <stdlib.h>
#include "xpqueue.h"
#define NUM_QUEUES 2
pq_queue_t pq_queue[NUM_QUEUES];
pq_queue_t *
pq_create_queue()
{
static int i;
pq_queue_t *q = NULL;
if (i >= NUM_QUEUES) {
return q;
}
q = &pq_queue[i++];
if (!q)
return q;
q->head = q->tail = q->len = 0;
return q;
}
int
pq_enqueue(pq_queue_t *q, queue_data *p)
{
if (q->len == PQ_QUEUE_SIZE)
return -1;
q->data[q->head] = p;
q->head = (q->head + 1)%PQ_QUEUE_SIZE;
q->len++;
return 0;
}
queue_data*
pq_dequeue(pq_queue_t *q)
{
int ptail;
if (q->len == 0)
return NULL;
ptail = q->tail;
q->tail = (q->tail + 1)%PQ_QUEUE_SIZE;
q->len--;
return q->data[ptail];
}
int
pq_qlength(pq_queue_t *q)
{
return q->len;
}

View file

@ -0,0 +1,62 @@
/******************************************************************************
*
* Copyright (C) 2007 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
#ifndef __LWIP_PBUF_QUEUE_H_
#define __LWIP_PBUF_QUEUE_H_
#include "xil_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define PQ_QUEUE_SIZE 20
typedef struct {
void *data;
u32 length;
} queue_data;
typedef struct {
queue_data *data[PQ_QUEUE_SIZE];
int head, tail, len;
} pq_queue_t;
pq_queue_t* pq_create_queue();
int pq_enqueue(pq_queue_t *q, queue_data *p);
queue_data* pq_dequeue(pq_queue_t *q);
int pq_qlength(pq_queue_t *q);
#ifdef __cplusplus
}
#endif
#endif