sw_apps: openamp matrix multiply: Added freertos support

Signed-off-by: Kinjal Pravinbhai Patel <patelki@xilinx.com>
Acked-by: Anirudha Sarangi   <anirudh@xilinx.com>
This commit is contained in:
Kinjal Pravinbhai Patel 2015-08-13 18:42:38 +05:30 committed by Nava kishore Manne
parent 0cdcbdafd3
commit da9e3d6e71
8 changed files with 736 additions and 45 deletions

View file

@ -90,7 +90,19 @@ 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"
file delete -force $ld_file
} else {
set ld_file "lscript_freertos.ld"
file delete -force $ld_file
}
return;
}
proc swapp_get_linker_constraints {} {

View file

@ -30,17 +30,23 @@
*/
#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();
@ -55,7 +61,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 +72,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 +194,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) {
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);

View file

@ -36,6 +36,25 @@
#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

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_ocm_ram_0_S_AXI_BASEADDR : ORIGIN = 0xFFFC0000, LENGTH = 0x00020000
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_ocm_ram_0_S_AXI_BASEADDR
.init : {
KEEP (*(.init))
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.fini : {
KEEP (*(.fini))
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.interp : {
KEEP (*(.interp))
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.note-ABI-tag : {
KEEP (*(.note-ABI-tag))
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.rodata : {
__rodata_start = .;
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
__rodata_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.rodata1 : {
__rodata1_start = .;
*(.rodata1)
*(.rodata1.*)
__rodata1_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.sdata2 : {
__sdata2_start = .;
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
__sdata2_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.sbss2 : {
__sbss2_start = .;
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
__sbss2_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.data : {
__data_start = .;
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.jcr)
*(.got)
*(.got.plt)
__data_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.data1 : {
__data1_start = .;
*(.data1)
*(.data1.*)
__data1_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.got : {
*(.got)
} > ps8_ocm_ram_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___ = .;
} > ps8_ocm_ram_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___ = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.fixup : {
__fixup_start = .;
*(.fixup)
__fixup_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.eh_frame : {
*(.eh_frame)
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.eh_framehdr : {
__eh_framehdr_start = .;
*(.eh_framehdr)
__eh_framehdr_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.gcc_except_table : {
*(.gcc_except_table)
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.mmu_tbl (ALIGN(16384)) : {
__mmu_tbl_start = .;
*(.mmu_tbl)
__mmu_tbl_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
*(.gnu.linkonce.armexidix.*.*)
__exidx_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.preinit_array : {
__preinit_array_start = .;
KEEP (*(SORT(.preinit_array.*)))
KEEP (*(.preinit_array))
__preinit_array_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.init_array : {
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.fini_array : {
__fini_array_start = .;
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array))
__fini_array_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.ARM.attributes : {
__ARM.attributes_start = .;
*(.ARM.attributes)
__ARM.attributes_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.sdata : {
__sdata_start = .;
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
__sdata_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.sbss (NOLOAD) : {
__sbss_start = .;
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
__sbss_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.tdata : {
__tdata_start = .;
*(.tdata)
*(.tdata.*)
*(.gnu.linkonce.td.*)
__tdata_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.tbss : {
__tbss_start = .;
*(.tbss)
*(.tbss.*)
*(.gnu.linkonce.tb.*)
__tbss_end = .;
} > ps8_ocm_ram_0_S_AXI_BASEADDR
.bss (NOLOAD) : {
. = ALIGN(4);
__bss_start__ = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > ps8_ocm_ram_1_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_ocm_ram_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 = .;
} > ps8_ocm_ram_1_S_AXI_BASEADDR
_end = .;
}

View file

@ -83,6 +83,7 @@
#include "xil_cache.h"
#include "xil_mmu.h"
#include "xreg_cortexr5.h"
#include "xil_exception.h"
#define MAX_SIZE 6
#define NUM_MATRIX 2
@ -98,42 +99,141 @@ 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 Matrix_Multiply(const matrix *m, const matrix *n, matrix *r);
static void init_system();
static void communication_task();
static void matrix_mul();
/* Globals */
/* Static variables */
static struct rpmsg_channel *app_rp_chnl;
void* mat_mul_lock;
int need_to_cal = 0;
static struct rpmsg_endpoint *rp_ept;
static matrix matrix_array[NUM_MATRIX];
static matrix matrix_result;
static struct remote_proc *proc = NULL;
static struct rsc_table_info rsc_info;
#ifdef USE_FREERTOS
static queue_data send_data,mat_array;
static TimerHandle_t stop_scheduler;
#else
static queue_data *send_data,*mat_array;
#endif
static queue_data recv_mat_data, mat_result_array;
#ifdef USE_FREERTOS
static TaskHandle_t comm_task;
static TaskHandle_t mat_mul;
static QueueSetHandle_t comm_queueset;
static QueueHandle_t mat_mul_queue;
#else
static pq_queue_t *mat_mul_queue;
#endif
static matrix matrix_array[NUM_MATRIX];
static matrix matrix_result;
/* Globals */
extern const struct remote_resource_table resources;
struct XOpenAMPInstPtr OpenAMPInstPtr;
/* Application entry point */
int main() {
Xil_ExceptionDisable();
int status = 0;
#ifdef USE_FREERTOS
BaseType_t stat;
/* Create the tasks */
stat = xTaskCreate(communication_task, ( const char * ) "HW2",
1024, NULL,2,&comm_task);
if(stat != pdPASS)
return -1;
/* Initialize HW system components */
init_system();
stat = xTaskCreate(matrix_mul, ( const char * ) "HW2",
1024, NULL, 1, &mat_mul );
if(stat != pdPASS)
return -1;
/*Create Queues*/
mat_mul_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);
#else
/*Create Queues*/
mat_mul_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 -1;
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
while (1) {
__asm__ ( "wfi\n\t" );
#ifdef USE_FREERTOS
QueueSetMemberHandle_t xActivatedMember;
env_enable_interrupt(VRING1_IPI_INTR_VECT, 0, 0);
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_enable_interrupt(VRING1_IPI_INTR_VECT, 0, 0);
env_acquire_sync_lock(OpenAMPInstPtr.lock);
process_communication(OpenAMPInstPtr);
matrix_mul();
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
}
}
return 0;
void matrix_mul(){
#ifdef USE_FREERTOS
for( ;; ){
if( xQueueReceive(mat_mul_queue, &mat_array, portMAX_DELAY )){
env_memcpy(matrix_array, mat_array.data, mat_array.length);
Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result);
mat_result_array.length = sizeof(matrix);
mat_result_array.data = &matrix_result;
xQueueSend( OpenAMPInstPtr.send_queue, &mat_result_array, portMAX_DELAY );
}
}
#else
if(pq_qlength(mat_mul_queue) > 0){
mat_array = pq_dequeue(mat_mul_queue);
env_memcpy(matrix_array, mat_array->data, mat_array->length);
/* Process received data and multiple matrices. */
Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result);
mat_result_array.length = sizeof(matrix);
mat_result_array.data = &matrix_result;
pq_enqueue(OpenAMPInstPtr.send_queue, &mat_result_array);
}
#endif
}
static void rpmsg_channel_created(struct rpmsg_channel *rp_chnl) {
@ -146,17 +246,30 @@ static void rpmsg_channel_deleted(struct rpmsg_channel *rp_chnl) {
rpmsg_destroy_ept(rp_ept);
}
#ifdef USE_FREERTOS
static void StopSchedulerTmrCallBack(TimerHandle_t timer)
{
vTaskEndScheduler();
}
#endif
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", 200, pdFALSE, (void *)&TempTimerId, StopSchedulerTmrCallBack);
xTimerStart(stop_scheduler, 0);
#endif
}else{
env_memcpy(matrix_array, data, len);
/* Process received data and multiple matrices. */
Matrix_Multiply(&matrix_array[0], &matrix_array[1], &matrix_result);
/* Send the result of matrix multiplication back to master. */
rpmsg_send(app_rp_chnl, &matrix_result, sizeof(matrix));
recv_mat_data.data = data;
recv_mat_data.length = len;
#ifdef USE_FREERTOS
xQueueSend(mat_mul_queue , &recv_mat_data, portMAX_DELAY );
#else
pq_enqueue(mat_mul_queue, &recv_mat_data);
#endif
}
}
@ -175,9 +288,39 @@ static void Matrix_Multiply(const matrix *m, const matrix *n, matrix *r) {
}
}
static void init_system() {
/* Initilaize GIC */
zynqMP_r5_gic_initialize();
#ifdef USE_FREERTOS
/*-----------------------------------------------------------*/
void vApplicationMallocFailedHook( void )
{
/* vApplicationMallocFailedHook() will only be called if
configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook
function that will get called if a call to pvPortMalloc() fails.
pvPortMalloc() is called internally by the kernel whenever a task, queue or
semaphore is created. It is also called by various parts of the demo
application. If heap_1.c or heap_2.c are used, then the size of the heap
available to pvPortMalloc() is defined by configTOTAL_HEAP_SIZE in
FreeRTOSConfig.h, and the xPortGetFreeHeapSize() API function can be used
to query the size of free heap space that remains (although it does not
provide information on how the remaining heap might be fragmented). */
xil_printf("malloc failed\r\n");
taskDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName )
{
( void ) pcTaskName;
( void ) pxTask;
/* vApplicationStackOverflowHook() will only be called if
configCHECK_FOR_STACK_OVERFLOW is set to either 1 or 2. The handle and name
of the offending task will be passed into the hook function via its
parameters. However, when a stack has overflowed, it is possible that the
parameters will have been corrupted, in which case the pxCurrentTCB variable
can be inspected directly. */
taskDISABLE_INTERRUPTS();
for( ;; );
}
#endif

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;
}

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