You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1022 lines
28 KiB
1022 lines
28 KiB
#! /usr/bin/env python |
|
# |
|
# sysgen - System Generator |
|
# |
|
# |
|
# Copyright (c) 2015, Wind River Systems, Inc. |
|
# |
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
|
# you may not use this file except in compliance with the License. |
|
# You may obtain a copy of the License at |
|
# |
|
# http://www.apache.org/licenses/LICENSE-2.0 |
|
# |
|
# Unless required by applicable law or agreed to in writing, software |
|
# distributed under the License is distributed on an "AS IS" BASIS, |
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
# See the License for the specific language governing permissions and |
|
# limitations under the License. |
|
# |
|
|
|
# Arguments: |
|
# - name of MDEF file |
|
# - name of directory for output files (optional) |
|
|
|
# Generates: |
|
# - kernel_main.c file |
|
# - kernel_main.h file (local copy) |
|
# - micro_private_types.h file (local copy) |
|
# - sysgen.h file |
|
|
|
import os |
|
import sys |
|
import subprocess |
|
|
|
# global variables describing system |
|
|
|
MIN_HEAP = 64 |
|
heap_pos_in_pool_list = -1 |
|
num_kargs = 0 |
|
num_timers = 0 |
|
num_prios = 0 |
|
num_task_irqs = 0 |
|
|
|
task_list = [] |
|
event_list = [] |
|
mutex_list = [] |
|
sema_list = [] |
|
fifo_list = [] |
|
pipe_list = [] |
|
mbx_list = [] |
|
map_list = [] |
|
pool_list = [] |
|
|
|
group_dictionary = {} |
|
group_key_list = [] |
|
|
|
# global variables used during generation of output files |
|
|
|
do_not_edit_warning = \ |
|
"\n\n\n/* THIS FILE IS AUTOGENERATED -- DO NOT MODIFY! */\n\n\n" |
|
|
|
copyright = \ |
|
"/*\n" + \ |
|
" * Copyright (c) 2015 Wind River Systems, Inc.\n" + \ |
|
" *\n" + \ |
|
" * Licensed under the Apache License, Version 2.0 (the \"License\");\n" + \ |
|
" * you may not use this file except in compliance with the License.\n" + \ |
|
" * You may obtain a copy of the License at\n" + \ |
|
" *\n" + \ |
|
" * http://www.apache.org/licenses/LICENSE-2.0\n" + \ |
|
" *\n" + \ |
|
" * Unless required by applicable law or agreed to in writing, software\n" + \ |
|
" * distributed under the License is distributed on an \"AS IS\" BASIS,\n" + \ |
|
" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + \ |
|
" * See the License for the specific language governing permissions and\n" + \ |
|
" * limitations under the License.\n" + \ |
|
" */\n" |
|
|
|
output_dir = "" |
|
|
|
|
|
def get_output_dir(): |
|
""" Handle optional output directory argument """ |
|
|
|
global output_dir |
|
if len(sys.argv) > 2: |
|
output_dir = sys.argv[2] |
|
|
|
|
|
def write_file(filename, contents): |
|
""" Create file using specified name and contents """ |
|
|
|
f = open(filename, 'w') # overwrites file if it already exists |
|
f.write(contents) |
|
f.close() |
|
|
|
|
|
# |
|
# ERROR HANDLING |
|
# |
|
|
|
|
|
def sysgen_error(msg): |
|
print("\n*** sysgen error: " + msg + "\n") |
|
sys.exit(1) |
|
|
|
|
|
def error_arg_count(line): |
|
sysgen_error("invalid number of arguments on following line\n" + line) |
|
|
|
|
|
# |
|
# CREATE INTERNAL REPRESENTATION OF SYSTEM |
|
# |
|
|
|
|
|
def mdef_parse(): |
|
""" Parse MDEF file """ |
|
|
|
global num_kargs |
|
global num_timers |
|
global num_prios |
|
global MIN_HEAP |
|
global heap_pos_in_pool_list |
|
|
|
# read file contents in a single shot |
|
with open(sys.argv[1], 'r') as infile: |
|
data = infile.read() |
|
|
|
# create list of the lines, breaking at line boundaries |
|
my_list = data.splitlines() |
|
|
|
# process each line |
|
for line in my_list: |
|
words = line.split() |
|
|
|
if (len(words) == 0): |
|
continue # ignore blank line |
|
|
|
if (words[0][0] == "%"): |
|
continue # ignore comment line |
|
|
|
if (words[0] == "CONFIG"): |
|
if (len(words) != 4): |
|
error_arg_count(line) |
|
num_kargs = int(words[1]) |
|
num_timers = int(words[2]) |
|
num_prios = int(words[3]) |
|
continue |
|
|
|
if (words[0] == "TASK"): |
|
if (len(words) != 6): |
|
error_arg_count(line) |
|
task_list.append((words[1], int(words[2]), words[3], |
|
int(words[4]), words[5])) |
|
continue |
|
|
|
if (words[0] == "TASKGROUP"): |
|
if (len(words) != 2): |
|
error_arg_count(line) |
|
if words[1] in group_dictionary: |
|
continue # ignore re-definition of a task group |
|
group_bitmask = 1 << len(group_dictionary) |
|
group_dictionary[words[1]] = group_bitmask |
|
group_key_list.append(words[1]) |
|
continue |
|
|
|
if (words[0] == "EVENT"): |
|
if (len(words) != 3): |
|
error_arg_count(line) |
|
event_list.append((words[1], words[2])) |
|
continue |
|
|
|
if (words[0] == "SEMA"): |
|
if (len(words) != 2): |
|
error_arg_count(line) |
|
sema_list.append((words[1],)) |
|
continue |
|
|
|
if (words[0] == "MUTEX"): |
|
if (len(words) != 2): |
|
error_arg_count(line) |
|
mutex_list.append((words[1],)) |
|
continue |
|
|
|
if (words[0] == "FIFO"): |
|
if (len(words) != 4): |
|
error_arg_count(line) |
|
fifo_list.append((words[1], int(words[2]), int(words[3]))) |
|
continue |
|
|
|
if (words[0] == "PIPE"): |
|
if (len(words) != 3): |
|
error_arg_count(line) |
|
pipe_list.append((words[1], int(words[2]))) |
|
continue |
|
|
|
if (words[0] == "MAILBOX"): |
|
if (len(words) != 2): |
|
error_arg_count(line) |
|
mbx_list.append((words[1],)) |
|
continue |
|
|
|
if (words[0] == "MAP"): |
|
if (len(words) != 4): |
|
error_arg_count(line) |
|
map_list.append((words[1], int(words[2]), int(words[3]))) |
|
continue |
|
|
|
if (words[0] == "POOL"): |
|
if (len(words) != 5): |
|
error_arg_count(line) |
|
pool_list.append((words[1], int(words[2]), int(words[3]), |
|
int(words[4]))) |
|
continue |
|
|
|
if (words[0] == "HEAP_SIZE"): |
|
if (len(words) != 2): |
|
error_arg_count(line) |
|
heap_size = int(words[1]) |
|
heap_pos_in_pool_list = len(pool_list) |
|
pool_list.append(("_HEAP_MEM_POOL", MIN_HEAP, heap_size, 1)) |
|
continue |
|
|
|
sysgen_error("unrecognized keyword %s on following line\n%s" % |
|
(words[0], line)) |
|
|
|
|
|
|
|
# |
|
# GENERATE kernel_main.c FILE |
|
# |
|
|
|
|
|
kernel_main_c_data = "" |
|
|
|
kernel_main_c_filename_str = \ |
|
"/* kernel_main.c - microkernel objects */\n\n" |
|
|
|
|
|
def kernel_main_c_out(string): |
|
""" Append a string to kernel_main.c """ |
|
|
|
global kernel_main_c_data |
|
kernel_main_c_data += string |
|
|
|
|
|
def kernel_main_c_header(): |
|
""" Generate initial portion of kernel_main.c """ |
|
|
|
kernel_main_c_out( |
|
kernel_main_c_filename_str + |
|
copyright + |
|
do_not_edit_warning + |
|
"\n" + |
|
"#include <sysgen.h>\n" + |
|
"#include <misc/debug/object_tracing_common.h>\n" + |
|
"#include <micro_private_types.h>\n" + |
|
"#include <kernel_main.h>\n" + |
|
"#include <toolchain.h>\n" + |
|
"#include <sections.h>\n") |
|
|
|
|
|
def kernel_main_c_kargs(): |
|
""" Generate command packet variables """ |
|
|
|
# command packets |
|
|
|
kernel_main_c_out("\n" + |
|
"struct k_args _k_server_command_packets[%s] =\n" % (num_kargs) + |
|
"{\n" + |
|
" {NULL, NULL, 0, 0, _K_SVC_UNDEFINED},\n") |
|
for i in range(1, num_kargs - 1): |
|
kernel_main_c_out( |
|
" {&_k_server_command_packets[%d], " % (i - 1) + |
|
"NULL, 0, 0, _K_SVC_UNDEFINED},\n") |
|
kernel_main_c_out( |
|
" {&_k_server_command_packets[%d], " % (num_kargs - 2) + |
|
"NULL, 0, 0, _K_SVC_UNDEFINED}\n" + |
|
"};\n") |
|
|
|
# linked list of free command packets |
|
|
|
kernel_main_c_out("\n" + |
|
"struct nano_lifo _k_server_command_packet_free = " + |
|
"{{NULL, &_k_server_command_packet_free.wait_q.head}, " + |
|
"(void *) &_k_server_command_packets[%d]};\n" % (num_kargs - 1)) |
|
|
|
|
|
def kernel_main_c_timers(): |
|
""" Generate timer system variables """ |
|
|
|
if (num_timers == 0): |
|
return |
|
|
|
# timer descriptors |
|
|
|
kernel_main_c_out("\n" + |
|
"struct k_timer _k_timer_blocks[%d] =\n" % (num_timers) + |
|
"{\n" + |
|
" {NULL, NULL, 0, 0, (struct k_args *)0xffffffff},\n") |
|
for i in range(1, num_timers - 1): |
|
kernel_main_c_out( |
|
" {&_k_timer_blocks[%d], " % (i - 1) + |
|
"NULL, 0, 0, (struct k_args *)0xffffffff},\n") |
|
kernel_main_c_out( |
|
" {&_k_timer_blocks[%d], " % (num_timers - 2) + |
|
"NULL, 0, 0, (struct k_args *)0xffffffff}\n" + |
|
"};\n") |
|
|
|
# linked list of free timers |
|
|
|
kernel_main_c_out("\n" + |
|
"struct nano_lifo _k_timer_free = " + |
|
"{{NULL, &_k_timer_free.wait_q.head}, " + |
|
"(void *) &_k_timer_blocks[%d]};\n" % (num_timers - 1)) |
|
|
|
|
|
def kernel_main_c_tasks(): |
|
""" Generate task variables """ |
|
|
|
global num_prios |
|
|
|
# task stack areas |
|
|
|
kernel_main_c_out("\n") |
|
for task in task_list: |
|
kernel_main_c_out("char __noinit __stack __%s_stack[%d];\n" % |
|
(task[0], task[3])) |
|
|
|
kernel_main_c_out("extern char main_task_stack[CONFIG_MAIN_STACK_SIZE];\n") |
|
|
|
# declare task entry points |
|
|
|
kernel_main_c_out("\n") |
|
for task in task_list: |
|
kernel_main_c_out("EXTERN_C void %s(void);\n" % task[2]) |
|
|
|
# task descriptors (including one for idle task) |
|
# |
|
# compiler puts these objects into the section as if |
|
# it is a stack. hence the need to reverse the list. |
|
# this is to preseve the order defined in MDEF file. |
|
|
|
kernel_main_c_out("\n") |
|
for task in reversed(task_list): |
|
name = task[0] |
|
prio = task[1] |
|
entry = task[2] |
|
size = task[3] |
|
obj_name = "_k_task_obj_%s" % (name) |
|
|
|
stack = "__" + task[0] + "_stack" |
|
|
|
# create bitmask of group(s) task belongs to |
|
group_bitmask = 0 |
|
group_set = task[4][1:len(task[4]) - 1] # drop [] surrounding groups |
|
if (group_set != ""): |
|
group_list = group_set.split(',') |
|
for group in group_list: |
|
group_bitmask |= group_dictionary[group] |
|
|
|
# invert bitmask to convert SYS indication to non-SYS indication |
|
# |
|
# NOTE: There actually is no SYS group; instead, there is a non-SYS |
|
# group that all tasks belong to unless they specify the 'SYS' name. |
|
# This approach allows the kernel to easily suspend all non-SYS tasks |
|
# during debugging, while minimizing the number of task entries that |
|
# have to explicitly indicate their SYS/non-SYS status. |
|
group_bitmask ^= group_dictionary['SYS'] |
|
|
|
kernel_main_c_out( |
|
"struct k_task %s " % (obj_name)+ |
|
"__in_section(_k_task_list, public, task) =\n" + |
|
" {NULL, NULL, %d, (ktask_t)&%s,\n" % (prio, obj_name) + |
|
" 0x00000001, %#010x,\n" % (group_bitmask) + |
|
" %s, %s, %d,\n" % (entry, stack, size) + |
|
" (taskabortfunction)NULL, NULL};\n" + |
|
"ktask_t _k_task_ptr_%s " % (name) + |
|
" __in_section(_k_task_ptr, public, task) = " + |
|
" (ktask_t)&%s;\n" % (obj_name)) |
|
|
|
kernel_main_c_out( |
|
"struct k_task _k_task_idle " + |
|
"__in_section(_k_task_list, idle, task) =\n" + |
|
" {NULL, NULL, %d, 0x00000000,\n" % (num_prios - 1) + |
|
" 0x00000000, 0x00000000,\n" + |
|
" (taskstartfunction)NULL, main_task_stack,\n" |
|
" CONFIG_MAIN_STACK_SIZE,\n" + |
|
" (taskabortfunction)NULL, NULL};\n" + |
|
"ktask_t _k_task_ptr_idle " + |
|
" __in_section(_k_task_ptr, idle, task) = " + |
|
" (ktask_t)&_k_task_idle;\n") |
|
|
|
# currently scheduled task (idle task) |
|
|
|
kernel_main_c_out("\n" + |
|
"struct k_task * _k_current_task = &_k_task_idle;\n") |
|
|
|
|
|
def kernel_main_c_priorities(): |
|
""" Generate task scheduling variables """ |
|
|
|
global num_prios |
|
|
|
total_tasks = len(task_list) + 1 |
|
|
|
# priority queue descriptors (lowest priority queue contains idle task) |
|
|
|
kernel_main_c_out("\n" + |
|
"struct k_tqhd _k_task_priority_list[%d] =\n" % (num_prios) + |
|
"{\n") |
|
for i in range(1, num_prios): |
|
kernel_main_c_out( |
|
" {NULL, (struct k_task *)&_k_task_priority_list[%d]},\n" % |
|
(i - 1)) |
|
kernel_main_c_out( |
|
" {&_k_task_idle, &_k_task_idle}\n" + |
|
"};\n") |
|
|
|
# active priority queue (idle task's queue) |
|
|
|
kernel_main_c_out("\n" + |
|
"struct k_tqhd * K_Prio = &_k_task_priority_list[%d];\n" % |
|
(num_prios - 1)) |
|
|
|
# priority queue bit map (indicates which priority queues are non-empty; |
|
# initially only the idle task's queue has a runnable task) |
|
|
|
num_bit_maps = ((num_prios + 31) // 32) |
|
|
|
kernel_main_c_out("\n" + |
|
"uint32_t _k_task_priority_bitmap[%d] = {" % (num_bit_maps)) |
|
for i in range(1, num_bit_maps): |
|
kernel_main_c_out("0, ") |
|
kernel_main_c_out("(1u << %d)};\n" % ((num_prios - 1) & 0x1f)) |
|
|
|
|
|
def kernel_main_c_events(): |
|
""" Generate event variables """ |
|
|
|
global num_task_irqs |
|
|
|
# event descriptors |
|
|
|
# pre-defined event for timer |
|
if (num_timers > 0): |
|
kernel_main_c_out("DEFINE_EVENT(TICK_EVENT, _k_ticker);\n") |
|
else: |
|
kernel_main_c_out("DEFINE_EVENT(TICK_EVENT, NULL);\n") |
|
|
|
# project-specific events |
|
for event in event_list: |
|
|
|
# if there is a handler function, it needs to be declared |
|
# before setting up the object via DEFINE_EVENT() |
|
# |
|
# in other words, no declaration if handler is NULL or 0 |
|
handler = event[1].strip().lower() |
|
if handler != "null" and handler != "0": |
|
kernel_main_c_out("extern int %s(int event);\n" % (event[1])) |
|
|
|
kernel_main_c_out("DEFINE_EVENT(%s, %s);\n" % (event[0], event[1])) |
|
|
|
if (event[0].startswith("_TaskIrqEvt")): |
|
num_task_irqs += 1 |
|
|
|
if (num_task_irqs > 0): |
|
kernel_main_c_out("const kevent_t _TaskIrqEvt_objIds[] = {\n") |
|
|
|
for i in range(0, num_task_irqs): |
|
kernel_main_c_out( |
|
" (kevent_t)&_k_event_obj__TaskIrqEvt%d,\n" % (i) |
|
) |
|
|
|
kernel_main_c_out("};\n") |
|
|
|
|
|
def kernel_main_c_mutexes(): |
|
""" Generate mutex variables """ |
|
|
|
total_mutexes = len(mutex_list) |
|
|
|
if (total_mutexes == 0): |
|
return |
|
|
|
# mutex descriptors |
|
|
|
kernel_main_c_out("\n") |
|
for mutex in mutex_list: |
|
name = mutex[0] |
|
kernel_main_c_out("struct _k_mutex_struct _k_mutex_obj_%s = " % (name) + |
|
"__MUTEX_DEFAULT;\n") |
|
|
|
|
|
def kernel_main_c_semas(): |
|
""" Generate semaphore variables """ |
|
|
|
total_semas = len(sema_list) |
|
|
|
if (total_semas == 0): |
|
return |
|
|
|
# semaphore descriptors |
|
|
|
kernel_main_c_out("\n") |
|
for semaphore in sema_list: |
|
name = semaphore[0] |
|
kernel_main_c_out("struct _k_sem_struct _k_sem_obj_%s = " % (name) + |
|
"__K_SEMAPHORE_DEFAULT;\n") |
|
|
|
|
|
def kernel_main_c_fifos(): |
|
""" Generate FIFO variables """ |
|
|
|
total_fifos = len(fifo_list) |
|
|
|
if (total_fifos == 0): |
|
return |
|
|
|
# FIFO buffers |
|
|
|
kernel_main_c_out("\n") |
|
|
|
for fifo in fifo_list: |
|
kernel_main_c_out( |
|
"char __noinit __%s_buffer[%d];\n" % (fifo[0], fifo[1] * fifo[2])) |
|
|
|
# FIFO descriptors |
|
|
|
kernel_main_c_out("\n") |
|
for fifo in fifo_list: |
|
name = fifo[0] |
|
depth = fifo[1] |
|
width = fifo[2] |
|
buffer = "__" + fifo[0] + "_buffer" |
|
kernel_main_c_out("struct _k_fifo_struct _k_fifo_obj_%s = " % (name) + |
|
"__K_FIFO_DEFAULT(%d, %d, %s);\n" % (depth, width, buffer)) |
|
kernel_main_c_out("\n") |
|
|
|
|
|
def kernel_main_c_pipes(): |
|
""" Generate pipe variables """ |
|
|
|
total_pipes = len(pipe_list) |
|
|
|
if (total_pipes == 0): |
|
return |
|
|
|
# pipe buffers |
|
|
|
kernel_main_c_out("\n") |
|
|
|
for pipe in pipe_list: |
|
kernel_main_c_out( |
|
"char __noinit __%s_buffer[%d];\n" % (pipe[0], pipe[1])) |
|
|
|
# pipe descriptors |
|
|
|
for pipe in pipe_list: |
|
name = pipe[0] |
|
size = pipe[1] |
|
buffer = "__" + pipe[0] + "_buffer" |
|
kernel_main_c_out("struct _k_pipe_struct _k_pipe_obj_%s = " % (name) + |
|
" __K_PIPE_INITIALIZER(%d, %s);\n" % (size, buffer) + |
|
"kpipe_t _k_pipe_ptr_%s " % (name) + |
|
" __in_section(_k_pipe_ptr, public, pipe) =\n" + |
|
" (kpipe_t)&_k_pipe_obj_%s;\n" % (name)) |
|
|
|
|
|
def kernel_main_c_mailboxes(): |
|
""" Generate mailbox variables """ |
|
|
|
total_mbxs = len(mbx_list) |
|
|
|
if (total_mbxs == 0): |
|
return |
|
|
|
# mailbox descriptors |
|
|
|
kernel_main_c_out("\n") |
|
for mbx in mbx_list: |
|
name = mbx[0] |
|
kernel_main_c_out("struct _k_mbox_struct _k_mbox_obj_%s = " % (name) + |
|
"__K_MAILBOX_DEFAULT;\n") |
|
kernel_main_c_out("\n") |
|
|
|
|
|
def kernel_main_c_maps(): |
|
""" Generate memory map variables """ |
|
|
|
total_maps = len(map_list) |
|
|
|
if (total_maps == 0): |
|
return |
|
|
|
# memory map buffers |
|
|
|
kernel_main_c_out("\n") |
|
|
|
for map in map_list: |
|
blocks = map[1] |
|
block_size = map[2] |
|
kernel_main_c_out("char __noinit __MAP_%s_buffer[%d];\n" % |
|
(map[0], blocks * block_size)) |
|
|
|
# memory map descriptors |
|
|
|
for map in map_list: |
|
name = map[0] |
|
blocks = map[1] |
|
block_size = map[2] |
|
kernel_main_c_out( |
|
"struct _k_mem_map_struct _k_mem_map_obj_%s = " % (name) + |
|
" __K_MEM_MAP_INITIALIZER(%d, %d, __MAP_%s_buffer);\n" % |
|
(blocks, block_size, map[0]) + |
|
"kmemory_map_t _k_mem_map_ptr_%s " % (name) + |
|
" __in_section(_k_mem_map_ptr, public, mem_map) =\n" + |
|
" (kmemory_map_t)&_k_mem_map_obj_%s;\n" % (name)) |
|
|
|
|
|
def kernel_main_c_pools(): |
|
""" Generate memory pool variables """ |
|
global heap_pos_in_pool_list |
|
|
|
total_pools = len(pool_list) |
|
|
|
# pool global variables |
|
|
|
kernel_main_c_out("\nint _k_mem_pool_count = %d;\n" % (total_pools)) |
|
|
|
if (total_pools == 0): |
|
kernel_main_c_out("\nstruct pool_struct * _k_mem_pool_list = NULL;\n") |
|
return |
|
# Heap pool if present can be indexed using the below variable |
|
if (heap_pos_in_pool_list != -1): |
|
kernel_main_c_out("\nconst kmemory_pool_t _heap_mem_pool_id = %d;\n" \ |
|
%(heap_pos_in_pool_list)) |
|
|
|
# start accumulating memory pool descriptor info |
|
|
|
pool_descriptors = "\nstruct pool_struct _k_mem_pool_list[%d] =\n{\n" % \ |
|
(total_pools) |
|
ident = 0x00010000 |
|
|
|
for pool in pool_list: |
|
|
|
kernel_main_c_out("\n") |
|
|
|
# create local variables relating to current pool |
|
|
|
min_block_size = pool[1] |
|
max_block_size = pool[2] |
|
num_maximal_blocks = pool[3] |
|
total_memory = max_block_size * num_maximal_blocks |
|
buffer = "__" + pool[0] + "_buffer" |
|
frag_table = "fragtab_%#010x" % ident |
|
|
|
# determine block sizes used by pool (including actual minimum size) |
|
|
|
frag_size_list = [max_block_size] |
|
while (ident != 0): # loop forever |
|
min_block_size_actual = frag_size_list[len(frag_size_list) - 1] |
|
min_block_size_proposed = min_block_size_actual / 4 |
|
if (min_block_size_proposed < min_block_size): |
|
break |
|
frag_size_list.append(min_block_size_proposed) |
|
frag_levels = len(frag_size_list) |
|
|
|
# determine size of block status arrays |
|
# - largest size gets special handling |
|
# - remainder of algorithm is a complete mystery ... |
|
|
|
block_status_sizes = [(num_maximal_blocks + 3) / 4] |
|
block_status_size_to_use = num_maximal_blocks |
|
for index in range(1, frag_levels): |
|
block_status_sizes.append(block_status_size_to_use) |
|
block_status_size_to_use *= 4 |
|
|
|
# generate block status areas |
|
|
|
for index in range(0, frag_levels): |
|
kernel_main_c_out( |
|
"struct block_stat blockstatus_%#010x_%d[%d];\n" % |
|
(ident, index, block_status_sizes[index])) |
|
|
|
# generate memory pool fragmentation descriptor |
|
|
|
kernel_main_c_out("\nstruct pool_block %s[%d] =\n{\n" % |
|
(frag_table, frag_levels)) |
|
for index in range(0, frag_levels): |
|
kernel_main_c_out(" { %d, %d, blockstatus_%#010x_%d},\n" % |
|
(frag_size_list[index], block_status_sizes[index], |
|
ident, index)) |
|
kernel_main_c_out("};\n") |
|
|
|
# generate memory pool buffer |
|
|
|
kernel_main_c_out("\nchar __noinit %s[%d];\n" % (buffer, total_memory)) |
|
|
|
# append memory pool descriptor info |
|
|
|
pool_descriptors += " {%d, %d, 2, %d, %d, %d, NULL, %s, %s},\n" % \ |
|
(max_block_size, min_block_size_actual, total_memory, |
|
num_maximal_blocks, frag_levels, frag_table, buffer) |
|
|
|
ident += 1 |
|
|
|
# generate memory pool descriptor info |
|
|
|
pool_descriptors += "};\n" |
|
kernel_main_c_out(pool_descriptors) |
|
|
|
|
|
def kernel_main_c_node_init(): |
|
""" Generate node initialization routine """ |
|
|
|
kernel_main_c_out("\n" + |
|
"void _k_init_dynamic(void)\n{\n") |
|
kernel_main_c_out(" _k_pipe_init();\n") |
|
kernel_main_c_out(" _k_mem_map_init();\n") |
|
if (len(pool_list) > 0): |
|
kernel_main_c_out(" _k_mem_pool_init();\n") |
|
|
|
kernel_main_c_out("#ifdef CONFIG_DEBUG_TRACING_KERNEL_OBJECTS\n") |
|
# mutex object ids |
|
for mutex in mutex_list: |
|
name = mutex[0] |
|
kernel_main_c_out("\tSYS_TRACING_OBJ_INIT(micro_mutex, " + |
|
"&_k_mutex_obj_%s);\n" % (name)) |
|
# semaphore object ids |
|
for semaphore in sema_list: |
|
name = semaphore[0] |
|
kernel_main_c_out("\tSYS_TRACING_OBJ_INIT(micro_sem, " + |
|
"&_k_sem_obj_%s);\n" % (name)) |
|
# fifo object ids |
|
for fifo in fifo_list: |
|
name = fifo[0] |
|
kernel_main_c_out("\tSYS_TRACING_OBJ_INIT(micro_fifo, " + |
|
"&_k_fifo_obj_%s);\n" % (name)) |
|
# mailbox object ids |
|
for mbx in mbx_list: |
|
name = mbx[0] |
|
kernel_main_c_out("\tSYS_TRACING_OBJ_INIT(micro_mbox, " + |
|
"&_k_mbox_obj_%s);\n" % (name)) |
|
# pipe object id |
|
for pipe in pipe_list: |
|
name = pipe[0]; |
|
kernel_main_c_out("\tSYS_TRACING_OBJ_INIT(micro_pipe, " + |
|
"&_k_pipe_obj_%s);\n" % (name)) |
|
# memory map object id |
|
for map in map_list: |
|
name = map[0]; |
|
kernel_main_c_out("\tSYS_TRACING_OBJ_INIT(micro_mem_map, " + |
|
"&_k_mem_map_obj_%s);\n" % (name)) |
|
# memory pool object id |
|
pool_count = 0; |
|
total_pools = len(pool_list); |
|
while (pool_count < total_pools): |
|
kernel_main_c_out("\tSYS_TRACING_OBJ_INIT(micro_mem_pool, " + |
|
"&(_k_mem_pool_list[%d]));\n" % (pool_count)) |
|
pool_count = pool_count + 1; |
|
|
|
# event map object id |
|
for event in event_list: |
|
# no need to expose the irq task events |
|
if not (event[0].startswith("_TaskIrqEvt")): |
|
name = event[0]; |
|
kernel_main_c_out("\tSYS_TRACING_OBJ_INIT(micro_event, " + |
|
"&_k_event_obj_%s);\n" % (name)) |
|
|
|
kernel_main_c_out("#endif\n") |
|
|
|
kernel_main_c_out("}\n") |
|
|
|
|
|
def kernel_main_c_generate(): |
|
""" Generate kernel_main.c file """ |
|
|
|
global kernel_main_c_data |
|
|
|
kernel_main_c_header() |
|
kernel_main_c_kargs() |
|
kernel_main_c_timers() |
|
kernel_main_c_tasks() |
|
kernel_main_c_priorities() |
|
kernel_main_c_events() |
|
kernel_main_c_mutexes() |
|
kernel_main_c_semas() |
|
kernel_main_c_fifos() |
|
kernel_main_c_pipes() |
|
kernel_main_c_mailboxes() |
|
kernel_main_c_maps() |
|
kernel_main_c_pools() |
|
kernel_main_c_node_init() |
|
|
|
write_file(output_dir + 'kernel_main.c', kernel_main_c_data) |
|
|
|
|
|
# |
|
# GENERATE kernel_main.h FILE |
|
# |
|
|
|
|
|
def kernel_main_h_generate(): |
|
""" Generate kernel_main.h file """ |
|
|
|
global output_dir |
|
|
|
subprocess.check_call([ |
|
"cp", |
|
"-f", |
|
os.environ["ZEPHYR_BASE"] + |
|
"/kernel/microkernel/include/kernel_main.h", |
|
output_dir]) |
|
|
|
|
|
# |
|
# GENERATE micro_private_types.h FILE |
|
# |
|
|
|
|
|
def micro_private_types_h_generate(): |
|
""" Generate micro_private_types.h file """ |
|
|
|
global output_dir |
|
|
|
subprocess.check_call([ |
|
"cp", |
|
"-f", |
|
os.environ["ZEPHYR_BASE"] + |
|
"/kernel/microkernel/include/micro_private_types.h", |
|
output_dir]) |
|
|
|
|
|
# |
|
# GENERATE sysgen.h FILE |
|
# |
|
|
|
|
|
sysgen_h_data = "" |
|
|
|
sysgen_h_filename_str = \ |
|
"/* sysgen.h - system generated microkernel definitions */\n\n" |
|
|
|
sysgen_h_include_guard = "_SYSGEN__H_" |
|
|
|
sysgen_h_header_include_guard_str = \ |
|
"#ifndef " + sysgen_h_include_guard + "\n" \ |
|
"#define " + sysgen_h_include_guard + "\n\n" |
|
|
|
|
|
def generate_sysgen_h_header(): |
|
|
|
global sysgen_h_data |
|
sysgen_h_data += \ |
|
sysgen_h_filename_str + \ |
|
copyright + \ |
|
do_not_edit_warning + \ |
|
"#include <microkernel.h>\n" + \ |
|
sysgen_h_header_include_guard_str + \ |
|
"\n" |
|
|
|
|
|
def generate_taskgroup_line(taskgroup, group_id): |
|
|
|
global sysgen_h_data |
|
sysgen_h_data += \ |
|
"#define " + taskgroup + " 0x%8.8x\n" % group_id |
|
|
|
|
|
def generate_sysgen_h_taskgroups(): |
|
|
|
global sysgen_h_data |
|
|
|
for group in group_key_list: |
|
generate_taskgroup_line(group, group_dictionary[group]) |
|
|
|
sysgen_h_data += "\n" |
|
|
|
|
|
def generate_obj_id_line(name, obj_id): |
|
|
|
return "#define " + name + " 0x0001%4.4x\n" % obj_id |
|
|
|
|
|
def generate_obj_id_lines(obj_types): |
|
|
|
data = "" |
|
for obj_type in obj_types: |
|
for obj in obj_type[0]: |
|
data += generate_obj_id_line(str(obj[0]), obj_type[1]) |
|
obj_type[1] += 1 |
|
if obj_type[1] > 0: |
|
data += "\n" |
|
|
|
return data |
|
|
|
|
|
def generate_sysgen_h_obj_ids(): |
|
|
|
global sysgen_h_data |
|
global num_task_irqs |
|
|
|
# mutex object ids |
|
|
|
sysgen_h_data += "\n" |
|
for mutex in mutex_list: |
|
name = mutex[0] |
|
sysgen_h_data += \ |
|
"extern struct _k_mutex_struct _k_mutex_obj_%s;\n" % (name) |
|
sysgen_h_data += \ |
|
"#define %s ((kmutex_t)&_k_mutex_obj_%s)\n\n" % (name, name) |
|
|
|
# semaphore object ids |
|
|
|
sysgen_h_data += "\n" |
|
for semaphore in sema_list: |
|
name = semaphore[0] |
|
sysgen_h_data += \ |
|
"extern struct _k_sem_struct _k_sem_obj_%s;\n" % (name) |
|
sysgen_h_data += \ |
|
"#define %s ((ksem_t)&_k_sem_obj_%s)\n\n" % (name, name) |
|
|
|
# fifo object ids |
|
|
|
sysgen_h_data += "\n" |
|
for fifo in fifo_list: |
|
name = fifo[0] |
|
sysgen_h_data += \ |
|
"extern struct _k_fifo_struct _k_fifo_obj_%s;\n" % (name) |
|
sysgen_h_data += \ |
|
"#define %s ((kfifo_t)&_k_fifo_obj_%s)\n\n" % (name, name) |
|
|
|
# mailbox object ids |
|
|
|
sysgen_h_data += "\n" |
|
for mbx in mbx_list: |
|
name = mbx[0] |
|
sysgen_h_data += \ |
|
"extern struct _k_mbox_struct _k_mbox_obj_%s;\n" % (name) |
|
sysgen_h_data += \ |
|
"#define %s ((kmbox_t)&_k_mbox_obj_%s)\n\n" % (name, name) |
|
|
|
# pipe object id |
|
|
|
sysgen_h_data += "\n" |
|
for pipe in pipe_list: |
|
name = pipe[0]; |
|
sysgen_h_data += \ |
|
"extern struct _k_pipe_struct _k_pipe_obj_%s;\n" % (name) + \ |
|
"#define %s ((kpipe_t)&_k_pipe_obj_%s)\n\n" % (name, name) |
|
|
|
# memory map object id |
|
|
|
sysgen_h_data += "\n" |
|
for map in map_list: |
|
name = map[0]; |
|
sysgen_h_data += \ |
|
"extern struct _k_mem_map_struct _k_mem_map_obj_%s;\n" % (name) + \ |
|
"#define %s ((kmemory_map_t)&_k_mem_map_obj_%s)\n" % (name, name) |
|
|
|
# task object id |
|
|
|
sysgen_h_data += "\n" |
|
for task in task_list: |
|
name = task[0]; |
|
sysgen_h_data += \ |
|
"extern struct k_task _k_task_obj_%s;\n" % (name) + \ |
|
"#define %s ((ktask_t)&_k_task_obj_%s)\n" % (name, name) |
|
|
|
# event object id |
|
|
|
sysgen_h_data += "\n" |
|
for event in event_list: |
|
# no need to expose the irq task events |
|
if not (event[0].startswith("_TaskIrqEvt")): |
|
name = event[0]; |
|
sysgen_h_data += \ |
|
"extern const kevent_t %s;\n" % (name) |
|
|
|
# all other object ids |
|
|
|
obj_types = [ |
|
[pool_list, 0], |
|
] |
|
sysgen_h_data += generate_obj_id_lines(obj_types) |
|
|
|
|
|
sysgen_h_footer_include_guard_str = \ |
|
"\n#endif /* " + sysgen_h_include_guard + " */\n" |
|
|
|
|
|
def generate_sysgen_h_footer(): |
|
|
|
global sysgen_h_data |
|
sysgen_h_data += \ |
|
sysgen_h_footer_include_guard_str |
|
|
|
|
|
def sysgen_h_generate(): |
|
""" Generate sysgen.h file """ |
|
|
|
generate_sysgen_h_header() |
|
generate_sysgen_h_taskgroups() |
|
generate_sysgen_h_obj_ids() |
|
generate_sysgen_h_footer() |
|
|
|
write_file(output_dir + 'sysgen.h', sysgen_h_data) |
|
|
|
|
|
# |
|
# SYSTEM GENERATOR MAINLINE |
|
# |
|
|
|
|
|
mdef_parse() |
|
get_output_dir() |
|
kernel_main_c_generate() |
|
kernel_main_h_generate() |
|
micro_private_types_h_generate() |
|
sysgen_h_generate()
|
|
|