diff --git a/lib/sw_apps/openamp_matrix_multiply/data/openamp_matrix_multiply.tcl b/lib/sw_apps/openamp_matrix_multiply/data/openamp_matrix_multiply.tcl index 51abf6b8..484b64d5 100755 --- a/lib/sw_apps/openamp_matrix_multiply/data/openamp_matrix_multiply.tcl +++ b/lib/sw_apps/openamp_matrix_multiply/data/openamp_matrix_multiply.tcl @@ -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 {} { diff --git a/lib/sw_apps/openamp_matrix_multiply/src/baremetal.c b/lib/sw_apps/openamp_matrix_multiply/src/baremetal.c index 2b225aae..19d66952 100644 --- a/lib/sw_apps/openamp_matrix_multiply/src/baremetal.c +++ b/lib/sw_apps/openamp_matrix_multiply/src/baremetal.c @@ -30,17 +30,23 @@ */ #include #include -#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); diff --git a/lib/sw_apps/openamp_matrix_multiply/src/baremetal.h b/lib/sw_apps/openamp_matrix_multiply/src/baremetal.h index 39627929..70add711 100644 --- a/lib/sw_apps/openamp_matrix_multiply/src/baremetal.h +++ b/lib/sw_apps/openamp_matrix_multiply/src/baremetal.h @@ -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 diff --git a/lib/sw_apps/openamp_matrix_multiply/src/lscript_freertos.ld b/lib/sw_apps/openamp_matrix_multiply/src/lscript_freertos.ld new file mode 100644 index 00000000..8a7868b0 --- /dev/null +++ b/lib/sw_apps/openamp_matrix_multiply/src/lscript_freertos.ld @@ -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 = .; +} diff --git a/lib/sw_apps/openamp_matrix_multiply/src/matrix_multiply.c b/lib/sw_apps/openamp_matrix_multiply/src/matrix_multiply.c index c58dd5de..5cab77dd 100644 --- a/lib/sw_apps/openamp_matrix_multiply/src/matrix_multiply.c +++ b/lib/sw_apps/openamp_matrix_multiply/src/matrix_multiply.c @@ -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 diff --git a/lib/sw_apps/openamp_matrix_multiply/src/platform.c b/lib/sw_apps/openamp_matrix_multiply/src/platform.c index c2467647..673bf34b 100644 --- a/lib/sw_apps/openamp_matrix_multiply/src/platform.c +++ b/lib/sw_apps/openamp_matrix_multiply/src/platform.c @@ -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; } diff --git a/lib/sw_apps/openamp_matrix_multiply/src/xpqueue.c b/lib/sw_apps/openamp_matrix_multiply/src/xpqueue.c new file mode 100644 index 00000000..dd446e3a --- /dev/null +++ b/lib/sw_apps/openamp_matrix_multiply/src/xpqueue.c @@ -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 + +#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; +} diff --git a/lib/sw_apps/openamp_matrix_multiply/src/xpqueue.h b/lib/sw_apps/openamp_matrix_multiply/src/xpqueue.h new file mode 100644 index 00000000..579be463 --- /dev/null +++ b/lib/sw_apps/openamp_matrix_multiply/src/xpqueue.h @@ -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