- Added Tricore TC1798 port.

git-svn-id: https://svn.code.sf.net/p/openblt/code/trunk@128 5dc33758-31d5-4daf-9ae8-b24bf3d40d73
This commit is contained in:
Frank Voorburg 2016-02-25 10:46:45 +00:00
parent fbfa8dfd31
commit 4ec12dabd5
17 changed files with 3507 additions and 0 deletions

View File

@ -0,0 +1,127 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\GCC\cpu_comp.c
* \brief Bootloader compiler specific cpu module source file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
/****************************************************************************************
* Include files
****************************************************************************************/
#include "boot.h" /* bootloader generic header */
/****************************************************************************************
* Local function prototypes
****************************************************************************************/
static void CpuWriteWDTCON0(blt_int32u uwValue);
/************************************************************************************//**
** \brief This macro clears the EndInit bit, which controls access to system critical
** registers. Clearing the EndInit bit unlocks all EndInit protectedd
** registers. Modifications of the EndInit bit are monitored by the watchdog
** timer such that after clearing the EndInit, the watchdog timer enters a
** defined time-out mode; EndInit must be set again before the time-out
** expires.
** \return none.
**
****************************************************************************************/
void CpuEnterInitMode(void)
{
/* request clearing of the EndInit bit */
CpuWriteWDTCON0(WDT_CON0.reg & ~0x00000001);
/* wait for hardware handshake */
while (WDT_CON0.bits.ENDINIT != 0)
{
/* keep the watchdog happy */
CopService();
}
} /*** end of CpuEnterInitMode ***/
/************************************************************************************//**
** \brief This macro sets the EndInit bit, which controls access to system critical
** registers. Setting the EndInit bit locks all EndInit protected registers.
** \return none.
**
****************************************************************************************/
void CpuLeaveInitMode(void)
{
/* set the EndInit bit */
CpuWriteWDTCON0(WDT_CON0.reg | 0x00000001);
} /*** end of CpuLeaveInitMode ***/
/************************************************************************************//**
** \brief Write a new value to the WDTCON0 register.
** \param value New value for the WDTCON0 register.
** \return none.
**
****************************************************************************************/
static void CpuWriteWDTCON0(blt_int32u value)
{
blt_int32u dummy;
/* load current value of the WDTCON0 register */
dummy = WDT_CON0.reg;
/* set HWPW1 = 1111b */
dummy |= 0x000000F0;
/* set HWPW0 = WDTDR */
if(WDT_CON1.bits.DR)
{
dummy |= 0x00000008;
}
else
{
dummy &= ~0x00000008;
}
/* set HWPW0 = WDTIR */
if(WDT_CON1.bits.IR)
{
dummy |= 0x00000004;
}
else
{
dummy &= ~0x00000004;
}
/* set WDTLCK = 0 */
dummy &= ~0x00000002;
/* unlock access */
WDT_CON0.reg = dummy;
/* set HWPW1 = 1111b and WDTLCK = 1 */
value |= 0x000000F2;
/* set HWPW0 = 00b */
value &= ~0x0000000C;
/* write access and lock */
WDT_CON0.reg = value;
} /*** end of CpuWriteWDTCON0 ***/
/*********************************** end of cpu_comp.c *********************************/

View File

@ -0,0 +1,62 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\GCC\cpu_comp.h
* \brief Bootloader compiler specific cpu module header file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
#ifndef CPU_COMP_H
#define CPU_COMP_H
/****************************************************************************************
* Include files
****************************************************************************************/
#include <TC1798.h>
#include <machine/intrinsics.h>
#include <machine/cint.h>
#include <sys/types.h>
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Macro for performing a processor specific desync. This part is located in the
* compiler specific part because it uses an inline assembly call.
*/
#define CpuSetDSYNC() asm("DSYNC")
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void CpuEnterInitMode(void);
void CpuLeaveInitMode(void);
#endif /* CPU_COMP_H */
/*********************************** end of cpu_comp.h *********************************/

View File

@ -0,0 +1,540 @@
/*
* crt0-tc1x.S -- Startup code for GNU/TriCore applications.
*
* Copyright (C) 1998-2012 HighTec EDV-Systeme GmbH.
*
* This file is part of GCC.
*
* GCC 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 3, or (at your option)
* any later version.
*
* GCC 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.
*
* Under Section 7 of GPL version 3, you are granted additional
* permissions described in the GCC Runtime Library Exception, version
* 3.1, as published by the Free Software Foundation.
*
* You should have received a copy of the GNU General Public License and
* a copy of the GCC Runtime Library Exception along with this program;
* see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
* <http://www.gnu.org/licenses/>. */
#ifndef __TRICORE_NAME__
#error Please define __TRICOR_NAME__
#endif
/* define the Derivate Name as a hexvalue
* this name is defined in tricore.specs for specific derivate to
* the derivate number as a hexvalue (e.g. TC1796 => 0x1796
* This name will be used in the memory.x Memory description to
* to confirm that the crt0.o and the memory.x will be get from
* same directory
*/
.global __TRICORE_DERIVATE_NAME__
.type __TRICORE_DERIVATE_NAME__,@object
.set __TRICORE_DERIVATE_NAME__,__TRICORE_NAME__
.section ".startup_code", "awx", @progbits
.global _start
.type _start,@function
_start:
.code32
j 0f
/*
* external boot memory configuration word
*/
.word __EBMCFG
.word __EBMCFG
.word __EBMCFG
.word __EBMCFG
/*
* default value for this configuration word
*/
.global __EBMCFG
.weak __EBMCFG
__EBMCFG = 0x0000808c
0:
#; check whether WDTCON0.ENDINIT is set
#; clear it if necessary
#; initialization code must write ENDINIT protected registers
ld.w %d1,$wdtcon0 # %d1 = *WDTCON0
jz.t %d1,0,endinit_done
jl asm_clear_endinit
endinit_done:
/*
* initialize user and interrupt stack pointers
*/
movh.a %sp,hi:__USTACK # load %sp
lea %sp,[%sp]lo:__USTACK
movh %d0,hi:__ISTACK # load $isp
addi %d0,%d0,lo:__ISTACK
mtcr $isp,%d0
isync
#; install trap handlers
movh %d0,hi:first_trap_table #; load $btv
addi %d0,%d0,lo:first_trap_table
mtcr $btv,%d0
isync
/*
* initialize call depth counter
*/
mfcr %d0,$psw
#ifdef MAX_CALLDEPTH_64
andn %d0,%d0,0x7f # reset call depth counter
or %d0,%d0,0x80 # set CDE bit
#else
or %d0,%d0,0x7f # disable call depth counting
andn %d0,%d0,0x80 # clear CDE bit
#endif
mtcr $psw,%d0
isync
/*
* initialize access to system global registers
*/
mfcr %d0,$psw
or %d0,%d0,0x100 # set GW bit
mtcr $psw,%d0
isync
/*
* initialize SDA base pointers
*/
.global _SMALL_DATA_,_SMALL_DATA2_,_SMALL_DATA3_,_SMALL_DATA4_
.weak _SMALL_DATA_,_SMALL_DATA2_,_SMALL_DATA3_,_SMALL_DATA4_
movh.a %a0,hi:_SMALL_DATA_ # %a0 addresses .sdata/.sbss
lea %a0,[%a0]lo:_SMALL_DATA_
movh.a %a1,hi:_SMALL_DATA2_ # %a1 addresses .sdata2/.sbss2
lea %a1,[%a1]lo:_SMALL_DATA2_
movh.a %a8,hi:_SMALL_DATA3_ # %a8 addresses .sdata3/.sbss3
lea %a8,[%a8]lo:_SMALL_DATA3_
movh.a %a9,hi:_SMALL_DATA4_ # %a9 addresses .sdata4/.sbss4
lea %a9,[%a9]lo:_SMALL_DATA4_
#ifdef READONLY_SYSREGS
mfcr %d0,$psw
andn %d0,%d0,0x100 # clear GW bit
mtcr $psw,%d0
isync
#endif
/*
* initialize target environment (PLLCLC, BUSCONx, ADDSELx etc)
*
* This is done by a user supplied assembler function __board_init
*/
#; force PC to remapped ROM address
movh.a %a15,hi:__remapped
lea %a15,[%a15]lo:__remapped
nop
ji %a15
__remapped:
# call _board_init
jl __board_init
__no_board_init:
/*
* disable code and data protection
*/
#ifdef DISABLE_CODE_PROTECTION
mfcr %d0,$cpm0_0 # disable code protection
andn %d0,%d0,0xff
mtcr $cpm0_0,%d0
isync
#endif
#ifdef DISABLE_DATA_PROTECTION
mfcr %d0,$dpm0_0 # disable data protection
andn %d0,%d0,0xff
mtcr $dpm0_0,%d0
isync
#endif
/*
* initialize software break service (OCDS)
*/
#ifdef INIT_SBS
SRCSB0 = 0xfffeffbc
SWBIPL = 31
mov.u %d0,lo:(SWBIPL + 0x00001000)
addih %d0,%d0,hi:(SWBIPL + 0x00001000)
movh.a %a5,hi:SRCSB0
lea %a5,[%a5]lo:SRCSB0
st.w [%a5],%d0
#endif
/*
* disable watchdog timer and set ENDINIT bit
*/
jl _disable_wdt
/*
* initialize context save areas
*/
jl __init_csa
/*
* handle clear table (i.e., fill BSS with zeros)
*/
jl __clear_table_func
/*
* handle copy table (support for romable code)
*/
jl __copy_table_func
/*
* call the initializer, constructors etc.
*/
call _init
/*
* _exit (main (0, NULL));
*/
mov %d4,0 # argc = 0
sub.a %sp,8
st.w [%sp]0, %d4
st.w [%sp]4, %d4
mov.aa %a4, %sp # argv
call main # int retval = main (0, NULL);
mov %d4,%d2
lea %sp,[%sp]8 # remove argv[0]
mov.u %d1, 0x900d # set exit code i(A14) for the simulator to
mov %d15, %d2 # 0x900d if the exit status is 0
movh %d3, 0xffff
or %d2, %d2, %d3
cmov %d1,%d15,%d2
mov.a %a14, %d1
j _exit # _exit (retval);
debug # should never come here
/*
* disable watchdog timer and set ENDINIT bit
*/
WDTMASK = 0xffffff03
WDTMASKA= 0xffffff01
WDTMASK2= 0xfffffff0
.globl _disable_wdt
.type _disable_wdt,function
_disable_wdt: # lock WDT via passwd access
movh %d2,hi:WDTMASK
addi %d2,%d2,lo:WDTMASK # %d2 = 0xffffff03
movh %d5,hi:WDTMASK2 # %d5 = 0xfffffff0
addi %d5,%d5,lo:WDTMASK2
mov %d6,0x8 # %d6 = "disable WDT"
st.w $wdtcon1,%d6 # WDTCON1.WDTDR = 1
ld.w %d0,$wdtcon0 # %d0 = *WDTCON0
ld.w %d1,$wdtcon1 # %d1 = *WDTCON1
and %d3,%d2,%d0 # %d3 = WDTCON0 & 0xffffff03
or %d3,%d3,0xf0 # %d3 |= 0xf0
and %d4,%d1,0xc
or %d3,%d3,%d4 # %d3 |= (WDTCON1 & 0xc)
xor %d3,%d3,0x2 # %d3 ^= 0x2
st.w $wdtcon0,%d3 # WDTCON = %d3
and %d3,%d3,%d5 # %d3 &= 0xfffffff0
or %d3,%d3,0x3 # WDTCON0.{WDTLCK,ENDINIT} = 1
st.w $wdtcon0,%d3 # write back new value
ld.w %d0,$wdtcon0 # ensure that value is written
ji %a11
/*
* initialize context save areas (CSAs), PCXI, LCX and FCX
*/
.globl __init_csa
.type __init_csa,function
__init_csa:
movh %d0,0
mtcr $pcxi,%d0
isync
movh %d0,hi:__CSA_BEGIN #; %d0 = begin of CSA
addi %d0,%d0,lo:__CSA_BEGIN
addi %d0,%d0,63 #; force alignment (2^6)
andn %d0,%d0,63
movh %d2,hi:__CSA_END #; %d2 = end of CSA
addi %d2,%d2,lo:__CSA_END
andn %d2,%d2,63 #; force alignment (2^6)
sub %d2,%d2,%d0
sh %d2,%d2,-6 #; %d2 = number of CSAs
mov.a %a3,%d0 #; %a3 = address of first CSA
extr.u %d0,%d0,28,4 #; %d0 = segment << 16
sh %d0,%d0,16
lea %a4,0 #; %a4 = previous CSA = 0
st.a [%a3], %a4 #; store it in 1st CSA
mov.aa %a4,%a3 #; %a4 = current CSA
lea %a3,[%a3]64 #; %a3 = %a3->nextCSA
mov.d %d1,%a3
extr.u %d1,%d1,6,16 #; get CSA index
or %d1,%d1,%d0 #; add segment number
mtcr $lcx,%d1 #; initialize LCX
add %d2,%d2,-2 #; CSAs to initialize -= 2
mov.a %a5, %d2 #; %a5 = loop counter
csa_loop:
mov.d %d1,%a4 #; %d1 = current CSA address
extr.u %d1,%d1,6,16 #; get CSA index
or %d1,%d1,%d0 #; add segment number
st.w [%a3],%d1 #; store "nextCSA" pointer
mov.aa %a4,%a3 #; %a4 = current CSA address
lea %a3,[%a3]64 #; %a3 = %a3->nextCSA
loop %a5, csa_loop #; repeat until done
mov.d %d1,%a4 #; %d1 = current CSA address
extr.u %d1,%d1,6,16 #; get CSA index
or %d1,%d1,%d0 #; add segment number
mtcr $fcx,%d1 #; initialize FCX
isync
ji %a11
.global asm_clear_endinit
.type asm_clear_endinit,@function
asm_clear_endinit:
ld.w %d0,$wdtcon0 # %d0 = *WDTCON0
ld.w %d1,$wdtcon1 # %d1 = *WDTCON1
movh %d2,hi:WDTMASKA
addi %d2,%d2,lo:WDTMASKA # %d2 = 0xffffff01
and %d0,%d2,%d0
or %d0,%d0,240
and %d4,%d1,12
or %d0,%d4,%d0
st.w $wdtcon0,%d0
movh %d4,hi:WDTMASK2 # %d4 = 0xfffffff0
addi %d4,%d4,lo:WDTMASK2
and %d0,%d4,%d0
or %d0,%d0,2 # ENDINIT = 0
isync
st.w $wdtcon0,%d0
ld.w %d0,$wdtcon0 # ensure that value is written
ji %a11
/*
* handle clear table (i.e., fill BSS with zeros)
*/
.global __clear_table_func
.type __clear_table_func,@function
__clear_table_func:
mov %d14,0 # %e14 = 0
mov %d15,0
movh.a %a13,hi:__clear_table # %a13 = &first table entry
lea %a13,[%a13]lo:__clear_table
__clear_table_next:
ld.a %a15,[%a13+]4 # %a15 = current block base
ld.w %d3,[%a13+]4 # %d3 = current block length
jeq %d3,-1,__clear_table_done # length == -1 => end of table
sh %d0,%d3,-3 # %d0 = length / 8 (doublewords)
and %d1,%d3,7 # %d1 = length % 8 (rem. bytes)
jz %d0,__clear_word # block size < 8 => clear word
addi %d0,%d0,-1 # else doublewords -= 1
mov.a %a2,%d0 # %a2 = loop counter
__clear_dword:
st.d [%a15+]8,%e14 # clear one doubleword
loop %a2,__clear_dword
__clear_word:
jz %d1,__clear_table_next
sh %d0,%d1,-2 # %d0 = length / 4 (words)
and %d1,%d1,3 # %d1 = length % 4 (rem. bytes)
jz %d0,__clear_hword # block size < 4 => clear hword
st.w [%a15+]4,%d15 # clear one word
__clear_hword:
jz %d1,__clear_table_next
sh %d0,%d1,-1 # %d0 = length / 2 (halfwords)
and %d1,%d1,1 # %d1 = length % 2 (rem. bytes)
jz %d0,__clear_byte # block size < 2 => clear byte
st.h [%a15+]2,%d15 # clear one halfword
__clear_byte:
jz %d1,__clear_table_next
st.b [%a15],%d15 # clear one byte
j __clear_table_next # handle next clear table entry
__clear_table_done:
ji %a11
/*
* handle copy table (support for romable code)
*/
.global __copy_table_func
.type __copy_table_func,@function
__copy_table_func:
movh.a %a13,hi:__copy_table # %a13 = &first table entry
lea %a13,[%a13]lo:__copy_table
__copy_table_next:
ld.a %a15,[%a13+]4 # %a15 = src address
ld.a %a14,[%a13+]4 # %a14 = dst address
ld.w %d3,[%a13+]4 # %d3 = block length
jeq %d3,-1,__copy_table_done # length == -1 => end of table
sh %d0,%d3,-3 # %d0 = length / 8 (doublewords)
and %d1,%d3,7 # %d1 = lenght % 8 (rem. bytes)
jz %d0,__copy_word # block size < 8 => copy word
addi %d0,%d0,-1 # else doublewords -= 1
mov.a %a2,%d0 # %a2 = loop counter
__copy_dword:
ld.d %e14,[%a15+]8 # copy one doubleword
st.d [%a14+]8,%e14
loop %a2,__copy_dword
__copy_word:
jz %d1,__copy_table_next
sh %d0,%d1,-2 # %d0 = length / 4 (words)
and %d1,%d1,3 # %d1 = lenght % 4 (rem. bytes)
jz %d0,__copy_hword # block size < 4 => copy hword
ld.w %d14,[%a15+]4 # copy one word
st.w [%a14+]4,%d14
__copy_hword:
jz %d1,__copy_table_next
sh %d0,%d1,-1 # %d0 = length / 2 (halfwords)
and %d1,%d1,1 # %d1 = lenght % 2 (rem. bytes)
jz %d0,__copy_byte # block size < 2 => copy byte
ld.h %d14,[%a15+]2 # copy one halfword
st.h [%a14+]2,%d14
__copy_byte:
jz %d1,__copy_table_next
ld.b %d14,[%a15]0 # copy one byte
st.b [%a14],%d14
j __copy_table_next # handle next copy table entry
__copy_table_done:
ji %a11
/*
* dummy board initilization function
.global __board_init
.weak __board_init
__board_init:
ji %a11
*/
.global boardSetupTabSize
.weak boardSetupTabSize
.global boardSetupTab
.weak boardSetupTab
boardSetupTab:
boardSetupTabSize:
.global __board_init
.type __board_init,@function
__board_init:
.code32
#;
#; initialize target environment (PLLCLC, BUSCONx, ADDSELx)
#;
#; this is done by board specific setup table (address/value - pairs)
#;
movh.a %a15,hi:boardSetupTabSize
lea %a15,[%a15]lo:boardSetupTabSize # %a14 address of table size
movh.a %a14,hi:boardSetupTab
lea %a14,[%a14]lo:boardSetupTab # %a14 address of setup table
jeq.a %a14, %a15, no_setup
ld.a %a15,[%a15]0 # %a15 = table size
jz.a %a15,no_setup
add.a %a15,-1 # correction for loop
setup_loop:
ld.a %a2,[%a14+] # %a2 = boardSetupTab.addr
ld.w %d2,[%a14+] # %d2 = boardSetupTab.val
st.w [%a2],%d2
loop %a15,setup_loop
isync
nop
nop
no_setup:
ji %a11
/*============================================================================*
* Exception handlers (exceptions in startup code)
*
* This is a minimal trap vector table, which consists of eight
* entries, each consisting of eight words (32 bytes).
*============================================================================*/
#; .section .traptab, "awx", @progbits
.macro trapentry from=0, to=7
debug
mov.u %d14, \from << 8
add %d14, %d14, %d15
mov.a %a14, %d14
addih.a %a14, %a14,0xdead
j _exit
0: j 0b
nop
rfe
.align 5
.if \to-\from
trapentry "(\from+1)",\to
.endif
.endm
.align 8
.globl first_trap_table
first_trap_table:
trapentry 0, 7

View File

@ -0,0 +1,40 @@
# Copyright (C) 1998-2012 HighTec EDV-Systeme GmbH.
#
# This file is part of GCC.
#
# GCC 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 3, or (at your option)
# any later version.
#
# GCC 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.
#
# Under Section 7 of GPL version 3, you are granted additional
# permissions described in the GCC Runtime Library Exception, version
# 3.1, as published by the Free Software Foundation.
#
# You should have received a copy of the GNU General Public License and
# a copy of the GCC Runtime Library Exception along with this program;
# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
# <http://www.gnu.org/licenses/>. */
# This file just makes sure that the .fini and .init sections do in
# fact return. Users may put any desired instructions in those sections.
# This file is the last thing linked into any executable.
# On the tricore we have just to return
.file "crtn.S"
.section ".init"
;;
ret
.section ".fini"
;;
ret
# end of crtn.asm

View File

@ -0,0 +1,656 @@
/*
* Name: memory.x
*
* Generated Linker Description File
* Copyright (C) 2010 HighTec EDV-Systeme GmbH.
* (!Do not edit outsite of the protection areas!)
*
* Description:
* internal flash configuration
*/
/*
* Define Entrypoint of Executable
*/
ENTRY(_start)
/*
* Global
*/
/*Program Flash Memory (PFLASH0)*/
__PMU_PFLASH0_BEGIN = 0x80000000;
__PMU_PFLASH0_SIZE = 2M;
/*Program Flash Memory (PFLASH1)*/
__PMU_PFLASH1_BEGIN = 0x80800000;
__PMU_PFLASH1_SIZE = 2M;
/*Data Flash Memory (DFLASH0)*/
__PMU_DFLASH0_BEGIN = 0xAF000000;
__PMU_DFLASH0_SIZE = 96K;
/*Data Flash Memory (DFLASH1)*/
__PMU_DFLASH1_BEGIN = 0xAF080000;
__PMU_DFLASH1_SIZE = 96K;
/*Boot ROM (BROM)*/
__BROM_BEGIN = 0xAFFFC000;
__BROM_SIZE = 16K;
/*Scratch-Pad RAM (PSPR)*/
__PMI_PSPR_BEGIN = 0xC0000000;
__PMI_PSPR_SIZE = 32K;
/*Local Data RAM (DSPR)*/
__DMI_DSPR_BEGIN = 0xD0000000;
__DMI_DSPR_SIZE = 128K;
/*PCP Code Memory (CMEM)*/
__PCP_CMEM_BEGIN = 0xF0060000;
__PCP_CMEM_SIZE = 32K;
/*PCP Data Memory (PRAM)*/
__PCP_PRAM_BEGIN = 0xF0050000;
__PCP_PRAM_SIZE = 16K;
/*External Code Memory*/
__EXT_FLASH_BEGIN = 0x84000000;
__EXT_FLASH_SIZE = 4M;
/*External Data Memory*/
__EXT_RAM_BEGIN = 0x83000000;
__EXT_RAM_SIZE = 1M;
__USTACK_SIZE = DEFINED (__USTACK_SIZE) ? __USTACK_SIZE : 1K; /* Section for ustack*/
__ISTACK_SIZE = DEFINED (__ISTACK_SIZE) ? __ISTACK_SIZE : 256; /* Section for istack*/
__HEAP_SIZE = DEFINED (__HEAP_SIZE) ? __HEAP_SIZE : 4K; /* Section for heap*/
__CSA_SIZE = DEFINED (__CSA_SIZE) ? __CSA_SIZE : 16K; /* Section for CSA*/
/**
* User defined global region
*/
/*PROTECTED REGION ID(Protection:iROM-Global) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
/*
* internal flash configuration
*/
MEMORY
{
PMU_PFLASH0 (rx!p): org = 0x80000000, len = 2M /*Program Flash Memory (PFLASH0)*/
PMU_PFLASH1 (rx!p): org = 0x80800000, len = 2M /*Program Flash Memory (PFLASH1)*/
PMU_DFLASH0 (r!xp): org = 0xAF000000, len = 96K /*Data Flash Memory (DFLASH0)*/
PMU_DFLASH1 (r!xp): org = 0xAF080000, len = 96K /*Data Flash Memory (DFLASH1)*/
BROM (rx!p): org = 0xAFFFC000, len = 16K /*Boot ROM (BROM)*/
PMI_PSPR (wx!p): org = 0xC0000000, len = 32K /*Scratch-Pad RAM (PSPR)*/
DMI_DSPR (w!xp): org = 0xD0000000, len = 128K /*Local Data RAM (DSPR)*/
PCP_CMEM (rxp): org = 0xF0060000, len = 32K /*PCP Code Memory (CMEM)*/
PCP_PRAM (wp!x): org = 0xF0050000, len = 16K /*PCP Data Memory (PRAM)*/
EXT_FLASH (rx): org = 0x84000000, len = 4M /*External Code Memory*/
EXT_RAM (w!x): org = 0x83000000, len = 1M /*External Data Memory*/
}
SECTIONS
{
/*Code-Sections*/
/*
* Startup code for TriCore
*/
.startup_code :
{
PROVIDE(__startup_code_start = .);
/*PROTECTED REGION ID(Protection: iROM .startup_code.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.startup_code) /*Startup code for TriCore*/
*(.startup_code*)
/*PROTECTED REGION ID(Protection: iROM .startup_code) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__startup_code_end = .);
. = ALIGN(8);
} > PMU_PFLASH0 /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*
* Code section
*/
.text :
{
PROVIDE(__text_start = .);
/*PROTECTED REGION ID(Protection: iROM .text.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.text) /*Code section*/
*(.text*)
*(.gnu.linkonce.t.*)
/*PROTECTED REGION ID(Protection: iROM .text) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__text_end = .);
. = ALIGN(8);
} > PMU_PFLASH0 /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*
* Code executed before calling main
*/
.init :
{
PROVIDE(__init_start = .);
/*PROTECTED REGION ID(Protection: iROM .init.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
KEEP(*(.init)) /*Code executed before calling main*/
KEEP(*(.init*))
/*PROTECTED REGION ID(Protection: iROM .init) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__init_end = .);
. = ALIGN(8);
} > PMU_PFLASH0 /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*
* Code executed before exiting program
*/
.fini :
{
PROVIDE(__fini_start = .);
/*PROTECTED REGION ID(Protection: iROM .fini.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
KEEP(*(.fini)) /*Code executed before exiting program*/
KEEP(*(.fini*))
/*PROTECTED REGION ID(Protection: iROM .fini) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__fini_end = .);
. = ALIGN(8);
} > PMU_PFLASH0 /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*
* Section for trap table
*/
.traptab :
{
PROVIDE(__traptab_start = .);
/*PROTECTED REGION ID(Protection: iROM .traptab.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.traptab) /*Section for trap table*/
*(.traptab*)
/*PROTECTED REGION ID(Protection: iROM .traptab) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__traptab_end = .);
. = ALIGN(8);
} > PMU_PFLASH0 /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*
* Section for interrupt table
*/
.inttab :
{
PROVIDE(__inttab_start = .);
/*PROTECTED REGION ID(Protection: iROM .inttab.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.inttab) /*Section for interrupt table*/
*(.inttab*)
/*PROTECTED REGION ID(Protection: iROM .inttab) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__inttab_end = .);
. = ALIGN(8);
} > PMU_PFLASH0 /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*
* Exception handling frame for C++ exceptions
*/
.eh_frame :
{
PROVIDE(__eh_frame_start = .);
/*PROTECTED REGION ID(Protection: iROM .eh_frame.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.eh_frame) /*Exception handling frame for C++ exceptions*/
*(.eh_frame*)
/*PROTECTED REGION ID(Protection: iROM .eh_frame) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__eh_frame_end = .);
. = ALIGN(8);
} > PMU_PFLASH0 /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*Absolute Data-Sections*/
/*
* Initialised data addressed as absolute
*/
.zdata :
{
PROVIDE(__zdata_start = .);
/*PROTECTED REGION ID(Protection: iROM .zdata.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.zdata) /*Initialised data addressed as absolute*/
*(.zdata*)
*(.zdata.rodata) /*.zdata.rodata*/
*(.zdata.rodata*)
*(.zrodata) /*.zrodata*/
*(.zrodata*)
*(.gnu.linkonce.z.*)
*(.gnu.linkonce.zr.*)
/*PROTECTED REGION ID(Protection: iROM .zdata) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__zdata_end = .);
. = ALIGN(8);
} > DMI_DSPR AT > PMU_PFLASH0 /* DMI_DSPR: Local Data RAM (DSPR) */ /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*
* Not initialised data addressed as absolute
*/
.zbss (NOLOAD) :
{
PROVIDE(__zbss_start = .);
/*PROTECTED REGION ID(Protection: iROM .zbss.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.zbss) /*Not Initialised data addressed as absolute*/
*(.zbss*)
*(.gnu.linkonce.zb.*)
/*PROTECTED REGION ID(Protection: iROM .zbss) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__zbss_end = .);
. = ALIGN(8);
} > DMI_DSPR /* DMI_DSPR: Local Data RAM (DSPR) */
/*
* Not initialised bit data
*/
.bbss (NOLOAD) :
{
PROVIDE(__bbss_start = .);
/*PROTECTED REGION ID(Protection: iROM .bbss.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.bbss) /*Not initialised bit data*/
*(.bbss*)
/*PROTECTED REGION ID(Protection: iROM .bbss) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__bbss_end = .);
. = ALIGN(8);
} > DMI_DSPR /* DMI_DSPR: Local Data RAM (DSPR) */
/*
* Bit variables
*/
.bdata :
{
PROVIDE(__bdata_start = .);
/*PROTECTED REGION ID(Protection: iROM .bdata.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.bdata) /*Bit variables*/
*(.bdata*)
/*PROTECTED REGION ID(Protection: iROM .bdata) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__bdata_end = .);
. = ALIGN(8);
} > DMI_DSPR AT > PMU_PFLASH0 /* DMI_DSPR: Local Data RAM (DSPR) */ /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*Small Data-Sections*/
/*
* Storage of write-protected data addressed as small
*/
.sdata2 :
{
PROVIDE(__sdata2_start = .);
/*PROTECTED REGION ID(Protection: iROM .sdata2.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.sdata.rodata) /*Storage of write-protected data addressed as small*/
*(.sdata.rodata*)
*(.gnu.linkonce.sr.*)
/*PROTECTED REGION ID(Protection: iROM .sdata2) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__sdata2_end = .);
. = ALIGN(8);
} > PMU_PFLASH0 /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*
* Section stores initialised data which is addressable by small data area pointer (%a0)
*/
.sdata :
{
PROVIDE(__sdata_start = .);
/*PROTECTED REGION ID(Protection: iROM .sdata.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.sdata) /*Section stores initialised data which is addressable by small data area pointer (%a0)*/
*(.sdata*)
*(.gnu.linkonce.s.*)
/*PROTECTED REGION ID(Protection: iROM .sdata) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__sdata_end = .);
. = ALIGN(8);
} > DMI_DSPR AT > PMU_PFLASH0 /* DMI_DSPR: Local Data RAM (DSPR) */ /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*
* Not initialised data in section .sbss, addressable by small data area pointer (%a0)
*/
.sbss (NOLOAD) :
{
PROVIDE(__sbss_start = .);
/*PROTECTED REGION ID(Protection: iROM .sbss.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.sbss) /*Not initialised data in section .sbss, addressable by small data area pointer (%a0)*/
*(.sbss*)
*(.gnu.linkonce.sb.*)
/*PROTECTED REGION ID(Protection: iROM .sbss) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__sbss_end = .);
. = ALIGN(8);
} > DMI_DSPR /* DMI_DSPR: Local Data RAM (DSPR) */
/*Normal Data-Sections*/
/*
* Storage of write-protected data
*/
.rodata :
{
PROVIDE(__rodata_start = .);
/*PROTECTED REGION ID(Protection: iROM .rodata.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.rodata) /*Storage of write-protected data*/
*(.rodata*)
*(.gnu.linkonce.r.*)
*(.jcr.*)
/*PROTECTED REGION ID(Protection: iROM .rodata) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__rodata_end = .);
. = ALIGN(8);
} > PMU_PFLASH0 /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*
* Initialised data
*/
.data :
{
PROVIDE(__data_start = .);
/*PROTECTED REGION ID(Protection: iROM .data.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.data) /*Initialised data*/
*(.data*)
*(.gnu.linkonce.d.*)
/*PROTECTED REGION ID(Protection: iROM .data) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__data_end = .);
. = ALIGN(8);
} > DMI_DSPR AT > PMU_PFLASH0 /* DMI_DSPR: Local Data RAM (DSPR) */ /* PMU_PFLASH0: Program Flash Memory (PFLASH0) */
/*
* Not Initialised data
*/
.bss (NOLOAD) :
{
PROVIDE(__bss_start = .);
/*PROTECTED REGION ID(Protection: iROM .bss.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
*(.bss) /*Not Initialised data*/
*(.bss*)
*(.gnu.linkonce.b.*)
/*PROTECTED REGION ID(Protection: iROM .bss) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
PROVIDE(__bss_end = .);
. = ALIGN(8);
} > DMI_DSPR /* DMI_DSPR: Local Data RAM (DSPR) */
/*
* Section for constructors
*/
.ctors :
{
__CTOR_LIST__ = . ;
/*PROTECTED REGION ID(Protection: iROMconstructor.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
LONG(0) ;
/*PROTECTED REGION ID(Protection: iROMconstructor) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
__CTOR_END__ = . ;
. = ALIGN(8);
} > PMU_PFLASH0
/*
* Section for destructors
*/
.dtors :
{
__DTOR_LIST__ = . ;
/*PROTECTED REGION ID(Protection: iROM destructor.begin) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2);
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
LONG(0) ;
/*PROTECTED REGION ID(Protection: iROM destructor) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
__DTOR_END__ = . ;
. = ALIGN(8);
} > PMU_PFLASH0
/*
* Section for clear table
*/
.clear_sec :
{
. = ALIGN(8);
PROVIDE(__clear_table = .) ;
LONG(0 + ADDR(.bss)); LONG(SIZEOF(.bss));
LONG(0 + ADDR(.sbss)); LONG(SIZEOF(.sbss));
LONG(0 + ADDR(.zbss)); LONG(SIZEOF(.zbss));
LONG(0 + ADDR(.bbss)); LONG(SIZEOF(.bbss));
/*PROTECTED REGION ID(Protection: iROM clear section) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
LONG(-1); LONG(-1);
} > PMU_PFLASH0
/*
* Section for copy table
*/
.copy_sec :
{
. = ALIGN(8);
PROVIDE(__copy_table = .) ;
LONG(LOADADDR(.data)); LONG(0 + ADDR(.data)); LONG(SIZEOF(.data));
LONG(LOADADDR(.sdata)); LONG(0 + ADDR(.sdata)); LONG(SIZEOF(.sdata));
LONG(LOADADDR(.zdata)); LONG(0 + ADDR(.zdata)); LONG(SIZEOF(.zdata));
LONG(LOADADDR(.bdata)); LONG(0 + ADDR(.bdata)); LONG(SIZEOF(.bdata));
/*PROTECTED REGION ID(Protection: iROM copy section) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
LONG(-1); LONG(-1); LONG(-1);
} > PMU_PFLASH0
/*
* Section for ustack
*/
.ustack :
{
. = ALIGN(8);
__USTACK_BEGIN = . ;
. += __USTACK_SIZE ;
. = ALIGN(8);
__USTACK = . ;
__USTACK_END = . ;
} > DMI_DSPR
/*
* Section for istack
*/
.istack :
{
. = ALIGN(8);
__ISTACK_BEGIN = . ;
. += __ISTACK_SIZE ;
. = ALIGN(8);
__ISTACK = . ;
__ISTACK_END = . ;
} > DMI_DSPR
/*
* Section for heap
*/
.heap :
{
. = ALIGN(8);
__HEAP_BEGIN = . ;
__HEAP = . ;
. += __HEAP_SIZE ;
. = ALIGN(8);
__HEAP_END = . ;
} > DMI_DSPR
/*
* Section for CSA
*/
.csa :
{
. = ALIGN(64);
__CSA_BEGIN = . ;
__CSA = . ;
. += __CSA_SIZE ;
. = ALIGN(64);
__CSA_END = . ;
} > DMI_DSPR
/*PROTECTED REGION ID(Protection:iROM-User-Sections) ENABLED START*/
/*Protection-Area for your own LDF-Code*/
/*PROTECTED REGION END*/
}

View File

@ -0,0 +1,140 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\cpu.c
* \brief Bootloader cpu module source file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
/****************************************************************************************
* Include files
****************************************************************************************/
#include "boot.h" /* bootloader generic header */
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Pointer to the user program's reset vector. */
#define CPU_USER_PROGRAM_STARTADDR_PTR ((blt_addr)(FlashGetUserProgBaseAddress()))
/****************************************************************************************
* Hook functions
****************************************************************************************/
#if (BOOT_CPU_USER_PROGRAM_START_HOOK > 0)
extern blt_bool CpuUserProgramStartHook(void);
#endif
/****************************************************************************************
* External functions
****************************************************************************************/
extern void _start(void); /* implemented in crt0-tc1x.S */
/************************************************************************************//**
** \brief Starts the user program, if one is present. In this case this function
** does not return.
** \return none.
**
****************************************************************************************/
void CpuStartUserProgram(void)
{
void (*pProgResetHandler)(void);
/* check if a user program is present by verifying the checksum */
if (NvmVerifyChecksum() == BLT_FALSE)
{
/* not a valid user program so it cannot be started */
return;
}
#if (BOOT_CPU_USER_PROGRAM_START_HOOK > 0)
/* invoke callback */
if (CpuUserProgramStartHook() == BLT_FALSE)
{
/* callback requests the user program to not be started */
return;
}
#endif
#if (BOOT_COM_ENABLE > 0)
/* release the communication interface */
ComFree();
#endif
/* reset the timer */
TimerReset();
/* set the address where the bootloader needs to jump to. the user program entry,
* typically called _start, is expected to be located at the start of the user program
* flash.
*/
pProgResetHandler = (void(*)(void))((blt_addr*)CPU_USER_PROGRAM_STARTADDR_PTR);
/* start the user program by activating its reset interrupt service routine */
pProgResetHandler();
} /*** end of CpuStartUserProgram ***/
/************************************************************************************//**
** \brief Copies data from the source to the destination address.
** \param dest Destination address for the data.
** \param src Source address of the data.
** \param len length of the data in bytes.
** \return none.
**
****************************************************************************************/
void CpuMemCopy(blt_addr dest, blt_addr src, blt_int16u len)
{
blt_int8u *from, *to;
/* set casted pointers */
from = (blt_int8u *)src;
to = (blt_int8u *)dest;
/* copy all bytes from source address to destination address */
while(len-- > 0)
{
/* store byte value from source to destination */
*to++ = *from++;
/* keep the watchdog happy */
CopService();
}
} /*** end of CpuMemCopy ***/
/************************************************************************************//**
** \brief Perform a soft reset of the microcontroller by starting from the reset ISR.
** \return none.
**
****************************************************************************************/
void CpuReset(void)
{
/* perform a software reset by calling the reset ISR routine */
_start();
} /*** end of CpuReset ***/
/*********************************** end of cpu.c **************************************/

View File

@ -0,0 +1,51 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\cpu.h
* \brief Bootloader cpu module header file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
#ifndef CPU_H
#define CPU_H
/****************************************************************************************
* Include files
****************************************************************************************/
#include "cpu_comp.h" /* compiler specific CPU definitions */
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void CpuStartUserProgram(void);
void CpuMemCopy(blt_addr dest, blt_addr src, blt_int16u len);
void CpuReset(void);
#endif /* CPU_H */
/*********************************** end of cpu.h **************************************/

View File

@ -0,0 +1,967 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\flash.c
* \brief Bootloader flash driver source file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
/****************************************************************************************
* Include files
****************************************************************************************/
#include "boot.h" /* bootloader generic header */
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Value for an invalid flash sector. */
#define FLASH_INVALID_SECTOR (0xffu)
/** \brief Value for an invalid flash address. */
#define FLASH_INVALID_ADDRESS (0xffffffffu)
/** \brief Standard size of a flash block for writing. */
#define FLASH_WRITE_BLOCK_SIZE (256u)
/** \brief Total numbers of sectors in array flashLayout[]. */
#define FLASH_TOTAL_SECTORS (sizeof(flashLayout)/sizeof(flashLayout[0]))
/** \brief The flash driver is setup to operate on the cached PFLASH addresses, whereas
* the actual PFLASH commands should operate on non-cached addresses. This
* macro defines the offset between cached (80xxxxxxh) and non-cached
* (A0xxxxxxh) addresses.
*/
#define FLASH_NON_CACHED_OFFSET (0x20000000u)
/** \brief Base address of the PFLASH0 module. */
#define FLASH_PFLASH0_BASE (0x80000000u)
/** \brief Base address of the PFLASH1 module. */
#define FLASH_PFLASH1_BASE (0x80800000u)
/** \brief Base address of the PFLASH0 flash status register. */
#define FLASH_PFLASH0_FSR_ADDR (0xF8002010u)
/** \brief Base address of the PFLASH0 flash status register. */
#define FLASH_PFLASH1_FSR_ADDR (0xF8004010u)
/** \brief Macro that returns the PFLASHx modules base address, giving any address
* in PFLASH.
*/
#define FLASH_GET_PFLASH_BASE(addr) ((addr < FLASH_PFLASH1_BASE) ? \
FLASH_PFLASH0_BASE : FLASH_PFLASH1_BASE)
/** \brief Macro that converts are 32 bit address into a pointer to a 32-bit unsigned
* value and writes a value to this pointer.
*/
#define FLASH_WRITE_TO_U32_PTR_BY_ADDR(addr, val) ((*((volatile blt_int32u *) (addr+FLASH_NON_CACHED_OFFSET))) = val)
/** \brief The FLASHx_FSR register is the only register used in this driver. Its address
* depends on the PFLASH module that is being operated on. This macro gets the
* correct base address for the FSR register.
*/
#define FLASH_GET_FSR_REG_ADDR(addr) ((addr < FLASH_PFLASH1_BASE) ? \
FLASH_PFLASH0_FSR_ADDR : FLASH_PFLASH1_FSR_ADDR)
/** \brief Offset in bytes from the bootblock's base address where the checksum is
* located.
*/
#define FLASH_CS_OFFSET (0x04u)
/** \brief Offset in bytes from the bootblock's base address where the checksum area
* starts.
*/
#define FLASH_CS_RANGE_START_OFFSET (0x08u)
/** \brief The total number of 32-bit words that are in the checksum address range. */
#define FLASH_CS_RANGE_TOTAL_WORDS ((FLASH_WRITE_BLOCK_SIZE/4u) - \
(FLASH_CS_RANGE_START_OFFSET/4u))
/****************************************************************************************
* Type definitions
****************************************************************************************/
/** \brief Flash sector descriptor type. */
typedef struct
{
blt_addr sector_start; /**< sector start address */
blt_int32u sector_size; /**< sector size in bytes */
blt_int8u sector_num; /**< sector number */
} tFlashSector;
/** \brief Structure type for grouping flash block information.
* \details Programming is done per block of max FLASH_WRITE_BLOCK_SIZE. for this a
* flash block manager is implemented in this driver. this flash block manager
* depends on this flash block info structure. It holds the base address of
* the flash block and the data that should be programmed into the flash
* block. The .base_addr must be a multiple of FLASH_WRITE_BLOCK_SIZE.
*/
typedef struct
{
blt_addr base_addr;
blt_int8u data[FLASH_WRITE_BLOCK_SIZE];
} tFlashBlockInfo;
/****************************************************************************************
* Function prototypes
****************************************************************************************/
static blt_bool FlashInitBlock(tFlashBlockInfo *block, blt_addr address);
static tFlashBlockInfo *FlashSwitchBlock(tFlashBlockInfo *block, blt_addr base_addr);
static blt_bool FlashAddToBlock(tFlashBlockInfo *block, blt_addr address,
blt_int8u *data, blt_int32u len);
static blt_bool FlashWriteBlock(tFlashBlockInfo *block);
static blt_bool FlashEraseSectors(blt_int8u first_sector, blt_int8u last_sector);
static blt_int8u FlashGetSector(blt_addr address);
static blt_addr FlashGetSectorBaseAddr(blt_int8u sector);
static blt_int32u FlashGetSectorSize(blt_int8u sector);
static blt_bool FlashTricoreProgramPage(blt_addr start_addr, blt_int8u *data);
static blt_bool FlashTricoreEraseSector(blt_addr start_addr);
/****************************************************************************************
* Local constant declarations
****************************************************************************************/
/** \brief Array wit the layout of the flash memory.
* \details The current implementation assumes that the bootloader is in the 2Mbyte
* PFLASH0 and supports flash operations only on the 2Mbyte PFLASH1. The reason
* for this is that a flash module cannot be in read mode and command mode at
* the same time. A future improvement is one where the actual flash command
* code is copied and run from RAM, to bypass this restriction.
*/
static const tFlashSector flashLayout[] =
{
{ 0x80800000, 0x04000, 0}, /* flash sector 0 - 16kb */
{ 0x80804000, 0x04000, 1}, /* flash sector 1 - 16kb */
{ 0x80808000, 0x04000, 2}, /* flash sector 2 - 16kb */
{ 0x8080C000, 0x04000, 3}, /* flash sector 3 - 16kb */
{ 0x80810000, 0x04000, 4}, /* flash sector 4 - 16kb */
{ 0x80814000, 0x04000, 5}, /* flash sector 5 - 16kb */
{ 0x80818000, 0x04000, 6}, /* flash sector 6 - 16kb */
{ 0x8081C000, 0x04000, 7}, /* flash sector 7 - 16kb */
{ 0x80820000, 0x20000, 8}, /* flash sector 8 - 128kb */
{ 0x80840000, 0x40000, 9}, /* flash sector 9 - 256kb */
{ 0x80880000, 0x40000, 10}, /* flash sector 10 - 256kb */
{ 0x808C0000, 0x40000, 11}, /* flash sector 11 - 256kb */
{ 0x80900000, 0x40000, 12}, /* flash sector 12 - 256kb */
{ 0x80940000, 0x40000, 13}, /* flash sector 13 - 256kb */
{ 0x80980000, 0x40000, 14}, /* flash sector 14 - 256kb */
{ 0x809C0000, 0x40000, 15}, /* flash sector 15 - 256kb */
#if (BOOT_NVM_SIZE_KB > 2048)
#error "BOOT_NVM_SIZE_KB > 2048 is currently not supported."
#endif
};
/****************************************************************************************
* Local data declarations
****************************************************************************************/
/** \brief Local variable with information about the flash block that is currently
* being operated on.
* \details The smallest amount of flash that can be programmed is
* FLASH_WRITE_BLOCK_SIZE. A flash block manager is implemented in this driver
* and stores info in this variable. Whenever new data should be flashed, it
* is first added to a RAM buffer, which is part of this variable. Whenever
* the RAM buffer, which has the size of a flash block, is full or data needs
* to be written to a different block, the contents of the RAM buffer are
* programmed to flash. The flash block manager requires some software
* overhead, yet results is faster flash programming because data is first
* harvested, ideally until there is enough to program an entire flash block,
* before the flash device is actually operated on.
*/
static tFlashBlockInfo blockInfo;
/** \brief Local variable with information about the flash boot block.
* \details The first block of the user program holds the vector table, which on the
* STM32 is also the where the checksum is written to. Is it likely that
* the vector table is first flashed and then, at the end of the programming
* sequence, the checksum. This means that this flash block need to be written
* to twice. Normally this is not a problem with flash memory, as long as you
* write the same values to those bytes that are not supposed to be changed
* and the locations where you do write to are still in the erased 0xFF state.
* Unfortunately, writing twice to flash this way, does not work reliably on
* all micros. This is why we need to have an extra block, the bootblock,
* placed under the management of the block manager. This way is it possible
* to implement functionality so that the bootblock is only written to once
* at the end of the programming sequence.
*/
static tFlashBlockInfo bootBlockInfo;
/************************************************************************************//**
** \brief Initializes the flash driver.
** \return none.
**
****************************************************************************************/
void FlashInit(void)
{
/* init the flash block info structs by setting the address to an invalid address */
blockInfo.base_addr = FLASH_INVALID_ADDRESS;
bootBlockInfo.base_addr = FLASH_INVALID_ADDRESS;
} /*** end of FlashInit ***/
/************************************************************************************//**
** \brief Writes the data to flash through a flash block manager. Note that this
** function also checks that no data is programmed outside the flash
** memory region, so the bootloader can never be overwritten.
** \param addr Start address.
** \param len Length in bytes.
** \param data Pointer to the data buffer.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FlashWrite(blt_addr addr, blt_int32u len, blt_int8u *data)
{
blt_addr base_addr;
/* make sure the addresses are within the flash device */
if ( (FlashGetSector(addr) == FLASH_INVALID_SECTOR) || \
(FlashGetSector(addr+len-1) == FLASH_INVALID_SECTOR) )
{
return BLT_FALSE;
}
/* if this is the bootblock, then let the boot block manager handle it */
base_addr = (addr/FLASH_WRITE_BLOCK_SIZE)*FLASH_WRITE_BLOCK_SIZE;
if (base_addr == flashLayout[0].sector_start)
{
/* let the boot block manager handle it */
return FlashAddToBlock(&bootBlockInfo, addr, data, len);
}
/* let the block manager handle it */
return FlashAddToBlock(&blockInfo, addr, data, len);
} /*** end of FlashWrite ***/
/************************************************************************************//**
** \brief Erases the flash memory. Note that this function also checks that no
** data is erased outside the flash memory region, so the bootloader can
** never be erased.
** \param addr Start address.
** \param len Length in bytes.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FlashErase(blt_addr addr, blt_int32u len)
{
blt_int8u first_sector;
blt_int8u last_sector;
/* obtain the first and last sector number */
first_sector = FlashGetSector(addr);
last_sector = FlashGetSector(addr+len-1);
/* check them */
if ( (first_sector == FLASH_INVALID_SECTOR) || (last_sector == FLASH_INVALID_SECTOR) )
{
return BLT_FALSE;
}
/* erase the sectors */
return FlashEraseSectors(first_sector, last_sector);
} /*** end of FlashErase ***/
/************************************************************************************//**
** \brief Writes a checksum of the user program to non-volatile memory. This is
** performed once the entire user program has been programmed. Through
** the checksum, the bootloader can check if the programming session
** was completed, which indicates that a valid user programming is
** present and can be started.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FlashWriteChecksum(void)
{
blt_int32u signature_checksum = 0;
blt_int8u wordIdx;
/* for the Tricore TC1798 target, the bootlblock is FLASH_WRITE_BLOCK_SIZE in size.
* the actual 32-bit checksum value in this bootblock is located at:
* <bootblock_base_addr> + 4.
* for this reason the checksum is defined as the one's complement value of the sum
* of everything else in the bootblock, so starting at:
* <bootblock_base_addr> + 8 and ending at:
* <bootblock_base_addr> + FLASH_WRITE_BLOCK_SIZE - 1;
*
* note that the user program need to be modified to reserve 32-bit at
* <bootblock_base_addr> + 4, because the bootload will write the checksum value
* here. refer to the port specific documentation for additional details.
*
* keep in mind that this checksum is just used as a user program signature, i.e. as
* a flag to figure out if a user program is present or not. the checksum is not
* calculated over the full user program size. such a checksum routine is typically
* application/customer specific and therefore not part of the standard bootloader.
* it can however be easily implemented by adding the following macro to blt_conf.h:
* #define BOOT_NVM_CHECKSUM_HOOKS_ENABLE (1).
* You can then implement your own checksum write/verify routines in the hook
* functions NvmWriteChecksumHook() and NvmVerifyChecksumHook().
*/
/* first check that the bootblock contains valid data. if not, this means the
* bootblock is not part of the reprogramming this time and therefore no
* new checksum needs to be written
*/
if (bootBlockInfo.base_addr == FLASH_INVALID_ADDRESS)
{
return BLT_TRUE;
}
/* compute the checksum. note that the data in the checksum range is not yet written
* to flash but is present in the bootblock data structure at this point.
*/
for (wordIdx = 0; wordIdx < FLASH_CS_RANGE_TOTAL_WORDS; wordIdx++)
{
signature_checksum += *((blt_int32u*)(&bootBlockInfo.data[(wordIdx*4)+FLASH_CS_RANGE_START_OFFSET]));
}
signature_checksum = ~signature_checksum; /* one's complement */
/* write the checksum */
return FlashWrite(flashLayout[0].sector_start+FLASH_CS_OFFSET,
sizeof(blt_addr), (blt_int8u*)&signature_checksum);
} /*** end of FlashWriteChecksum ***/
/************************************************************************************//**
** \brief Verifies the checksum, which indicates that a valid user program is
** present and can be started.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FlashVerifyChecksum(void)
{
blt_int32u signature_checksum = 0;
blt_int32u signature_checksum_rom;
blt_int8u wordIdx;
/* compute the checksum by reading it from flash */
for (wordIdx = 0; wordIdx < FLASH_CS_RANGE_TOTAL_WORDS; wordIdx++)
{
signature_checksum += *((blt_int32u*)(flashLayout[0].sector_start + (wordIdx*4) + FLASH_CS_RANGE_START_OFFSET));
}
signature_checksum = ~signature_checksum; /* one's complement */
/* read the checksum value from flash that was writtin by the bootloader at the end
* of the last firmware update
*/
signature_checksum_rom = *((blt_int32u*)(flashLayout[0].sector_start + FLASH_CS_OFFSET));
/* verify that they are both the same */
if (signature_checksum == signature_checksum_rom)
{
/* checksum okay */
return BLT_TRUE;
}
/* checksum incorrect */
return BLT_FALSE;
} /*** end of FlashVerifyChecksum ***/
/************************************************************************************//**
** \brief Finalizes the flash driver operations. There could still be data in
** the currently active block that needs to be flashed.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool FlashDone(void)
{
/* check if there is still data waiting to be programmed in the boot block */
if (bootBlockInfo.base_addr != FLASH_INVALID_ADDRESS)
{
if (FlashWriteBlock(&bootBlockInfo) == BLT_FALSE)
{
return BLT_FALSE;
}
}
/* check if there is still data waiting to be programmed */
if (blockInfo.base_addr != FLASH_INVALID_ADDRESS)
{
if (FlashWriteBlock(&blockInfo) == BLT_FALSE)
{
return BLT_FALSE;
}
}
/* still here so all is okay */
return BLT_TRUE;
} /*** end of FlashDone ***/
/************************************************************************************//**
** \brief Obtains the base address of the flash memory available to the user program.
** This is basically the first address in the flashLayout table.
** \return Base address.
**
****************************************************************************************/
blt_addr FlashGetUserProgBaseAddress(void)
{
return flashLayout[0].sector_start;
} /*** end of FlashGetUserProgBaseAddress ***/
/************************************************************************************//**
** \brief Copies data currently in flash to the block->data and sets the
** base address.
** \param block Pointer to flash block info structure to operate on.
** \param address Base address of the block data.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool FlashInitBlock(tFlashBlockInfo *block, blt_addr address)
{
/* check address alignment */
if ((address % FLASH_WRITE_BLOCK_SIZE) != 0)
{
return BLT_FALSE;
}
/* make sure that we are initializing a new block and not the same one */
if (block->base_addr == address)
{
/* block already initialized, so nothing to do */
return BLT_TRUE;
}
/* set the base address and copies the current data from flash */
block->base_addr = address;
CpuMemCopy((blt_addr)block->data, address, FLASH_WRITE_BLOCK_SIZE);
return BLT_TRUE;
} /*** end of FlashInitBlock ***/
/************************************************************************************//**
** \brief Switches blocks by programming the current one and initializing the
** next.
** \param block Pointer to flash block info structure to operate on.
** \param base_addr Base address of the next block.
** \return The pointer of the block info struct that is no being used, or a NULL
** pointer in case of error.
**
****************************************************************************************/
static tFlashBlockInfo *FlashSwitchBlock(tFlashBlockInfo *block, blt_addr base_addr)
{
/* check if a switch needs to be made away from the boot block. in this case the boot
* block shouldn't be written yet, because this is done at the end of the programming
* session by FlashDone(), this is right after the checksum was written.
*/
if (block == &bootBlockInfo)
{
/* switch from the boot block to the generic block info structure */
block = &blockInfo;
}
/* check if a switch back into the bootblock is needed. in this case the generic block
* doesn't need to be written here yet.
*/
else if (base_addr == flashLayout[0].sector_start)
{
/* switch from the generic block to the boot block info structure */
block = &bootBlockInfo;
base_addr = flashLayout[0].sector_start;
}
else
{
/* need to switch to a new block, so program the current one and init the next */
if (FlashWriteBlock(block) == BLT_FALSE)
{
return BLT_NULL;
}
}
/* initialize tne new block when necessary */
if (FlashInitBlock(block, base_addr) == BLT_FALSE)
{
return BLT_NULL;
}
/* still here to all is okay */
return block;
} /*** end of FlashSwitchBlock ***/
/************************************************************************************//**
** \brief Programming is done per block. This function adds data to the block
** that is currently collecting data to be written to flash. If the
** address is outside of the current block, the current block is written
** to flash an a new block is initialized.
** \param block Pointer to flash block info structure to operate on.
** \param address Flash destination address.
** \param data Pointer to the byte array with data.
** \param len Number of bytes to add to the block.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool FlashAddToBlock(tFlashBlockInfo *block, blt_addr address,
blt_int8u *data, blt_int32u len)
{
blt_addr current_base_addr;
blt_int8u *dst;
blt_int8u *src;
/* determine the current base address */
current_base_addr = (address/FLASH_WRITE_BLOCK_SIZE)*FLASH_WRITE_BLOCK_SIZE;
/* make sure the blockInfo is not uninitialized */
if (block->base_addr == FLASH_INVALID_ADDRESS)
{
/* initialize the blockInfo struct for the current block */
if (FlashInitBlock(block, current_base_addr) == BLT_FALSE)
{
return BLT_FALSE;
}
}
/* check if the new data fits in the current block */
if (block->base_addr != current_base_addr)
{
/* need to switch to a new block, so program the current one and init the next */
block = FlashSwitchBlock(block, current_base_addr);
if (block == BLT_NULL)
{
return BLT_FALSE;
}
}
/* add the data to the current block, but check for block overflow */
dst = &(block->data[address - block->base_addr]);
src = data;
do
{
/* keep the watchdog happy */
CopService();
/* buffer overflow? */
if ((blt_addr)(dst-&(block->data[0])) >= FLASH_WRITE_BLOCK_SIZE)
{
/* need to switch to a new block, so program the current one and init the next */
block = FlashSwitchBlock(block, current_base_addr+FLASH_WRITE_BLOCK_SIZE);
if (block == BLT_NULL)
{
return BLT_FALSE;
}
/* reset destination pointer */
dst = &(block->data[0]);
}
/* write the data to the buffer */
*dst = *src;
/* update pointers */
dst++;
src++;
/* decrement byte counter */
len--;
}
while (len > 0);
/* still here so all is good */
return BLT_TRUE;
} /*** end of FlashAddToBlock ***/
/************************************************************************************//**
** \brief Programs FLASH_WRITE_BLOCK_SIZE bytes to flash from the block->data
** array.
** \param block Pointer to flash block info structure to operate on.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool FlashWriteBlock(tFlashBlockInfo *block)
{
blt_int8u sector_num;
/* check that address is actually within flash */
sector_num = FlashGetSector(block->base_addr);
if (sector_num == FLASH_INVALID_SECTOR)
{
return BLT_FALSE;
}
/* the FLASH_WRITE_BLOCK_SIZE is configured to exactly match the size of a page in
* PFLASH. so here simply need to program one page in PFLASH.
*/
return FlashTricoreProgramPage(block->base_addr, block->data);
} /*** end of FlashWriteBlock ***/
/************************************************************************************//**
** \brief Erases the flash sectors from first_sector up until last_sector.
** \param first_sector First flash sector number.
** \param last_sector Last flash sector number.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool FlashEraseSectors(blt_int8u first_sector, blt_int8u last_sector)
{
blt_int8u current_sector;
blt_bool result = BLT_TRUE;
/* validate the sector numbers */
if (first_sector > last_sector)
{
return BLT_FALSE;
}
if ( (first_sector < flashLayout[0].sector_num) || \
(last_sector > flashLayout[FLASH_TOTAL_SECTORS-1].sector_num) )
{
return BLT_FALSE;
}
/* the table flashLayout[] is implemented such that it exactly matches the sectors
* in PFLASH. this means that here we simply need to loop through the sectors one-
* by-one and erase them.
*/
for (current_sector = first_sector; current_sector <= last_sector; current_sector++)
{
if (FlashTricoreEraseSector(FlashGetSectorBaseAddr(current_sector)) == BLT_FALSE)
{
/* flag error and stop the loop */
result = BLT_FALSE;
break;
}
/* keep the watchdog happy */
CopService();
}
/* return the result */
return result;
} /*** end of FlashEraseSectors ***/
/************************************************************************************//**
** \brief Determines the flash sector the address is in.
** \param address Address in the flash sector.
** \return Flash sector number or FLASH_INVALID_SECTOR.
**
****************************************************************************************/
static blt_int8u FlashGetSector(blt_addr address)
{
blt_int8u sectorIdx;
/* search through the sectors to find the right one */
for (sectorIdx = 0; sectorIdx < FLASH_TOTAL_SECTORS; sectorIdx++)
{
/* keep the watchdog happy */
CopService();
/* is the address in this sector? */
if ( (address >= flashLayout[sectorIdx].sector_start) && \
(address < (flashLayout[sectorIdx].sector_start + \
flashLayout[sectorIdx].sector_size)) )
{
/* return the sector number */
return flashLayout[sectorIdx].sector_num;
}
}
/* still here so no valid sector found */
return FLASH_INVALID_SECTOR;
} /*** end of FlashGetSector ***/
/************************************************************************************//**
** \brief Determines the flash sector base address.
** \param sector Sector to get the base address of.
** \return Flash sector base address or FLASH_INVALID_ADDRESS.
**
****************************************************************************************/
static blt_addr FlashGetSectorBaseAddr(blt_int8u sector)
{
blt_int8u sectorIdx;
/* search through the sectors to find the right one */
for (sectorIdx = 0; sectorIdx < FLASH_TOTAL_SECTORS; sectorIdx++)
{
/* keep the watchdog happy */
CopService();
if (flashLayout[sectorIdx].sector_num == sector)
{
return flashLayout[sectorIdx].sector_start;
}
}
/* still here so no valid sector found */
return FLASH_INVALID_ADDRESS;
} /*** end of FlashGetSectorBaseAddr ***/
/************************************************************************************//**
** \brief Determines the flash sector size.
** \param sector Sector to get the size of.
** \return Flash sector size or 0.
**
****************************************************************************************/
static blt_int32u FlashGetSectorSize(blt_int8u sector)
{
blt_int8u sectorIdx;
/* search through the sectors to find the right one */
for (sectorIdx = 0; sectorIdx < FLASH_TOTAL_SECTORS; sectorIdx++)
{
/* keep the watchdog happy */
CopService();
if (flashLayout[sectorIdx].sector_num == sector)
{
return flashLayout[sectorIdx].sector_size;
}
}
/* still here so no valid sector found */
return 0;
} /*** end of FlashGetSectorSize ***/
/************************************************************************************//**
** \brief Programs FLASH_WRITE_BLOCK_SIZE bytes into flash starting at the page's base
** address.
** \param start_addr Starting address of the page where the bytes should be
** programmed. Should be aligned to FLASH_WRITE_BLOCK_SIZE.
** \param data Pointer to a byte array with the data to be programmed. The array
** should have FLASH_WRITE_BLOCK_SIZE bytes.
** \return BLT_TRUE is the page was programmed successfully, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool FlashTricoreProgramPage(blt_addr start_addr, blt_int8u *data)
{
blt_addr baseAddr;
blt_int32u *dataPtr;
blt_int8u *readPtr;
blt_int32u idx;
FLASHn_FSR_t *pflashFSR;
/* check address alignment to a page in PFLASH */
if ((start_addr % FLASH_WRITE_BLOCK_SIZE) != 0)
{
return BLT_FALSE;
}
/* determine base address of the PFLASH module */
baseAddr = FLASH_GET_PFLASH_BASE(start_addr);
/* set pointer for the PFLASH module's FSR register */
pflashFSR = (FLASHn_FSR_t *)FLASH_GET_FSR_REG_ADDR(start_addr);
/* use "clear status" command to clear flags */
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0x5554u, 0x000000F5u);
/* execute "enter page mode" command to activate the PFLASH assembly buffer */
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0x5554u, 0x00000050u);
/* perform DSYNC */
CpuSetDSYNC();
/* wait until FSR.xFPAGE = '1' */
while(pflashFSR->bits.PFPAGE != 1)
{
/* fail if FSR.SQER = '1' */
if (pflashFSR->bits.SQER == 1)
{
return BLT_FALSE;
}
/* fail if FSR.PROER = '1' */
if (pflashFSR->bits.PROER == 1)
{
return BLT_FALSE;
}
/* keep the watchdog happy */
CopService();
}
/* load FLASH_WRITE_BLOCK_SIZE bytes of program data into the assembly buffer */
dataPtr = (blt_int32u *)data;
for (idx = 0; idx <(FLASH_WRITE_BLOCK_SIZE/8u); idx++)
{
/* write first 32-bit value */
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0x55F0U, *dataPtr);
dataPtr++;
/* write second 32-bit value */
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0x55F4U, *dataPtr);
dataPtr++;
}
/* launch the "write page" command */
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0x5554u, 0x000000AAu);
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0xAAA8u, 0x00000055u);
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0x5554u, 0x000000A0u);
FLASH_WRITE_TO_U32_PTR_BY_ADDR(start_addr, 0x000000AAu);
/* perform DSYNC */
CpuSetDSYNC();
/* wait until FSR.PROG = '1' */
while(pflashFSR->bits.PROG != 1)
{
/* fail if FSR.SQER = '1' */
if (pflashFSR->bits.SQER == 1)
{
return BLT_FALSE;
}
/* fail if FSR.PROER = '1' */
if (pflashFSR->bits.PROER == 1)
{
return BLT_FALSE;
}
/* keep the watchdog happy */
CopService();
}
/* wait until FSR.xBUSY = '0' */
while(pflashFSR->bits.PBUSY == 1)
{
/* check flag FSR.xFOPER for 1 as abort criterion to protect against hardware
* failures causing BUSY to stay '1'
*/
if (pflashFSR->bits.PFOPER == 1)
{
return BLT_FALSE;
}
/* keep the watchdog happy */
CopService();
}
/* check FSR.VER flag */
if (pflashFSR->bits.VER != 0)
{
return BLT_FALSE;
}
/* fail if FSR.xFOPER = '1' */
if (pflashFSR->bits.PFOPER != 0)
{
return BLT_FALSE;
}
/* evaluate FSR.xDBER */
if(pflashFSR->bits.PFDBER != 0)
{
return BLT_FALSE;
}
/* use "clear status" command to clear flags */
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0x5554u, 0x000000F5u);
/* perform verification by checking the written values. do this on a byte-per-byte
* basis to also check the code for byte swapping mistakes.
*/
readPtr = (blt_int8u *)start_addr;
for (idx = 0; idx <FLASH_WRITE_BLOCK_SIZE; idx++)
{
/* verify 32-bits at a time */
if (*readPtr != data[idx])
{
return BLT_FALSE;
}
/* increment pointer */
readPtr++;
}
/* still here so programming was completed successfully */
return BLT_TRUE;
} /*** end of FlashTricoreProgramPage ***/
/************************************************************************************//**
** \brief Erases a sector in PFLASH. The sector is identified using its start
** address.
** \param start_addr Starting address of the sector that is to be erased.
** \return BLT_TRUE is the sector was successfully erased, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool FlashTricoreEraseSector(blt_addr start_addr)
{
blt_addr baseAddr;
FLASHn_FSR_t *pflashFSR;
blt_int32u sectorWords;
blt_int8u sectorNum;
blt_int32u *readPtr;
blt_int32u idx;
/* determine base address of the PFLASH module */
baseAddr = FLASH_GET_PFLASH_BASE(start_addr);
/* set pointer for the PFLASH module's FSR register */
pflashFSR = (FLASHn_FSR_t *)FLASH_GET_FSR_REG_ADDR(start_addr);
/* use "clear status" command to clear flags */
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0x5554u, 0x000000F5u);
/* issue "erase sector" command */
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0x5554u, 0x000000AAu);
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0xAAA8u, 0x00000055u);
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0x5554u, 0x00000080u);
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0x5554u, 0x000000AAu);
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0xAAA8u, 0x00000055u);
FLASH_WRITE_TO_U32_PTR_BY_ADDR(start_addr, 0x00000030u);
/* perform DSYNC */
CpuSetDSYNC();
/* wait until FSR.ERASE = '1' */
while(pflashFSR->bits.ERASE != 1)
{
/* fail if FSR.SQER = '1' */
if (pflashFSR->bits.SQER == 1)
{
return BLT_FALSE;
}
/* fail if FSR.PROER = '1' */
if (pflashFSR->bits.PROER == 1)
{
return BLT_FALSE;
}
/* keep the watchdog happy */
CopService();
}
/* wait until FSR.xBUSY = '0' */
while(pflashFSR->bits.PBUSY == 1)
{
/* check flag FSR.xFOPER for 1 as abort criterion to protect against hardware
* failures causing BUSY to stay '1'
*/
if (pflashFSR->bits.PFOPER == 1)
{
return BLT_FALSE;
}
/* keep the watchdog happy */
CopService();
}
/* check FSR.VER flag */
if (pflashFSR->bits.VER != 0)
{
return BLT_FALSE;
}
/* fail if FSR.xFOPER = '1' */
if (pflashFSR->bits.PFOPER != 0)
{
return BLT_FALSE;
}
/* use "clear status" command to clear flags */
FLASH_WRITE_TO_U32_PTR_BY_ADDR(baseAddr + 0x5554u, 0x000000F5u);
/* perform erase verification */
sectorNum = FlashGetSector(start_addr);
if (sectorNum == FLASH_INVALID_SECTOR)
{
/* should not happen */
return BLT_FALSE;
}
/* get sector size in words and set the read pointer to the first word in the sector */
sectorWords = FlashGetSectorSize(sectorNum) / sizeof(blt_int32u);
if (sectorWords == 0)
{
/* should not happen */
return BLT_FALSE;
}
readPtr = (blt_int32u *)(FlashGetSectorBaseAddr(sectorNum));
/* loop through all words in the sector and check that they are in the erase state.
* note that this is a 0 value for PFLASH.
*/
for (idx=0; idx<sectorWords; idx++)
{
if (*readPtr != 0)
{
/* not in the erased state */
return BLT_FALSE;
}
/* continue with the next word */
readPtr++;
/* keep the watchdog happy. this is a fast loop so no need to do it every iteration */
if ((idx % 100) == 0)
{
CopService();
}
}
/* still here so erase operation was completed successfully */
return BLT_TRUE;
} /*** end of FlashTricoreEraseSector ***/
/*********************************** end of flash.c ************************************/

View File

@ -0,0 +1,49 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\flash.c
* \brief Bootloader flash driver source file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
#ifndef FLASH_H
#define FLASH_H
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void FlashInit(void);
blt_bool FlashWrite(blt_addr addr, blt_int32u len, blt_int8u *data);
blt_bool FlashErase(blt_addr addr, blt_int32u len);
blt_bool FlashWriteChecksum(void);
blt_bool FlashVerifyChecksum(void);
blt_bool FlashDone(void);
blt_addr FlashGetUserProgBaseAddress(void);
#endif /* FLASH_H */
/*********************************** end of flash.h ************************************/

View File

@ -0,0 +1,216 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\nvm.c
* \brief Bootloader non-volatile memory driver source file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
/****************************************************************************************
* Include files
****************************************************************************************/
#include "boot.h" /* bootloader generic header */
/****************************************************************************************
* Hook functions
****************************************************************************************/
#if (BOOT_NVM_HOOKS_ENABLE > 0)
extern void NvmInitHook(void);
extern blt_int8u NvmWriteHook(blt_addr addr, blt_int32u len, blt_int8u *data);
extern blt_int8u NvmEraseHook(blt_addr addr, blt_int32u len);
extern blt_bool NvmDoneHook(void);
#endif
#if (BOOT_NVM_CHECKSUM_HOOKS_ENABLE > 0)
extern blt_bool NvmWriteChecksumHook(void);
extern blt_bool NvmVerifyChecksumHook(void);
#endif
/************************************************************************************//**
** \brief Initializes the NVM driver.
** \return none.
**
****************************************************************************************/
void NvmInit(void)
{
#if (BOOT_NVM_HOOKS_ENABLE > 0)
/* give the application a chance to initialize a driver for operating on NVM
* that is not by default supported by this driver.
*/
NvmInitHook();
#endif
/* init the internal driver */
FlashInit();
} /*** end of NvmInit ***/
/************************************************************************************//**
** \brief Programs the non-volatile memory.
** \param addr Start address.
** \param len Length in bytes.
** \param data Pointer to the data buffer.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool NvmWrite(blt_addr addr, blt_int32u len, blt_int8u *data)
{
#if (BOOT_NVM_HOOKS_ENABLE > 0)
blt_int8u result = BLT_NVM_NOT_IN_RANGE;
#endif
#if (BOOT_NVM_HOOKS_ENABLE > 0)
/* give the application a chance to operate on memory that is not by default supported
* by this driver.
*/
result = NvmWriteHook(addr, len, data);
/* process the return code */
if (result == BLT_NVM_OKAY)
{
/* data was within range of the additionally supported memory and succesfully
* programmed, so we are all done.
*/
return BLT_TRUE;
}
else if (result == BLT_NVM_ERROR)
{
/* data was within range of the additionally supported memory and attempted to be
* programmed, but an error occurred, so we can't continue.
*/
return BLT_FALSE;
}
#endif
/* still here so the internal driver should try and perform the program operation */
return FlashWrite(addr, len, data);
} /*** end of NvmWrite ***/
/************************************************************************************//**
** \brief Erases the non-volatile memory.
** \param addr Start address.
** \param len Length in bytes.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool NvmErase(blt_addr addr, blt_int32u len)
{
#if (BOOT_NVM_HOOKS_ENABLE > 0)
blt_int8u result = BLT_NVM_NOT_IN_RANGE;
#endif
#if (BOOT_NVM_HOOKS_ENABLE > 0)
/* give the application a chance to operate on memory that is not by default supported
* by this driver.
*/
result = NvmEraseHook(addr, len);
/* process the return code */
if (result == BLT_NVM_OKAY)
{
/* address was within range of the additionally supported memory and succesfully
* erased, so we are all done.
*/
return BLT_TRUE;
}
else if (result == BLT_NVM_ERROR)
{
/* address was within range of the additionally supported memory and attempted to be
* erased, but an error occurred, so we can't continue.
*/
return BLT_FALSE;
}
#endif
/* still here so the internal driver should try and perform the erase operation */
return FlashErase(addr, len);
} /*** end of NvmErase ***/
/************************************************************************************//**
** \brief Verifies the checksum, which indicates that a valid user program is
** present and can be started.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool NvmVerifyChecksum(void)
{
#if (BOOT_NVM_CHECKSUM_HOOKS_ENABLE > 0)
/* check checksum using the application specific method. */
return NvmVerifyChecksumHook();
#else
/* check checksum using the interally supported method. */
return FlashVerifyChecksum();
#endif
} /*** end of NvmVerifyChecksum ***/
/************************************************************************************//**
** \brief Once all erase and programming operations are completed, this
** function is called, so at the end of the programming session and
** right before a software reset is performed. It is used to calculate
** a checksum and program this into flash. This checksum is later used
** to determine if a valid user program is present in flash.
** \return BLT_TRUE if successful, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool NvmDone(void)
{
#if (BOOT_NVM_HOOKS_ENABLE > 0)
/* give the application's NVM driver a chance to finish up */
if (NvmDoneHook() == BLT_FALSE)
{
/* error so no need to continue */
return BLT_FALSE;
}
#endif
#if (BOOT_NVM_CHECKSUM_HOOKS_ENABLE > 0)
/* compute and write checksum, using the application specific method. */
if (NvmWriteChecksumHook() == BLT_FALSE)
{
return BLT_FALSE;
}
#else
/* compute and write checksum, which is programmed by the internal driver. */
if (FlashWriteChecksum() == BLT_FALSE)
{
return BLT_FALSE;
}
#endif
/* finish up internal driver operations */
return FlashDone();
} /*** end of NvmDone ***/
/*********************************** end of nvm.c **************************************/

View File

@ -0,0 +1,65 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\nvm.h
* \brief Bootloader non-volatile memory driver header file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
#ifndef NVM_H
#define NVM_H
/****************************************************************************************
* Include files
****************************************************************************************/
#include "flash.h" /* LPC2xxx flash driver */
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void NvmInit(void);
blt_bool NvmWrite(blt_addr addr, blt_int32u len, blt_int8u *data);
blt_bool NvmErase(blt_addr addr, blt_int32u len);
blt_bool NvmVerifyChecksum(void);
blt_bool NvmDone(void);
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/* return codes for hook function NvmWrite/Erase */
/** \brief Return code for success. */
#define BLT_NVM_ERROR (0x00)
/** \brief Return code for error. */
#define BLT_NVM_OKAY (0x01)
/** \brief Return code for not in range. */
#define BLT_NVM_NOT_IN_RANGE (0x02)
#endif /* NVM_H */
/*********************************** end of nvm.h **************************************/

View File

@ -0,0 +1,8 @@
/**
\defgroup Target_TRICORE_TC1798 Target Tricore TC1798
\brief Target dependent code for the Tricore TC1798 microcontroller family.
\details This module implements the bootloader's target dependent part for the
Tricore TC1798 microcontroller family.
*/

View File

@ -0,0 +1,148 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\timer.c
* \brief Bootloader timer driver source file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
/****************************************************************************************
* Include files
****************************************************************************************/
#include "boot.h" /* bootloader generic header */
/****************************************************************************************
* Local data declarations
****************************************************************************************/
/** \brief Local variable for storing the number of milliseconds that have elapsed since
* startup.
*/
static blt_int32u millisecond_counter;
/** \brief Holds the timer tick count for 1 millisecond. */
static blt_int16u millisecond_ticks;
/************************************************************************************//**
** \brief Initializes the polling based millisecond timer driver.
** \return none.
**
****************************************************************************************/
void TimerInit(void)
{
blt_int32u dummy;
/* reset the timer configuration */
TimerReset();
/* obtain "E" access rights */
CpuEnterInitMode();
/* enable the GPT12 timer module */
GPT120_CLC.reg = 0x00000000;
/* dummy read to avoid pipeline effects */
dummy = GPT120_CLC.reg;
/* release "E" access rights */
CpuLeaveInitMode();
/* core timer 3 is used for polling millisecond events. its configuration is:
* - timer 3 works in timer mode
* - external up/down control is disabled
* - prescaler factor is 128 (Ftimer3 = BOOT_CPU_SYSTEM_SPEED_KHZ / 128)
* - up/down control bit is reset
* - alternate output function T3OUT is disabled
* - timer 3 output toggle latch (T3OTL) is set to 0
* - timer 3 run bit is set
*/
GPT120_T3CON.reg = 0x00000845;
/* reset the timer 3 register so that counter starts at 0 */
GPT120_T3.reg = 0x00000000;
/* calculate the number of timer ticks in 1 millisecond */
millisecond_ticks = ((blt_int32u)BOOT_CPU_SYSTEM_SPEED_KHZ / 128);
/* reset the millisecond counter value */
millisecond_counter = 0;
} /*** end of TimerInit ***/
/************************************************************************************//**
** \brief Reset the timer by placing the timer back into it's default reset
** configuration.
** \return none.
**
****************************************************************************************/
void TimerReset(void)
{
blt_int32u dummy;
/* revert back to timer 3 configuration reset value */
GPT120_T3CON.reg = 0x00000000;
/* revert back to timer 3 reset value */
GPT120_T3.reg = 0x00000000;
/* obtain "E" access rights */
CpuEnterInitMode();
/* disable the GPT12 timer module */
GPT120_CLC.reg = 0x00000003;
/* dummy read to avoid pipeline effects */
dummy = GPT120_CLC.reg;
/* release "E" access rights */
CpuLeaveInitMode();
} /* end of TimerReset */
/************************************************************************************//**
** \brief Updates the millisecond timer.
** \return none.
**
****************************************************************************************/
void TimerUpdate(void)
{
/* check if the millisecond event occurred */
if (GPT120_T3.reg >= millisecond_ticks)
{
GPT120_T3.reg = 0;
/* reset timer 3 register for detecting the next millisecond */
/* increment the millisecond counter */
millisecond_counter++;
}
} /*** end of TimerUpdate ***/
/************************************************************************************//**
** \brief Obtains the counter value of the millisecond timer.
** \return Current value of the millisecond timer.
**
****************************************************************************************/
blt_int32u TimerGet(void)
{
/* updating timer here allows this function to be called in a loop with timeout
* detection.
*/
TimerUpdate();
/* read and return the amount of milliseconds that passed since initialization */
return millisecond_counter;
} /*** end of TimerGet ***/
/*********************************** end of timer.c ************************************/

View File

@ -0,0 +1,46 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\timer.h
* \brief Bootloader timer driver header file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
#ifndef TIMER_H
#define TIMER_H
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void TimerInit(void);
void TimerUpdate(void);
blt_int32u TimerGet(void);
void TimerReset(void);
#endif /* TIMER_H */
/*********************************** end of timer.h ************************************/

View File

@ -0,0 +1,63 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\types.h
* \brief Bootloader types header file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
#ifndef TYPES_H
#define TYPES_H
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Boolean true value. */
#define BLT_TRUE (1)
/** \brief Boolean false value. */
#define BLT_FALSE (0)
/** \brief NULL pointer value. */
#define BLT_NULL ((void *)0)
/****************************************************************************************
* Type definitions
****************************************************************************************/
typedef unsigned char blt_bool; /**< boolean type */
typedef char blt_char; /**< character type */
typedef unsigned long blt_addr; /**< memory address type */
typedef unsigned char blt_int8u; /**< 8-bit unsigned integer */
typedef signed char blt_int8s; /**< 8-bit signed integer */
typedef unsigned short blt_int16u; /**< 16-bit unsigned integer */
typedef signed short blt_int16s; /**< 16-bit signed integer */
typedef unsigned int blt_int32u; /**< 32-bit unsigned integer */
typedef signed int blt_int32s; /**< 32-bit signed integer */
#endif /* TYPES_H */
/*********************************** end of types.h ************************************/

View File

@ -0,0 +1,282 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\uart.c
* \brief Bootloader UART communication interface source file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
/****************************************************************************************
* Include files
****************************************************************************************/
#include "boot.h" /* bootloader generic header */
#if (BOOT_COM_UART_ENABLE > 0)
/****************************************************************************************
* Type definitions
****************************************************************************************/
typedef struct
{
blt_int32u reserved0[0x1]; /* 0x0 */
ASCn_PISEL_t PISEL; /* 0x4 */
ASCn_ID_t ID; /* 0x8 */
blt_int32u reserved3[0x1]; /* 0xc */
ASCn_CON_t CON; /* 0x10 */
ASCn_BG_t BG; /* 0x14 */
ASCn_FDV_t FDV; /* 0x18 */
blt_int32u reserved7[0x1]; /* 0x1c */
ASCn_TBUF_t TBUF; /* 0x20 */
ASCn_RBUF_t RBUF; /* 0x24 */
blt_int32u reserved10[0xa]; /* 0x28 */
ASCn_WHBCON_t WHBCON; /* 0x50 */
blt_int32u reserved12[0x27]; /* 0x54 */
ASCn_TSRC_t TSRC; /* 0xf0 */
ASCn_RSRC_t RSRC; /* 0xf4 */
ASCn_ESRC_t ESRC; /* 0xf8 */
ASCn_TBSRC_t TBSRC; /* 0xfc */
} tUartRegs;
/****************************************************************************************
* Macro definitions
****************************************************************************************/
/** \brief Timeout time for the reception of a CTO packet. The timer is started upon
* reception of the first packet byte.
*/
#define UART_CTO_RX_PACKET_TIMEOUT_MS (100u)
/****************************************************************************************
* Register definitions
****************************************************************************************/
#if (BOOT_COM_UART_CHANNEL_INDEX == 0)
/** \brief Set UART base address to ASC0. */
#define UARTx ((tUartRegs *) (blt_int32u)0xf0000a00)
#elif (BOOT_COM_UART_CHANNEL_INDEX == 1)
/** \brief Set UART base address to ASC1. */
#define UARTx ((tUartRegs *) (blt_int32u)0xf0000b00)
#else
/** \brief Set UART base address to ASC0 by default. */
#define UARTx ((tUartRegs *) (blt_int32u)0xf0000a00)
#endif
/****************************************************************************************
* Function prototypes
****************************************************************************************/
static blt_bool UartReceiveByte(blt_int8u *data);
static blt_bool UartTransmitByte(blt_int8u data);
/************************************************************************************//**
** \brief Initializes the UART communication interface.
** \return none.
**
****************************************************************************************/
void UartInit(void)
{
blt_int32u frequency, reload_value, fdv, dfreq;
/* Compute system frequency and reload value for ASC */
frequency = BOOT_CPU_SYSTEM_SPEED_KHZ * 1000;
/* reload_value = fdv/512 * freq/16/baudrate -1 ==>
* reload_value = (512*freq)/(baudrate * 512*16) - 1
* fdv = (reload_value + 1) * (baudrate*512*16/freq)
* reload_value = (frequency / 32) / baudrate - 1;
*/
reload_value = (frequency / ((blt_int32u)BOOT_COM_UART_BAUDRATE * 16)) - 1;
dfreq = frequency / (16*512);
fdv = (reload_value + 1) * (blt_int32u)BOOT_COM_UART_BAUDRATE / dfreq;
/* enable ASC module */
CpuEnterInitMode();
ASC0_CLC.bits.RMC = 1;
ASC0_CLC.bits.DISR = 0;
CpuLeaveInitMode();
/* configure the ASC module for 8,n,1 */
UARTx->CON.reg = 0;
UARTx->BG.reg = reload_value;
UARTx->FDV.reg = fdv;
UARTx->CON.bits.M = 0x01;
UARTx->CON.bits.R = 1;
UARTx->CON.bits.REN = 1;
UARTx->CON.bits.FDE = 1;
} /*** end of UartInit ***/
/************************************************************************************//**
** \brief Transmits a packet formatted for the communication interface.
** \param data Pointer to byte array with data that it to be transmitted.
** \param len Number of bytes that are to be transmitted.
** \return none.
**
****************************************************************************************/
void UartTransmitPacket(blt_int8u *data, blt_int8u len)
{
blt_int16u data_index;
blt_bool result;
/* verify validity of the len-paramenter */
ASSERT_RT(len <= BOOT_COM_UART_TX_MAX_DATA);
/* first transmit the length of the packet */
result = UartTransmitByte(len);
ASSERT_RT(result == BLT_TRUE);
/* transmit all the packet bytes one-by-one */
for (data_index = 0; data_index < len; data_index++)
{
/* keep the watchdog happy */
CopService();
/* write byte */
result = UartTransmitByte(data[data_index]);
ASSERT_RT(result == BLT_TRUE);
}
} /*** end of UartTransmitPacket ***/
/************************************************************************************//**
** \brief Receives a communication interface packet if one is present.
** \param data Pointer to byte array where the data is to be stored.
** \return BLT_TRUE if a packet was received, BLT_FALSE otherwise.
**
****************************************************************************************/
blt_bool UartReceivePacket(blt_int8u *data)
{
static blt_int8u xcpCtoReqPacket[BOOT_COM_UART_RX_MAX_DATA+1]; /* one extra for length */
static blt_int8u xcpCtoRxLength;
static blt_bool xcpCtoRxInProgress = BLT_FALSE;
static blt_int32u xcpCtoRxStartTime = 0;
/* start of cto packet received? */
if (xcpCtoRxInProgress == BLT_FALSE)
{
/* store the message length when received */
if (UartReceiveByte(&xcpCtoReqPacket[0]) == BLT_TRUE)
{
if (xcpCtoReqPacket[0] > 0)
{
/* store the start time */
xcpCtoRxStartTime = TimerGet();
/* reset packet data count */
xcpCtoRxLength = 0;
/* indicate that a cto packet is being received */
xcpCtoRxInProgress = BLT_TRUE;
}
}
}
else
{
/* store the next packet byte */
if (UartReceiveByte(&xcpCtoReqPacket[xcpCtoRxLength+1]) == BLT_TRUE)
{
/* increment the packet data count */
xcpCtoRxLength++;
/* check to see if the entire packet was received */
if (xcpCtoRxLength == xcpCtoReqPacket[0])
{
/* copy the packet data */
CpuMemCopy((blt_int32u)data, (blt_int32u)&xcpCtoReqPacket[1], xcpCtoRxLength);
/* done with cto packet reception */
xcpCtoRxInProgress = BLT_FALSE;
/* packet reception complete */
return BLT_TRUE;
}
}
else
{
/* check packet reception timeout */
if (TimerGet() > (xcpCtoRxStartTime + UART_CTO_RX_PACKET_TIMEOUT_MS))
{
/* cancel cto packet reception due to timeout. note that that automaticaly
* discards the already received packet bytes, allowing the host to retry.
*/
xcpCtoRxInProgress = BLT_FALSE;
}
}
}
/* packet reception not yet complete */
return BLT_FALSE;
} /*** end of UartReceivePacket ***/
/************************************************************************************//**
** \brief Receives a communication interface byte if one is present.
** \param data Pointer to byte where the data is to be stored.
** \return BLT_TRUE if a byte was received, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool UartReceiveByte(blt_int8u *data)
{
blt_bool result = BLT_FALSE;
/* reception event pending? */
if (UARTx->RSRC.bits.SRR != 0)
{
/* read out the newly received byte */
*data = UARTx->RBUF.bits.RD_VALUE;
/* reset the reception event flag */
UARTx->RSRC.bits.CLRR = 1;
/* set result to indicate that a new byte was received */
result = BLT_TRUE;
}
/* inform caller about the result */
return result;
} /*** end of UartReceiveByte ***/
/************************************************************************************//**
** \brief Transmits a communication interface byte.
** \param data Value of byte that is to be transmitted.
** \return BLT_TRUE if the byte was transmitted, BLT_FALSE otherwise.
**
****************************************************************************************/
static blt_bool UartTransmitByte(blt_int8u data)
{
/* reset transmit buffer interrupt request */
UARTx->TBSRC.bits.CLRR = 1;
/* write byte to transmit buffer register */
UARTx->TBUF.reg = data;
/* wait for transmit buffer register to be empty */
while(UARTx->TBSRC.bits.SRR == 0)
{
CopService();
}
/* byte transmitted */
return BLT_TRUE;
} /*** end of UartTransmitByte ***/
#endif /* BOOT_COM_UART_ENABLE > 0 */
/*********************************** end of uart.c *************************************/

View File

@ -0,0 +1,47 @@
/************************************************************************************//**
* \file Source\TRICORE_TC1798\uart.h
* \brief Bootloader UART communication interface header file.
* \ingroup Target_TRICORE_TC1798
* \internal
*----------------------------------------------------------------------------------------
* C O P Y R I G H T
*----------------------------------------------------------------------------------------
* Copyright (c) 2015 by Feaser http://www.feaser.com All rights reserved
*
*----------------------------------------------------------------------------------------
* L I C E N S E
*----------------------------------------------------------------------------------------
* This file is part of OpenBLT. OpenBLT 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 3 of the License, or (at your option) any later
* version.
*
* OpenBLT 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 OpenBLT.
* If not, see <http://www.gnu.org/licenses/>.
*
* A special exception to the GPL is included to allow you to distribute a combined work
* that includes OpenBLT without being obliged to provide the source code for any
* proprietary components. The exception text is included at the bottom of the license
* file <license.html>.
*
* \endinternal
****************************************************************************************/
#ifndef UART_H
#define UART_H
#if (BOOT_COM_UART_ENABLE > 0)
/****************************************************************************************
* Function prototypes
****************************************************************************************/
void UartInit(void);
void UartTransmitPacket(blt_int8u *data, blt_int8u len);
blt_bool UartReceivePacket(blt_int8u *data);
#endif /* BOOT_COM_UART_ENABLE > 0 */
#endif /* UART_H */
/*********************************** end of uart.h *************************************/