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:
Himanshu Chauhan
2011-05-18 22:35:45 +05:30
parent 916dc11a0c
commit daf07b5946
10 changed files with 2258 additions and 0 deletions

1161
ports/mips/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

107
ports/mips/Makefile Normal file
View 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
View 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
View 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)

View 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_ */

View 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 */

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