############################################################################## | |
# | |
# (c) Copyright 2011 Xilinx, Inc. All rights reserved. | |
# | |
# This file contains confidential and proprietary information of Xilinx, Inc. | |
# and is protected under U.S. and international copyright and other | |
# intellectual property laws. | |
# | |
# DISCLAIMER | |
# This disclaimer is not a license and does not grant any rights to the | |
# materials distributed herewith. Except as otherwise provided in a valid | |
# license issued to you by Xilinx, and to the maximum extent permitted by | |
# applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL | |
# FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, | |
# IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF | |
# MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; | |
# and (2) Xilinx shall not be liable (whether in contract or tort, including | |
# negligence, or under any other theory of liability) for any loss or damage | |
# of any kind or nature related to, arising under or in connection with these | |
# materials, including for any direct, or any indirect, special, incidental, | |
# or consequential loss or damage (including loss of data, profits, goodwill, | |
# or any type of loss or damage suffered as a result of any action brought by | |
# a third party) even if such damage or loss was reasonably foreseeable or | |
# Xilinx had been advised of the possibility of the same. | |
# | |
# CRITICAL APPLICATIONS | |
# Xilinx products are not designed or intended to be fail-safe, or for use in | |
# any application requiring fail-safe performance, such as life-support or | |
# safety devices or systems, Class III medical devices, nuclear facilities, | |
# applications related to the deployment of airbags, or any other applications | |
# that could lead to death, personal injury, or severe property or | |
# environmental damage (individually and collectively, "Critical | |
# Applications"). Customer assumes the sole risk and liability of any use of | |
# Xilinx products in Critical Applications, subject only to applicable laws | |
# and regulations governing limitations on product liability. | |
# | |
# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE | |
# AT ALL TIMES. | |
# | |
# This file is part of FreeRTOS. | |
# | |
# $Id: freertos_v2_1_0.tcl,v 1.1.2.8 2010/12/10 07:27:08 svemula Exp $ | |
############################################################################### | |
# standalone bsp version. set this to the latest "ACTIVE" version. | |
set standalone_version standalone_v3_01_a | |
proc kernel_drc {os_handle} { | |
set sw_proc_handle [xget_libgen_proc_handle] | |
set hw_proc_handle [xget_handle $sw_proc_handle "IPINST"] | |
set proctype [xget_value $hw_proc_handle "OPTION" "IPNAME"] | |
set compiler [xget_value $sw_proc_handle "PARAMETER" "COMPILER"] | |
# check for valid compiler | |
if { [string first "mb-gcc" $compiler] == 0 && [string first "mb-g++" $compiler] == 0} { | |
error "Wrong compiler requested. FreeRTOS can be compiled only with the GNU compiler for MicroBlaze." "" "mdt_error" | |
} | |
# check for valid stdio parameters | |
set stdin [xget_value $os_handle "PARAMETER" "STDIN"] | |
set stdout [xget_value $os_handle "PARAMETER" "STDOUT"] | |
if { $stdin == "none" || $stdout == "none" } { | |
error "The STDIN/STDOUT parameters are not set. FreeRTOS requires stdin/stdout to be set." "" "mdt_error" | |
} | |
# check if the design has a intc | |
set intr_port [xget_value $hw_proc_handle "PORT" "Interrupt"] | |
if { [llength $intr_port] == 0 } { | |
error "CPU has no connection to Interrupt controller." "" "mdt_error" | |
} | |
# support only AXI/PLB | |
set interconnect [xget_value $hw_proc_handle "PARAMETER" "C_INTERCONNECT"] | |
if { $interconnect == 1 } { | |
set bus_name [xget_hw_busif_value $hw_proc_handle "DPLB"] | |
} elseif { $interconnect == 2 } { | |
set bus_name [xget_hw_busif_value $hw_proc_handle "M_AXI_DP"] | |
} else { | |
error "FreeRTOS supports Microblaze with only a AXI or PLB interconnect" "" "mdt_error" | |
} | |
# obtain handles to all the peripherals in the design | |
set mhs_handle [xget_hw_parent_handle $hw_proc_handle] | |
set slave_ifs [xget_hw_connected_busifs_handle $mhs_handle $bus_name "slave"] | |
set timer_count 0 | |
set timer_has_intr 0 | |
# check for a valid timer | |
foreach if $slave_ifs { | |
set ip_handle [xget_hw_parent_handle $if] | |
if {$ip_handle != $hw_proc_handle} { | |
set type [xget_hw_value $ip_handle] | |
if { $type == "xps_timer" || $type == "axi_timer" } { | |
incr timer_count | |
# check if the timer interrupts are enabled | |
set intr_port [xget_value $ip_handle "PORT" "Interrupt"] | |
if { [llength $intr_port] != 0 } { | |
set timer_has_intr 1 | |
} | |
} | |
} | |
} | |
if { $timer_count == 0 } { | |
error "FreeRTOS for Microblaze requires an axi_timer or xps_timer. The HW platform doesn't have a valid timer." "" "mdt_error" | |
} | |
if { $timer_has_intr == 0 } { | |
error "FreeRTOS for Microblaze requires interrupts enabled for a timer." "" "mdt_error" | |
} | |
set systmr_interval_ms [xget_value $os_handle "PARAMETER" "systmr_interval"] | |
if { $systmr_interval_ms <= 0 } { | |
error "Invalid value for parameter systmr_interval specified. Please specify a positive value." "" "mdt_error" | |
} | |
### ToDo: Add DRC specific to FreeRTOS | |
} | |
proc generate {os_handle} { | |
variable standalone_version | |
set sw_proc_handle [xget_libgen_proc_handle] | |
set hw_proc_handle [xget_handle $sw_proc_handle "IPINST"] | |
set proctype [xget_value $hw_proc_handle "OPTION" "IPNAME"] | |
set procver [xget_value $hw_proc_handle "PARAMETER" "HW_VER"] | |
set need_config_file "false" | |
# proctype should be "microblaze" | |
set mbsrcdir "../${standalone_version}/src/microblaze" | |
set commondir "../${standalone_version}/src/common" | |
set datadir "../${standalone_version}/data" | |
foreach entry [glob -nocomplain [file join $commondir *]] { | |
file copy -force $entry [file join ".." "${standalone_version}" "src"] | |
} | |
# proctype should be "microblaze" | |
switch -regexp $proctype { | |
"microblaze" { | |
foreach entry [glob -nocomplain [file join $mbsrcdir *]] { | |
if { [string first "microblaze_interrupt_handler" $entry] == -1 } { ;# Do not copy over the Standalone BSP exception handler | |
file copy -force $entry [file join ".." "${standalone_version}" "src"] | |
} | |
} | |
set need_config_file "true" | |
} | |
"default" {puts "unknown processor type $proctype\n"} | |
} | |
# Write the config.make file | |
set makeconfig [open "../standalone_v3_01_a/src/config.make" w] | |
xprint_generated_header_tcl $makeconfig "Configuration parameters for Standalone Makefile" | |
if { $proctype == "microblaze" } { | |
if { [mb_has_exceptions $hw_proc_handle] } { | |
puts $makeconfig "LIBSOURCES = *.s *.c *.S" | |
} else { | |
puts $makeconfig "LIBSOURCES = *.s *.c" | |
} | |
} | |
puts $makeconfig "LIBS = standalone_libs" | |
close $makeconfig | |
# Remove microblaze directories... | |
file delete -force $mbsrcdir | |
# copy required files to the main src directory | |
file copy -force [file join src Source tasks.c] src | |
file copy -force [file join src Source queue.c] src | |
file copy -force [file join src Source list.c] src | |
file copy -force [file join src Source timers.c] src | |
file copy -force [file join src Source portable MemMang heap_3.c] src | |
file copy -force [file join src Source portable GCC MicroBlazeV8 port.c] src | |
file copy -force [file join src Source portable GCC MicroBlazeV8 port_exceptions.c] src | |
file copy -force [file join src Source portable GCC MicroBlazeV8 portasm.S] src | |
file copy -force [file join src Source portable GCC MicroBlazeV8 portmacro.h] src | |
set headers [glob -join ./src/Source/include *.\[h\]] | |
foreach header $headers { | |
file copy -force $header src | |
} | |
file delete -force [file join src Source] | |
file delete -force [file join src Source] | |
# Handle stdin and stdout | |
xhandle_stdin $os_handle | |
xhandle_stdout $os_handle | |
# Create config file for microblaze interrupt handling | |
if {[string compare -nocase $need_config_file "true"] == 0} { | |
xhandle_mb_interrupts | |
} | |
# Create config files for Microblaze exception handling | |
if { $proctype == "microblaze" && [mb_has_exceptions $hw_proc_handle] } { | |
xcreate_mb_exc_config_file | |
} | |
# Create bspconfig file | |
set bspcfg_fn [file join ".." "${standalone_version}" "src" "bspconfig.h"] | |
file delete $bspcfg_fn | |
set bspcfg_fh [open $bspcfg_fn w] | |
xprint_generated_header $bspcfg_fh "Configurations for Standalone BSP" | |
if { $proctype == "microblaze" && [mb_has_pvr $hw_proc_handle] } { | |
set pvr [xget_value $hw_proc_handle "PARAMETER" "C_PVR"] | |
switch $pvr { | |
"0" { | |
puts $bspcfg_fh "#define MICROBLAZE_PVR_NONE" | |
} | |
"1" { | |
puts $bspcfg_fh "#define MICROBLAZE_PVR_BASIC" | |
} | |
"2" { | |
puts $bspcfg_fh "#define MICROBLAZE_PVR_FULL" | |
} | |
"default" { | |
puts $bspcfg_fh "#define MICROBLAZE_PVR_NONE" | |
} | |
} | |
} | |
close $bspcfg_fh | |
# ToDO: FreeRTOS does not handle the following, refer xilkernel TCL script | |
# - MPU settings | |
set config_file [xopen_new_include_file "./src/FreeRTOSConfig.h" "FreeRTOS Configuration parameters"] | |
puts $config_file "\#include \"xparameters.h\" \n" | |
set val [xget_value $os_handle "PARAMETER" "use_preemption"] | |
if {$val == "false"} { | |
xput_define $config_file "configUSE_PREEMPTION" "0" | |
} else { | |
xput_define $config_file "configUSE_PREEMPTION" "1" | |
} | |
set val [xget_value $os_handle "PARAMETER" "use_mutexes"] | |
if {$val == "false"} { | |
xput_define $config_file "configUSE_MUTEXES" "0" | |
} else { | |
xput_define $config_file "configUSE_MUTEXES" "1" | |
} | |
set val [xget_value $os_handle "PARAMETER" "use_recursive_mutexes"] | |
if {$val == "false"} { | |
xput_define $config_file "configUSE_RECURSIVE_MUTEXES" "0" | |
} else { | |
xput_define $config_file "configUSE_RECURSIVE_MUTEXES" "1" | |
} | |
set val [xget_value $os_handle "PARAMETER" "use_counting_semaphores"] | |
if {$val == "false"} { | |
xput_define $config_file "configUSE_COUNTING_SEMAPHORES" "0" | |
} else { | |
xput_define $config_file "configUSE_COUNTING_SEMAPHORES" "1" | |
} | |
set val [xget_value $os_handle "PARAMETER" "use_timers"] | |
if {$val == "false"} { | |
xput_define $config_file "configUSE_TIMERS" "0" | |
} else { | |
xput_define $config_file "configUSE_TIMERS" "1" | |
} | |
set val [xget_value $os_handle "PARAMETER" "use_idle_hook"] | |
if {$val == "false"} { | |
xput_define $config_file "configUSE_IDLE_HOOK" "0" | |
} else { | |
xput_define $config_file "configUSE_IDLE_HOOK" "1" | |
} | |
set val [xget_value $os_handle "PARAMETER" "use_tick_hook"] | |
if {$val == "false"} { | |
xput_define $config_file "configUSE_TICK_HOOK" "0" | |
} else { | |
xput_define $config_file "configUSE_TICK_HOOK" "1" | |
} | |
set val [xget_value $os_handle "PARAMETER" "use_malloc_failed_hook"] | |
if {$val == "false"} { | |
xput_define $config_file "configUSE_MALLOC_FAILED_HOOK" "0" | |
} else { | |
xput_define $config_file "configUSE_MALLOC_FAILED_HOOK" "1" | |
} | |
set val [xget_value $os_handle "PARAMETER" "use_trace_facility"] | |
if {$val == "false"} { | |
xput_define $config_file "configUSE_TRACE_FACILITY" "0" | |
} else { | |
xput_define $config_file "configUSE_TRACE_FACILITY" "1" | |
} | |
xput_define $config_file "configUSE_16_BIT_TICKS" "0" | |
xput_define $config_file "configUSE_APPLICATION_TASK_TAG" "0" | |
xput_define $config_file "configUSE_CO_ROUTINES" "0" | |
# System timer tick rate (Microblaze only. kernel DRC ensures this) | |
set systmr_interval [xget_value $os_handle "PARAMETER" "systmr_interval"] | |
xput_define $config_file "configTICK_RATE_HZ" $systmr_interval | |
set max_priorities [xget_value $os_handle "PARAMETER" "max_priorities"] | |
xput_define $config_file "configMAX_PRIORITIES" $max_priorities | |
xput_define $config_file "configMAX_CO_ROUTINE_PRIORITIES" "2" | |
set min_stack [xget_value $os_handle "PARAMETER" "minimal_stack_size"] | |
set min_stack [expr [expr $min_stack + 3] & 0xFFFFFFFC] | |
xput_define $config_file "configMINIMAL_STACK_SIZE" $min_stack | |
set total_heap_size [xget_value $os_handle "PARAMETER" "total_heap_size"] | |
set total_heap_size [expr [expr $total_heap_size + 3] & 0xFFFFFFFC] | |
xput_define $config_file "configTOTAL_HEAP_SIZE" $total_heap_size | |
set max_task_name_len [xget_value $os_handle "PARAMETER" "max_task_name_len"] | |
xput_define $config_file "configMAX_TASK_NAME_LEN" $max_task_name_len | |
set val [xget_value $os_handle "PARAMETER" "idle_yield"] | |
if {$val == "false"} { | |
xput_define $config_file "configIDLE_SHOULD_YIELD" "0" | |
} else { | |
xput_define $config_file "configIDLE_SHOULD_YIELD" "1" | |
} | |
set val [xget_value $os_handle "PARAMETER" "check_for_stack_overflow"] | |
if {$val == "false"} { | |
xput_define $config_file "configCHECK_FOR_STACK_OVERFLOW" "0" | |
} else { | |
xput_define $config_file "configCHECK_FOR_STACK_OVERFLOW" "2" | |
} | |
set val [xget_value $os_handle "PARAMETER" "queue_registry_size"] | |
if {$val == "false"} { | |
xput_define $config_file "configQUEUE_REGISTRY_SIZE" "0" | |
} else { | |
xput_define $config_file "configQUEUE_REGISTRY_SIZE" "10" | |
} | |
xput_define $config_file "configGENERATE_RUN_TIME_STATS" "0" | |
set val [xget_value $os_handle "PARAMETER" "timer_task_priority"] | |
if {$val == "false"} { | |
xput_define $config_file "configTIMER_TASK_PRIORITY" "0" | |
} else { | |
xput_define $config_file "configTIMER_TASK_PRIORITY" "10" | |
} | |
set val [xget_value $os_handle "PARAMETER" "timer_command_queue_length"] | |
if {$val == "false"} { | |
xput_define $config_file "configTIMER_QUEUE_LENGTH" "0" | |
} else { | |
xput_define $config_file "configTIMER_QUEUE_LENGTH" "10" | |
} | |
set val [xget_value $os_handle "PARAMETER" "timer_task_stack_depth"] | |
if {$val == "false"} { | |
xput_define $config_file "configTIMER_TASK_STACK_DEPTH" "0" | |
} else { | |
xput_define $config_file "configTIMER_TASK_STACK_DEPTH" $min_stack | |
} | |
if { [mb_has_exceptions $hw_proc_handle] } { | |
xput_define $config_file "configINSTALL_EXCEPTION_HANDLERS" "1" | |
} else { | |
xput_define $config_file "configINSTALL_EXCEPTION_HANDLERS" "0" | |
} | |
xput_define $config_file "configINTERRUPT_CONTROLLER_TO_USE" "XPAR_INTC_SINGLE_DEVICE_ID" | |
xput_define $config_file "INCLUDE_vTaskCleanUpResources" "0" | |
xput_define $config_file "INCLUDE_vTaskDelay" "1" | |
xput_define $config_file "INCLUDE_vTaskDelayUntil" "1" | |
xput_define $config_file "INCLUDE_vTaskDelete" "1" | |
xput_define $config_file "INCLUDE_xTaskGetCurrentTaskHandle" "1" | |
xput_define $config_file "INCLUDE_xTaskGetIdleTaskHandle" "1" | |
xput_define $config_file "INCLUDE_xTaskGetSchedulerState" "1" | |
xput_define $config_file "INCLUDE_xTimerGetTimerDaemonTaskHandle" "1" | |
xput_define $config_file "INCLUDE_uxTaskGetStackHighWaterMark" "1" | |
xput_define $config_file "INCLUDE_uxTaskPriorityGet" "1" | |
xput_define $config_file "INCLUDE_vTaskPrioritySet" "1" | |
xput_define $config_file "INCLUDE_xTaskResumeFromISR" "1" | |
xput_define $config_file "INCLUDE_vTaskSuspend" "1" | |
xput_define $config_file "INCLUDE_pcTaskGetTaskName" "1" | |
xput_define $config_file "INCLUDE_xTaskGetIdleTaskHandle" "1" | |
xput_define $config_file "INCLUDE_xTimerGetTimerDaemonTaskHandle" "1" | |
# complete the header protectors | |
puts $config_file "\#endif" | |
close $config_file | |
} | |
proc xopen_new_include_file { filename description } { | |
set inc_file [open $filename w] | |
xprint_generated_header $inc_file $description | |
set newfname [string map {. _} [lindex [split $filename {\/}] end]] | |
puts $inc_file "\#ifndef _[string toupper $newfname]" | |
puts $inc_file "\#define _[string toupper $newfname]\n\n" | |
return $inc_file | |
} | |
proc xadd_define { config_file os_handle parameter } { | |
set param_value [xget_value $os_handle "PARAMETER" $parameter] | |
puts $config_file "#define [string toupper $parameter] $param_value\n" | |
# puts "creating #define [string toupper $parameter] $param_value\n" | |
} | |
proc xput_define { config_file parameter param_value } { | |
puts $config_file "#define $parameter $param_value\n" | |
# puts "creating #define [string toupper $parameter] $param_value\n" | |
} | |
# args field of the array | |
proc xadd_extern_fname {initfile oshandle arrayname arg} { | |
set arrhandle [xget_handle $oshandle "ARRAY" $arrayname] | |
set elements [xget_handle $arrhandle "ELEMENTS" "*"] | |
set count 0 | |
set max_count [llength $elements] | |
foreach ele $elements { | |
incr count | |
set arg_value [xget_value $ele "PARAMETER" $arg] | |
puts $initfile "extern void $arg_value\(\)\;" | |
} | |
puts $initfile "" | |
} | |
# args is variable no - fields of the array | |
proc xadd_struct {initfile oshandle structtype structname arrayname args} { | |
set arrhandle [xget_handle $oshandle "ARRAY" $arrayname] | |
set elements [xget_handle $arrhandle "ELEMENTS" "*"] | |
set count 0 | |
set max_count [llength $elements] | |
puts $initfile "struct $structtype $structname\[$max_count\] = \{" | |
foreach ele $elements { | |
incr count | |
puts -nonewline $initfile "\t\{" | |
foreach field $args { | |
set field_value [xget_value $ele "PARAMETER" $field] | |
# puts "$arrayname ( $count )->$field is $field_value" | |
puts -nonewline $initfile "$field_value" | |
if { $field != [lindex $args end] } { | |
puts -nonewline $initfile "," | |
} | |
} | |
if {$count < $max_count} { | |
puts $initfile "\}," | |
} else { | |
puts $initfile "\}" | |
} | |
} | |
puts $initfile "\}\;" | |
} | |
# return the sum of all the arg field values in arrayname | |
proc get_field_sum {oshandle arrayname arg} { | |
set arrhandle [xget_handle $oshandle "ARRAY" $arrayname] | |
set elements [xget_handle $arrhandle "ELEMENTS" "*"] | |
set count 0 | |
set max_count [llength $elements] | |
foreach ele $elements { | |
set field_value [xget_value $ele "PARAMETER" $arg] | |
set count [expr $field_value+$count] | |
} | |
return $count | |
} | |
# return the sum of the product of field values in arrayname | |
proc get_field_product_sum {oshandle arrayname field1 field2} { | |
set arrhandle [xget_handle $oshandle "ARRAY" $arrayname] | |
set elements [xget_handle $arrhandle "ELEMENTS" "*"] | |
set count 0 | |
set max_count [llength $elements] | |
foreach ele $elements { | |
set field1_value [xget_value $ele "PARAMETER" $field1] | |
set field2_value [xget_value $ele "PARAMETER" $field2] | |
set incr_value [expr $field1_value*$field2_value] | |
set count [expr $count+$incr_value] | |
} | |
return $count | |
} | |
proc xhandle_mb_interrupts {} { | |
set default_interrupt_handler "XNullHandler" | |
set default_arg "XNULL" | |
set source_interrupt_handler $default_interrupt_handler | |
set source_handler_arg $default_arg | |
# Handle the interrupt pin | |
set sw_proc_handle [xget_libgen_proc_handle] | |
set periph [xget_handle $sw_proc_handle "IPINST"] | |
set source_ports [xget_interrupt_sources $periph] | |
if {[llength $source_ports] > 1} { | |
error "Too many interrupting ports on the MicroBlaze. Should only find 1" "" "libgen_error" | |
return | |
} | |
if {[llength $source_ports] == 1} { | |
set source_port [lindex $source_ports 0] | |
if {[llength $source_port] != 0} { | |
set source_port_name [xget_value $source_port "VALUE"] | |
set source_periph [xget_handle $source_port "PARENT"] | |
set source_name [xget_value $source_periph "NAME"] | |
set source_driver [xget_sw_driver_handle_for_ipinst $sw_proc_handle $source_name] | |
if {[string compare -nocase $source_driver ""] != 0} { | |
set int_array [xget_handle $source_driver "ARRAY" "interrupt_handler"] | |
if {[llength $int_array] != 0} { | |
set int_array_elems [xget_handle $int_array "ELEMENTS" "*"] | |
if {[llength $int_array_elems] != 0} { | |
foreach int_array_elem $int_array_elems { | |
set int_port [xget_value $int_array_elem "PARAMETER" "int_port"] | |
if {[llength $int_port] != 0} { | |
if {[string compare -nocase $int_port $source_port_name] == 0 } { | |
set source_interrupt_handler [xget_value $int_array_elem "PARAMETER" "int_handler"] | |
set source_handler_arg [xget_value $int_array_elem "PARAMETER" "int_handler_arg"] | |
if {[string compare -nocase $source_handler_arg DEVICE_ID] == 0 } { | |
set source_handler_arg [xget_name $source_periph "DEVICE_ID"] | |
} else { | |
if {[string compare -nocase "global" [xget_port_type $source_port]] == 0} { | |
set source_handler_arg $default_arg | |
} else { | |
set source_handler_arg [xget_name $source_periph "C_BASEADDR"] | |
} | |
} | |
break | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
# Generate microblaze_interrupts_g.c file... | |
xcreate_mb_intr_config_file $source_interrupt_handler $source_handler_arg | |
} | |
proc xcreate_mb_intr_config_file {handler arg} { | |
set mb_table "MB_InterruptVectorTable" | |
set filename [file join "../standalone_v3_01_a/src" "microblaze_interrupts_g.c"] | |
file delete $filename | |
set config_file [open $filename w] | |
xprint_generated_header $config_file "Interrupt Handler Table for MicroBlaze Processor" | |
puts $config_file "#include \"microblaze_interrupts_i.h\"" | |
puts $config_file "#include \"xparameters.h\"" | |
puts $config_file "\n" | |
puts $config_file [format "extern void %s (void *);" $handler] | |
puts $config_file "\n/*" | |
puts $config_file "* The interrupt handler table for microblaze processor" | |
puts $config_file "*/\n" | |
puts $config_file [format "%sEntry %s\[\] =" $mb_table $mb_table] | |
puts $config_file "\{" | |
puts -nonewline $config_file [format "\{\t%s" $handler] | |
puts -nonewline $config_file [format ",\n\t(void*) %s\}" $arg] | |
puts -nonewline $config_file "\n\};" | |
puts $config_file "\n" | |
close $config_file | |
} | |
# ------------------------------------------- | |
# Tcl procedure xcreate_mb_exc_config file | |
# ------------------------------------------- | |
proc xcreate_mb_exc_config_file { } { | |
set hfilename [file join "src" "microblaze_exceptions_g.h"] | |
file delete $hfilename | |
set hconfig_file [open $hfilename w] | |
xprint_generated_header $hconfig_file "Exception Handling Header for MicroBlaze Processor" | |
puts $hconfig_file "\n" | |
set sw_proc_handle [xget_libgen_proc_handle] | |
set hw_proc_handle [xget_handle $sw_proc_handle "IPINST"] | |
set procver [xget_value $hw_proc_handle "PARAMETER" "HW_VER"] | |
if { ![mb_has_exceptions $hw_proc_handle]} { ;# NO exceptions are enabled | |
close $hconfig_file ;# Do not generate any info in either the header or the C file | |
return | |
} | |
puts $hconfig_file "\#define MICROBLAZE_EXCEPTIONS_ENABLED 1" | |
if { [mb_can_handle_exceptions_in_delay_slots $procver] } { | |
puts $hconfig_file "#define MICROBLAZE_CAN_HANDLE_EXCEPTIONS_IN_DELAY_SLOTS" | |
} | |
close $hconfig_file | |
} | |
# -------------------------------------- | |
# Tcl procedure post_generate | |
# This proc removes from libxil.a the basic | |
# and standalone BSP versions of | |
# _interrupt_handler and _hw_exception_handler | |
# routines | |
# -------------------------------------- | |
proc post_generate {os_handle} { | |
set sw_proc_handle [xget_libgen_proc_handle] | |
set hw_proc_handle [xget_handle $sw_proc_handle "IPINST"] | |
set proctype [xget_value $hw_proc_handle "OPTION" "IPNAME"] | |
set procname [xget_value $hw_proc_handle "NAME"] | |
set procdrv [xget_sw_driver_handle_for_ipinst $sw_proc_handle $procname] | |
set archiver [xget_value $procdrv "PARAMETER" "archiver"] | |
if {[string compare -nocase $proctype "microblaze"] == 0 } { | |
# Remove _interrupt_handler.o from libxil.a for FreeRTOS | |
set libxil_a [file join .. .. lib libxil.a] | |
exec $archiver -d $libxil_a _interrupt_handler.o | |
# We have linkage problems due to how these platforms are defined. Can't do this right now. | |
# # Remove _exception_handler.o from libxil.a for FreeRTOS | |
# exec bash -c "$archiver -d ../../lib/libxil.a _exception_handler.o" | |
# Remove _hw_exception_handler.o from libxil.a for microblaze cores with exception support | |
if {[mb_has_exceptions $hw_proc_handle]} { | |
exec $archiver -d ../../lib/libxil.a _hw_exception_handler.o | |
} | |
} | |
} | |
# -------------------------------------- | |
# Tcl procedure execs_generate | |
# This proc removes from libxil.a all | |
# the stuff that we are overriding | |
# with xilkernel | |
# We currently override, | |
# MicroBlaze | |
# - Dummy _interrupt_hander and _hw_exception_handler | |
# (in post_generate) | |
# PPC | |
# - xvectors.o; sleep.o (IF config_time is true) | |
# Common to all processors | |
# - errno.o | |
# -------------------------------------- | |
proc execs_generate {os_handle} { | |
set sw_proc_handle [xget_libgen_proc_handle] | |
set hw_proc_handle [xget_handle $sw_proc_handle "IPINST"] | |
set proctype [xget_value $hw_proc_handle "OPTION" "IPNAME"] | |
set procname [xget_value $hw_proc_handle "NAME"] | |
set procdrv [xget_sw_driver_handle_for_ipinst $sw_proc_handle $procname] | |
# Remove _interrupt_handler.o from libxil.a for mb-gcc | |
set archiver [xget_value $procdrv "PARAMETER" "archiver"] | |
set libxil_a [file join .. .. lib libxil.a] | |
# exec $archiver -d $libxil_a errno.o | |
# We have linkage problems due to how these platforms are defined. Can't do this right now. | |
# exec "$archiver -d $libxil_a microblaze_interrupt_handler.o" | |
} | |
# -------------------------------------- | |
# Return true if this MB has | |
# exception handling support | |
# -------------------------------------- | |
proc mb_has_exceptions { hw_proc_handle } { | |
# Check if the following parameters exist on this MicroBlaze's MPD | |
set ee [xget_value $hw_proc_handle "PARAMETER" "C_UNALIGNED_EXCEPTIONS"] | |
if { $ee != "" } { | |
return true | |
} | |
set ee [xget_value $hw_proc_handle "PARAMETER" "C_ILL_OPCODE_EXCEPTION"] | |
if { $ee != "" } { | |
return true | |
} | |
set ee [xget_value $hw_proc_handle "PARAMETER" "C_IOPB_BUS_EXCEPTION"] | |
if { $ee != "" } { | |
return true | |
} | |
set ee [xget_value $hw_proc_handle "PARAMETER" "C_DOPB_BUS_EXCEPTION"] | |
if { $ee != "" } { | |
return true | |
} | |
set ee [xget_value $hw_proc_handle "PARAMETER" "C_DIV_BY_ZERO_EXCEPTION"] | |
if { $ee != "" } { | |
return true | |
} | |
set ee [xget_value $hw_proc_handle "PARAMETER" "C_DIV_ZERO_EXCEPTION"] | |
if { $ee != "" } { | |
return true | |
} | |
set ee [xget_value $hw_proc_handle "PARAMETER" "C_FPU_EXCEPTION"] | |
if { $ee != "" } { | |
return true | |
} | |
set ee [xget_value $hw_proc_handle "PARAMETER" "C_USE_MMU"] | |
if { $ee != "" && $ee != 0 } { | |
return true | |
} | |
return false | |
} | |
# -------------------------------------- | |
# Return true if this MB has | |
# FPU exception handling support | |
# -------------------------------------- | |
proc mb_has_fpu_exceptions { hw_proc_handle } { | |
# Check if the following parameters exist on this MicroBlaze's MPD | |
set ee [xget_value $hw_proc_handle "PARAMETER" "C_FPU_EXCEPTION"] | |
if { $ee != "" } { | |
return true | |
} | |
return false | |
} | |
# -------------------------------------- | |
# Return true if this MB has PVR support | |
# -------------------------------------- | |
proc mb_has_pvr { hw_proc_handle } { | |
# Check if the following parameters exist on this MicroBlaze's MPD | |
set pvr [xget_value $hw_proc_handle "PARAMETER" "C_PVR"] | |
if { $pvr != "" } { | |
return true | |
} | |
return false | |
} | |
# -------------------------------------- | |
# Return true if MB ver 'procver' has | |
# support for handling exceptions in | |
# delay slots | |
# -------------------------------------- | |
proc mb_can_handle_exceptions_in_delay_slots { procver } { | |
if { [string compare -nocase $procver "5.00.a"] >= 0 } { | |
return true | |
} else { | |
return false | |
} | |
} | |
# -------------------------------------------------------------------------- | |
# Gets all the handles that are memory controller cores. | |
# -------------------------------------------------------------------------- | |
proc xget_memory_controller_handles { mhs } { | |
set ret_list "" | |
# Gets all MhsInsts in the system | |
set mhsinsts [xget_hw_ipinst_handle $mhs "*"] | |
# Loop thru each MhsInst and determine if have "ADDR_TYPE = MEMORY" in | |
# the parameters. | |
foreach mhsinst $mhsinsts { | |
# Gets all parameters of the component | |
set params [xget_hw_parameter_handle $mhsinst "*"] | |
# Loop thru each param and find tag "ADDR_TYPE = MEMORY" | |
foreach param $params { | |
if {$param == 0} { | |
continue | |
} elseif {$param == ""} { | |
continue | |
} | |
set addrTypeValue [ xget_hw_subproperty_value $param "ADDR_TYPE" ] | |
# Found tag! Add MhsInst to list and break to go to next MhsInst | |
if {[string compare -nocase $addrTypeValue "MEMORY"] == 0} { | |
lappend ret_list $mhsinst | |
break | |
} | |
} | |
} | |
return $ret_list | |
} |