mirror of
https://github.com/kelvinlawson/atomthreads.git
synced 2026-08-02 04:20:06 +02:00
Initial port of MIPS architecture.
Completely untested. Shouldn't be merged to master. Signed-off-by: Himanshu Chauhan <hschauhan@nulltrace.org>
This commit is contained in:
1161
ports/mips/Doxyfile
Normal file
1161
ports/mips/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
107
ports/mips/Makefile
Normal file
107
ports/mips/Makefile
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
############
|
||||||
|
# Settings #
|
||||||
|
############
|
||||||
|
|
||||||
|
# Build all test applications:
|
||||||
|
# make
|
||||||
|
#
|
||||||
|
# Program a test application using UISP (appname => test app e.g. sems1):
|
||||||
|
# make program app=appname
|
||||||
|
|
||||||
|
# Location of build tools and atomthreads sources
|
||||||
|
KERNEL_DIR=../../kernel
|
||||||
|
TESTS_DIR=../../tests
|
||||||
|
CC=mips-linux-gnu-gcc
|
||||||
|
OBJCOPY=mips-linux-gnu-objcopy
|
||||||
|
|
||||||
|
# Enable stack-checking. WARNING: the full automated test suite currently
|
||||||
|
# requires a little over 1KB RAM with stack-checking enabled. If you are
|
||||||
|
# using a device with 1KB internal SRAM and no external SRAM then you
|
||||||
|
# must disable stack-checking to run all of the automated tests.
|
||||||
|
#STACK_CHECK=true
|
||||||
|
|
||||||
|
# Directory for built objects
|
||||||
|
BUILD_DIR=build
|
||||||
|
|
||||||
|
# Port/application object files
|
||||||
|
APP_OBJECTS = atomport.o test-main.o
|
||||||
|
APP_ASM_OBJECTS = atomport-asm.o atomport-entry.o
|
||||||
|
|
||||||
|
# Kernel object files
|
||||||
|
KERNEL_OBJECTS = atomkernel.o atomsem.o atommutex.o atomtimer.o atomqueue.o
|
||||||
|
|
||||||
|
# Collection of built objects (excluding test applications)
|
||||||
|
ALL_OBJECTS = $(APP_OBJECTS) $(APP_ASM_OBJECTS) $(KERNEL_OBJECTS)
|
||||||
|
BUILT_OBJECTS = $(patsubst %,$(BUILD_DIR)/%,$(ALL_OBJECTS))
|
||||||
|
|
||||||
|
# Test object files (dealt with separately as only one per application build)
|
||||||
|
TEST_OBJECTS = $(notdir $(patsubst %.c,%.o,$(wildcard $(TESTS_DIR)/*.c)))
|
||||||
|
|
||||||
|
# Target application filenames (.elf and .hex) for each test object
|
||||||
|
TEST_ELFS = $(patsubst %.o,%.elf,$(TEST_OBJECTS))
|
||||||
|
TEST_HEXS = $(patsubst %.o,%.hex,$(TEST_OBJECTS))
|
||||||
|
|
||||||
|
# Search build/output directory for dependencies
|
||||||
|
vpath %.o ./$(BUILD_DIR)
|
||||||
|
vpath %.elf ./$(BUILD_DIR)
|
||||||
|
vpath %.hex ./$(BUILD_DIR)
|
||||||
|
|
||||||
|
# GCC flags
|
||||||
|
CFLAGS=-g -Wall -Werror
|
||||||
|
|
||||||
|
# Enable stack-checking (disable if not required)
|
||||||
|
ifeq ($(STACK_CHECK),true)
|
||||||
|
CFLAGS += -DATOM_STACK_CHECKING
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
#################
|
||||||
|
# Build targets #
|
||||||
|
#################
|
||||||
|
|
||||||
|
# All tests
|
||||||
|
all: $(BUILD_DIR) $(TEST_HEXS) Makefile
|
||||||
|
|
||||||
|
# Make build/output directory
|
||||||
|
$(BUILD_DIR):
|
||||||
|
mkdir $(BUILD_DIR)
|
||||||
|
|
||||||
|
# Test HEX files (one application build for each test)
|
||||||
|
$(TEST_HEXS): %.hex: %.elf
|
||||||
|
@echo Building $@
|
||||||
|
$(OBJCOPY) -j .text -j .data -O ihex $(BUILD_DIR)/$< $(BUILD_DIR)/$@
|
||||||
|
|
||||||
|
# Test ELF files (one application build for each test)
|
||||||
|
$(TEST_ELFS): %.elf: %.o $(KERNEL_OBJECTS) $(APP_OBJECTS) $(APP_ASM_OBJECTS)
|
||||||
|
$(CC) $(CFLAGS) $(BUILD_DIR)/$(notdir $<) $(BUILT_OBJECTS) --output $(BUILD_DIR)/$@ -Wl,-Map,$(BUILD_DIR)/$(basename $@).map
|
||||||
|
|
||||||
|
# Kernel objects builder
|
||||||
|
$(KERNEL_OBJECTS): %.o: $(KERNEL_DIR)/%.c
|
||||||
|
$(CC) -c $(CFLAGS) -I. $< -o $(BUILD_DIR)/$(notdir $@)
|
||||||
|
|
||||||
|
# Test objects builder
|
||||||
|
$(TEST_OBJECTS): %.o: $(TESTS_DIR)/%.c
|
||||||
|
$(CC) -c $(CFLAGS) -I. -I$(KERNEL_DIR) $< -o $(BUILD_DIR)/$(notdir $@)
|
||||||
|
|
||||||
|
# Application C objects builder
|
||||||
|
$(APP_OBJECTS): %.o: ./%.c
|
||||||
|
$(CC) -c $(CFLAGS) -I. -I$(KERNEL_DIR) -I$(TESTS_DIR) $< -o $(BUILD_DIR)/$(notdir $@)
|
||||||
|
|
||||||
|
# Application asm objects builder
|
||||||
|
$(APP_ASM_OBJECTS): %.o: ./%.s
|
||||||
|
$(CC) -c $(CFLAGS) -x assembler-with-cpp -I. -I$(KERNEL_DIR) $< -o $(BUILD_DIR)/$(notdir $@)
|
||||||
|
|
||||||
|
# .lst file builder
|
||||||
|
%.lst: %.c
|
||||||
|
$(CC) $(CFLAGS) -I. -I$(KERNEL_DIR) -I$(TESTS_DIR) -Wa,-al $< > $@
|
||||||
|
|
||||||
|
# Clean
|
||||||
|
clean:
|
||||||
|
rm -f *.o *.elf *.map *.hex *.bin *.lst
|
||||||
|
rm -rf doxygen-kernel
|
||||||
|
rm -rf doxygen-avr
|
||||||
|
rm -rf build
|
||||||
|
|
||||||
|
doxygen:
|
||||||
|
doxygen $(KERNEL_DIR)/Doxyfile
|
||||||
|
doxygen ./Doxyfile
|
||||||
97
ports/mips/atomport-asm.s
Normal file
97
ports/mips/atomport-asm.s
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010, Atomthreads Project. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. No personal names or organizations' names associated with the
|
||||||
|
* Atomthreads project may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <atomport-private.h>
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that performs the contextSwitch. Whether its a voluntary release
|
||||||
|
* of CPU by thread or a pre-emption, under both conditions this function is
|
||||||
|
* called. The signature is as follows:
|
||||||
|
*
|
||||||
|
* archContextSwitch(ATOM_TCB *old_tcb, ATOM_TCB *new_tcb)
|
||||||
|
*/
|
||||||
|
.globl archContextSwitch
|
||||||
|
archContextSwitch:
|
||||||
|
lw k0, 0(a0) /* assume that sp_save_ptr is always at base of ATOM_TCB */
|
||||||
|
lw k1, 0(a1)
|
||||||
|
|
||||||
|
sw s0, (s0_IDX * 4)(a0)
|
||||||
|
sw s1, (s1_IDX * 4)(a0)
|
||||||
|
sw s2, (s2_IDX * 4)(a0)
|
||||||
|
sw s3, (s3_IDX * 4)(a0)
|
||||||
|
sw s4, (s4_IDX * 4)(a0)
|
||||||
|
sw s5, (s5_IDX * 4)(a0)
|
||||||
|
sw s6, (s6_IDX * 4)(a0)
|
||||||
|
sw s7, (s7_IDX * 4)(a0)
|
||||||
|
sw s8, (s8_IDX * 4)(a0)
|
||||||
|
sw sp, (sp_IDX * 4)(a0)
|
||||||
|
sw gp, (gp_IDX * 4)(a0)
|
||||||
|
|
||||||
|
lw s0, (s0_IDX * 4)(a1)
|
||||||
|
lw s1, (s1_IDX * 4)(a1)
|
||||||
|
lw s2, (s2_IDX * 4)(a1)
|
||||||
|
lw s3, (s3_IDX * 4)(a1)
|
||||||
|
lw s4, (s4_IDX * 4)(a1)
|
||||||
|
lw s5, (s5_IDX * 4)(a1)
|
||||||
|
lw s6, (s6_IDX * 4)(a1)
|
||||||
|
lw s7, (s7_IDX * 4)(a1)
|
||||||
|
lw s8, (s8_IDX * 4)(a1)
|
||||||
|
lw sp, (sp_IDX * 4)(a1)
|
||||||
|
lw gp, (gp_IDX * 4)(a1)
|
||||||
|
|
||||||
|
j ra
|
||||||
|
nop
|
||||||
|
|
||||||
|
/**
|
||||||
|
* archFirstThreadRestore(ATOM_TCB *new_tcb)
|
||||||
|
*
|
||||||
|
* This function is responsible for restoring and starting the first
|
||||||
|
* thread the OS runs. It expects to find the thread context exactly
|
||||||
|
* as it would be if a context save had previously taken place on it.
|
||||||
|
* The only real difference between this and the archContextSwitch()
|
||||||
|
* routine is that there is no previous thread for which context must
|
||||||
|
* be saved.
|
||||||
|
*
|
||||||
|
* The final action this function must do is to restore interrupts.
|
||||||
|
*/
|
||||||
|
.globl archFirstThreadRestore
|
||||||
|
archFirstThreadRestore:
|
||||||
|
move k0, a0 /* save the copy of tcb pointer in k0 */
|
||||||
|
lw k1, 0(k0) /* Assume that sp_save_ptr is always at base of ATOM_TCB */
|
||||||
|
lw a0, (a0_IDX * 4)(k1)
|
||||||
|
lw sp, (sp_IDX * 4)(k1)
|
||||||
|
lw s8, (s8_IDX * 4)(k1)
|
||||||
|
lw k0, (ra_IDX * 4)(k1)
|
||||||
|
mtc0 k0, CP0_EPC
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
eret
|
||||||
230
ports/mips/atomport-entry.s
Normal file
230
ports/mips/atomport-entry.s
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2010 Himanshu Chauhan.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||||
|
*
|
||||||
|
* @file start.S
|
||||||
|
* @version 0.1
|
||||||
|
* @author Himanshu Chauhan (hschauhan@nulltrace.org)
|
||||||
|
* @brief 24Kc startup file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "atomport-private.h"
|
||||||
|
|
||||||
|
.extern _stack_start
|
||||||
|
.section .start.text,"ax",@progbits
|
||||||
|
|
||||||
|
EXCEPTION_VECTOR(_tlbmiss, 0x00, _handle_tlbmiss)
|
||||||
|
EXCEPTION_VECTOR(_cache_error, 0x100, _handle_cache_error)
|
||||||
|
EXCEPTION_VECTOR(_general_exception, 0x180, _handle_general_exception)
|
||||||
|
/* FIXME: We don't need this when in EIC mode. */
|
||||||
|
EXCEPTION_VECTOR(_interrupts, 0x200, _handle_interrupt)
|
||||||
|
|
||||||
|
LEAF(_start)
|
||||||
|
mtc0 ZERO, CP0_CONTEXT
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
|
||||||
|
/* globally disable interrupts until we are prepared. */
|
||||||
|
disable_global_interrupts
|
||||||
|
|
||||||
|
/* clear CPU timer counters. We don't want surprises. */
|
||||||
|
mtc0 ZERO, CP0_COMPARE
|
||||||
|
mtc0 ZERO, CP0_COUNT
|
||||||
|
|
||||||
|
/* Read number of tlb entries from config register */
|
||||||
|
bal num_tlb_entries
|
||||||
|
nop
|
||||||
|
|
||||||
|
/* initialize tlb */
|
||||||
|
bal tlb_init
|
||||||
|
move A0, V0
|
||||||
|
|
||||||
|
la SP, _stack_start /* setup the stack (bss segment) */
|
||||||
|
la T0, cpu_init
|
||||||
|
j T0 /* Call the C- code now */
|
||||||
|
nop
|
||||||
|
|
||||||
|
1: b 1b /* we should not come here whatsoever */
|
||||||
|
END(_start)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read config 1 register and return the number
|
||||||
|
* of TLB entries in this CPU.
|
||||||
|
*/
|
||||||
|
LEAF(num_tlb_entries)
|
||||||
|
mfc0 A1, CP0_CONFIG1
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
srl V0, A1, 25
|
||||||
|
and V0, V0, 0x3F
|
||||||
|
jr RA
|
||||||
|
nop
|
||||||
|
END(num_tlb_entries)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tlb_init
|
||||||
|
* Initialize the TLB to a power-up state, guaranteeing that all entries
|
||||||
|
* are unique and invalid.
|
||||||
|
* Arguments:
|
||||||
|
* a0 = Maximum TLB index (from MMUSize field of C0_Config1)
|
||||||
|
* Returns:
|
||||||
|
* No value
|
||||||
|
* Restrictions:
|
||||||
|
* This routine must be called in unmapped space
|
||||||
|
* Algorithm:
|
||||||
|
* va = kseg0_base;
|
||||||
|
* for (entry = max_TLB_index ; entry >= 0, entry--) {
|
||||||
|
* while (TLB_Probe_Hit(va)) {
|
||||||
|
* va += Page_Size;
|
||||||
|
* }
|
||||||
|
* TLB_Write(entry, va, 0, 0, 0);
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
LEAF(tlb_init)
|
||||||
|
/* Clear PageMask, EntryLo0 and EntryLo1 so that valid bits are off, PFN values
|
||||||
|
* are zero, and the default page size is used.
|
||||||
|
*/
|
||||||
|
mtc0 ZERO, CP0_ENTRYLO0
|
||||||
|
/* Clear out PFN and valid bits */
|
||||||
|
mtc0 ZERO, CP0_ENTRYLO1
|
||||||
|
mtc0 ZERO, CP0_PAGEMASK
|
||||||
|
/* Clear out mask register */
|
||||||
|
/* Start with the base address of kseg0 for the VA part of the TLB */
|
||||||
|
li T0, 0x80000000
|
||||||
|
/*
|
||||||
|
* Write the VA candidate to EntryHi and probe the TLB to see if if is
|
||||||
|
* already there. If it is, a write to the TLB may cause a machine
|
||||||
|
* check, so just increment the VA candidate by one page and try again.
|
||||||
|
*/
|
||||||
|
10:
|
||||||
|
mtc0 T0, CP0_ENTRYHI
|
||||||
|
/* Write VA candidate */
|
||||||
|
tlbp_write_hazard
|
||||||
|
/* Clear EntryHi hazard (ssnop/ehb in R1/2) */
|
||||||
|
tlbp
|
||||||
|
/* Probe the TLB to check for a match */
|
||||||
|
tlbp_read_hazard
|
||||||
|
/* Clear Index hazard (ssnop/ehb in R1/2) */
|
||||||
|
mfc0 T1, CP0_INDEX
|
||||||
|
addiu T0, (1 << S_EntryHiVPN2)
|
||||||
|
/* Read back flag to check for match */
|
||||||
|
bgez T1, 10b
|
||||||
|
nop
|
||||||
|
/* Add 1 to VPN index in va */
|
||||||
|
/*
|
||||||
|
* A write of the VPN candidate will be unique, so write this entry
|
||||||
|
* into the next index, decrement the index, and continue until the
|
||||||
|
* index goes negative (thereby writing all TLB entries)
|
||||||
|
*/
|
||||||
|
mtc0 A0, CP0_INDEX
|
||||||
|
/* Use this as next TLB index */
|
||||||
|
tlbw_write_hazard
|
||||||
|
/* Clear Index hazard (ssnop/ehb in R1/2) */
|
||||||
|
tlbwi
|
||||||
|
/* Write the TLB entry */
|
||||||
|
/* Branch if more TLB entries to do */
|
||||||
|
addiu A0, A0, -1
|
||||||
|
bne A0, ZERO, 10b
|
||||||
|
nop
|
||||||
|
|
||||||
|
/* Decrement the TLB index */
|
||||||
|
/*
|
||||||
|
* Clear Index and EntryHi simply to leave the state constant for all
|
||||||
|
* returns
|
||||||
|
*/
|
||||||
|
mtc0 ZERO, CP0_INDEX
|
||||||
|
mtc0 ZERO, CP0_ENTRYHI
|
||||||
|
jr RA
|
||||||
|
/* Return to caller */
|
||||||
|
nop
|
||||||
|
END(tlb_init)
|
||||||
|
|
||||||
|
.extern vmm_cpu_handle_pagefault
|
||||||
|
|
||||||
|
LEAF(_handle_tlbmiss)
|
||||||
|
disable_global_interrupts
|
||||||
|
move K0, SP
|
||||||
|
SAVE_INT_CONTEXT(_int_stack)
|
||||||
|
move A0, SP
|
||||||
|
bal vmm_cpu_handle_pagefault
|
||||||
|
nop
|
||||||
|
enable_global_interrupts
|
||||||
|
eret
|
||||||
|
END(_handle_tlbmiss)
|
||||||
|
|
||||||
|
.extern generic_int_handler
|
||||||
|
.extern _int_stack
|
||||||
|
.extern vmm_regs_dump
|
||||||
|
LEAF(_handle_interrupt)
|
||||||
|
disable_global_interrupts
|
||||||
|
SAVE_INT_CONTEXT(_int_stack)
|
||||||
|
move A0, SP
|
||||||
|
bal generic_int_handler
|
||||||
|
nop
|
||||||
|
RESTORE_INT_CONTEXT(SP)
|
||||||
|
enable_global_interrupts
|
||||||
|
eret
|
||||||
|
END(_handle_interrupt)
|
||||||
|
|
||||||
|
LEAF(_handle_cache_error)
|
||||||
|
b _handle_cache_error
|
||||||
|
nop
|
||||||
|
END(_handle_cache_error)
|
||||||
|
|
||||||
|
LEAF(_handle_general_exception)
|
||||||
|
//move K0, SP
|
||||||
|
//SAVE_INT_CONTEXT(_int_stack)
|
||||||
|
//bal vmm_regs_dump
|
||||||
|
//move A0, SP
|
||||||
|
|
||||||
|
b _handle_general_exception
|
||||||
|
nop
|
||||||
|
END(_handle_general_exception)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A0 -> Contains virtual address.
|
||||||
|
* A1 -> Contains physical address.
|
||||||
|
* A2 -> TLB index: If -1 select automatically.
|
||||||
|
*/
|
||||||
|
.globl create_tlb_entry
|
||||||
|
LEAF(create_tlb_entry)
|
||||||
|
mtc0 A2, CP0_INDEX /* load the tlb index to be programmed. */
|
||||||
|
srl A0, A0, 12 /* get the VPN */
|
||||||
|
sll A0, A0, 12
|
||||||
|
nop
|
||||||
|
mtc0 A0, CP0_ENTRYHI /* load VPN in entry hi */
|
||||||
|
addi T0, A1, 0x1000 /* next PFN for entry lo1 in T0 */
|
||||||
|
srl A1, A1, 12 /* get the PFN */
|
||||||
|
sll A1, A1, 6 /* get the PFN */
|
||||||
|
srl T0, T0, 12
|
||||||
|
sll T0, T0, 6
|
||||||
|
ori A1, A1, 0x7 /* mark the page writable, global and valid */
|
||||||
|
mtc0 A1, CP0_ENTRYLO0
|
||||||
|
ori T0, T0, 0x7 /* mark the next physical page writable, global and valid */
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
mtc0 T0, CP0_ENTRYLO1
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
tlbwi
|
||||||
|
ehb
|
||||||
|
j RA
|
||||||
|
nop
|
||||||
|
END(create_tlb_entry)
|
||||||
148
ports/mips/atomport-private.h
Normal file
148
ports/mips/atomport-private.h
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010, Atomthreads Project. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. No personal names or organizations' names associated with the
|
||||||
|
* Atomthreads project may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ATOMPORT_PRIVATE_H_
|
||||||
|
#define __ATOMPORT_PRIVATE_H_
|
||||||
|
|
||||||
|
#define zero $0
|
||||||
|
#define at $1
|
||||||
|
#define v0 $2
|
||||||
|
#define v1 $3
|
||||||
|
#define a0 $4
|
||||||
|
#define a1 $5
|
||||||
|
#define a2 $6
|
||||||
|
#define a3 $7
|
||||||
|
#define t0 $8
|
||||||
|
#define t1 $9
|
||||||
|
#define t2 $10
|
||||||
|
#define t3 $11
|
||||||
|
#define t4 $12
|
||||||
|
#define t5 $13
|
||||||
|
#define t6 $14
|
||||||
|
#define t7 $15
|
||||||
|
#define t8 $24
|
||||||
|
#define t9 $25
|
||||||
|
#define s0 $16
|
||||||
|
#define s1 $17
|
||||||
|
#define s2 $18
|
||||||
|
#define s3 $19
|
||||||
|
#define s4 $20
|
||||||
|
#define s5 $21
|
||||||
|
#define s6 $22
|
||||||
|
#define s7 $23
|
||||||
|
#define k0 $26
|
||||||
|
#define k1 $27
|
||||||
|
#define gp $28
|
||||||
|
#define sp $29
|
||||||
|
#define s8 $30
|
||||||
|
#define fp $30
|
||||||
|
#define ra $31
|
||||||
|
|
||||||
|
#define NUM_REGISTERS 32
|
||||||
|
#define WORD_SIZE 4
|
||||||
|
|
||||||
|
#define v0_IDX 0
|
||||||
|
#define v1_IDX 1
|
||||||
|
#define a0_IDX 2
|
||||||
|
#define a1_IDX 3
|
||||||
|
#define a2_IDX 4
|
||||||
|
#define a3_IDX 5
|
||||||
|
#define t0_IDX 6
|
||||||
|
#define t1_IDX 7
|
||||||
|
#define t2_IDX 8
|
||||||
|
#define t3_IDX 9
|
||||||
|
#define t4_IDX 10
|
||||||
|
#define t5_IDX 11
|
||||||
|
#define t6_IDX 12
|
||||||
|
#define t7_IDX 13
|
||||||
|
#define s0_IDX 14
|
||||||
|
#define s1_IDX 15
|
||||||
|
#define s2_IDX 16
|
||||||
|
#define s3_IDX 17
|
||||||
|
#define s4_IDX 18
|
||||||
|
#define s5_IDX 19
|
||||||
|
#define s6_IDX 20
|
||||||
|
#define s7_IDX 21
|
||||||
|
#define t8_IDX 22
|
||||||
|
#define t9_IDX 23
|
||||||
|
#define sp_IDX 24
|
||||||
|
#define gp_IDX 25
|
||||||
|
#define s8_IDX 26
|
||||||
|
#define ra_IDX 27
|
||||||
|
#define k0_IDX 28
|
||||||
|
#define k1_IDX 29
|
||||||
|
#define at_IDX 30
|
||||||
|
#define zero_IDX 31
|
||||||
|
|
||||||
|
#define CP0_INDEX $0
|
||||||
|
#define CP0_RANDOM $1
|
||||||
|
#define CP0_ENTRYLO0 $2
|
||||||
|
#define CP0_ENTRYLO1 $3
|
||||||
|
#define CP0_CONTEXT $4
|
||||||
|
#define CP0_PAGEMASK $5
|
||||||
|
#define CP0_WIRED $6
|
||||||
|
#define CP0_HWRENA $7
|
||||||
|
#define CP0_BADVADDR $8
|
||||||
|
#define CP0_COUNT $9
|
||||||
|
#define CP0_ENTRYHI $10
|
||||||
|
#define CP0_COMPARE $11
|
||||||
|
#define CP0_STATUS $12
|
||||||
|
#define CP0_INTCTL $12,1
|
||||||
|
#define CP0_SRSCTL $12,2
|
||||||
|
#define CP0_SRSMAP $12,3
|
||||||
|
#define CP0_CAUSE $13
|
||||||
|
#define CP0_EPC $14
|
||||||
|
#define CP0_PRID $15
|
||||||
|
#define CP0_EBASE $15,1
|
||||||
|
#define CP0_CONFIG $16
|
||||||
|
#define CP0_CONFIG1 $16,1
|
||||||
|
#define CP0_CONFIG2 $16,2
|
||||||
|
#define CP0_CONFIG3 $16,3
|
||||||
|
#define CP0_LLADDR $17
|
||||||
|
#define CP0_WATCHLO $18
|
||||||
|
#define CP0_WATCHHI $19
|
||||||
|
#define CP0_DEBUG $23
|
||||||
|
#define CP0_DEPC $24
|
||||||
|
#define CP0_PERFCTL $25,0
|
||||||
|
#define CP0_PERFCNT $25,1
|
||||||
|
#define CP0_ECC $26
|
||||||
|
#define CP0_CACHEERR $27
|
||||||
|
#define CP0_TAGLO $28
|
||||||
|
#define CP0_DATALO $28,1
|
||||||
|
#define CP0_TAGHI $29
|
||||||
|
#define CP0_DATAHI $29,1
|
||||||
|
#define CP0_ERRORPC $30
|
||||||
|
|
||||||
|
#define SAVE_REG(addr, reg, val) \
|
||||||
|
sw reg, (reg ## _IDX * WORD_SIZE)(addr)
|
||||||
|
|
||||||
|
#define LOAD_REG(addr, reg, val) \
|
||||||
|
lw reg, (reg ## _IDX * WORD_SIZE)(addr)
|
||||||
|
|
||||||
|
#endif /* __ATOMPORT_PRIVATE_H_ */
|
||||||
48
ports/mips/atomport-tests.h
Normal file
48
ports/mips/atomport-tests.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011, Himanshu Chauhan. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. No personal names or organizations' names associated with the
|
||||||
|
* Atomthreads project may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ATOM_PORT_TESTS_H
|
||||||
|
#define __ATOM_PORT_TESTS_H
|
||||||
|
|
||||||
|
/* Include Atomthreads kernel API */
|
||||||
|
#include "atom.h"
|
||||||
|
|
||||||
|
/* Logger macro for viewing test results */
|
||||||
|
/* FIXME: Add uart out routine once uart is supported */
|
||||||
|
#define ATOMLOG(x)
|
||||||
|
#define _STR(x)
|
||||||
|
|
||||||
|
/* Default thread stack size (in bytes) */
|
||||||
|
#define TEST_THREAD_STACK_SIZE 128
|
||||||
|
|
||||||
|
/* Uncomment to enable logging of stack usage to UART */
|
||||||
|
/* #define TESTS_LOG_STACK_USAGE */
|
||||||
|
|
||||||
|
#endif /* __ATOM_PORT_TESTS_H */
|
||||||
|
|
||||||
42
ports/mips/atomport-types.h
Normal file
42
ports/mips/atomport-types.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011, Himanshu Chauhan. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. No personal names or organizations' names associated with the
|
||||||
|
* Atomthreads project may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ATOMPORT_TYPES_H
|
||||||
|
#define __ATOMPORT_TYPES_H
|
||||||
|
|
||||||
|
typedef signed int int32_t;
|
||||||
|
typedef signed short int16_t;
|
||||||
|
typedef signed char int8_t;
|
||||||
|
typedef unsigned int uint32_t;
|
||||||
|
typedef unsigned short uint16_t;
|
||||||
|
typedef unsigned char uint8_t;
|
||||||
|
|
||||||
|
#define UINT32 uint32_t
|
||||||
|
|
||||||
|
#endif /* __ATOMPORT_TYPES_H */
|
||||||
75
ports/mips/atomport.c
Normal file
75
ports/mips/atomport.c
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011, Himanshu Chauhan for Atomthreads Project.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. No personal names or organizations' names associated with the
|
||||||
|
* Atomthreads project may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <atom.h>
|
||||||
|
#include <atomport-private.h>
|
||||||
|
#include <atomport.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function initialises each thread's stack during creation, before the
|
||||||
|
* thread is first run. New threads are scheduled in using the same
|
||||||
|
* context-switch function used for threads which were previously scheduled
|
||||||
|
* out, therefore this function should set up a stack context which looks
|
||||||
|
* much like a thread which has been scheduled out and had its context saved.
|
||||||
|
* We fill part of the stack with those registers which are involved in the
|
||||||
|
* context switch, including appropriate stack or register contents to cause
|
||||||
|
* the thread to branch to its entry point function when it is scheduled in.
|
||||||
|
*
|
||||||
|
* Interrupts should also be enabled whenever a thread is restored, hence
|
||||||
|
* ports may wish to explicitly include the interrupt-enable register here
|
||||||
|
* which will be restored when the thread is scheduled in. Other methods
|
||||||
|
* can be used to enable interrupts, however, without explicitly storing
|
||||||
|
* it in the thread's context.
|
||||||
|
*/
|
||||||
|
void archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top,
|
||||||
|
void (*entry_point)(UINT32),
|
||||||
|
UINT32 entry_param)
|
||||||
|
{
|
||||||
|
|
||||||
|
#define STORE_VAL(base, reg, val) \
|
||||||
|
*((uint32_t *)(base + ((reg ## _IDX) * WORD_SIZE))) = (uint32_t)val
|
||||||
|
|
||||||
|
void *stack_start = (stack_top - (WORD_SIZE * NUM_REGISTERS));
|
||||||
|
|
||||||
|
tcb_ptr->sp_save_ptr = stack_start;
|
||||||
|
|
||||||
|
STORE_VAL(stack_start, sp, stack_start);
|
||||||
|
STORE_VAL(stack_start, s8, stack_start);
|
||||||
|
STORE_VAL(stack_start, s1, 0);
|
||||||
|
STORE_VAL(stack_start, s2, 0);
|
||||||
|
STORE_VAL(stack_start, s3, 0);
|
||||||
|
STORE_VAL(stack_start, s4, 0);
|
||||||
|
STORE_VAL(stack_start, s5, 0);
|
||||||
|
STORE_VAL(stack_start, s6, 0);
|
||||||
|
STORE_VAL(stack_start, s7, 0);
|
||||||
|
STORE_VAL(stack_start, ra, entry_point);
|
||||||
|
STORE_VAL(stack_start, a0, entry_param);
|
||||||
|
}
|
||||||
|
|
||||||
53
ports/mips/atomport.h
Normal file
53
ports/mips/atomport.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011, Himanshu Chauhan. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. No personal names or organizations' names associated with the
|
||||||
|
* Atomthreads project may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ATOM_PORT_H
|
||||||
|
#define __ATOM_PORT_H
|
||||||
|
|
||||||
|
#include "atomport-types.h"
|
||||||
|
|
||||||
|
/* Required number of system ticks per second (normally 100 for 10ms tick) */
|
||||||
|
#define SYSTEM_TICKS_PER_SEC 100
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Architecture-specific types.
|
||||||
|
* Most of these are available from stdint.h on this platform, which is
|
||||||
|
* included above.
|
||||||
|
*/
|
||||||
|
#define POINTER void *
|
||||||
|
|
||||||
|
/* Critical region protection */
|
||||||
|
#define CRITICAL_STORE
|
||||||
|
#define CRITICAL_START() __asm__ __volatile__("di $0\n\t")
|
||||||
|
#define CRITICAL_END() __asm__ __volatile__("ei $0\n\t");
|
||||||
|
|
||||||
|
/* Uncomment to enable stack-checking */
|
||||||
|
/* #define ATOM_STACK_CHECKING */
|
||||||
|
|
||||||
|
#endif /* __ATOM_PORT_H */
|
||||||
297
ports/mips/tests-main.c
Normal file
297
ports/mips/tests-main.c
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2010, Kelvin Lawson. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. No personal names or organizations' names associated with the
|
||||||
|
* Atomthreads project may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "atom.h"
|
||||||
|
#include "atomport-private.h"
|
||||||
|
#include "atomtests.h"
|
||||||
|
#include "atomtimer.h"
|
||||||
|
|
||||||
|
/* Constants */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Idle thread stack size
|
||||||
|
*
|
||||||
|
* This needs to be large enough to handle any interrupt handlers
|
||||||
|
* and callbacks called by interrupt handlers (e.g. user-created
|
||||||
|
* timer callbacks) as well as the saving of all context when
|
||||||
|
* switching away from this thread.
|
||||||
|
*
|
||||||
|
* In this case, the idle stack is allocated on the BSS via the
|
||||||
|
* idle_thread_stack[] byte array.
|
||||||
|
*/
|
||||||
|
#define IDLE_STACK_SIZE_BYTES 128
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Main thread stack size
|
||||||
|
*
|
||||||
|
* Note that this is not a required OS kernel thread - you will replace
|
||||||
|
* this with your own application thread.
|
||||||
|
*
|
||||||
|
* In this case the Main thread is responsible for calling out to the
|
||||||
|
* test routines. Once a test routine has finished, the test status is
|
||||||
|
* printed out on the UART and the thread remains running in a loop
|
||||||
|
* flashing a LED.
|
||||||
|
*
|
||||||
|
* The Main thread stack generally needs to be larger than the idle
|
||||||
|
* thread stack, as not only does it need to store interrupt handler
|
||||||
|
* stack saves and context switch saves, but the application main thread
|
||||||
|
* will generally be carrying out more nested function calls and require
|
||||||
|
* stack for application code local variables etc.
|
||||||
|
*
|
||||||
|
* With all OS tests implemented to date on the AVR, the Main thread
|
||||||
|
* stack has not exceeded 198 bytes. To allow all tests to run we set
|
||||||
|
* a minimum main thread stack size of 204 bytes. This may increase in
|
||||||
|
* future as the codebase changes but for the time being is enough to
|
||||||
|
* cope with all of the automated tests.
|
||||||
|
*/
|
||||||
|
#define MAIN_STACK_SIZE_BYTES 204
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Startup code stack
|
||||||
|
*
|
||||||
|
* Some stack space is required at initial startup for running the main()
|
||||||
|
* routine. This stack space is only temporarily required at first bootup
|
||||||
|
* and is no longer required as soon as the OS is started. By default
|
||||||
|
* GCC sets this to the top of RAM (RAMEND) and it grows down from there.
|
||||||
|
* Because we only need this temporarily, though, it would be wasteful to
|
||||||
|
* set aside a region at the top of RAM which is not used during runtime.
|
||||||
|
*
|
||||||
|
* What we do here is to reuse part of the idle thread's stack during
|
||||||
|
* initial startup. As soon as we enter the main() routine we move the
|
||||||
|
* stack pointer to half-way down the idle thread's stack. This is used
|
||||||
|
* temporarily while calls are made to atomOSInit(), atomThreadCreate()
|
||||||
|
* and atomOSStart(). Once the OS is started this stack area is no
|
||||||
|
* longer required, and can be used for its original purpose (for the
|
||||||
|
* idle thread's stack).
|
||||||
|
*
|
||||||
|
* This does mean, however, that we cannot monitor the stack usage of the
|
||||||
|
* idle thread. Stack usage is monitored by prefilling the stack with a
|
||||||
|
* known value, and we are obliterating some of that prefilled area by
|
||||||
|
* using it as our startup stack, so we cannot use the stack-checking API
|
||||||
|
* to get a true picture of idle thread stack usage. If you wish to
|
||||||
|
* monitor idle thread stack usage for your applications then you are
|
||||||
|
* free to use a different region for the startup stack (e.g. set aside
|
||||||
|
* an area permanently, or place it somewhere you know you can reuse
|
||||||
|
* later in the application). For the time being, this method gives us a
|
||||||
|
* simple way of reducing the memory consumption without having to add
|
||||||
|
* any special AVR-specific considerations to the automated test
|
||||||
|
* applications.
|
||||||
|
*
|
||||||
|
* This optimisation was required to allow some of the larger automated
|
||||||
|
* test modules to run on devices with 1KB of RAM. You should avoid doing
|
||||||
|
* this if you can afford to set aside 64 bytes or so, or if you are
|
||||||
|
* writing your own applications in which you have further control over
|
||||||
|
* where data is located.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Local data */
|
||||||
|
|
||||||
|
/* Application threads' TCBs */
|
||||||
|
static ATOM_TCB main_tcb;
|
||||||
|
|
||||||
|
/* Main thread's stack area */
|
||||||
|
static uint8_t main_thread_stack[MAIN_STACK_SIZE_BYTES];
|
||||||
|
|
||||||
|
/* Idle thread's stack area */
|
||||||
|
static uint8_t idle_thread_stack[IDLE_STACK_SIZE_BYTES];
|
||||||
|
|
||||||
|
/* STDIO stream */
|
||||||
|
static FILE uart_stdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
static void main_thread_func (uint32_t data);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \b main
|
||||||
|
*
|
||||||
|
* Program entry point.
|
||||||
|
*
|
||||||
|
* Sets up the AVR hardware resources (system tick timer interrupt) necessary
|
||||||
|
* for the OS to be started. Creates an application thread and starts the OS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main ( void )
|
||||||
|
{
|
||||||
|
int8_t status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reuse part of the idle thread's stack for the stack required
|
||||||
|
* during this startup function.
|
||||||
|
*/
|
||||||
|
SP = (int)&idle_thread_stack[(IDLE_STACK_SIZE_BYTES/2) - 1];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: to protect OS structures and data during initialisation,
|
||||||
|
* interrupts must remain disabled until the first thread
|
||||||
|
* has been restored. They are reenabled at the very end of
|
||||||
|
* the first thread restore, at which point it is safe for a
|
||||||
|
* reschedule to take place.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise the OS before creating our threads.
|
||||||
|
*
|
||||||
|
* Note that we tell the OS that the idle stack is half its actual
|
||||||
|
* size. This prevents it prefilling the bottom half with known
|
||||||
|
* values for stack-checkig purposes, which we cannot allow because
|
||||||
|
* we are temporarily using it for our own stack. The remainder will
|
||||||
|
* still be available once the OS is started, this only prevents the
|
||||||
|
* OS from prefilling it.
|
||||||
|
*
|
||||||
|
* If you are not reusing the idle thread's stack during startup then
|
||||||
|
* you should pass in the correct size here.
|
||||||
|
*/
|
||||||
|
status = atomOSInit(&idle_thread_stack[IDLE_STACK_SIZE_BYTES - 1], (IDLE_STACK_SIZE_BYTES/2));
|
||||||
|
if (status == ATOM_OK)
|
||||||
|
{
|
||||||
|
/* Enable the system tick timer */
|
||||||
|
avrInitSystemTickTimer();
|
||||||
|
|
||||||
|
/* Create an application thread */
|
||||||
|
status = atomThreadCreate(&main_tcb,
|
||||||
|
TEST_THREAD_PRIO, main_thread_func, 0,
|
||||||
|
&main_thread_stack[MAIN_STACK_SIZE_BYTES - 1],
|
||||||
|
MAIN_STACK_SIZE_BYTES);
|
||||||
|
if (status == ATOM_OK)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* First application thread successfully created. It is
|
||||||
|
* now possible to start the OS. Execution will not return
|
||||||
|
* from atomOSStart(), which will restore the context of
|
||||||
|
* our application thread and start executing it.
|
||||||
|
*
|
||||||
|
* Note that interrupts are still disabled at this point.
|
||||||
|
* They will be enabled as we restore and execute our first
|
||||||
|
* thread in archFirstThreadRestore().
|
||||||
|
*/
|
||||||
|
atomOSStart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
;
|
||||||
|
|
||||||
|
/* There was an error starting the OS if we reach here */
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \b main_thread_func
|
||||||
|
*
|
||||||
|
* Entry point for main application thread.
|
||||||
|
*
|
||||||
|
* This is the first thread that will be executed when the OS is started.
|
||||||
|
*
|
||||||
|
* @param[in] data Unused (optional thread entry parameter)
|
||||||
|
*
|
||||||
|
* @return None
|
||||||
|
*/
|
||||||
|
static void main_thread_func (uint32_t data)
|
||||||
|
{
|
||||||
|
uint32_t test_status;
|
||||||
|
int sleep_ticks;
|
||||||
|
|
||||||
|
/* Enable all LEDs (STK500-specific) */
|
||||||
|
DDRB = 0xFF;
|
||||||
|
PORTB = 0xFF;
|
||||||
|
|
||||||
|
/* Initialise UART (9600bps) */
|
||||||
|
if (uart_init(9600) != 0)
|
||||||
|
{
|
||||||
|
/* Error initialising UART */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redirect stdout via the UART. Note that the UART write routine
|
||||||
|
* is protected via a semaphore, so the OS must be started before
|
||||||
|
* use of the UART.
|
||||||
|
*/
|
||||||
|
stdout = &uart_stdout;
|
||||||
|
|
||||||
|
/* Put a message out on the UART */
|
||||||
|
printf_P(PSTR("Go\n"));
|
||||||
|
|
||||||
|
/* Start test. All tests use the same start API. */
|
||||||
|
test_status = test_start();
|
||||||
|
|
||||||
|
/* Check main thread stack usage (if enabled) */
|
||||||
|
#ifdef ATOM_STACK_CHECKING
|
||||||
|
if (test_status == 0)
|
||||||
|
{
|
||||||
|
uint32_t used_bytes, free_bytes;
|
||||||
|
|
||||||
|
/* Check idle thread stack usage */
|
||||||
|
if (atomThreadStackCheck (&main_tcb, &used_bytes, &free_bytes) == ATOM_OK)
|
||||||
|
{
|
||||||
|
/* Check the thread did not use up to the end of stack */
|
||||||
|
if (free_bytes == 0)
|
||||||
|
{
|
||||||
|
printf_P (PSTR("Main stack overflow\n"));
|
||||||
|
test_status++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Log the stack usage */
|
||||||
|
#ifdef TESTS_LOG_STACK_USAGE
|
||||||
|
printf_P (PSTR("MainUse:%d\n"), used_bytes);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Log final status */
|
||||||
|
if (test_status == 0)
|
||||||
|
{
|
||||||
|
printf_P (PSTR("Pass\n"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf_P (PSTR("Fail(%d)\n"), test_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flash LED once per second if passed, very quickly if failed */
|
||||||
|
sleep_ticks = (test_status == 0) ? SYSTEM_TICKS_PER_SEC : (SYSTEM_TICKS_PER_SEC/8);
|
||||||
|
|
||||||
|
/* Test finished, flash slowly for pass, fast for fail */
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
/* Toggle a LED (STK500-specific) */
|
||||||
|
PORTB ^= (1 << 7);
|
||||||
|
|
||||||
|
/* Sleep then toggle LED again */
|
||||||
|
atomTimerDelay(sleep_ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user