mirror of https://github.com/rusefi/openblt.git
- 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:
parent
fbfa8dfd31
commit
4ec12dabd5
|
@ -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 *********************************/
|
|
@ -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 *********************************/
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -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*/
|
||||
|
||||
}
|
||||
|
|
@ -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 **************************************/
|
|
@ -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 **************************************/
|
|
@ -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 ************************************/
|
|
@ -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 ************************************/
|
|
@ -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 **************************************/
|
|
@ -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 **************************************/
|
|
@ -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.
|
||||
*/
|
||||
|
||||
|
|
@ -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 ************************************/
|
|
@ -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 ************************************/
|
|
@ -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 ************************************/
|
|
@ -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 *************************************/
|
|
@ -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 *************************************/
|
Loading…
Reference in New Issue