mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-12-07 05:34:59 -05:00
Normalize line endings and whitespace in source files
This commit is contained in:
parent
151fb04ad1
commit
01820d3ed9
574 changed files with 162626 additions and 172362 deletions
|
|
@ -1,2 +1,2 @@
|
|||
The FreeRTOS GCC port layer also builds and works with the ARMClang compiler.
|
||||
To use the ARMClang compiler build the port files from FreeRTOS/Source/portable/GCC.
|
||||
The FreeRTOS GCC port layer also builds and works with the ARMClang compiler.
|
||||
To use the ARMClang compiler build the port files from FreeRTOS/Source/portable/GCC.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
This directory tree contains the master copy of the FreeeRTOS Armv8-M and
|
||||
Armv8.1-M ports.
|
||||
Do not use the files located here! These file are copied into separate
|
||||
FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85]_NNN directories prior to each
|
||||
FreeRTOS release.
|
||||
|
||||
If your Armv8-M and Armv8.1-M application uses TrustZone then use the files from the
|
||||
FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85] directories.
|
||||
|
||||
If your Armv8-M and Armv8.1-M application does not use TrustZone then use the files from
|
||||
the FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85]_NTZ directories.
|
||||
This directory tree contains the master copy of the FreeeRTOS Armv8-M and
|
||||
Armv8.1-M ports.
|
||||
Do not use the files located here! These file are copied into separate
|
||||
FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85]_NNN directories prior to each
|
||||
FreeRTOS release.
|
||||
|
||||
If your Armv8-M and Armv8.1-M application uses TrustZone then use the files from the
|
||||
FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85] directories.
|
||||
|
||||
If your Armv8-M and Armv8.1-M application does not use TrustZone then use the files from
|
||||
the FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85]_NTZ directories.
|
||||
|
|
|
|||
|
|
@ -1,152 +1,152 @@
|
|||
#/*
|
||||
# * FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
# * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
# *
|
||||
# * SPDX-License-Identifier: MIT
|
||||
# *
|
||||
# * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
# * this software and associated documentation files (the "Software"), to deal in
|
||||
# * the Software without restriction, including without limitation the rights to
|
||||
# * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
# * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
# * subject to the following conditions:
|
||||
# *
|
||||
# * The above copyright notice and this permission notice shall be included in all
|
||||
# * copies or substantial portions of the Software.
|
||||
# *
|
||||
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
# * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
# * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
# * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
# *
|
||||
# * https://www.FreeRTOS.org
|
||||
# * https://github.com/FreeRTOS
|
||||
# *
|
||||
# */
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
_THIS_FILE_DIRECTORY_ = os.path.dirname(os.path.realpath(__file__))
|
||||
_FREERTOS_PORTABLE_DIRECTORY_ = os.path.dirname(_THIS_FILE_DIRECTORY_)
|
||||
|
||||
_COMPILERS_ = ['GCC', 'IAR']
|
||||
_ARCH_NS_ = ['ARM_CM85', 'ARM_CM85_NTZ', 'ARM_CM55', 'ARM_CM55_NTZ', 'ARM_CM33', 'ARM_CM33_NTZ', 'ARM_CM23', 'ARM_CM23_NTZ']
|
||||
_ARCH_S_ = ['ARM_CM85', 'ARM_CM55', 'ARM_CM33', 'ARM_CM23']
|
||||
|
||||
# Files to be compiled in the Secure Project
|
||||
_SECURE_COMMON_FILE_PATHS_ = [
|
||||
os.path.join('secure', 'context'),
|
||||
os.path.join('secure', 'heap'),
|
||||
os.path.join('secure', 'init'),
|
||||
os.path.join('secure', 'macros')
|
||||
]
|
||||
|
||||
_SECURE_PORTABLE_FILE_PATHS_ = {
|
||||
'GCC':{
|
||||
'ARM_CM23':[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM23')],
|
||||
'ARM_CM33':[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM33')],
|
||||
'ARM_CM55':[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM33')],
|
||||
'ARM_CM85':[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM33')]
|
||||
},
|
||||
'IAR':{
|
||||
'ARM_CM23':[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM23')],
|
||||
'ARM_CM33':[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM33')],
|
||||
'ARM_CM55':[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM33')],
|
||||
'ARM_CM85':[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM33')]
|
||||
}
|
||||
}
|
||||
|
||||
# Files to be compiled in the Non-Secure Project
|
||||
_NONSECURE_COMMON_FILE_PATHS_ = [
|
||||
'non_secure'
|
||||
]
|
||||
|
||||
_NONSECURE_PORTABLE_FILE_PATHS_ = {
|
||||
'GCC':{
|
||||
'ARM_CM23' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM23')],
|
||||
'ARM_CM23_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM23_NTZ')],
|
||||
'ARM_CM33' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33')],
|
||||
'ARM_CM33_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ')],
|
||||
'ARM_CM55' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'portasm.c'),
|
||||
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM55', 'portmacro.h')],
|
||||
'ARM_CM55_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'portasm.c'),
|
||||
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM55', 'portmacro.h')],
|
||||
'ARM_CM85' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'portasm.c'),
|
||||
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM85', 'portmacro.h')],
|
||||
'ARM_CM85_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'portasm.c'),
|
||||
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM85', 'portmacro.h')]
|
||||
},
|
||||
'IAR':{
|
||||
'ARM_CM23' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM23')],
|
||||
'ARM_CM23_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM23_NTZ')],
|
||||
'ARM_CM33' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33')],
|
||||
'ARM_CM33_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ')],
|
||||
'ARM_CM55' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'portasm.s'),
|
||||
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM55', 'portmacro.h')],
|
||||
'ARM_CM55_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'portasm.s'),
|
||||
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM55', 'portmacro.h')],
|
||||
'ARM_CM85' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'portasm.s'),
|
||||
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM85', 'portmacro.h')],
|
||||
'ARM_CM85_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'portasm.s'),
|
||||
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM85', 'portmacro.h')]
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def copy_files_in_dir(src_abs_path, dst_abs_path):
|
||||
if os.path.isfile(src_abs_path):
|
||||
print('Src: {}'.format(src_abs_path))
|
||||
print('Dst: {}\n'.format(dst_abs_path))
|
||||
shutil.copy2(src_abs_path, dst_abs_path)
|
||||
else:
|
||||
for src_file in os.listdir(src_abs_path):
|
||||
src_file_abs_path = os.path.join(src_abs_path, src_file)
|
||||
if os.path.isfile(src_file_abs_path) and src_file != 'ReadMe.txt':
|
||||
if not os.path.exists(dst_abs_path):
|
||||
os.makedirs(dst_abs_path)
|
||||
print('Src: {}'.format(src_file_abs_path))
|
||||
print('Dst: {}\n'.format(dst_abs_path))
|
||||
shutil.copy2(src_file_abs_path, dst_abs_path)
|
||||
|
||||
|
||||
def copy_common_files_for_compiler_and_arch(compiler, arch, src_paths, dst_path):
|
||||
for src_path in src_paths:
|
||||
|
||||
src_abs_path = os.path.join(_THIS_FILE_DIRECTORY_, src_path)
|
||||
dst_abs_path = os.path.join(_FREERTOS_PORTABLE_DIRECTORY_, compiler, arch, dst_path)
|
||||
|
||||
copy_files_in_dir(src_abs_path, dst_abs_path)
|
||||
|
||||
|
||||
def copy_portable_files_for_compiler_and_arch(compiler, arch, src_paths, dst_path):
|
||||
for src_path in src_paths[compiler][arch]:
|
||||
|
||||
src_abs_path = os.path.join(_THIS_FILE_DIRECTORY_, src_path)
|
||||
dst_abs_path = os.path.join(_FREERTOS_PORTABLE_DIRECTORY_, compiler, arch, dst_path)
|
||||
|
||||
copy_files_in_dir(src_abs_path, dst_abs_path)
|
||||
|
||||
|
||||
def copy_files():
|
||||
# Copy Secure Files
|
||||
for compiler in _COMPILERS_:
|
||||
for arch in _ARCH_S_:
|
||||
copy_common_files_for_compiler_and_arch(compiler, arch, _SECURE_COMMON_FILE_PATHS_, 'secure')
|
||||
copy_portable_files_for_compiler_and_arch(compiler, arch, _SECURE_PORTABLE_FILE_PATHS_, 'secure')
|
||||
|
||||
# Copy Non-Secure Files
|
||||
for compiler in _COMPILERS_:
|
||||
for arch in _ARCH_NS_:
|
||||
copy_common_files_for_compiler_and_arch(compiler, arch, _NONSECURE_COMMON_FILE_PATHS_, 'non_secure')
|
||||
copy_portable_files_for_compiler_and_arch(compiler, arch, _NONSECURE_PORTABLE_FILE_PATHS_, 'non_secure')
|
||||
|
||||
|
||||
def main():
|
||||
copy_files()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
#/*
|
||||
# * FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
# * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
# *
|
||||
# * SPDX-License-Identifier: MIT
|
||||
# *
|
||||
# * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
# * this software and associated documentation files (the "Software"), to deal in
|
||||
# * the Software without restriction, including without limitation the rights to
|
||||
# * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
# * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
# * subject to the following conditions:
|
||||
# *
|
||||
# * The above copyright notice and this permission notice shall be included in all
|
||||
# * copies or substantial portions of the Software.
|
||||
# *
|
||||
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
# * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
# * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
# * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
# * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
# *
|
||||
# * https://www.FreeRTOS.org
|
||||
# * https://github.com/FreeRTOS
|
||||
# *
|
||||
# */
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
_THIS_FILE_DIRECTORY_ = os.path.dirname(os.path.realpath(__file__))
|
||||
_FREERTOS_PORTABLE_DIRECTORY_ = os.path.dirname(_THIS_FILE_DIRECTORY_)
|
||||
|
||||
_COMPILERS_ = ['GCC', 'IAR']
|
||||
_ARCH_NS_ = ['ARM_CM85', 'ARM_CM85_NTZ', 'ARM_CM55', 'ARM_CM55_NTZ', 'ARM_CM33', 'ARM_CM33_NTZ', 'ARM_CM23', 'ARM_CM23_NTZ']
|
||||
_ARCH_S_ = ['ARM_CM85', 'ARM_CM55', 'ARM_CM33', 'ARM_CM23']
|
||||
|
||||
# Files to be compiled in the Secure Project
|
||||
_SECURE_COMMON_FILE_PATHS_ = [
|
||||
os.path.join('secure', 'context'),
|
||||
os.path.join('secure', 'heap'),
|
||||
os.path.join('secure', 'init'),
|
||||
os.path.join('secure', 'macros')
|
||||
]
|
||||
|
||||
_SECURE_PORTABLE_FILE_PATHS_ = {
|
||||
'GCC':{
|
||||
'ARM_CM23':[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM23')],
|
||||
'ARM_CM33':[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM33')],
|
||||
'ARM_CM55':[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM33')],
|
||||
'ARM_CM85':[os.path.join('secure', 'context', 'portable', 'GCC', 'ARM_CM33')]
|
||||
},
|
||||
'IAR':{
|
||||
'ARM_CM23':[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM23')],
|
||||
'ARM_CM33':[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM33')],
|
||||
'ARM_CM55':[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM33')],
|
||||
'ARM_CM85':[os.path.join('secure', 'context', 'portable', 'IAR', 'ARM_CM33')]
|
||||
}
|
||||
}
|
||||
|
||||
# Files to be compiled in the Non-Secure Project
|
||||
_NONSECURE_COMMON_FILE_PATHS_ = [
|
||||
'non_secure'
|
||||
]
|
||||
|
||||
_NONSECURE_PORTABLE_FILE_PATHS_ = {
|
||||
'GCC':{
|
||||
'ARM_CM23' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM23')],
|
||||
'ARM_CM23_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM23_NTZ')],
|
||||
'ARM_CM33' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33')],
|
||||
'ARM_CM33_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ')],
|
||||
'ARM_CM55' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'portasm.c'),
|
||||
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM55', 'portmacro.h')],
|
||||
'ARM_CM55_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'portasm.c'),
|
||||
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM55', 'portmacro.h')],
|
||||
'ARM_CM85' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33', 'portasm.c'),
|
||||
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM85', 'portmacro.h')],
|
||||
'ARM_CM85_NTZ' : [os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM33_NTZ', 'portasm.c'),
|
||||
os.path.join('non_secure', 'portable', 'GCC', 'ARM_CM85', 'portmacro.h')]
|
||||
},
|
||||
'IAR':{
|
||||
'ARM_CM23' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM23')],
|
||||
'ARM_CM23_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM23_NTZ')],
|
||||
'ARM_CM33' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33')],
|
||||
'ARM_CM33_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ')],
|
||||
'ARM_CM55' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'portasm.s'),
|
||||
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM55', 'portmacro.h')],
|
||||
'ARM_CM55_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'portasm.s'),
|
||||
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM55', 'portmacro.h')],
|
||||
'ARM_CM85' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33', 'portasm.s'),
|
||||
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM85', 'portmacro.h')],
|
||||
'ARM_CM85_NTZ' : [os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM33_NTZ', 'portasm.s'),
|
||||
os.path.join('non_secure', 'portable', 'IAR', 'ARM_CM85', 'portmacro.h')]
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def copy_files_in_dir(src_abs_path, dst_abs_path):
|
||||
if os.path.isfile(src_abs_path):
|
||||
print('Src: {}'.format(src_abs_path))
|
||||
print('Dst: {}\n'.format(dst_abs_path))
|
||||
shutil.copy2(src_abs_path, dst_abs_path)
|
||||
else:
|
||||
for src_file in os.listdir(src_abs_path):
|
||||
src_file_abs_path = os.path.join(src_abs_path, src_file)
|
||||
if os.path.isfile(src_file_abs_path) and src_file != 'ReadMe.txt':
|
||||
if not os.path.exists(dst_abs_path):
|
||||
os.makedirs(dst_abs_path)
|
||||
print('Src: {}'.format(src_file_abs_path))
|
||||
print('Dst: {}\n'.format(dst_abs_path))
|
||||
shutil.copy2(src_file_abs_path, dst_abs_path)
|
||||
|
||||
|
||||
def copy_common_files_for_compiler_and_arch(compiler, arch, src_paths, dst_path):
|
||||
for src_path in src_paths:
|
||||
|
||||
src_abs_path = os.path.join(_THIS_FILE_DIRECTORY_, src_path)
|
||||
dst_abs_path = os.path.join(_FREERTOS_PORTABLE_DIRECTORY_, compiler, arch, dst_path)
|
||||
|
||||
copy_files_in_dir(src_abs_path, dst_abs_path)
|
||||
|
||||
|
||||
def copy_portable_files_for_compiler_and_arch(compiler, arch, src_paths, dst_path):
|
||||
for src_path in src_paths[compiler][arch]:
|
||||
|
||||
src_abs_path = os.path.join(_THIS_FILE_DIRECTORY_, src_path)
|
||||
dst_abs_path = os.path.join(_FREERTOS_PORTABLE_DIRECTORY_, compiler, arch, dst_path)
|
||||
|
||||
copy_files_in_dir(src_abs_path, dst_abs_path)
|
||||
|
||||
|
||||
def copy_files():
|
||||
# Copy Secure Files
|
||||
for compiler in _COMPILERS_:
|
||||
for arch in _ARCH_S_:
|
||||
copy_common_files_for_compiler_and_arch(compiler, arch, _SECURE_COMMON_FILE_PATHS_, 'secure')
|
||||
copy_portable_files_for_compiler_and_arch(compiler, arch, _SECURE_PORTABLE_FILE_PATHS_, 'secure')
|
||||
|
||||
# Copy Non-Secure Files
|
||||
for compiler in _COMPILERS_:
|
||||
for arch in _ARCH_NS_:
|
||||
copy_common_files_for_compiler_and_arch(compiler, arch, _NONSECURE_COMMON_FILE_PATHS_, 'non_secure')
|
||||
copy_portable_files_for_compiler_and_arch(compiler, arch, _NONSECURE_PORTABLE_FILE_PATHS_, 'non_secure')
|
||||
|
||||
|
||||
def main():
|
||||
copy_files()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
This directory tree contains the master copy of the FreeRTOS Armv8-M and
|
||||
Armv8.1-M ports.
|
||||
Do not use the files located here! These file are copied into separate
|
||||
FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85]_NNN directories prior to
|
||||
each FreeRTOS release.
|
||||
|
||||
If your Armv8-M/Armv8.1-M application uses TrustZone then use the files from the
|
||||
FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85] directories.
|
||||
|
||||
If your Armv8-M/Armv8.1-M application does not use TrustZone then use the files from
|
||||
the FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85]_NTZ directories.
|
||||
This directory tree contains the master copy of the FreeRTOS Armv8-M and
|
||||
Armv8.1-M ports.
|
||||
Do not use the files located here! These file are copied into separate
|
||||
FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85]_NNN directories prior to
|
||||
each FreeRTOS release.
|
||||
|
||||
If your Armv8-M/Armv8.1-M application uses TrustZone then use the files from the
|
||||
FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85] directories.
|
||||
|
||||
If your Armv8-M/Armv8.1-M application does not use TrustZone then use the files from
|
||||
the FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85]_NTZ directories.
|
||||
|
|
|
|||
|
|
@ -1,478 +1,478 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||
* is defined correctly and privileged functions are placed in correct sections. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" movs r5, #4 \n"/* r5 = 4. */
|
||||
" str r5, [r2] \n"/* Program RNR = 4. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r5, #5 \n"/* r5 = 5. */
|
||||
" str r5, [r2] \n"/* Program RNR = 5. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r5, #6 \n"/* r5 = 6. */
|
||||
" str r5, [r2] \n"/* Program RNR = 6. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r5, #7 \n"/* r5 = 7. */
|
||||
" str r5, [r2] \n"/* Program RNR = 7. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
" ldr r5, xSecureContextConst2 \n"
|
||||
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r3 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r4 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
" ldr r4, xSecureContextConst2 \n"
|
||||
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst2: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
" beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
|
||||
" movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" running_privileged: \n"
|
||||
" movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" bics r0, r1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" orrs r0, r1 \n"/* r0 = r0 | r1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" .extern SecureContext_SaveContext \n"
|
||||
" .extern SecureContext_LoadContext \n"
|
||||
" \n"
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later.*/
|
||||
" mrs r2, psp \n"/* Read PSP in r2. */
|
||||
" \n"
|
||||
" cbz r0, save_ns_context \n"/* No secure context to save. */
|
||||
" push {r0-r2, r14} \n"
|
||||
" bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r0-r3} \n"/* LR is now in r3. */
|
||||
" mov lr, r3 \n"/* LR = r3. */
|
||||
" lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" b select_next_task \n"
|
||||
" \n"
|
||||
" save_ns_context: \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" adds r2, r2, #16 \n"/* r2 = r2 + 16. */
|
||||
" stmia r2!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" subs r2, r2, #48 \n"/* r2 = r2 - 48. */
|
||||
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" select_next_task: \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r3] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r3] \n"/* Program MAIR0. */
|
||||
" ldr r4, xRNRConst \n"/* r4 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" movs r5, #4 \n"/* r5 = 4. */
|
||||
" str r5, [r4] \n"/* Program RNR = 4. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r5, #5 \n"/* r5 = 5. */
|
||||
" str r5, [r4] \n"/* Program RNR = 5. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r5, #6 \n"/* r5 = 6. */
|
||||
" str r5, [r4] \n"/* Program RNR = 6. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r5, #7 \n"/* r5 = 7. */
|
||||
" str r5, [r4] \n"/* Program RNR = 7. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r3] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r3] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" push {r2, r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r2, r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r3] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" push {r2, r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r2, r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" restore_ns_context: \n"
|
||||
" adds r2, r2, #16 \n"/* Move to the high registers. */
|
||||
" ldmia r2!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n"/* r8 = r4. */
|
||||
" mov r9, r5 \n"/* r9 = r5. */
|
||||
" mov r10, r6 \n"/* r10 = r6. */
|
||||
" mov r11, r7 \n"/* r11 = r7. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" subs r2, r2, #32 \n"/* Go back to the low registers. */
|
||||
" ldmia r2!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" movs r0, #4 \n"
|
||||
" mov r1, lr \n"
|
||||
" tst r0, r1 \n"
|
||||
" beq stacking_used_msp \n"
|
||||
" mrs r0, psp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" stacking_used_msp: \n"
|
||||
" mrs r0, msp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" svc %0 \n"/* Secure context is allocated in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */
|
||||
" ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */
|
||||
" cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
|
||||
" bne free_secure_context \n"/* Branch if r1 != 0. */
|
||||
" bx lr \n"/* There is no secure context (xSecureContext is NULL). */
|
||||
" free_secure_context: \n"
|
||||
" svc %0 \n"/* Secure context is freed in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||
* is defined correctly and privileged functions are placed in correct sections. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" movs r5, #4 \n"/* r5 = 4. */
|
||||
" str r5, [r2] \n"/* Program RNR = 4. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r5, #5 \n"/* r5 = 5. */
|
||||
" str r5, [r2] \n"/* Program RNR = 5. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r5, #6 \n"/* r5 = 6. */
|
||||
" str r5, [r2] \n"/* Program RNR = 6. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r5, #7 \n"/* r5 = 7. */
|
||||
" str r5, [r2] \n"/* Program RNR = 7. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
" ldr r5, xSecureContextConst2 \n"
|
||||
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r3 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r4 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
" ldr r4, xSecureContextConst2 \n"
|
||||
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst2: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
" beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
|
||||
" movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" running_privileged: \n"
|
||||
" movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" bics r0, r1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" orrs r0, r1 \n"/* r0 = r0 | r1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" .extern SecureContext_SaveContext \n"
|
||||
" .extern SecureContext_LoadContext \n"
|
||||
" \n"
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later.*/
|
||||
" mrs r2, psp \n"/* Read PSP in r2. */
|
||||
" \n"
|
||||
" cbz r0, save_ns_context \n"/* No secure context to save. */
|
||||
" push {r0-r2, r14} \n"
|
||||
" bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r0-r3} \n"/* LR is now in r3. */
|
||||
" mov lr, r3 \n"/* LR = r3. */
|
||||
" lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" b select_next_task \n"
|
||||
" \n"
|
||||
" save_ns_context: \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" adds r2, r2, #16 \n"/* r2 = r2 + 16. */
|
||||
" stmia r2!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" subs r2, r2, #48 \n"/* r2 = r2 - 48. */
|
||||
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" select_next_task: \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r3] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r3] \n"/* Program MAIR0. */
|
||||
" ldr r4, xRNRConst \n"/* r4 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" movs r5, #4 \n"/* r5 = 4. */
|
||||
" str r5, [r4] \n"/* Program RNR = 4. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r5, #5 \n"/* r5 = 5. */
|
||||
" str r5, [r4] \n"/* Program RNR = 5. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r5, #6 \n"/* r5 = 6. */
|
||||
" str r5, [r4] \n"/* Program RNR = 6. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r5, #7 \n"/* r5 = 7. */
|
||||
" str r5, [r4] \n"/* Program RNR = 7. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r3] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r3] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" push {r2, r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r2, r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r3] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" push {r2, r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r2, r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" restore_ns_context: \n"
|
||||
" adds r2, r2, #16 \n"/* Move to the high registers. */
|
||||
" ldmia r2!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n"/* r8 = r4. */
|
||||
" mov r9, r5 \n"/* r9 = r5. */
|
||||
" mov r10, r6 \n"/* r10 = r6. */
|
||||
" mov r11, r7 \n"/* r11 = r7. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" subs r2, r2, #32 \n"/* Go back to the low registers. */
|
||||
" ldmia r2!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" movs r0, #4 \n"
|
||||
" mov r1, lr \n"
|
||||
" tst r0, r1 \n"
|
||||
" beq stacking_used_msp \n"
|
||||
" mrs r0, psp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" stacking_used_msp: \n"
|
||||
" mrs r0, msp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" svc %0 \n"/* Secure context is allocated in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */
|
||||
" ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */
|
||||
" cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
|
||||
" bne free_secure_context \n"/* Branch if r1 != 0. */
|
||||
" bx lr \n"/* There is no secure context (xSecureContext is NULL). */
|
||||
" free_secure_context: \n"
|
||||
" svc %0 \n"/* Secure context is freed in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,71 +1,71 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,381 +1,381 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||
* is defined correctly and privileged functions are placed in correct sections. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n"/* r4 = 1. */
|
||||
" bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
" str r3, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" movs r4, #4 \n"/* r4 = 4. */
|
||||
" str r4, [r2] \n"/* Program RNR = 4. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r4, #5 \n"/* r4 = 5. */
|
||||
" str r4, [r2] \n"/* Program RNR = 5. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r4, #6 \n"/* r4 = 6. */
|
||||
" str r4, [r2] \n"/* Program RNR = 6. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r4, #7 \n"/* r4 = 7. */
|
||||
" str r4, [r2] \n"/* Program RNR = 7. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n"/* r4 = 1. */
|
||||
" orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
" str r3, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r2 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r2 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
" beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
|
||||
" movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" running_privileged: \n"
|
||||
" movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" bics r0, r1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" orrs r0, r1 \n"/* r0 = r0 | r1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, psp \n"/* Read PSP in r0. */
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r0, r0, #44 \n"/* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r0, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r2, control \n"/* r2 = CONTROL. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r0!, {r1-r7} \n"/* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r0, r0, #40 \n"/* Make space for PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r0, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r0!, {r2-r7} \n"/* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n"/* r4 = 1. */
|
||||
" bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
" str r3, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" movs r4, #4 \n"/* r4 = 4. */
|
||||
" str r4, [r2] \n"/* Program RNR = 4. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r4, #5 \n"/* r4 = 5. */
|
||||
" str r4, [r2] \n"/* Program RNR = 5. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r4, #6 \n"/* r4 = 6. */
|
||||
" str r4, [r2] \n"/* Program RNR = 6. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r4, #7 \n"/* r4 = 7. */
|
||||
" str r4, [r2] \n"/* Program RNR = 7. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n"/* r4 = 1. */
|
||||
" orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
" str r3, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" adds r0, r0, #28 \n"/* Move to the high registers. */
|
||||
" ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n"/* r8 = r4. */
|
||||
" mov r9, r5 \n"/* r9 = r5. */
|
||||
" mov r10, r6 \n"/* r10 = r6. */
|
||||
" mov r11, r7 \n"/* r11 = r7. */
|
||||
" msr psp, r0 \n"/* Remember the new top of stack for the task. */
|
||||
" subs r0, r0, #44 \n"/* Move to the starting of the saved context. */
|
||||
" ldmia r0!, {r1-r7} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */
|
||||
" bx r3 \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" adds r0, r0, #24 \n"/* Move to the high registers. */
|
||||
" ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n"/* r8 = r4. */
|
||||
" mov r9, r5 \n"/* r9 = r5. */
|
||||
" mov r10, r6 \n"/* r10 = r6. */
|
||||
" mov r11, r7 \n"/* r11 = r7. */
|
||||
" msr psp, r0 \n"/* Remember the new top of stack for the task. */
|
||||
" subs r0, r0, #40 \n"/* Move to the starting of the saved context. */
|
||||
" ldmia r0!, {r2-r7} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
|
||||
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" bx r3 \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" movs r0, #4 \n"
|
||||
" mov r1, lr \n"
|
||||
" tst r0, r1 \n"
|
||||
" beq stacking_used_msp \n"
|
||||
" mrs r0, psp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" stacking_used_msp: \n"
|
||||
" mrs r0, msp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||
* is defined correctly and privileged functions are placed in correct sections. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n"/* r4 = 1. */
|
||||
" bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
" str r3, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" movs r4, #4 \n"/* r4 = 4. */
|
||||
" str r4, [r2] \n"/* Program RNR = 4. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r4, #5 \n"/* r4 = 5. */
|
||||
" str r4, [r2] \n"/* Program RNR = 5. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r4, #6 \n"/* r4 = 6. */
|
||||
" str r4, [r2] \n"/* Program RNR = 6. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r4, #7 \n"/* r4 = 7. */
|
||||
" str r4, [r2] \n"/* Program RNR = 7. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n"/* r4 = 1. */
|
||||
" orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
" str r3, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r2 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r2 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
" beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
|
||||
" movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" running_privileged: \n"
|
||||
" movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" bics r0, r1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" orrs r0, r1 \n"/* r0 = r0 | r1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, psp \n"/* Read PSP in r0. */
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r0, r0, #44 \n"/* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r0, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r2, control \n"/* r2 = CONTROL. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r0!, {r1-r7} \n"/* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r0, r0, #40 \n"/* Make space for PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r0, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r0!, {r2-r7} \n"/* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n"/* r4 = 1. */
|
||||
" bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
" str r3, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" movs r4, #4 \n"/* r4 = 4. */
|
||||
" str r4, [r2] \n"/* Program RNR = 4. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r4, #5 \n"/* r4 = 5. */
|
||||
" str r4, [r2] \n"/* Program RNR = 5. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r4, #6 \n"/* r4 = 6. */
|
||||
" str r4, [r2] \n"/* Program RNR = 6. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r4, #7 \n"/* r4 = 7. */
|
||||
" str r4, [r2] \n"/* Program RNR = 7. */
|
||||
" ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r4, #1 \n"/* r4 = 1. */
|
||||
" orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
" str r3, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" adds r0, r0, #28 \n"/* Move to the high registers. */
|
||||
" ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n"/* r8 = r4. */
|
||||
" mov r9, r5 \n"/* r9 = r5. */
|
||||
" mov r10, r6 \n"/* r10 = r6. */
|
||||
" mov r11, r7 \n"/* r11 = r7. */
|
||||
" msr psp, r0 \n"/* Remember the new top of stack for the task. */
|
||||
" subs r0, r0, #44 \n"/* Move to the starting of the saved context. */
|
||||
" ldmia r0!, {r1-r7} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */
|
||||
" bx r3 \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" adds r0, r0, #24 \n"/* Move to the high registers. */
|
||||
" ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n"/* r8 = r4. */
|
||||
" mov r9, r5 \n"/* r9 = r5. */
|
||||
" mov r10, r6 \n"/* r10 = r6. */
|
||||
" mov r11, r7 \n"/* r11 = r7. */
|
||||
" msr psp, r0 \n"/* Remember the new top of stack for the task. */
|
||||
" subs r0, r0, #40 \n"/* Move to the starting of the saved context. */
|
||||
" ldmia r0!, {r2-r7} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
|
||||
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" bx r3 \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" movs r0, #4 \n"
|
||||
" mov r1, lr \n"
|
||||
" tst r0, r1 \n"
|
||||
" beq stacking_used_msp \n"
|
||||
" mrs r0, psp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" stacking_used_msp: \n"
|
||||
" mrs r0, msp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,71 +1,71 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,470 +1,470 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||
* is defined correctly and privileged functions are placed in correct sections. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #4 \n"/* r4 = 4. */
|
||||
" str r4, [r2] \n"/* Program RNR = 4. */
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #8 \n"/* r4 = 8. */
|
||||
" str r4, [r2] \n"/* Program RNR = 8. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #12 \n"/* r4 = 12. */
|
||||
" str r4, [r2] \n"/* Program RNR = 12. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
" ldr r5, xSecureContextConst2 \n"
|
||||
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r3 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
|
||||
" bx r4 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
" ldr r4, xSecureContextConst2 \n"
|
||||
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst2: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
" ite ne \n"
|
||||
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" bic r0, #1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" orr r0, #1 \n"/* r0 = r0 | 1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
|
||||
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" msr basepri, r0 \n"/* basepri = ulMask. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n"/* Return. */
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" .extern SecureContext_SaveContext \n"
|
||||
" .extern SecureContext_LoadContext \n"
|
||||
" \n"
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
|
||||
" mrs r2, psp \n"/* Read PSP in r2. */
|
||||
" \n"
|
||||
" cbz r0, save_ns_context \n"/* No secure context to save. */
|
||||
" push {r0-r2, r14} \n"
|
||||
" bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r0-r3} \n"/* LR is now in r3. */
|
||||
" mov lr, r3 \n"/* LR = r3. */
|
||||
" lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB.*/
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" b select_next_task \n"
|
||||
" \n"
|
||||
" save_ns_context: \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
" it eq \n"
|
||||
" vstmdbeq r2!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" adds r2, r2, #16 \n"/* r2 = r2 + 16. */
|
||||
" stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" subs r2, r2, #16 \n"/* r2 = r2 - 16. */
|
||||
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" adds r2, r2, #12 \n"/* r2 = r2 + 12. */
|
||||
" stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" subs r2, r2, #12 \n"/* r2 = r2 - 12. */
|
||||
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" select_next_task: \n"
|
||||
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n"/* r0 = 0. */
|
||||
" msr basepri, r0 \n"/* Enable interrupts. */
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r3] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r3] \n"/* Program MAIR0. */
|
||||
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #4 \n"/* r4 = 4. */
|
||||
" str r4, [r3] \n"/* Program RNR = 4. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #8 \n"/* r4 = 8. */
|
||||
" str r4, [r3] \n"/* Program RNR = 8. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #12 \n"/* r4 = 12. */
|
||||
" str r4, [r3] \n"/* Program RNR = 12. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||
" \n"
|
||||
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r3] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r3] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" push {r2, r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r2, r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r3] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" push {r2, r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r2, r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" restore_ns_context: \n"
|
||||
" ldmia r2!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
" it eq \n"
|
||||
" vldmiaeq r2!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" tst lr, #4 \n"
|
||||
" ite eq \n"
|
||||
" mrseq r0, msp \n"
|
||||
" mrsne r0, psp \n"
|
||||
" ldr r1, svchandler_address_const \n"
|
||||
" bx r1 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" svc %0 \n"/* Secure context is allocated in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */
|
||||
" ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */
|
||||
" cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
|
||||
" it ne \n"
|
||||
" svcne %0 \n"/* Secure context is freed in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||
* is defined correctly and privileged functions are placed in correct sections. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #4 \n"/* r4 = 4. */
|
||||
" str r4, [r2] \n"/* Program RNR = 4. */
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #8 \n"/* r4 = 8. */
|
||||
" str r4, [r2] \n"/* Program RNR = 8. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #12 \n"/* r4 = 12. */
|
||||
" str r4, [r2] \n"/* Program RNR = 12. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
" ldr r5, xSecureContextConst2 \n"
|
||||
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r3 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
|
||||
" bx r4 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
" ldr r4, xSecureContextConst2 \n"
|
||||
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst2: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
" ite ne \n"
|
||||
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" bic r0, #1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" orr r0, #1 \n"/* r0 = r0 | 1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
|
||||
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" msr basepri, r0 \n"/* basepri = ulMask. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n"/* Return. */
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" .extern SecureContext_SaveContext \n"
|
||||
" .extern SecureContext_LoadContext \n"
|
||||
" \n"
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
|
||||
" mrs r2, psp \n"/* Read PSP in r2. */
|
||||
" \n"
|
||||
" cbz r0, save_ns_context \n"/* No secure context to save. */
|
||||
" push {r0-r2, r14} \n"
|
||||
" bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r0-r3} \n"/* LR is now in r3. */
|
||||
" mov lr, r3 \n"/* LR = r3. */
|
||||
" lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB.*/
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" b select_next_task \n"
|
||||
" \n"
|
||||
" save_ns_context: \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
" it eq \n"
|
||||
" vstmdbeq r2!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" adds r2, r2, #16 \n"/* r2 = r2 + 16. */
|
||||
" stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" subs r2, r2, #16 \n"/* r2 = r2 - 16. */
|
||||
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" adds r2, r2, #12 \n"/* r2 = r2 + 12. */
|
||||
" stm r2, {r4-r11} \n"/* Store the registers that are not saved automatically. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" subs r2, r2, #12 \n"/* r2 = r2 - 12. */
|
||||
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" select_next_task: \n"
|
||||
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n"/* r0 = 0. */
|
||||
" msr basepri, r0 \n"/* Enable interrupts. */
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r3] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r3] \n"/* Program MAIR0. */
|
||||
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #4 \n"/* r4 = 4. */
|
||||
" str r4, [r3] \n"/* Program RNR = 4. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #8 \n"/* r4 = 8. */
|
||||
" str r4, [r3] \n"/* Program RNR = 8. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" ldr r3, xRNRConst \n"/* r3 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r4, #12 \n"/* r4 = 12. */
|
||||
" str r4, [r3] \n"/* Program RNR = 12. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r3!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||
" \n"
|
||||
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r3] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r3] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" push {r2, r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r2, r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r3] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" push {r2, r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r2, r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" restore_ns_context: \n"
|
||||
" ldmia r2!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
" it eq \n"
|
||||
" vldmiaeq r2!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" tst lr, #4 \n"
|
||||
" ite eq \n"
|
||||
" mrseq r0, msp \n"
|
||||
" mrsne r0, psp \n"
|
||||
" ldr r1, svchandler_address_const \n"
|
||||
" bx r1 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" svc %0 \n"/* Secure context is allocated in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */
|
||||
" ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */
|
||||
" cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
|
||||
" it ne \n"
|
||||
" svcne %0 \n"/* Secure context is freed in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,66 +1,66 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,365 +1,365 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||
* is defined correctly and privileged functions are placed in correct sections. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r3, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #4 \n"/* r3 = 4. */
|
||||
" str r3, [r2] \n"/* Program RNR = 4. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #8 \n"/* r3 = 8. */
|
||||
" str r3, [r2] \n"/* Program RNR = 8. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #12 \n"/* r3 = 12. */
|
||||
" str r3, [r2] \n"/* Program RNR = 12. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r2 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
|
||||
" bx r2 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
" ite ne \n"
|
||||
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" bic r0, #1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" orr r0, #1 \n"/* r0 = r0 | 1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
|
||||
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" msr basepri, r0 \n"/* basepri = ulMask. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n"/* Return. */
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, psp \n"/* Read PSP in r0. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
" it eq \n"
|
||||
" vstmdbeq r0!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r2, control \n"/* r2 = CONTROL. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
|
||||
#else /* configENABLE_MPU */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" str r0, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" \n"
|
||||
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n"/* r0 = 0. */
|
||||
" msr basepri, r0 \n"/* Enable interrupts. */
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r3, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #4 \n"/* r3 = 4. */
|
||||
" str r3, [r2] \n"/* Program RNR = 4. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #8 \n"/* r3 = 8. */
|
||||
" str r3, [r2] \n"/* Program RNR = 8. */
|
||||
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #12 \n"/* r3 = 12. */
|
||||
" str r3, [r2] \n"/* Program RNR = 12. */
|
||||
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
" it eq \n"
|
||||
" vldmiaeq r0!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */
|
||||
#else /* configENABLE_MPU */
|
||||
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" msr psp, r0 \n"/* Remember the new top of stack for the task. */
|
||||
" bx r3 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" tst lr, #4 \n"
|
||||
" ite eq \n"
|
||||
" mrseq r0, msp \n"
|
||||
" mrsne r0, psp \n"
|
||||
" ldr r1, svchandler_address_const \n"
|
||||
" bx r1 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||
* is defined correctly and privileged functions are placed in correct sections. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r3, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #4 \n"/* r3 = 4. */
|
||||
" str r3, [r2] \n"/* Program RNR = 4. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #8 \n"/* r3 = 8. */
|
||||
" str r3, [r2] \n"/* Program RNR = 8. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #12 \n"/* r3 = 12. */
|
||||
" str r3, [r2] \n"/* Program RNR = 12. */
|
||||
" ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r2 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
" msr psplim, r1 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" mov r0, #0 \n"
|
||||
" msr basepri, r0 \n"/* Ensure that interrupts are enabled when the first task starts. */
|
||||
" bx r2 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
" ite ne \n"
|
||||
" movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" bic r0, #1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" orr r0, #1 \n"/* r0 = r0 | 1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" cpsie f \n"
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */
|
||||
" mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" msr basepri, r0 \n"/* basepri = ulMask. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bx lr \n"/* Return. */
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, psp \n"/* Read PSP in r0. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
" it eq \n"
|
||||
" vstmdbeq r0!, {s16-s31} \n"/* Store the additional FP context registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r2, control \n"/* r2 = CONTROL. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
|
||||
#else /* configENABLE_MPU */
|
||||
" mrs r2, psplim \n"/* r2 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" str r0, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" \n"
|
||||
" mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */
|
||||
" msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" mov r0, #0 \n"/* r0 = 0. */
|
||||
" msr basepri, r0 \n"/* Enable interrupts. */
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r3, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #4 \n"/* r3 = 4. */
|
||||
" str r3, [r2] \n"/* Program RNR = 4. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" \n"
|
||||
#if ( configTOTAL_MPU_REGIONS == 16 )
|
||||
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #8 \n"/* r3 = 8. */
|
||||
" str r3, [r2] \n"/* Program RNR = 8. */
|
||||
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
" ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" movs r3, #12 \n"/* r3 = 12. */
|
||||
" str r3, [r2] \n"/* Program RNR = 12. */
|
||||
" ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
" ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
" stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
#endif /* configTOTAL_MPU_REGIONS == 16 */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
" it eq \n"
|
||||
" vldmiaeq r0!, {s16-s31} \n"/* Restore the additional FP context registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r2 \n"/* Restore the CONTROL register value for the task. */
|
||||
#else /* configENABLE_MPU */
|
||||
" msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" msr psp, r0 \n"/* Remember the new top of stack for the task. */
|
||||
" bx r3 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" tst lr, #4 \n"
|
||||
" ite eq \n"
|
||||
" mrseq r0, msp \n"
|
||||
" mrsne r0, psp \n"
|
||||
" ldr r1, svchandler_address_const \n"
|
||||
" bx r1 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,66 +1,66 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,391 +1,391 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN xSecureContext
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
EXTERN SecureContext_SaveContext
|
||||
EXTERN SecureContext_LoadContext
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
PUBLIC vPortAllocateSecureContext
|
||||
PUBLIC vRestoreContextOfFirstTask
|
||||
PUBLIC vRaisePrivilege
|
||||
PUBLIC vStartFirstTask
|
||||
PUBLIC ulSetInterruptMask
|
||||
PUBLIC vClearInterruptMask
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC SVC_Handler
|
||||
PUBLIC vPortFreeSecureContext
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*---------------- Unprivileged Functions -------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
tst r0, r1 /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
beq running_privileged /* If the result of previous AND operation was 0, branch. */
|
||||
movs r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
bx lr /* Return. */
|
||||
running_privileged:
|
||||
movs r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
orrs r0, r1 /* r0 = r0 | r1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortAllocateSecureContext:
|
||||
svc 0 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 0. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*----------------- Privileged Functions --------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION privileged_functions:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r3, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r5, #1 /* r5 = 1. */
|
||||
bics r4, r5 /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
movs r5, #4 /* r5 = 4. */
|
||||
str r5, [r2] /* Program RNR = 4. */
|
||||
ldmia r3!, {r6,r7} /* Read first set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write first set of RBAR/RLAR registers. */
|
||||
movs r5, #5 /* r5 = 5. */
|
||||
str r5, [r2] /* Program RNR = 5. */
|
||||
ldmia r3!, {r6,r7} /* Read second set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write second set of RBAR/RLAR registers. */
|
||||
movs r5, #6 /* r5 = 6. */
|
||||
str r5, [r2] /* Program RNR = 6. */
|
||||
ldmia r3!, {r6,r7} /* Read third set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write third set of RBAR/RLAR registers. */
|
||||
movs r5, #7 /* r5 = 7. */
|
||||
str r5, [r2] /* Program RNR = 7. */
|
||||
ldmia r3!, {r6,r7} /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write fourth set of RBAR/RLAR registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r5, #1 /* r5 = 1. */
|
||||
orrs r4, r5 /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
ldr r5, =xSecureContext
|
||||
str r1, [r5] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
msr control, r3 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r4 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
ldr r4, =xSecureContext
|
||||
str r1, [r4] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
movs r1, #2 /* r1 = 2. */
|
||||
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRaisePrivilege:
|
||||
mrs r0, control /* Read the CONTROL register. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
bics r0, r1 /* Clear the bit 0. */
|
||||
msr control, r0 /* Write back the new CONTROL value. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vStartFirstTask:
|
||||
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
dsb
|
||||
isb
|
||||
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMask:
|
||||
mrs r0, PRIMASK
|
||||
cpsid i
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMask:
|
||||
msr PRIMASK, r0
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
PendSV_Handler:
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
|
||||
mrs r2, psp /* Read PSP in r2. */
|
||||
|
||||
cbz r0, save_ns_context /* No secure context to save. */
|
||||
push {r0-r2, r14}
|
||||
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r0-r3} /* LR is now in r3. */
|
||||
mov lr, r3 /* LR = r3. */
|
||||
lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r2, r2, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r2, r2, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
b select_next_task
|
||||
|
||||
save_ns_context:
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r2, r2, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
adds r2, r2, #16 /* r2 = r2 + 16. */
|
||||
stmia r2!, {r4-r7} /* Store the low registers that are not saved automatically. */
|
||||
mov r4, r8 /* r4 = r8. */
|
||||
mov r5, r9 /* r5 = r9. */
|
||||
mov r6, r10 /* r6 = r10. */
|
||||
mov r7, r11 /* r7 = r11. */
|
||||
stmia r2!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
subs r2, r2, #48 /* r2 = r2 - 48. */
|
||||
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r2!, {r0, r1, r3-r7} /* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
|
||||
mov r4, r8 /* r4 = r8. */
|
||||
mov r5, r9 /* r5 = r9. */
|
||||
mov r6, r10 /* r6 = r10. */
|
||||
mov r7, r11 /* r7 = r11. */
|
||||
stmia r2!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
select_next_task:
|
||||
cpsid i
|
||||
bl vTaskSwitchContext
|
||||
cpsie i
|
||||
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r3] /* Read the value of MPU_CTRL. */
|
||||
movs r5, #1 /* r5 = 1. */
|
||||
bics r4, r5 /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r3] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
ldr r3, =0xe000edc0 /* r3 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r3] /* Program MAIR0. */
|
||||
ldr r4, =0xe000ed98 /* r4 = 0xe000ed98 [Location of RNR]. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
movs r5, #4 /* r5 = 4. */
|
||||
str r5, [r4] /* Program RNR = 4. */
|
||||
ldmia r1!, {r6,r7} /* Read first set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r6,r7} /* Write first set of RBAR/RLAR registers. */
|
||||
movs r5, #5 /* r5 = 5. */
|
||||
str r5, [r4] /* Program RNR = 5. */
|
||||
ldmia r1!, {r6,r7} /* Read second set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r6,r7} /* Write second set of RBAR/RLAR registers. */
|
||||
movs r5, #6 /* r5 = 6. */
|
||||
str r5, [r4] /* Program RNR = 6. */
|
||||
ldmia r1!, {r6,r7} /* Read third set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r6,r7} /* Write third set of RBAR/RLAR registers. */
|
||||
movs r5, #7 /* r5 = 7. */
|
||||
str r5, [r4] /* Program RNR = 7. */
|
||||
ldmia r1!, {r6,r7} /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r6,r7} /* Write fourth set of RBAR/RLAR registers. */
|
||||
|
||||
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r3] /* Read the value of MPU_CTRL. */
|
||||
movs r5, #1 /* r5 = 1. */
|
||||
orrs r4, r5 /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r3] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r2!, {r0, r1, r3, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r3 /* Restore the CONTROL register value for the task. */
|
||||
mov lr, r4 /* LR = r4. */
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r3] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
push {r2, r4}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r2, r4}
|
||||
mov lr, r4 /* LR = r4. */
|
||||
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#else /* configENABLE_MPU */
|
||||
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
mov lr, r4 /* LR = r4. */
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r3] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
push {r2, r4}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r2, r4}
|
||||
mov lr, r4 /* LR = r4. */
|
||||
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
restore_ns_context:
|
||||
adds r2, r2, #16 /* Move to the high registers. */
|
||||
ldmia r2!, {r4-r7} /* Restore the high registers that are not automatically restored. */
|
||||
mov r8, r4 /* r8 = r4. */
|
||||
mov r9, r5 /* r9 = r5. */
|
||||
mov r10, r6 /* r10 = r6. */
|
||||
mov r11, r7 /* r11 = r7. */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
subs r2, r2, #32 /* Go back to the low registers. */
|
||||
ldmia r2!, {r4-r7} /* Restore the low registers that are not automatically restored. */
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SVC_Handler:
|
||||
movs r0, #4
|
||||
mov r1, lr
|
||||
tst r0, r1
|
||||
beq stacking_used_msp
|
||||
mrs r0, psp
|
||||
b vPortSVCHandler_C
|
||||
stacking_used_msp:
|
||||
mrs r0, msp
|
||||
b vPortSVCHandler_C
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortFreeSecureContext:
|
||||
ldr r2, [r0] /* The first item in the TCB is the top of the stack. */
|
||||
ldr r1, [r2] /* The first item on the stack is the task's xSecureContext. */
|
||||
cmp r1, #0 /* Raise svc if task's xSecureContext is not NULL. */
|
||||
bne free_secure_context /* Branch if r1 != 0. */
|
||||
bx lr /* There is no secure context (xSecureContext is NULL). */
|
||||
free_secure_context:
|
||||
svc 1 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 1. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN xSecureContext
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
EXTERN SecureContext_SaveContext
|
||||
EXTERN SecureContext_LoadContext
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
PUBLIC vPortAllocateSecureContext
|
||||
PUBLIC vRestoreContextOfFirstTask
|
||||
PUBLIC vRaisePrivilege
|
||||
PUBLIC vStartFirstTask
|
||||
PUBLIC ulSetInterruptMask
|
||||
PUBLIC vClearInterruptMask
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC SVC_Handler
|
||||
PUBLIC vPortFreeSecureContext
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*---------------- Unprivileged Functions -------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
tst r0, r1 /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
beq running_privileged /* If the result of previous AND operation was 0, branch. */
|
||||
movs r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
bx lr /* Return. */
|
||||
running_privileged:
|
||||
movs r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
orrs r0, r1 /* r0 = r0 | r1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortAllocateSecureContext:
|
||||
svc 0 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 0. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*----------------- Privileged Functions --------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION privileged_functions:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r3, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r5, #1 /* r5 = 1. */
|
||||
bics r4, r5 /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
movs r5, #4 /* r5 = 4. */
|
||||
str r5, [r2] /* Program RNR = 4. */
|
||||
ldmia r3!, {r6,r7} /* Read first set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write first set of RBAR/RLAR registers. */
|
||||
movs r5, #5 /* r5 = 5. */
|
||||
str r5, [r2] /* Program RNR = 5. */
|
||||
ldmia r3!, {r6,r7} /* Read second set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write second set of RBAR/RLAR registers. */
|
||||
movs r5, #6 /* r5 = 6. */
|
||||
str r5, [r2] /* Program RNR = 6. */
|
||||
ldmia r3!, {r6,r7} /* Read third set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write third set of RBAR/RLAR registers. */
|
||||
movs r5, #7 /* r5 = 7. */
|
||||
str r5, [r2] /* Program RNR = 7. */
|
||||
ldmia r3!, {r6,r7} /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write fourth set of RBAR/RLAR registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r5, #1 /* r5 = 1. */
|
||||
orrs r4, r5 /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
ldr r5, =xSecureContext
|
||||
str r1, [r5] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
msr control, r3 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r4 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
ldr r4, =xSecureContext
|
||||
str r1, [r4] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
movs r1, #2 /* r1 = 2. */
|
||||
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRaisePrivilege:
|
||||
mrs r0, control /* Read the CONTROL register. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
bics r0, r1 /* Clear the bit 0. */
|
||||
msr control, r0 /* Write back the new CONTROL value. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vStartFirstTask:
|
||||
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
dsb
|
||||
isb
|
||||
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMask:
|
||||
mrs r0, PRIMASK
|
||||
cpsid i
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMask:
|
||||
msr PRIMASK, r0
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
PendSV_Handler:
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
|
||||
mrs r2, psp /* Read PSP in r2. */
|
||||
|
||||
cbz r0, save_ns_context /* No secure context to save. */
|
||||
push {r0-r2, r14}
|
||||
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r0-r3} /* LR is now in r3. */
|
||||
mov lr, r3 /* LR = r3. */
|
||||
lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r2, r2, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r2, r2, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
b select_next_task
|
||||
|
||||
save_ns_context:
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r2, r2, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
adds r2, r2, #16 /* r2 = r2 + 16. */
|
||||
stmia r2!, {r4-r7} /* Store the low registers that are not saved automatically. */
|
||||
mov r4, r8 /* r4 = r8. */
|
||||
mov r5, r9 /* r5 = r9. */
|
||||
mov r6, r10 /* r6 = r10. */
|
||||
mov r7, r11 /* r7 = r11. */
|
||||
stmia r2!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
subs r2, r2, #48 /* r2 = r2 - 48. */
|
||||
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r2!, {r0, r1, r3-r7} /* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
|
||||
mov r4, r8 /* r4 = r8. */
|
||||
mov r5, r9 /* r5 = r9. */
|
||||
mov r6, r10 /* r6 = r10. */
|
||||
mov r7, r11 /* r7 = r11. */
|
||||
stmia r2!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
select_next_task:
|
||||
cpsid i
|
||||
bl vTaskSwitchContext
|
||||
cpsie i
|
||||
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r3] /* Read the value of MPU_CTRL. */
|
||||
movs r5, #1 /* r5 = 1. */
|
||||
bics r4, r5 /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r3] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
ldr r3, =0xe000edc0 /* r3 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r3] /* Program MAIR0. */
|
||||
ldr r4, =0xe000ed98 /* r4 = 0xe000ed98 [Location of RNR]. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
movs r5, #4 /* r5 = 4. */
|
||||
str r5, [r4] /* Program RNR = 4. */
|
||||
ldmia r1!, {r6,r7} /* Read first set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r6,r7} /* Write first set of RBAR/RLAR registers. */
|
||||
movs r5, #5 /* r5 = 5. */
|
||||
str r5, [r4] /* Program RNR = 5. */
|
||||
ldmia r1!, {r6,r7} /* Read second set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r6,r7} /* Write second set of RBAR/RLAR registers. */
|
||||
movs r5, #6 /* r5 = 6. */
|
||||
str r5, [r4] /* Program RNR = 6. */
|
||||
ldmia r1!, {r6,r7} /* Read third set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r6,r7} /* Write third set of RBAR/RLAR registers. */
|
||||
movs r5, #7 /* r5 = 7. */
|
||||
str r5, [r4] /* Program RNR = 7. */
|
||||
ldmia r1!, {r6,r7} /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r6,r7} /* Write fourth set of RBAR/RLAR registers. */
|
||||
|
||||
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r3] /* Read the value of MPU_CTRL. */
|
||||
movs r5, #1 /* r5 = 1. */
|
||||
orrs r4, r5 /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r3] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r2!, {r0, r1, r3, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r3 /* Restore the CONTROL register value for the task. */
|
||||
mov lr, r4 /* LR = r4. */
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r3] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
push {r2, r4}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r2, r4}
|
||||
mov lr, r4 /* LR = r4. */
|
||||
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#else /* configENABLE_MPU */
|
||||
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
mov lr, r4 /* LR = r4. */
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r3] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
push {r2, r4}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r2, r4}
|
||||
mov lr, r4 /* LR = r4. */
|
||||
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
restore_ns_context:
|
||||
adds r2, r2, #16 /* Move to the high registers. */
|
||||
ldmia r2!, {r4-r7} /* Restore the high registers that are not automatically restored. */
|
||||
mov r8, r4 /* r8 = r4. */
|
||||
mov r9, r5 /* r9 = r5. */
|
||||
mov r10, r6 /* r10 = r6. */
|
||||
mov r11, r7 /* r11 = r7. */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
subs r2, r2, #32 /* Go back to the low registers. */
|
||||
ldmia r2!, {r4-r7} /* Restore the low registers that are not automatically restored. */
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SVC_Handler:
|
||||
movs r0, #4
|
||||
mov r1, lr
|
||||
tst r0, r1
|
||||
beq stacking_used_msp
|
||||
mrs r0, psp
|
||||
b vPortSVCHandler_C
|
||||
stacking_used_msp:
|
||||
mrs r0, msp
|
||||
b vPortSVCHandler_C
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortFreeSecureContext:
|
||||
ldr r2, [r0] /* The first item in the TCB is the top of the stack. */
|
||||
ldr r1, [r2] /* The first item on the stack is the task's xSecureContext. */
|
||||
cmp r1, #0 /* Raise svc if task's xSecureContext is not NULL. */
|
||||
bne free_secure_context /* Branch if r1 != 0. */
|
||||
bx lr /* There is no secure context (xSecureContext is NULL). */
|
||||
free_secure_context:
|
||||
svc 1 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 1. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
|
|
|
|||
|
|
@ -1,78 +1,78 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portDONT_DISCARD __root
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||
* the source code because to do so would cause other compilers to generate
|
||||
* warnings. */
|
||||
#pragma diag_suppress=Be006
|
||||
#pragma diag_suppress=Pa082
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portDONT_DISCARD __root
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||
* the source code because to do so would cause other compilers to generate
|
||||
* warnings. */
|
||||
#pragma diag_suppress=Be006
|
||||
#pragma diag_suppress=Pa082
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,310 +1,310 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
PUBLIC vRestoreContextOfFirstTask
|
||||
PUBLIC vRaisePrivilege
|
||||
PUBLIC vStartFirstTask
|
||||
PUBLIC ulSetInterruptMask
|
||||
PUBLIC vClearInterruptMask
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC SVC_Handler
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*---------------- Unprivileged Functions -------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
tst r0, r1 /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
beq running_privileged /* If the result of previous AND operation was 0, branch. */
|
||||
movs r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
bx lr /* Return. */
|
||||
running_privileged:
|
||||
movs r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
bx lr /* Return. */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
orrs r0, r1 /* r0 = r0 | r1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*----------------- Privileged Functions --------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION privileged_functions:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r4, #1 /* r4 = 1. */
|
||||
bics r3, r4 /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
str r3, [r2] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r2] /* Program RNR = 4. */
|
||||
ldmia r1!, {r5,r6} /* Read first set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write first set of RBAR/RLAR registers. */
|
||||
movs r4, #5 /* r4 = 5. */
|
||||
str r4, [r2] /* Program RNR = 5. */
|
||||
ldmia r1!, {r5,r6} /* Read second set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write second set of RBAR/RLAR registers. */
|
||||
movs r4, #6 /* r4 = 6. */
|
||||
str r4, [r2] /* Program RNR = 6. */
|
||||
ldmia r1!, {r5,r6} /* Read third set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write third set of RBAR/RLAR registers. */
|
||||
movs r4, #7 /* r4 = 7. */
|
||||
str r4, [r2] /* Program RNR = 7. */
|
||||
ldmia r1!, {r5,r6} /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write fourth set of RBAR/RLAR registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r4, #1 /* r4 = 1. */
|
||||
orrs r3, r4 /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
str r3, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||
msr control, r2 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||
movs r1, #2 /* r1 = 2. */
|
||||
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r2 /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRaisePrivilege:
|
||||
mrs r0, control /* Read the CONTROL register. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
bics r0, r1 /* Clear the bit 0. */
|
||||
msr control, r0 /* Write back the new CONTROL value. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vStartFirstTask:
|
||||
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
dsb
|
||||
isb
|
||||
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
|
||||
nop
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMask:
|
||||
mrs r0, PRIMASK
|
||||
cpsid i
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMask:
|
||||
msr PRIMASK, r0
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
PendSV_Handler:
|
||||
mrs r0, psp /* Read PSP in r0. */
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r0, r0, #44 /* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
str r0, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r2, control /* r2 = CONTROL. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r0!, {r1-r7} /* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */
|
||||
mov r4, r8 /* r4 = r8. */
|
||||
mov r5, r9 /* r5 = r9. */
|
||||
mov r6, r10 /* r6 = r10. */
|
||||
mov r7, r11 /* r7 = r11. */
|
||||
stmia r0!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r0, r0, #40 /* Make space for PSPLIM, LR and the remaining registers on the stack. */
|
||||
str r0, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r0!, {r2-r7} /* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
|
||||
mov r4, r8 /* r4 = r8. */
|
||||
mov r5, r9 /* r5 = r9. */
|
||||
mov r6, r10 /* r6 = r10. */
|
||||
mov r7, r11 /* r7 = r11. */
|
||||
stmia r0!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
cpsid i
|
||||
bl vTaskSwitchContext
|
||||
cpsie i
|
||||
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r4, #1 /* r4 = 1. */
|
||||
bics r3, r4 /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
str r3, [r2] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r2] /* Program RNR = 4. */
|
||||
ldmia r1!, {r5,r6} /* Read first set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write first set of RBAR/RLAR registers. */
|
||||
movs r4, #5 /* r4 = 5. */
|
||||
str r4, [r2] /* Program RNR = 5. */
|
||||
ldmia r1!, {r5,r6} /* Read second set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write second set of RBAR/RLAR registers. */
|
||||
movs r4, #6 /* r4 = 6. */
|
||||
str r4, [r2] /* Program RNR = 6. */
|
||||
ldmia r1!, {r5,r6} /* Read third set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write third set of RBAR/RLAR registers. */
|
||||
movs r4, #7 /* r4 = 7. */
|
||||
str r4, [r2] /* Program RNR = 7. */
|
||||
ldmia r1!, {r5,r6} /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write fourth set of RBAR/RLAR registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r4, #1 /* r4 = 1. */
|
||||
orrs r3, r4 /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
str r3, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
adds r0, r0, #28 /* Move to the high registers. */
|
||||
ldmia r0!, {r4-r7} /* Restore the high registers that are not automatically restored. */
|
||||
mov r8, r4 /* r8 = r4. */
|
||||
mov r9, r5 /* r9 = r5. */
|
||||
mov r10, r6 /* r10 = r6. */
|
||||
mov r11, r7 /* r11 = r7. */
|
||||
msr psp, r0 /* Remember the new top of stack for the task. */
|
||||
subs r0, r0, #44 /* Move to the starting of the saved context. */
|
||||
ldmia r0!, {r1-r7} /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r2 /* Restore the CONTROL register value for the task. */
|
||||
bx r3
|
||||
#else /* configENABLE_MPU */
|
||||
adds r0, r0, #24 /* Move to the high registers. */
|
||||
ldmia r0!, {r4-r7} /* Restore the high registers that are not automatically restored. */
|
||||
mov r8, r4 /* r8 = r4. */
|
||||
mov r9, r5 /* r9 = r5. */
|
||||
mov r10, r6 /* r10 = r6. */
|
||||
mov r11, r7 /* r11 = r7. */
|
||||
msr psp, r0 /* Remember the new top of stack for the task. */
|
||||
subs r0, r0, #40 /* Move to the starting of the saved context. */
|
||||
ldmia r0!, {r2-r7} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
|
||||
msr psplim, r2 /* Restore the PSPLIM register value for the task. */
|
||||
bx r3
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SVC_Handler:
|
||||
movs r0, #4
|
||||
mov r1, lr
|
||||
tst r0, r1
|
||||
beq stacking_used_msp
|
||||
mrs r0, psp
|
||||
b vPortSVCHandler_C
|
||||
stacking_used_msp:
|
||||
mrs r0, msp
|
||||
b vPortSVCHandler_C
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
PUBLIC vRestoreContextOfFirstTask
|
||||
PUBLIC vRaisePrivilege
|
||||
PUBLIC vStartFirstTask
|
||||
PUBLIC ulSetInterruptMask
|
||||
PUBLIC vClearInterruptMask
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC SVC_Handler
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*---------------- Unprivileged Functions -------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
tst r0, r1 /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
beq running_privileged /* If the result of previous AND operation was 0, branch. */
|
||||
movs r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
bx lr /* Return. */
|
||||
running_privileged:
|
||||
movs r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
bx lr /* Return. */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
orrs r0, r1 /* r0 = r0 | r1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*----------------- Privileged Functions --------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION privileged_functions:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r4, #1 /* r4 = 1. */
|
||||
bics r3, r4 /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
str r3, [r2] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r2] /* Program RNR = 4. */
|
||||
ldmia r1!, {r5,r6} /* Read first set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write first set of RBAR/RLAR registers. */
|
||||
movs r4, #5 /* r4 = 5. */
|
||||
str r4, [r2] /* Program RNR = 5. */
|
||||
ldmia r1!, {r5,r6} /* Read second set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write second set of RBAR/RLAR registers. */
|
||||
movs r4, #6 /* r4 = 6. */
|
||||
str r4, [r2] /* Program RNR = 6. */
|
||||
ldmia r1!, {r5,r6} /* Read third set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write third set of RBAR/RLAR registers. */
|
||||
movs r4, #7 /* r4 = 7. */
|
||||
str r4, [r2] /* Program RNR = 7. */
|
||||
ldmia r1!, {r5,r6} /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write fourth set of RBAR/RLAR registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r4, #1 /* r4 = 1. */
|
||||
orrs r3, r4 /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
str r3, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||
msr control, r2 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||
movs r1, #2 /* r1 = 2. */
|
||||
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r2 /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRaisePrivilege:
|
||||
mrs r0, control /* Read the CONTROL register. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
bics r0, r1 /* Clear the bit 0. */
|
||||
msr control, r0 /* Write back the new CONTROL value. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vStartFirstTask:
|
||||
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
dsb
|
||||
isb
|
||||
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
|
||||
nop
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMask:
|
||||
mrs r0, PRIMASK
|
||||
cpsid i
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMask:
|
||||
msr PRIMASK, r0
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
PendSV_Handler:
|
||||
mrs r0, psp /* Read PSP in r0. */
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r0, r0, #44 /* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
str r0, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r2, control /* r2 = CONTROL. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r0!, {r1-r7} /* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */
|
||||
mov r4, r8 /* r4 = r8. */
|
||||
mov r5, r9 /* r5 = r9. */
|
||||
mov r6, r10 /* r6 = r10. */
|
||||
mov r7, r11 /* r7 = r11. */
|
||||
stmia r0!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r0, r0, #40 /* Make space for PSPLIM, LR and the remaining registers on the stack. */
|
||||
str r0, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r0!, {r2-r7} /* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
|
||||
mov r4, r8 /* r4 = r8. */
|
||||
mov r5, r9 /* r5 = r9. */
|
||||
mov r6, r10 /* r6 = r10. */
|
||||
mov r7, r11 /* r7 = r11. */
|
||||
stmia r0!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
cpsid i
|
||||
bl vTaskSwitchContext
|
||||
cpsie i
|
||||
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r4, #1 /* r4 = 1. */
|
||||
bics r3, r4 /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
str r3, [r2] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r2] /* Program RNR = 4. */
|
||||
ldmia r1!, {r5,r6} /* Read first set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write first set of RBAR/RLAR registers. */
|
||||
movs r4, #5 /* r4 = 5. */
|
||||
str r4, [r2] /* Program RNR = 5. */
|
||||
ldmia r1!, {r5,r6} /* Read second set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write second set of RBAR/RLAR registers. */
|
||||
movs r4, #6 /* r4 = 6. */
|
||||
str r4, [r2] /* Program RNR = 6. */
|
||||
ldmia r1!, {r5,r6} /* Read third set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write third set of RBAR/RLAR registers. */
|
||||
movs r4, #7 /* r4 = 7. */
|
||||
str r4, [r2] /* Program RNR = 7. */
|
||||
ldmia r1!, {r5,r6} /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write fourth set of RBAR/RLAR registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r4, #1 /* r4 = 1. */
|
||||
orrs r3, r4 /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
str r3, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
adds r0, r0, #28 /* Move to the high registers. */
|
||||
ldmia r0!, {r4-r7} /* Restore the high registers that are not automatically restored. */
|
||||
mov r8, r4 /* r8 = r4. */
|
||||
mov r9, r5 /* r9 = r5. */
|
||||
mov r10, r6 /* r10 = r6. */
|
||||
mov r11, r7 /* r11 = r7. */
|
||||
msr psp, r0 /* Remember the new top of stack for the task. */
|
||||
subs r0, r0, #44 /* Move to the starting of the saved context. */
|
||||
ldmia r0!, {r1-r7} /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r2 /* Restore the CONTROL register value for the task. */
|
||||
bx r3
|
||||
#else /* configENABLE_MPU */
|
||||
adds r0, r0, #24 /* Move to the high registers. */
|
||||
ldmia r0!, {r4-r7} /* Restore the high registers that are not automatically restored. */
|
||||
mov r8, r4 /* r8 = r4. */
|
||||
mov r9, r5 /* r9 = r5. */
|
||||
mov r10, r6 /* r10 = r6. */
|
||||
mov r11, r7 /* r11 = r7. */
|
||||
msr psp, r0 /* Remember the new top of stack for the task. */
|
||||
subs r0, r0, #40 /* Move to the starting of the saved context. */
|
||||
ldmia r0!, {r2-r7} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
|
||||
msr psplim, r2 /* Restore the PSPLIM register value for the task. */
|
||||
bx r3
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SVC_Handler:
|
||||
movs r0, #4
|
||||
mov r1, lr
|
||||
tst r0, r1
|
||||
beq stacking_used_msp
|
||||
mrs r0, psp
|
||||
b vPortSVCHandler_C
|
||||
stacking_used_msp:
|
||||
mrs r0, msp
|
||||
b vPortSVCHandler_C
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
|
|
|
|||
|
|
@ -1,78 +1,78 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portDONT_DISCARD __root
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||
* the source code because to do so would cause other compilers to generate
|
||||
* warnings. */
|
||||
#pragma diag_suppress=Be006
|
||||
#pragma diag_suppress=Pa082
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portDONT_DISCARD __root
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||
* the source code because to do so would cause other compilers to generate
|
||||
* warnings. */
|
||||
#pragma diag_suppress=Be006
|
||||
#pragma diag_suppress=Pa082
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,353 +1,353 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN xSecureContext
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
EXTERN SecureContext_SaveContext
|
||||
EXTERN SecureContext_LoadContext
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
PUBLIC vPortAllocateSecureContext
|
||||
PUBLIC vRestoreContextOfFirstTask
|
||||
PUBLIC vRaisePrivilege
|
||||
PUBLIC vStartFirstTask
|
||||
PUBLIC ulSetInterruptMask
|
||||
PUBLIC vClearInterruptMask
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC SVC_Handler
|
||||
PUBLIC vPortFreeSecureContext
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*---------------- Unprivileged Functions -------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
ite ne
|
||||
movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
orr r0, r0, #1 /* r0 = r0 | 1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortAllocateSecureContext:
|
||||
svc 0 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 0. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*----------------- Privileged Functions --------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION privileged_functions:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r3, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r2] /* Program RNR = 4. */
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r3!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
ldr r5, =xSecureContext
|
||||
str r1, [r5] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
msr control, r3 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||
bx r4 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
ldr r4, =xSecureContext
|
||||
str r1, [r4] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
movs r1, #2 /* r1 = 2. */
|
||||
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRaisePrivilege:
|
||||
mrs r0, control /* Read the CONTROL register. */
|
||||
bic r0, r0, #1 /* Clear the bit 0. */
|
||||
msr control, r0 /* Write back the new CONTROL value. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vStartFirstTask:
|
||||
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMask:
|
||||
mrs r0, basepri /* r0 = basepri. Return original basepri value. */
|
||||
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r1 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMask:
|
||||
msr basepri, r0 /* basepri = ulMask. */
|
||||
dsb
|
||||
isb
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
PendSV_Handler:
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
|
||||
mrs r2, psp /* Read PSP in r2. */
|
||||
|
||||
cbz r0, save_ns_context /* No secure context to save. */
|
||||
push {r0-r2, r14}
|
||||
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r0-r3} /* LR is now in r3. */
|
||||
mov lr, r3 /* LR = r3. */
|
||||
lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r2, r2, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r2, r2, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
b select_next_task
|
||||
|
||||
save_ns_context:
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
it eq
|
||||
vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r2, r2, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
adds r2, r2, #16 /* r2 = r2 + 16. */
|
||||
stm r2, {r4-r11} /* Store the registers that are not saved automatically. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
subs r2, r2, #16 /* r2 = r2 - 16. */
|
||||
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
adds r2, r2, #12 /* r2 = r2 + 12. */
|
||||
stm r2, {r4-r11} /* Store the registers that are not saved automatically. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
subs r2, r2, #12 /* r2 = r2 - 12. */
|
||||
stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
select_next_task:
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0 /* r0 = 0. */
|
||||
msr basepri, r0 /* Enable interrupts. */
|
||||
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r3] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r3] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
ldr r3, =0xe000edc0 /* r3 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r3] /* Program MAIR0. */
|
||||
ldr r3, =0xe000ed98 /* r3 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r3] /* Program RNR = 4. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r3!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r3] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r3] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r2!, {r0, r1, r3, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r3 /* Restore the CONTROL register value for the task. */
|
||||
mov lr, r4 /* LR = r4. */
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r3] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
push {r2, r4}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r2, r4}
|
||||
mov lr, r4 /* LR = r4. */
|
||||
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#else /* configENABLE_MPU */
|
||||
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
mov lr, r4 /* LR = r4. */
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r3] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
push {r2, r4}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r2, r4}
|
||||
mov lr, r4 /* LR = r4. */
|
||||
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
restore_ns_context:
|
||||
ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
it eq
|
||||
vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SVC_Handler:
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, msp
|
||||
mrsne r0, psp
|
||||
b vPortSVCHandler_C
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortFreeSecureContext:
|
||||
/* r0 = uint32_t *pulTCB. */
|
||||
ldr r2, [r0] /* The first item in the TCB is the top of the stack. */
|
||||
ldr r1, [r2] /* The first item on the stack is the task's xSecureContext. */
|
||||
cmp r1, #0 /* Raise svc if task's xSecureContext is not NULL. */
|
||||
it ne
|
||||
svcne 1 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 1. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN xSecureContext
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
EXTERN SecureContext_SaveContext
|
||||
EXTERN SecureContext_LoadContext
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
PUBLIC vPortAllocateSecureContext
|
||||
PUBLIC vRestoreContextOfFirstTask
|
||||
PUBLIC vRaisePrivilege
|
||||
PUBLIC vStartFirstTask
|
||||
PUBLIC ulSetInterruptMask
|
||||
PUBLIC vClearInterruptMask
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC SVC_Handler
|
||||
PUBLIC vPortFreeSecureContext
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*---------------- Unprivileged Functions -------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
ite ne
|
||||
movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
orr r0, r0, #1 /* r0 = r0 | 1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortAllocateSecureContext:
|
||||
svc 0 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 0. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*----------------- Privileged Functions --------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION privileged_functions:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r3, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r2] /* Program RNR = 4. */
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r3!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
ldr r5, =xSecureContext
|
||||
str r1, [r5] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
msr control, r3 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||
bx r4 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
ldr r4, =xSecureContext
|
||||
str r1, [r4] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
movs r1, #2 /* r1 = 2. */
|
||||
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRaisePrivilege:
|
||||
mrs r0, control /* Read the CONTROL register. */
|
||||
bic r0, r0, #1 /* Clear the bit 0. */
|
||||
msr control, r0 /* Write back the new CONTROL value. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vStartFirstTask:
|
||||
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMask:
|
||||
mrs r0, basepri /* r0 = basepri. Return original basepri value. */
|
||||
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r1 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMask:
|
||||
msr basepri, r0 /* basepri = ulMask. */
|
||||
dsb
|
||||
isb
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
PendSV_Handler:
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
ldr r0, [r3] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later. */
|
||||
mrs r2, psp /* Read PSP in r2. */
|
||||
|
||||
cbz r0, save_ns_context /* No secure context to save. */
|
||||
push {r0-r2, r14}
|
||||
bl SecureContext_SaveContext /* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r0-r3} /* LR is now in r3. */
|
||||
mov lr, r3 /* LR = r3. */
|
||||
lsls r1, r3, #25 /* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl save_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r2, r2, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r2, r2, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
b select_next_task
|
||||
|
||||
save_ns_context:
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
it eq
|
||||
vstmdbeq r2!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r2, r2, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
adds r2, r2, #16 /* r2 = r2 + 16. */
|
||||
stm r2, {r4-r11} /* Store the registers that are not saved automatically. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
subs r2, r2, #16 /* r2 = r2 - 16. */
|
||||
stmia r2!, {r0, r1, r3, r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r2, r2, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
str r2, [r1] /* Save the new top of stack in TCB. */
|
||||
adds r2, r2, #12 /* r2 = r2 + 12. */
|
||||
stm r2, {r4-r11} /* Store the registers that are not saved automatically. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
subs r2, r2, #12 /* r2 = r2 - 12. */
|
||||
stmia r2!, {r0, r1, r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
select_next_task:
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0 /* r0 = 0. */
|
||||
msr basepri, r0 /* Enable interrupts. */
|
||||
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
ldr r2, [r1] /* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r3] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r3] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
ldr r3, =0xe000edc0 /* r3 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r3] /* Program MAIR0. */
|
||||
ldr r3, =0xe000ed98 /* r3 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r3] /* Program RNR = 4. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r3!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r3, =0xe000ed94 /* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r3] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r3] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r2!, {r0, r1, r3, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r3 /* Restore the CONTROL register value for the task. */
|
||||
mov lr, r4 /* LR = r4. */
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r3] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
push {r2, r4}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r2, r4}
|
||||
mov lr, r4 /* LR = r4. */
|
||||
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#else /* configENABLE_MPU */
|
||||
ldmia r2!, {r0, r1, r4} /* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
mov lr, r4 /* LR = r4. */
|
||||
ldr r3, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r3] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r3] /* Read pxCurrentTCB. */
|
||||
push {r2, r4}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
pop {r2, r4}
|
||||
mov lr, r4 /* LR = r4. */
|
||||
lsls r1, r4, #25 /* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl restore_ns_context /* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
restore_ns_context:
|
||||
ldmia r2!, {r4-r11} /* Restore the registers that are not automatically restored. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
it eq
|
||||
vldmiaeq r2!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
msr psp, r2 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SVC_Handler:
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, msp
|
||||
mrsne r0, psp
|
||||
b vPortSVCHandler_C
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortFreeSecureContext:
|
||||
/* r0 = uint32_t *pulTCB. */
|
||||
ldr r2, [r0] /* The first item in the TCB is the top of the stack. */
|
||||
ldr r1, [r2] /* The first item on the stack is the task's xSecureContext. */
|
||||
cmp r1, #0 /* Raise svc if task's xSecureContext is not NULL. */
|
||||
it ne
|
||||
svcne 1 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 1. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
|
|
|
|||
|
|
@ -1,78 +1,78 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portDONT_DISCARD __root
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||
* the source code because to do so would cause other compilers to generate
|
||||
* warnings. */
|
||||
#pragma diag_suppress=Be006
|
||||
#pragma diag_suppress=Pa082
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portDONT_DISCARD __root
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||
* the source code because to do so would cause other compilers to generate
|
||||
* warnings. */
|
||||
#pragma diag_suppress=Be006
|
||||
#pragma diag_suppress=Pa082
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,262 +1,262 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
PUBLIC vRestoreContextOfFirstTask
|
||||
PUBLIC vRaisePrivilege
|
||||
PUBLIC vStartFirstTask
|
||||
PUBLIC ulSetInterruptMask
|
||||
PUBLIC vClearInterruptMask
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC SVC_Handler
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*---------------- Unprivileged Functions -------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
ite ne
|
||||
movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
orr r0, r0, #1 /* r0 = r0 | 1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*----------------- Privileged Functions --------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION privileged_functions:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r3, [r1] /* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r3, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r3, #4 /* r3 = 4. */
|
||||
str r3, [r2] /* Program RNR = 4. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||
msr control, r2 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||
movs r1, #2 /* r1 = 2. */
|
||||
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||
bx r2 /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRaisePrivilege:
|
||||
mrs r0, control /* Read the CONTROL register. */
|
||||
bic r0, r0, #1 /* Clear the bit 0. */
|
||||
msr control, r0 /* Write back the new CONTROL value. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vStartFirstTask:
|
||||
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMask:
|
||||
mrs r0, basepri /* r0 = basepri. Return original basepri value. */
|
||||
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r1 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMask:
|
||||
msr basepri, r0 /* basepri = ulMask. */
|
||||
dsb
|
||||
isb
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
PendSV_Handler:
|
||||
mrs r0, psp /* Read PSP in r0. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
it eq
|
||||
vstmdbeq r0!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r2, control /* r2 = CONTROL. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmdb r0!, {r1-r11} /* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
|
||||
#else /* configENABLE_MPU */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
str r0, [r1] /* Save the new top of stack in TCB. */
|
||||
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0 /* r0 = 0. */
|
||||
msr basepri, r0 /* Enable interrupts. */
|
||||
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r3, [r1] /* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r3, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r3, #4 /* r3 = 4. */
|
||||
str r3, [r2] /* Program RNR = 4. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r0!, {r1-r11} /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
tst r3, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
it eq
|
||||
vldmiaeq r0!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r2 /* Restore the CONTROL register value for the task. */
|
||||
#else /* configENABLE_MPU */
|
||||
msr psplim, r2 /* Restore the PSPLIM register value for the task. */
|
||||
#endif /* configENABLE_MPU */
|
||||
msr psp, r0 /* Remember the new top of stack for the task. */
|
||||
bx r3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SVC_Handler:
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, msp
|
||||
mrsne r0, psp
|
||||
b vPortSVCHandler_C
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
PUBLIC vRestoreContextOfFirstTask
|
||||
PUBLIC vRaisePrivilege
|
||||
PUBLIC vStartFirstTask
|
||||
PUBLIC ulSetInterruptMask
|
||||
PUBLIC vClearInterruptMask
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC SVC_Handler
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*---------------- Unprivileged Functions -------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
ite ne
|
||||
movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
orr r0, r0, #1 /* r0 = r0 | 1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*----------------- Privileged Functions --------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION privileged_functions:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r3, [r1] /* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r3, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r3, #4 /* r3 = 4. */
|
||||
str r3, [r2] /* Program RNR = 4. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||
msr control, r2 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||
movs r1, #2 /* r1 = 2. */
|
||||
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0 /* Ensure that interrupts are enabled when the first task starts. */
|
||||
bx r2 /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRaisePrivilege:
|
||||
mrs r0, control /* Read the CONTROL register. */
|
||||
bic r0, r0, #1 /* Clear the bit 0. */
|
||||
msr control, r0 /* Write back the new CONTROL value. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vStartFirstTask:
|
||||
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMask:
|
||||
mrs r0, basepri /* r0 = basepri. Return original basepri value. */
|
||||
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r1 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMask:
|
||||
msr basepri, r0 /* basepri = ulMask. */
|
||||
dsb
|
||||
isb
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
PendSV_Handler:
|
||||
mrs r0, psp /* Read PSP in r0. */
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
it eq
|
||||
vstmdbeq r0!, {s16-s31} /* Store the additional FP context registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r2, control /* r2 = CONTROL. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmdb r0!, {r1-r11} /* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
|
||||
#else /* configENABLE_MPU */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
str r0, [r1] /* Save the new top of stack in TCB. */
|
||||
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0 /* r0 = 0. */
|
||||
msr basepri, r0 /* Enable interrupts. */
|
||||
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r3, [r1] /* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r3, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r3, #4 /* r3 = 4. */
|
||||
str r3, [r2] /* Program RNR = 4. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r0!, {r1-r11} /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
tst r3, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the Extended Stack Frame is in use. */
|
||||
it eq
|
||||
vldmiaeq r0!, {s16-s31} /* Restore the additional FP context registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r2 /* Restore the CONTROL register value for the task. */
|
||||
#else /* configENABLE_MPU */
|
||||
msr psplim, r2 /* Restore the PSPLIM register value for the task. */
|
||||
#endif /* configENABLE_MPU */
|
||||
msr psp, r0 /* Remember the new top of stack for the task. */
|
||||
bx r3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SVC_Handler:
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, msp
|
||||
mrsne r0, psp
|
||||
b vPortSVCHandler_C
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
|
|
|
|||
|
|
@ -1,78 +1,78 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portDONT_DISCARD __root
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||
* the source code because to do so would cause other compilers to generate
|
||||
* warnings. */
|
||||
#pragma diag_suppress=Be006
|
||||
#pragma diag_suppress=Pa082
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portDONT_DISCARD __root
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
|
||||
* the source code because to do so would cause other compilers to generate
|
||||
* warnings. */
|
||||
#pragma diag_suppress=Be006
|
||||
#pragma diag_suppress=Pa082
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,114 +1,114 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ASM_H__
|
||||
#define __PORT_ASM_H__
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/**
|
||||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* @note This is a privileged function and should only be called from the kenrel
|
||||
* code.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ASM_H__
|
||||
#define __PORT_ASM_H__
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/**
|
||||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* @note This is a privileged function and should only be called from the kenrel
|
||||
* code.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
|
|
|
|||
|
|
@ -155,9 +155,9 @@
|
|||
* 8-bit values encoded as follows:
|
||||
* Bit[7:4] - 0000 - Device Memory
|
||||
* Bit[3:2] - 00 --> Device-nGnRnE
|
||||
* 01 --> Device-nGnRE
|
||||
* 10 --> Device-nGRE
|
||||
* 11 --> Device-GRE
|
||||
* 01 --> Device-nGnRE
|
||||
* 10 --> Device-nGRE
|
||||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
This directory tree contains the master copy of the FreeRTOS Armv8-M and
|
||||
Armv8.1-M ports.
|
||||
Do not use the files located here! These file are copied into separate
|
||||
FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85]_NNN directories prior to
|
||||
each FreeRTOS release.
|
||||
|
||||
If your Armv8-M/Armv8.1-M application uses TrustZone then use the files from the
|
||||
FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85] directories.
|
||||
|
||||
If your Armv8-M/Armv8.1-M application does not use TrustZone then use the files from
|
||||
the FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85]_NTZ directories.
|
||||
This directory tree contains the master copy of the FreeRTOS Armv8-M and
|
||||
Armv8.1-M ports.
|
||||
Do not use the files located here! These file are copied into separate
|
||||
FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85]_NNN directories prior to
|
||||
each FreeRTOS release.
|
||||
|
||||
If your Armv8-M/Armv8.1-M application uses TrustZone then use the files from the
|
||||
FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85] directories.
|
||||
|
||||
If your Armv8-M/Armv8.1-M application does not use TrustZone then use the files from
|
||||
the FreeRTOS/Source/portable/[compiler]/ARM_CM[23|33|55|85]_NTZ directories.
|
||||
|
|
|
|||
|
|
@ -1,99 +1,99 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||
|
||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
|
||||
{
|
||||
/* pxSecureContext value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" ldmia r0!, {r1, r2} \n" /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
" msr control, r3 \n" /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" msr psplim, r2 \n" /* PSPLIM = r2. */
|
||||
" msr psp, r1 \n" /* PSP = r1. */
|
||||
" \n"
|
||||
" load_ctx_therad_mode: \n"
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
::: "r0", "r1", "r2"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )
|
||||
{
|
||||
/* pxSecureContext value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" mrs r1, psp \n" /* r1 = PSP. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||
" subs r1, r1, #4 \n" /* Make space for the CONTROL value on the stack. */
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
" stmia r1!, {r2} \n" /* Store CONTROL value on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */
|
||||
" msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */
|
||||
" msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
" \n"
|
||||
" save_ctx_therad_mode: \n"
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
::"i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||
|
||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
|
||||
{
|
||||
/* pxSecureContext value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" ldmia r0!, {r1, r2} \n" /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
" msr control, r3 \n" /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" msr psplim, r2 \n" /* PSPLIM = r2. */
|
||||
" msr psp, r1 \n" /* PSP = r1. */
|
||||
" \n"
|
||||
" load_ctx_therad_mode: \n"
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
::: "r0", "r1", "r2"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )
|
||||
{
|
||||
/* pxSecureContext value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" mrs r1, psp \n" /* r1 = PSP. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||
" subs r1, r1, #4 \n" /* Make space for the CONTROL value on the stack. */
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
" stmia r1!, {r2} \n" /* Store CONTROL value on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */
|
||||
" msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */
|
||||
" msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
" \n"
|
||||
" save_ctx_therad_mode: \n"
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
::"i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,97 +1,97 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||
|
||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
|
||||
{
|
||||
/* pxSecureContext value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" ldmia r0!, {r1, r2} \n" /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
" msr control, r3 \n" /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" msr psplim, r2 \n" /* PSPLIM = r2. */
|
||||
" msr psp, r1 \n" /* PSP = r1. */
|
||||
" \n"
|
||||
" load_ctx_therad_mode: \n"
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
::: "r0", "r1", "r2"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )
|
||||
{
|
||||
/* pxSecureContext value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" mrs r1, psp \n" /* r1 = PSP. */
|
||||
" \n"
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" vstmdb r1!, {s0} \n" /* Trigger the deferred stacking of FPU registers. */
|
||||
" vldmia r1!, {s0} \n" /* Nullify the effect of the previous statement. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||
" stmdb r1!, {r2} \n" /* Store CONTROL value on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */
|
||||
" msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */
|
||||
" msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
" \n"
|
||||
" save_ctx_therad_mode: \n"
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
::"i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||
|
||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
|
||||
{
|
||||
/* pxSecureContext value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" ldmia r0!, {r1, r2} \n" /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
" msr control, r3 \n" /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" msr psplim, r2 \n" /* PSPLIM = r2. */
|
||||
" msr psp, r1 \n" /* PSP = r1. */
|
||||
" \n"
|
||||
" load_ctx_therad_mode: \n"
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
::: "r0", "r1", "r2"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )
|
||||
{
|
||||
/* pxSecureContext value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" mrs r1, psp \n" /* r1 = PSP. */
|
||||
" \n"
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
" vstmdb r1!, {s0} \n" /* Trigger the deferred stacking of FPU registers. */
|
||||
" vldmia r1!, {s0} \n" /* Nullify the effect of the previous statement. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||
" stmdb r1!, {r2} \n" /* Store CONTROL value on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */
|
||||
" msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */
|
||||
" msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
" \n"
|
||||
" save_ctx_therad_mode: \n"
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
::"i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,88 +1,88 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
PUBLIC SecureContext_LoadContextAsm
|
||||
PUBLIC SecureContext_SaveContextAsm
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SecureContext_LoadContextAsm:
|
||||
/* pxSecureContext value is in r0. */
|
||||
mrs r1, ipsr /* r1 = IPSR. */
|
||||
cbz r1, load_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||
ldmia r0!, {r1, r2} /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r1!, {r3} /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
msr control, r3 /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
msr psplim, r2 /* PSPLIM = r2. */
|
||||
msr psp, r1 /* PSP = r1. */
|
||||
|
||||
load_ctx_therad_mode:
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SecureContext_SaveContextAsm:
|
||||
/* pxSecureContext value is in r0. */
|
||||
mrs r1, ipsr /* r1 = IPSR. */
|
||||
cbz r1, save_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||
mrs r1, psp /* r1 = PSP. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
mrs r2, control /* r2 = CONTROL. */
|
||||
subs r1, r1, #4 /* Make space for the CONTROL value on the stack. */
|
||||
str r1, [r0] /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
stmia r1!, {r2} /* Store CONTROL value on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
str r1, [r0] /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
movs r1, #0 /* r1 = securecontextNO_STACK. */
|
||||
msr psplim, r1 /* PSPLIM = securecontextNO_STACK. */
|
||||
msr psp, r1 /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
|
||||
save_ctx_therad_mode:
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
PUBLIC SecureContext_LoadContextAsm
|
||||
PUBLIC SecureContext_SaveContextAsm
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SecureContext_LoadContextAsm:
|
||||
/* pxSecureContext value is in r0. */
|
||||
mrs r1, ipsr /* r1 = IPSR. */
|
||||
cbz r1, load_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||
ldmia r0!, {r1, r2} /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r1!, {r3} /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
msr control, r3 /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
msr psplim, r2 /* PSPLIM = r2. */
|
||||
msr psp, r1 /* PSP = r1. */
|
||||
|
||||
load_ctx_therad_mode:
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SecureContext_SaveContextAsm:
|
||||
/* pxSecureContext value is in r0. */
|
||||
mrs r1, ipsr /* r1 = IPSR. */
|
||||
cbz r1, save_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||
mrs r1, psp /* r1 = PSP. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
mrs r2, control /* r2 = CONTROL. */
|
||||
subs r1, r1, #4 /* Make space for the CONTROL value on the stack. */
|
||||
str r1, [r0] /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
stmia r1!, {r2} /* Store CONTROL value on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
str r1, [r0] /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
movs r1, #0 /* r1 = securecontextNO_STACK. */
|
||||
msr psplim, r1 /* PSPLIM = securecontextNO_STACK. */
|
||||
msr psp, r1 /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
|
||||
save_ctx_therad_mode:
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
|
|
|
|||
|
|
@ -1,86 +1,86 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
PUBLIC SecureContext_LoadContextAsm
|
||||
PUBLIC SecureContext_SaveContextAsm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SecureContext_LoadContextAsm:
|
||||
/* pxSecureContext value is in r0. */
|
||||
mrs r1, ipsr /* r1 = IPSR. */
|
||||
cbz r1, load_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||
ldmia r0!, {r1, r2} /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r1!, {r3} /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
msr control, r3 /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
msr psplim, r2 /* PSPLIM = r2. */
|
||||
msr psp, r1 /* PSP = r1. */
|
||||
|
||||
load_ctx_therad_mode:
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SecureContext_SaveContextAsm:
|
||||
/* pxSecureContext value is in r0. */
|
||||
mrs r1, ipsr /* r1 = IPSR. */
|
||||
cbz r1, save_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||
mrs r1, psp /* r1 = PSP. */
|
||||
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
vstmdb r1!, {s0} /* Trigger the deferred stacking of FPU registers. */
|
||||
vldmia r1!, {s0} /* Nullify the effect of the previous statement. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
mrs r2, control /* r2 = CONTROL. */
|
||||
stmdb r1!, {r2} /* Store CONTROL value on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
str r1, [r0] /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
movs r1, #0 /* r1 = securecontextNO_STACK. */
|
||||
msr psplim, r1 /* PSPLIM = securecontextNO_STACK. */
|
||||
msr psp, r1 /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
|
||||
save_ctx_therad_mode:
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
PUBLIC SecureContext_LoadContextAsm
|
||||
PUBLIC SecureContext_SaveContextAsm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SecureContext_LoadContextAsm:
|
||||
/* pxSecureContext value is in r0. */
|
||||
mrs r1, ipsr /* r1 = IPSR. */
|
||||
cbz r1, load_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||
ldmia r0!, {r1, r2} /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r1!, {r3} /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
msr control, r3 /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
msr psplim, r2 /* PSPLIM = r2. */
|
||||
msr psp, r1 /* PSP = r1. */
|
||||
|
||||
load_ctx_therad_mode:
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SecureContext_SaveContextAsm:
|
||||
/* pxSecureContext value is in r0. */
|
||||
mrs r1, ipsr /* r1 = IPSR. */
|
||||
cbz r1, save_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||
mrs r1, psp /* r1 = PSP. */
|
||||
|
||||
#if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
|
||||
vstmdb r1!, {s0} /* Trigger the deferred stacking of FPU registers. */
|
||||
vldmia r1!, {s0} /* Nullify the effect of the previous statement. */
|
||||
#endif /* configENABLE_FPU || configENABLE_MVE */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
mrs r2, control /* r2 = CONTROL. */
|
||||
stmdb r1!, {r2} /* Store CONTROL value on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
str r1, [r0] /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
movs r1, #0 /* r1 = securecontextNO_STACK. */
|
||||
msr psplim, r1 /* PSPLIM = securecontextNO_STACK. */
|
||||
msr psp, r1 /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
|
||||
save_ctx_therad_mode:
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
|
|
|
|||
|
|
@ -1,351 +1,351 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for privileged tasks.
|
||||
*
|
||||
* Bit[0] - 0 --> Thread mode is privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for un-privileged tasks.
|
||||
*
|
||||
* Bit[0] - 1 --> Thread mode is un-privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
|
||||
|
||||
/**
|
||||
* @brief Size of stack seal values in bytes.
|
||||
*/
|
||||
#define securecontextSTACK_SEAL_SIZE 8
|
||||
|
||||
/**
|
||||
* @brief Stack seal value as recommended by ARM.
|
||||
*/
|
||||
#define securecontextSTACK_SEAL_VALUE 0xFEF5EDA5
|
||||
|
||||
/**
|
||||
* @brief Maximum number of secure contexts.
|
||||
*/
|
||||
#ifndef secureconfigMAX_SECURE_CONTEXTS
|
||||
#define secureconfigMAX_SECURE_CONTEXTS 8UL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Pre-allocated array of secure contexts.
|
||||
*/
|
||||
SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Get a free secure context for a task from the secure context pool (xSecureContexts).
|
||||
*
|
||||
* This function ensures that only one secure context is allocated for a task.
|
||||
*
|
||||
* @param[in] pvTaskHandle The task handle for which the secure context is allocated.
|
||||
*
|
||||
* @return Index of a free secure context in the xSecureContexts array.
|
||||
*/
|
||||
static uint32_t ulGetSecureContext( void * pvTaskHandle );
|
||||
|
||||
/**
|
||||
* @brief Return the secure context to the secure context pool (xSecureContexts).
|
||||
*
|
||||
* @param[in] ulSecureContextIndex Index of the context in the xSecureContexts array.
|
||||
*/
|
||||
static void vReturnSecureContext( uint32_t ulSecureContextIndex );
|
||||
|
||||
/* These are implemented in assembly. */
|
||||
extern void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext );
|
||||
extern void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static uint32_t ulGetSecureContext( void * pvTaskHandle )
|
||||
{
|
||||
/* Start with invalid index. */
|
||||
uint32_t i, ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
|
||||
|
||||
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
|
||||
{
|
||||
if( ( xSecureContexts[ i ].pucCurrentStackPointer == NULL ) &&
|
||||
( xSecureContexts[ i ].pucStackLimit == NULL ) &&
|
||||
( xSecureContexts[ i ].pucStackStart == NULL ) &&
|
||||
( xSecureContexts[ i ].pvTaskHandle == NULL ) &&
|
||||
( ulSecureContextIndex == secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = i;
|
||||
}
|
||||
else if( xSecureContexts[ i ].pvTaskHandle == pvTaskHandle )
|
||||
{
|
||||
/* A task can only have one secure context. Do not allocate a second
|
||||
* context for the same task. */
|
||||
ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ulSecureContextIndex;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void vReturnSecureContext( uint32_t ulSecureContextIndex )
|
||||
{
|
||||
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;
|
||||
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
|
||||
{
|
||||
uint32_t ulIPSR, i;
|
||||
static uint32_t ulSecureContextsInitialized = 0;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ( ulIPSR != 0 ) && ( ulSecureContextsInitialized == 0 ) )
|
||||
{
|
||||
/* Ensure to initialize secure contexts only once. */
|
||||
ulSecureContextsInitialized = 1;
|
||||
|
||||
/* No stack for thread mode until a task's context is loaded. */
|
||||
secureportSET_PSPLIM( securecontextNO_STACK );
|
||||
secureportSET_PSP( securecontextNO_STACK );
|
||||
|
||||
/* Initialize all secure contexts. */
|
||||
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
|
||||
{
|
||||
xSecureContexts[ i ].pucCurrentStackPointer = NULL;
|
||||
xSecureContexts[ i ].pucStackLimit = NULL;
|
||||
xSecureContexts[ i ].pucStackStart = NULL;
|
||||
xSecureContexts[ i ].pvTaskHandle = NULL;
|
||||
}
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be unprivileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be privileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
uint32_t ulIsTaskPrivileged,
|
||||
void * pvTaskHandle )
|
||||
#else /* configENABLE_MPU */
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
void * pvTaskHandle )
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
uint8_t * pucStackMemory = NULL;
|
||||
uint8_t * pucStackLimit;
|
||||
uint32_t ulIPSR, ulSecureContextIndex;
|
||||
SecureContextHandle_t xSecureContextHandle = securecontextINVALID_CONTEXT_ID;
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
uint32_t * pulCurrentStackPointer = NULL;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
|
||||
* Register (PSPLIM) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
secureportREAD_PSPLIM( pucStackLimit );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode.
|
||||
* Also do nothing, if a secure context us already loaded. PSPLIM is set to
|
||||
* securecontextNO_STACK when no secure context is loaded. */
|
||||
if( ( ulIPSR != 0 ) && ( pucStackLimit == securecontextNO_STACK ) )
|
||||
{
|
||||
/* Ontain a free secure context. */
|
||||
ulSecureContextIndex = ulGetSecureContext( pvTaskHandle );
|
||||
|
||||
/* Were we able to get a free context? */
|
||||
if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
|
||||
{
|
||||
/* Allocate the stack space. */
|
||||
pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
|
||||
|
||||
if( pucStackMemory != NULL )
|
||||
{
|
||||
/* Since stack grows down, the starting point will be the last
|
||||
* location. Note that this location is next to the last
|
||||
* allocated byte for stack (excluding the space for seal values)
|
||||
* because the hardware decrements the stack pointer before
|
||||
* writing i.e. if stack pointer is 0x2, a push operation will
|
||||
* decrement the stack pointer to 0x1 and then write at 0x1. */
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;
|
||||
|
||||
/* Seal the created secure process stack. */
|
||||
*( uint32_t * )( pucStackMemory + ulSecureStackSize ) = securecontextSTACK_SEAL_VALUE;
|
||||
*( uint32_t * )( pucStackMemory + ulSecureStackSize + 4 ) = securecontextSTACK_SEAL_VALUE;
|
||||
|
||||
/* The stack cannot go beyond this location. This value is
|
||||
* programmed in the PSPLIM register on context switch.*/
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;
|
||||
|
||||
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = pvTaskHandle;
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Store the correct CONTROL value for the task on the stack.
|
||||
* This value is programmed in the CONTROL register on
|
||||
* context switch. */
|
||||
pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;
|
||||
pulCurrentStackPointer--;
|
||||
|
||||
if( ulIsTaskPrivileged )
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
/* Store the current stack pointer. This value is programmed in
|
||||
* the PSP register on context switch. */
|
||||
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Current SP is set to the starting of the stack. This
|
||||
* value programmed in the PSP register on context switch. */
|
||||
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Ensure to never return 0 as a valid context handle. */
|
||||
xSecureContextHandle = ulSecureContextIndex + 1UL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xSecureContextHandle;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
|
||||
{
|
||||
uint32_t ulIPSR, ulSecureContextIndex;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Only free if a valid context handle is passed. */
|
||||
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||
|
||||
/* Ensure that the secure context being deleted is associated with
|
||||
* the task. */
|
||||
if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
|
||||
{
|
||||
/* Free the stack space. */
|
||||
vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
|
||||
|
||||
/* Return the secure context back to the free secure contexts pool. */
|
||||
vReturnSecureContext( ulSecureContextIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
|
||||
{
|
||||
uint8_t * pucStackLimit;
|
||||
uint32_t ulSecureContextIndex;
|
||||
|
||||
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||
|
||||
secureportREAD_PSPLIM( pucStackLimit );
|
||||
|
||||
/* Ensure that no secure context is loaded and the task is loading it's
|
||||
* own context. */
|
||||
if( ( pucStackLimit == securecontextNO_STACK ) &&
|
||||
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
|
||||
{
|
||||
SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
|
||||
{
|
||||
uint8_t * pucStackLimit;
|
||||
uint32_t ulSecureContextIndex;
|
||||
|
||||
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||
|
||||
secureportREAD_PSPLIM( pucStackLimit );
|
||||
|
||||
/* Ensure that task's context is loaded and the task is saving it's own
|
||||
* context. */
|
||||
if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
|
||||
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
|
||||
{
|
||||
SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for privileged tasks.
|
||||
*
|
||||
* Bit[0] - 0 --> Thread mode is privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for un-privileged tasks.
|
||||
*
|
||||
* Bit[0] - 1 --> Thread mode is un-privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
|
||||
|
||||
/**
|
||||
* @brief Size of stack seal values in bytes.
|
||||
*/
|
||||
#define securecontextSTACK_SEAL_SIZE 8
|
||||
|
||||
/**
|
||||
* @brief Stack seal value as recommended by ARM.
|
||||
*/
|
||||
#define securecontextSTACK_SEAL_VALUE 0xFEF5EDA5
|
||||
|
||||
/**
|
||||
* @brief Maximum number of secure contexts.
|
||||
*/
|
||||
#ifndef secureconfigMAX_SECURE_CONTEXTS
|
||||
#define secureconfigMAX_SECURE_CONTEXTS 8UL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Pre-allocated array of secure contexts.
|
||||
*/
|
||||
SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Get a free secure context for a task from the secure context pool (xSecureContexts).
|
||||
*
|
||||
* This function ensures that only one secure context is allocated for a task.
|
||||
*
|
||||
* @param[in] pvTaskHandle The task handle for which the secure context is allocated.
|
||||
*
|
||||
* @return Index of a free secure context in the xSecureContexts array.
|
||||
*/
|
||||
static uint32_t ulGetSecureContext( void * pvTaskHandle );
|
||||
|
||||
/**
|
||||
* @brief Return the secure context to the secure context pool (xSecureContexts).
|
||||
*
|
||||
* @param[in] ulSecureContextIndex Index of the context in the xSecureContexts array.
|
||||
*/
|
||||
static void vReturnSecureContext( uint32_t ulSecureContextIndex );
|
||||
|
||||
/* These are implemented in assembly. */
|
||||
extern void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext );
|
||||
extern void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static uint32_t ulGetSecureContext( void * pvTaskHandle )
|
||||
{
|
||||
/* Start with invalid index. */
|
||||
uint32_t i, ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
|
||||
|
||||
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
|
||||
{
|
||||
if( ( xSecureContexts[ i ].pucCurrentStackPointer == NULL ) &&
|
||||
( xSecureContexts[ i ].pucStackLimit == NULL ) &&
|
||||
( xSecureContexts[ i ].pucStackStart == NULL ) &&
|
||||
( xSecureContexts[ i ].pvTaskHandle == NULL ) &&
|
||||
( ulSecureContextIndex == secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = i;
|
||||
}
|
||||
else if( xSecureContexts[ i ].pvTaskHandle == pvTaskHandle )
|
||||
{
|
||||
/* A task can only have one secure context. Do not allocate a second
|
||||
* context for the same task. */
|
||||
ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ulSecureContextIndex;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void vReturnSecureContext( uint32_t ulSecureContextIndex )
|
||||
{
|
||||
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;
|
||||
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
|
||||
{
|
||||
uint32_t ulIPSR, i;
|
||||
static uint32_t ulSecureContextsInitialized = 0;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ( ulIPSR != 0 ) && ( ulSecureContextsInitialized == 0 ) )
|
||||
{
|
||||
/* Ensure to initialize secure contexts only once. */
|
||||
ulSecureContextsInitialized = 1;
|
||||
|
||||
/* No stack for thread mode until a task's context is loaded. */
|
||||
secureportSET_PSPLIM( securecontextNO_STACK );
|
||||
secureportSET_PSP( securecontextNO_STACK );
|
||||
|
||||
/* Initialize all secure contexts. */
|
||||
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
|
||||
{
|
||||
xSecureContexts[ i ].pucCurrentStackPointer = NULL;
|
||||
xSecureContexts[ i ].pucStackLimit = NULL;
|
||||
xSecureContexts[ i ].pucStackStart = NULL;
|
||||
xSecureContexts[ i ].pvTaskHandle = NULL;
|
||||
}
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be unprivileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be privileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
uint32_t ulIsTaskPrivileged,
|
||||
void * pvTaskHandle )
|
||||
#else /* configENABLE_MPU */
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
void * pvTaskHandle )
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
uint8_t * pucStackMemory = NULL;
|
||||
uint8_t * pucStackLimit;
|
||||
uint32_t ulIPSR, ulSecureContextIndex;
|
||||
SecureContextHandle_t xSecureContextHandle = securecontextINVALID_CONTEXT_ID;
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
uint32_t * pulCurrentStackPointer = NULL;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
|
||||
* Register (PSPLIM) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
secureportREAD_PSPLIM( pucStackLimit );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode.
|
||||
* Also do nothing, if a secure context us already loaded. PSPLIM is set to
|
||||
* securecontextNO_STACK when no secure context is loaded. */
|
||||
if( ( ulIPSR != 0 ) && ( pucStackLimit == securecontextNO_STACK ) )
|
||||
{
|
||||
/* Ontain a free secure context. */
|
||||
ulSecureContextIndex = ulGetSecureContext( pvTaskHandle );
|
||||
|
||||
/* Were we able to get a free context? */
|
||||
if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
|
||||
{
|
||||
/* Allocate the stack space. */
|
||||
pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
|
||||
|
||||
if( pucStackMemory != NULL )
|
||||
{
|
||||
/* Since stack grows down, the starting point will be the last
|
||||
* location. Note that this location is next to the last
|
||||
* allocated byte for stack (excluding the space for seal values)
|
||||
* because the hardware decrements the stack pointer before
|
||||
* writing i.e. if stack pointer is 0x2, a push operation will
|
||||
* decrement the stack pointer to 0x1 and then write at 0x1. */
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;
|
||||
|
||||
/* Seal the created secure process stack. */
|
||||
*( uint32_t * )( pucStackMemory + ulSecureStackSize ) = securecontextSTACK_SEAL_VALUE;
|
||||
*( uint32_t * )( pucStackMemory + ulSecureStackSize + 4 ) = securecontextSTACK_SEAL_VALUE;
|
||||
|
||||
/* The stack cannot go beyond this location. This value is
|
||||
* programmed in the PSPLIM register on context switch.*/
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;
|
||||
|
||||
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = pvTaskHandle;
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Store the correct CONTROL value for the task on the stack.
|
||||
* This value is programmed in the CONTROL register on
|
||||
* context switch. */
|
||||
pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;
|
||||
pulCurrentStackPointer--;
|
||||
|
||||
if( ulIsTaskPrivileged )
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
/* Store the current stack pointer. This value is programmed in
|
||||
* the PSP register on context switch. */
|
||||
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Current SP is set to the starting of the stack. This
|
||||
* value programmed in the PSP register on context switch. */
|
||||
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Ensure to never return 0 as a valid context handle. */
|
||||
xSecureContextHandle = ulSecureContextIndex + 1UL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xSecureContextHandle;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
|
||||
{
|
||||
uint32_t ulIPSR, ulSecureContextIndex;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Only free if a valid context handle is passed. */
|
||||
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||
|
||||
/* Ensure that the secure context being deleted is associated with
|
||||
* the task. */
|
||||
if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
|
||||
{
|
||||
/* Free the stack space. */
|
||||
vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
|
||||
|
||||
/* Return the secure context back to the free secure contexts pool. */
|
||||
vReturnSecureContext( ulSecureContextIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
|
||||
{
|
||||
uint8_t * pucStackLimit;
|
||||
uint32_t ulSecureContextIndex;
|
||||
|
||||
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||
|
||||
secureportREAD_PSPLIM( pucStackLimit );
|
||||
|
||||
/* Ensure that no secure context is loaded and the task is loading it's
|
||||
* own context. */
|
||||
if( ( pucStackLimit == securecontextNO_STACK ) &&
|
||||
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
|
||||
{
|
||||
SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
|
||||
{
|
||||
uint8_t * pucStackLimit;
|
||||
uint32_t ulSecureContextIndex;
|
||||
|
||||
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||
|
||||
secureportREAD_PSPLIM( pucStackLimit );
|
||||
|
||||
/* Ensure that task's context is loaded and the task is saving it's own
|
||||
* context. */
|
||||
if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
|
||||
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
|
||||
{
|
||||
SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,135 +1,135 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_CONTEXT_H__
|
||||
#define __SECURE_CONTEXT_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
/**
|
||||
* @brief PSP value when no secure context is loaded.
|
||||
*/
|
||||
#define securecontextNO_STACK 0x0
|
||||
|
||||
/**
|
||||
* @brief Invalid context ID.
|
||||
*/
|
||||
#define securecontextINVALID_CONTEXT_ID 0UL
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Structure to represent a secure context.
|
||||
*
|
||||
* @note Since stack grows down, pucStackStart is the highest address while
|
||||
* pucStackLimit is the first address of the allocated memory.
|
||||
*/
|
||||
typedef struct SecureContext
|
||||
{
|
||||
uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
|
||||
uint8_t * pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
|
||||
uint8_t * pucStackStart; /**< First location of the stack memory. */
|
||||
void * pvTaskHandle; /**< Task handle of the task this context is associated with. */
|
||||
} SecureContext_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Opaque handle for a secure context.
|
||||
*/
|
||||
typedef uint32_t SecureContextHandle_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the secure context management system.
|
||||
*
|
||||
* PSP is set to NULL and therefore a task must allocate and load a context
|
||||
* before calling any secure side function in the thread mode.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureContext_Init( void );
|
||||
|
||||
/**
|
||||
* @brief Allocates a context on the secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] ulSecureStackSize Size of the stack to allocate on secure side.
|
||||
* @param[in] ulIsTaskPrivileged 1 if the calling task is privileged, 0 otherwise.
|
||||
*
|
||||
* @return Opaque context handle if context is successfully allocated, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
uint32_t ulIsTaskPrivileged,
|
||||
void * pvTaskHandle );
|
||||
#else /* configENABLE_MPU */
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
void * pvTaskHandle );
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/**
|
||||
* @brief Frees the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the
|
||||
* context to be freed.
|
||||
*/
|
||||
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
|
||||
|
||||
/**
|
||||
* @brief Loads the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be loaded.
|
||||
*/
|
||||
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
|
||||
|
||||
/**
|
||||
* @brief Saves the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be saved.
|
||||
*/
|
||||
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
|
||||
|
||||
#endif /* __SECURE_CONTEXT_H__ */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_CONTEXT_H__
|
||||
#define __SECURE_CONTEXT_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
/**
|
||||
* @brief PSP value when no secure context is loaded.
|
||||
*/
|
||||
#define securecontextNO_STACK 0x0
|
||||
|
||||
/**
|
||||
* @brief Invalid context ID.
|
||||
*/
|
||||
#define securecontextINVALID_CONTEXT_ID 0UL
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Structure to represent a secure context.
|
||||
*
|
||||
* @note Since stack grows down, pucStackStart is the highest address while
|
||||
* pucStackLimit is the first address of the allocated memory.
|
||||
*/
|
||||
typedef struct SecureContext
|
||||
{
|
||||
uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
|
||||
uint8_t * pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
|
||||
uint8_t * pucStackStart; /**< First location of the stack memory. */
|
||||
void * pvTaskHandle; /**< Task handle of the task this context is associated with. */
|
||||
} SecureContext_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Opaque handle for a secure context.
|
||||
*/
|
||||
typedef uint32_t SecureContextHandle_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the secure context management system.
|
||||
*
|
||||
* PSP is set to NULL and therefore a task must allocate and load a context
|
||||
* before calling any secure side function in the thread mode.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureContext_Init( void );
|
||||
|
||||
/**
|
||||
* @brief Allocates a context on the secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] ulSecureStackSize Size of the stack to allocate on secure side.
|
||||
* @param[in] ulIsTaskPrivileged 1 if the calling task is privileged, 0 otherwise.
|
||||
*
|
||||
* @return Opaque context handle if context is successfully allocated, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
uint32_t ulIsTaskPrivileged,
|
||||
void * pvTaskHandle );
|
||||
#else /* configENABLE_MPU */
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
void * pvTaskHandle );
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/**
|
||||
* @brief Frees the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the
|
||||
* context to be freed.
|
||||
*/
|
||||
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
|
||||
|
||||
/**
|
||||
* @brief Loads the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be loaded.
|
||||
*/
|
||||
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
|
||||
|
||||
/**
|
||||
* @brief Saves the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be saved.
|
||||
*/
|
||||
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
|
||||
|
||||
#endif /* __SECURE_CONTEXT_H__ */
|
||||
|
|
|
|||
|
|
@ -1,454 +1,454 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Secure context heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Total heap size.
|
||||
*/
|
||||
#ifndef secureconfigTOTAL_HEAP_SIZE
|
||||
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
|
||||
#endif
|
||||
|
||||
/* No test marker by default. */
|
||||
#ifndef mtCOVERAGE_TEST_MARKER
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceMALLOC
|
||||
#define traceMALLOC( pvReturn, xWantedSize )
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceFREE
|
||||
#define traceFREE( pv, xBlockSize )
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#else /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
/**
|
||||
* @brief The linked list structure.
|
||||
*
|
||||
* This is used to link free blocks in order of their memory address.
|
||||
*/
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Called automatically to setup the required heap structures the first
|
||||
* time pvPortMalloc() is called.
|
||||
*/
|
||||
static void prvHeapInit( void );
|
||||
|
||||
/**
|
||||
* @brief Inserts a block of memory that is being freed into the correct
|
||||
* position in the list of free memory blocks.
|
||||
*
|
||||
* The block being freed will be merged with the block in front it and/or the
|
||||
* block behind it if the memory blocks are adjacent to each other.
|
||||
*
|
||||
* @param[in] pxBlockToInsert The block being freed.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief The size of the structure placed at the beginning of each allocated
|
||||
* memory block must by correctly byte aligned.
|
||||
*/
|
||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( secureportBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
|
||||
/**
|
||||
* @brief Create a couple of list links to mark the start and end of the list.
|
||||
*/
|
||||
static BlockLink_t xStart;
|
||||
static BlockLink_t * pxEnd = NULL;
|
||||
|
||||
/**
|
||||
* @brief Keeps track of the number of free bytes remaining, but says nothing
|
||||
* about fragmentation.
|
||||
*/
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
|
||||
/**
|
||||
* @brief Gets set to the top bit of an size_t type.
|
||||
*
|
||||
* When this bit in the xBlockSize member of an BlockLink_t structure is set
|
||||
* then the block belongs to the application. When the bit is free the block is
|
||||
* still part of the free heap space.
|
||||
*/
|
||||
static size_t xBlockAllocatedBit = 0;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHeapInit( void )
|
||||
{
|
||||
BlockLink_t * pxFirstFreeBlock;
|
||||
uint8_t * pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = ( size_t ) ucHeap;
|
||||
|
||||
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
|
||||
}
|
||||
|
||||
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( void * ) uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
|
||||
{
|
||||
BlockLink_t * pxIterator;
|
||||
uint8_t * puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void * pvPortMalloc( size_t xWantedSize )
|
||||
{
|
||||
BlockLink_t * pxBlock;
|
||||
BlockLink_t * pxPreviousBlock;
|
||||
BlockLink_t * pxNewBlockLink;
|
||||
void * pvReturn = NULL;
|
||||
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Check the requested block size is not so large that the top bit is set.
|
||||
* The top bit of the block size member of the BlockLink_t structure is used
|
||||
* to determine who owns the block - the application or the kernel, so it
|
||||
* must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number of
|
||||
* bytes. */
|
||||
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
|
||||
secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size was
|
||||
* not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the single
|
||||
* block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned by
|
||||
* the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
|
||||
#if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
|
||||
|
||||
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
uint8_t * puc = ( uint8_t * ) pv;
|
||||
BlockLink_t * pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
}
|
||||
secureportENABLE_NON_SECURE_INTERRUPTS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Secure context heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Total heap size.
|
||||
*/
|
||||
#ifndef secureconfigTOTAL_HEAP_SIZE
|
||||
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
|
||||
#endif
|
||||
|
||||
/* No test marker by default. */
|
||||
#ifndef mtCOVERAGE_TEST_MARKER
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceMALLOC
|
||||
#define traceMALLOC( pvReturn, xWantedSize )
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceFREE
|
||||
#define traceFREE( pv, xBlockSize )
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#else /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
/**
|
||||
* @brief The linked list structure.
|
||||
*
|
||||
* This is used to link free blocks in order of their memory address.
|
||||
*/
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Called automatically to setup the required heap structures the first
|
||||
* time pvPortMalloc() is called.
|
||||
*/
|
||||
static void prvHeapInit( void );
|
||||
|
||||
/**
|
||||
* @brief Inserts a block of memory that is being freed into the correct
|
||||
* position in the list of free memory blocks.
|
||||
*
|
||||
* The block being freed will be merged with the block in front it and/or the
|
||||
* block behind it if the memory blocks are adjacent to each other.
|
||||
*
|
||||
* @param[in] pxBlockToInsert The block being freed.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief The size of the structure placed at the beginning of each allocated
|
||||
* memory block must by correctly byte aligned.
|
||||
*/
|
||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( secureportBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
|
||||
/**
|
||||
* @brief Create a couple of list links to mark the start and end of the list.
|
||||
*/
|
||||
static BlockLink_t xStart;
|
||||
static BlockLink_t * pxEnd = NULL;
|
||||
|
||||
/**
|
||||
* @brief Keeps track of the number of free bytes remaining, but says nothing
|
||||
* about fragmentation.
|
||||
*/
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
|
||||
/**
|
||||
* @brief Gets set to the top bit of an size_t type.
|
||||
*
|
||||
* When this bit in the xBlockSize member of an BlockLink_t structure is set
|
||||
* then the block belongs to the application. When the bit is free the block is
|
||||
* still part of the free heap space.
|
||||
*/
|
||||
static size_t xBlockAllocatedBit = 0;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHeapInit( void )
|
||||
{
|
||||
BlockLink_t * pxFirstFreeBlock;
|
||||
uint8_t * pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = ( size_t ) ucHeap;
|
||||
|
||||
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
|
||||
}
|
||||
|
||||
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( void * ) uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
|
||||
{
|
||||
BlockLink_t * pxIterator;
|
||||
uint8_t * puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void * pvPortMalloc( size_t xWantedSize )
|
||||
{
|
||||
BlockLink_t * pxBlock;
|
||||
BlockLink_t * pxPreviousBlock;
|
||||
BlockLink_t * pxNewBlockLink;
|
||||
void * pvReturn = NULL;
|
||||
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Check the requested block size is not so large that the top bit is set.
|
||||
* The top bit of the block size member of the BlockLink_t structure is used
|
||||
* to determine who owns the block - the application or the kernel, so it
|
||||
* must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number of
|
||||
* bytes. */
|
||||
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
|
||||
secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size was
|
||||
* not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the single
|
||||
* block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned by
|
||||
* the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
|
||||
#if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
|
||||
|
||||
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
uint8_t * puc = ( uint8_t * ) pv;
|
||||
BlockLink_t * pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
}
|
||||
secureportENABLE_NON_SECURE_INTERRUPTS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,66 +1,66 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_HEAP_H__
|
||||
#define __SECURE_HEAP_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from heap.
|
||||
*
|
||||
* @param[in] xWantedSize The size of the memory to be allocated.
|
||||
*
|
||||
* @return Pointer to the memory region if the allocation is successful, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
void * pvPortMalloc( size_t xWantedSize );
|
||||
|
||||
/**
|
||||
* @brief Frees the previously allocated memory.
|
||||
*
|
||||
* @param[in] pv Pointer to the memory to be freed.
|
||||
*/
|
||||
void vPortFree( void * pv );
|
||||
|
||||
/**
|
||||
* @brief Get the free heap size.
|
||||
*
|
||||
* @return Free heap size.
|
||||
*/
|
||||
size_t xPortGetFreeHeapSize( void );
|
||||
|
||||
/**
|
||||
* @brief Get the minimum ever free heap size.
|
||||
*
|
||||
* @return Minimum ever free heap size.
|
||||
*/
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void );
|
||||
|
||||
#endif /* __SECURE_HEAP_H__ */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_HEAP_H__
|
||||
#define __SECURE_HEAP_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from heap.
|
||||
*
|
||||
* @param[in] xWantedSize The size of the memory to be allocated.
|
||||
*
|
||||
* @return Pointer to the memory region if the allocation is successful, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
void * pvPortMalloc( size_t xWantedSize );
|
||||
|
||||
/**
|
||||
* @brief Frees the previously allocated memory.
|
||||
*
|
||||
* @param[in] pv Pointer to the memory to be freed.
|
||||
*/
|
||||
void vPortFree( void * pv );
|
||||
|
||||
/**
|
||||
* @brief Get the free heap size.
|
||||
*
|
||||
* @return Free heap size.
|
||||
*/
|
||||
size_t xPortGetFreeHeapSize( void );
|
||||
|
||||
/**
|
||||
* @brief Get the minimum ever free heap size.
|
||||
*
|
||||
* @return Minimum ever free heap size.
|
||||
*/
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void );
|
||||
|
||||
#endif /* __SECURE_HEAP_H__ */
|
||||
|
|
|
|||
|
|
@ -1,106 +1,106 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Secure init includes. */
|
||||
#include "secure_init.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
|
||||
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
|
||||
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
|
||||
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
|
||||
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define secureinitFPCCR_LSPENS_POS ( 29UL )
|
||||
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
|
||||
#define secureinitFPCCR_TS_POS ( 26UL )
|
||||
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
|
||||
|
||||
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
|
||||
#define secureinitNSACR_CP10_POS ( 10UL )
|
||||
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
|
||||
#define secureinitNSACR_CP11_POS ( 11UL )
|
||||
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
|
||||
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
|
||||
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
|
||||
* permitted. CP11 should be programmed to the same value as CP10. */
|
||||
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
|
||||
|
||||
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
|
||||
* that we can enable/disable lazy stacking in port.c file. */
|
||||
*( secureinitFPCCR ) &= ~( secureinitFPCCR_LSPENS_MASK );
|
||||
|
||||
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
|
||||
* registers (S16-S31) are also pushed to stack on exception entry and
|
||||
* restored on exception return. */
|
||||
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Secure init includes. */
|
||||
#include "secure_init.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
|
||||
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
|
||||
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
|
||||
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
|
||||
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define secureinitFPCCR_LSPENS_POS ( 29UL )
|
||||
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
|
||||
#define secureinitFPCCR_TS_POS ( 26UL )
|
||||
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
|
||||
|
||||
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
|
||||
#define secureinitNSACR_CP10_POS ( 10UL )
|
||||
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
|
||||
#define secureinitNSACR_CP11_POS ( 11UL )
|
||||
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
|
||||
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
|
||||
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
|
||||
* permitted. CP11 should be programmed to the same value as CP10. */
|
||||
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
|
||||
|
||||
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
|
||||
* that we can enable/disable lazy stacking in port.c file. */
|
||||
*( secureinitFPCCR ) &= ~( secureinitFPCCR_LSPENS_MASK );
|
||||
|
||||
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
|
||||
* registers (S16-S31) are also pushed to stack on exception entry and
|
||||
* restored on exception return. */
|
||||
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,54 +1,54 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_INIT_H__
|
||||
#define __SECURE_INIT_H__
|
||||
|
||||
/**
|
||||
* @brief De-prioritizes the non-secure exceptions.
|
||||
*
|
||||
* This is needed to ensure that the non-secure PendSV runs at the lowest
|
||||
* priority. Context switch is done in the non-secure PendSV handler.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_DePrioritizeNSExceptions( void );
|
||||
|
||||
/**
|
||||
* @brief Sets up the Floating Point Unit (FPU) for Non-Secure access.
|
||||
*
|
||||
* Also sets FPCCR.TS=1 to ensure that the content of the Floating Point
|
||||
* Registers are not leaked to the non-secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_EnableNSFPUAccess( void );
|
||||
|
||||
#endif /* __SECURE_INIT_H__ */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_INIT_H__
|
||||
#define __SECURE_INIT_H__
|
||||
|
||||
/**
|
||||
* @brief De-prioritizes the non-secure exceptions.
|
||||
*
|
||||
* This is needed to ensure that the non-secure PendSV runs at the lowest
|
||||
* priority. Context switch is done in the non-secure PendSV handler.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_DePrioritizeNSExceptions( void );
|
||||
|
||||
/**
|
||||
* @brief Sets up the Floating Point Unit (FPU) for Non-Secure access.
|
||||
*
|
||||
* Also sets FPCCR.TS=1 to ensure that the content of the Floating Point
|
||||
* Registers are not leaked to the non-secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_EnableNSFPUAccess( void );
|
||||
|
||||
#endif /* __SECURE_INIT_H__ */
|
||||
|
|
|
|||
|
|
@ -1,140 +1,140 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_PORT_MACROS_H__
|
||||
#define __SECURE_PORT_MACROS_H__
|
||||
|
||||
/**
|
||||
* @brief Byte alignment requirements.
|
||||
*/
|
||||
#define secureportBYTE_ALIGNMENT 8
|
||||
#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
|
||||
/**
|
||||
* @brief Macro to declare a function as non-secure callable.
|
||||
*/
|
||||
#if defined( __IAR_SYSTEMS_ICC__ )
|
||||
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
|
||||
#else
|
||||
#define secureportNON_SECURE_CALLABLE __attribute__( ( cmse_nonsecure_entry ) ) __attribute__( ( used ) )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Set the non-secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_NON_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the PSP value in the given variable.
|
||||
*/
|
||||
#define secureportREAD_PSP( pucOutCurrentStackPointer ) \
|
||||
__asm volatile ( "mrs %0, psp" : "=r" ( pucOutCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSP to the given value.
|
||||
*/
|
||||
#define secureportSET_PSP( pucCurrentStackPointer ) \
|
||||
__asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Read the PSPLIM value in the given variable.
|
||||
*/
|
||||
#define secureportREAD_PSPLIM( pucOutStackLimit ) \
|
||||
__asm volatile ( "mrs %0, psplim" : "=r" ( pucOutStackLimit ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSPLIM to the given value.
|
||||
*/
|
||||
#define secureportSET_PSPLIM( pucStackLimit ) \
|
||||
__asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
|
||||
|
||||
/**
|
||||
* @brief Set the NonSecure MSP to the given value.
|
||||
*/
|
||||
#define secureportSET_MSP_NS( pucMainStackPointer ) \
|
||||
__asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the CONTROL register to the given value.
|
||||
*/
|
||||
#define secureportSET_CONTROL( ulControl ) \
|
||||
__asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the Interrupt Program Status Register (IPSR) value in the given
|
||||
* variable.
|
||||
*/
|
||||
#define secureportREAD_IPSR( ulIPSR ) \
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) )
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to enable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to disable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1
|
||||
|
||||
/**
|
||||
* @brief Disable secure interrupts.
|
||||
*/
|
||||
#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Disable non-secure interrupts.
|
||||
*
|
||||
* This effectively disables context switches.
|
||||
*/
|
||||
#define secureportDISABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Enable non-secure interrupts.
|
||||
*/
|
||||
#define secureportENABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Assert definition.
|
||||
*/
|
||||
#define secureportASSERT( x ) \
|
||||
if( ( x ) == 0 ) \
|
||||
{ \
|
||||
secureportDISABLE_SECURE_INTERRUPTS(); \
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
|
||||
for( ; ; ) {; } \
|
||||
}
|
||||
|
||||
#endif /* __SECURE_PORT_MACROS_H__ */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_PORT_MACROS_H__
|
||||
#define __SECURE_PORT_MACROS_H__
|
||||
|
||||
/**
|
||||
* @brief Byte alignment requirements.
|
||||
*/
|
||||
#define secureportBYTE_ALIGNMENT 8
|
||||
#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
|
||||
/**
|
||||
* @brief Macro to declare a function as non-secure callable.
|
||||
*/
|
||||
#if defined( __IAR_SYSTEMS_ICC__ )
|
||||
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
|
||||
#else
|
||||
#define secureportNON_SECURE_CALLABLE __attribute__( ( cmse_nonsecure_entry ) ) __attribute__( ( used ) )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Set the non-secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_NON_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the PSP value in the given variable.
|
||||
*/
|
||||
#define secureportREAD_PSP( pucOutCurrentStackPointer ) \
|
||||
__asm volatile ( "mrs %0, psp" : "=r" ( pucOutCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSP to the given value.
|
||||
*/
|
||||
#define secureportSET_PSP( pucCurrentStackPointer ) \
|
||||
__asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Read the PSPLIM value in the given variable.
|
||||
*/
|
||||
#define secureportREAD_PSPLIM( pucOutStackLimit ) \
|
||||
__asm volatile ( "mrs %0, psplim" : "=r" ( pucOutStackLimit ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSPLIM to the given value.
|
||||
*/
|
||||
#define secureportSET_PSPLIM( pucStackLimit ) \
|
||||
__asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
|
||||
|
||||
/**
|
||||
* @brief Set the NonSecure MSP to the given value.
|
||||
*/
|
||||
#define secureportSET_MSP_NS( pucMainStackPointer ) \
|
||||
__asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the CONTROL register to the given value.
|
||||
*/
|
||||
#define secureportSET_CONTROL( ulControl ) \
|
||||
__asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the Interrupt Program Status Register (IPSR) value in the given
|
||||
* variable.
|
||||
*/
|
||||
#define secureportREAD_IPSR( ulIPSR ) \
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) )
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to enable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to disable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1
|
||||
|
||||
/**
|
||||
* @brief Disable secure interrupts.
|
||||
*/
|
||||
#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Disable non-secure interrupts.
|
||||
*
|
||||
* This effectively disables context switches.
|
||||
*/
|
||||
#define secureportDISABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Enable non-secure interrupts.
|
||||
*/
|
||||
#define secureportENABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Assert definition.
|
||||
*/
|
||||
#define secureportASSERT( x ) \
|
||||
if( ( x ) == 0 ) \
|
||||
{ \
|
||||
secureportDISABLE_SECURE_INTERRUPTS(); \
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
|
||||
for( ; ; ) {; } \
|
||||
}
|
||||
|
||||
#endif /* __SECURE_PORT_MACROS_H__ */
|
||||
|
|
|
|||
|
|
@ -1,245 +1,244 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V1.00:
|
||||
|
||||
+ Call to taskYIELD() from within tick ISR has been replaced by the more
|
||||
efficient portSWITCH_CONTEXT().
|
||||
+ ISR function definitions renamed to include the prv prefix.
|
||||
|
||||
Changes from V2.6.1
|
||||
|
||||
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
|
||||
macro to be consistent with the later ports.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the Flashlite 186
|
||||
* port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#include <dos.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "portasm.h"
|
||||
|
||||
/*lint -e950 Non ANSI reserved words okay in this file only. */
|
||||
|
||||
#define portTIMER_EOI_TYPE ( 8 )
|
||||
#define portRESET_PIC() portOUTPUT_WORD( ( uint16_t ) 0xff22, portTIMER_EOI_TYPE )
|
||||
#define portTIMER_INT_NUMBER 0x12
|
||||
|
||||
#define portTIMER_1_CONTROL_REGISTER ( ( uint16_t ) 0xff5e )
|
||||
#define portTIMER_0_CONTROL_REGISTER ( ( uint16_t ) 0xff56 )
|
||||
#define portTIMER_INTERRUPT_ENABLE ( ( uint16_t ) 0x2000 )
|
||||
|
||||
/* Setup the hardware to generate the required tick frequency. */
|
||||
static void prvSetTickFrequency( uint32_t ulTickRateHz );
|
||||
|
||||
/* Set the hardware back to the state as per before the scheduler started. */
|
||||
static void prvExitFunction( void );
|
||||
|
||||
/* The ISR used depends on whether the preemptive or cooperative scheduler
|
||||
is being used. */
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
/* Tick service routine used by the scheduler when preemptive scheduling is
|
||||
being used. */
|
||||
static void __interrupt __far prvPreemptiveTick( void );
|
||||
#else
|
||||
/* Tick service routine used by the scheduler when cooperative scheduling is
|
||||
being used. */
|
||||
static void __interrupt __far prvNonPreemptiveTick( void );
|
||||
#endif
|
||||
|
||||
/* Trap routine used by taskYIELD() to manually cause a context switch. */
|
||||
static void __interrupt __far prvYieldProcessor( void );
|
||||
|
||||
/*lint -e956 File scopes necessary here. */
|
||||
|
||||
/* Set true when the vectors are set so the scheduler will service the tick. */
|
||||
static BaseType_t xSchedulerRunning = pdFALSE;
|
||||
|
||||
/* Points to the original routine installed on the vector we use for manual
|
||||
context switches. This is then used to restore the original routine during
|
||||
prvExitFunction(). */
|
||||
static void ( __interrupt __far *pxOldSwitchISR )();
|
||||
|
||||
/* Used to restore the original DOS context when the scheduler is ended. */
|
||||
static jmp_buf xJumpBuf;
|
||||
|
||||
/*lint +e956 */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* This is called with interrupts already disabled. */
|
||||
|
||||
/* Remember what was on the interrupts we are going to use
|
||||
so we can put them back later if required. */
|
||||
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
|
||||
|
||||
/* Put our manual switch (yield) function on a known
|
||||
vector. */
|
||||
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
|
||||
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
{
|
||||
/* Put our tick switch function on the timer interrupt. */
|
||||
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* We want the timer interrupt to just increment the tick count. */
|
||||
_dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
|
||||
}
|
||||
#endif
|
||||
|
||||
prvSetTickFrequency( configTICK_RATE_HZ );
|
||||
|
||||
/* Clean up function if we want to return to DOS. */
|
||||
if( setjmp( xJumpBuf ) != 0 )
|
||||
{
|
||||
prvExitFunction();
|
||||
xSchedulerRunning = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xSchedulerRunning = pdTRUE;
|
||||
|
||||
/* Kick off the scheduler by setting up the context of the first task. */
|
||||
portFIRST_CONTEXT();
|
||||
}
|
||||
|
||||
return xSchedulerRunning;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The ISR used depends on whether the preemptive or cooperative scheduler
|
||||
is being used. */
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
static void __interrupt __far prvPreemptiveTick( void )
|
||||
{
|
||||
/* Get the scheduler to update the task states following the tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Switch in the context of the next task to be run. */
|
||||
portSWITCH_CONTEXT();
|
||||
}
|
||||
|
||||
/* Reset the PIC ready for the next time. */
|
||||
portRESET_PIC();
|
||||
}
|
||||
#else
|
||||
static void __interrupt __far prvNonPreemptiveTick( void )
|
||||
{
|
||||
/* Same as preemptive tick, but the cooperative scheduler is being used
|
||||
so we don't have to switch in the context of the next task. */
|
||||
xTaskIncrementTick();
|
||||
portRESET_PIC();
|
||||
}
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void __interrupt __far prvYieldProcessor( void )
|
||||
{
|
||||
/* Switch in the context of the next task to be run. */
|
||||
portSWITCH_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Jump back to the processor state prior to starting the
|
||||
scheduler. This means we are not going to be using a
|
||||
task stack frame so the task can be deleted. */
|
||||
longjmp( xJumpBuf, 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvExitFunction( void )
|
||||
{
|
||||
const uint16_t usTimerDisable = 0x0000;
|
||||
uint16_t usTimer0Control;
|
||||
|
||||
/* Interrupts should be disabled here anyway - but no
|
||||
harm in making sure. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
if( xSchedulerRunning == pdTRUE )
|
||||
{
|
||||
/* Put back the switch interrupt routines that was in place
|
||||
before the scheduler started. */
|
||||
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
|
||||
}
|
||||
|
||||
/* Disable the timer used for the tick to ensure the scheduler is
|
||||
not called before restoring interrupts. There was previously nothing
|
||||
on this timer so there is no old ISR to restore. */
|
||||
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable );
|
||||
|
||||
/* Restart the DOS tick. */
|
||||
usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
|
||||
usTimer0Control |= portTIMER_INTERRUPT_ENABLE;
|
||||
portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
|
||||
|
||||
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetTickFrequency( uint32_t ulTickRateHz )
|
||||
{
|
||||
const uint16_t usMaxCountRegister = 0xff5a;
|
||||
const uint16_t usTimerPriorityRegister = 0xff32;
|
||||
const uint16_t usTimerEnable = 0xC000;
|
||||
const uint16_t usRetrigger = 0x0001;
|
||||
const uint16_t usTimerHighPriority = 0x0000;
|
||||
uint16_t usTimer0Control;
|
||||
|
||||
/* ( CPU frequency / 4 ) / clock 2 max count [inpw( 0xff62 ) = 7] */
|
||||
|
||||
const uint32_t ulClockFrequency = ( uint32_t ) 0x7f31a0UL;
|
||||
|
||||
uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz;
|
||||
|
||||
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger );
|
||||
portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount );
|
||||
portOUTPUT_WORD( usTimerPriorityRegister, usTimerHighPriority );
|
||||
|
||||
/* Stop the DOS tick - don't do this if you want to maintain a TOD clock. */
|
||||
usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
|
||||
usTimer0Control &= ~portTIMER_INTERRUPT_ENABLE;
|
||||
portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
|
||||
}
|
||||
|
||||
|
||||
/*lint +e950 */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V1.00:
|
||||
|
||||
+ Call to taskYIELD() from within tick ISR has been replaced by the more
|
||||
efficient portSWITCH_CONTEXT().
|
||||
+ ISR function definitions renamed to include the prv prefix.
|
||||
|
||||
Changes from V2.6.1
|
||||
|
||||
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
|
||||
macro to be consistent with the later ports.
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the Flashlite 186
|
||||
* port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
#include <dos.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "portasm.h"
|
||||
|
||||
/*lint -e950 Non ANSI reserved words okay in this file only. */
|
||||
|
||||
#define portTIMER_EOI_TYPE ( 8 )
|
||||
#define portRESET_PIC() portOUTPUT_WORD( ( uint16_t ) 0xff22, portTIMER_EOI_TYPE )
|
||||
#define portTIMER_INT_NUMBER 0x12
|
||||
|
||||
#define portTIMER_1_CONTROL_REGISTER ( ( uint16_t ) 0xff5e )
|
||||
#define portTIMER_0_CONTROL_REGISTER ( ( uint16_t ) 0xff56 )
|
||||
#define portTIMER_INTERRUPT_ENABLE ( ( uint16_t ) 0x2000 )
|
||||
|
||||
/* Setup the hardware to generate the required tick frequency. */
|
||||
static void prvSetTickFrequency( uint32_t ulTickRateHz );
|
||||
|
||||
/* Set the hardware back to the state as per before the scheduler started. */
|
||||
static void prvExitFunction( void );
|
||||
|
||||
/* The ISR used depends on whether the preemptive or cooperative scheduler
|
||||
is being used. */
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
/* Tick service routine used by the scheduler when preemptive scheduling is
|
||||
being used. */
|
||||
static void __interrupt __far prvPreemptiveTick( void );
|
||||
#else
|
||||
/* Tick service routine used by the scheduler when cooperative scheduling is
|
||||
being used. */
|
||||
static void __interrupt __far prvNonPreemptiveTick( void );
|
||||
#endif
|
||||
|
||||
/* Trap routine used by taskYIELD() to manually cause a context switch. */
|
||||
static void __interrupt __far prvYieldProcessor( void );
|
||||
|
||||
/*lint -e956 File scopes necessary here. */
|
||||
|
||||
/* Set true when the vectors are set so the scheduler will service the tick. */
|
||||
static BaseType_t xSchedulerRunning = pdFALSE;
|
||||
|
||||
/* Points to the original routine installed on the vector we use for manual
|
||||
context switches. This is then used to restore the original routine during
|
||||
prvExitFunction(). */
|
||||
static void ( __interrupt __far *pxOldSwitchISR )();
|
||||
|
||||
/* Used to restore the original DOS context when the scheduler is ended. */
|
||||
static jmp_buf xJumpBuf;
|
||||
|
||||
/*lint +e956 */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* This is called with interrupts already disabled. */
|
||||
|
||||
/* Remember what was on the interrupts we are going to use
|
||||
so we can put them back later if required. */
|
||||
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
|
||||
|
||||
/* Put our manual switch (yield) function on a known
|
||||
vector. */
|
||||
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
|
||||
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
{
|
||||
/* Put our tick switch function on the timer interrupt. */
|
||||
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* We want the timer interrupt to just increment the tick count. */
|
||||
_dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
|
||||
}
|
||||
#endif
|
||||
|
||||
prvSetTickFrequency( configTICK_RATE_HZ );
|
||||
|
||||
/* Clean up function if we want to return to DOS. */
|
||||
if( setjmp( xJumpBuf ) != 0 )
|
||||
{
|
||||
prvExitFunction();
|
||||
xSchedulerRunning = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xSchedulerRunning = pdTRUE;
|
||||
|
||||
/* Kick off the scheduler by setting up the context of the first task. */
|
||||
portFIRST_CONTEXT();
|
||||
}
|
||||
|
||||
return xSchedulerRunning;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The ISR used depends on whether the preemptive or cooperative scheduler
|
||||
is being used. */
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
static void __interrupt __far prvPreemptiveTick( void )
|
||||
{
|
||||
/* Get the scheduler to update the task states following the tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Switch in the context of the next task to be run. */
|
||||
portSWITCH_CONTEXT();
|
||||
}
|
||||
|
||||
/* Reset the PIC ready for the next time. */
|
||||
portRESET_PIC();
|
||||
}
|
||||
#else
|
||||
static void __interrupt __far prvNonPreemptiveTick( void )
|
||||
{
|
||||
/* Same as preemptive tick, but the cooperative scheduler is being used
|
||||
so we don't have to switch in the context of the next task. */
|
||||
xTaskIncrementTick();
|
||||
portRESET_PIC();
|
||||
}
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void __interrupt __far prvYieldProcessor( void )
|
||||
{
|
||||
/* Switch in the context of the next task to be run. */
|
||||
portSWITCH_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Jump back to the processor state prior to starting the
|
||||
scheduler. This means we are not going to be using a
|
||||
task stack frame so the task can be deleted. */
|
||||
longjmp( xJumpBuf, 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvExitFunction( void )
|
||||
{
|
||||
const uint16_t usTimerDisable = 0x0000;
|
||||
uint16_t usTimer0Control;
|
||||
|
||||
/* Interrupts should be disabled here anyway - but no
|
||||
harm in making sure. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
if( xSchedulerRunning == pdTRUE )
|
||||
{
|
||||
/* Put back the switch interrupt routines that was in place
|
||||
before the scheduler started. */
|
||||
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
|
||||
}
|
||||
|
||||
/* Disable the timer used for the tick to ensure the scheduler is
|
||||
not called before restoring interrupts. There was previously nothing
|
||||
on this timer so there is no old ISR to restore. */
|
||||
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable );
|
||||
|
||||
/* Restart the DOS tick. */
|
||||
usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
|
||||
usTimer0Control |= portTIMER_INTERRUPT_ENABLE;
|
||||
portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
|
||||
|
||||
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetTickFrequency( uint32_t ulTickRateHz )
|
||||
{
|
||||
const uint16_t usMaxCountRegister = 0xff5a;
|
||||
const uint16_t usTimerPriorityRegister = 0xff32;
|
||||
const uint16_t usTimerEnable = 0xC000;
|
||||
const uint16_t usRetrigger = 0x0001;
|
||||
const uint16_t usTimerHighPriority = 0x0000;
|
||||
uint16_t usTimer0Control;
|
||||
|
||||
/* ( CPU frequency / 4 ) / clock 2 max count [inpw( 0xff62 ) = 7] */
|
||||
|
||||
const uint32_t ulClockFrequency = ( uint32_t ) 0x7f31a0UL;
|
||||
|
||||
uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz;
|
||||
|
||||
portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger );
|
||||
portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount );
|
||||
portOUTPUT_WORD( usTimerPriorityRegister, usTimerHighPriority );
|
||||
|
||||
/* Stop the DOS tick - don't do this if you want to maintain a TOD clock. */
|
||||
usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER );
|
||||
usTimer0Control &= ~portTIMER_INTERRUPT_ENABLE;
|
||||
portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control );
|
||||
}
|
||||
|
||||
|
||||
/*lint +e950 */
|
||||
|
|
|
|||
|
|
@ -1,98 +1,97 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE long
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portSTACK_TYPE uint16_t
|
||||
#define portBASE_TYPE portSHORT
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef short BaseType_t;
|
||||
typedef unsigned short UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section handling. */
|
||||
#define portENTER_CRITICAL() __asm{ pushf } \
|
||||
__asm{ cli } \
|
||||
|
||||
#define portEXIT_CRITICAL() __asm{ popf }
|
||||
|
||||
#define portDISABLE_INTERRUPTS() __asm{ cli }
|
||||
|
||||
#define portENABLE_INTERRUPTS() __asm{ sti }
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portNOP() __asm{ nop }
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portSWITCH_INT_NUMBER 0x80
|
||||
#define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 2
|
||||
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Compiler specifics. */
|
||||
#define portINPUT_BYTE( xAddr ) inp( xAddr )
|
||||
#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue )
|
||||
#define portINPUT_WORD( xAddr ) inpw( xAddr )
|
||||
#define portOUTPUT_WORD( xAddr, usValue ) outpw( xAddr, usValue )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE long
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portSTACK_TYPE uint16_t
|
||||
#define portBASE_TYPE portSHORT
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef short BaseType_t;
|
||||
typedef unsigned short UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section handling. */
|
||||
#define portENTER_CRITICAL() __asm{ pushf } \
|
||||
__asm{ cli } \
|
||||
|
||||
#define portEXIT_CRITICAL() __asm{ popf }
|
||||
|
||||
#define portDISABLE_INTERRUPTS() __asm{ cli }
|
||||
|
||||
#define portENABLE_INTERRUPTS() __asm{ sti }
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portNOP() __asm{ nop }
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portSWITCH_INT_NUMBER 0x80
|
||||
#define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 2
|
||||
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Compiler specifics. */
|
||||
#define portINPUT_BYTE( xAddr ) inp( xAddr )
|
||||
#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue )
|
||||
#define portINPUT_WORD( xAddr ) inpw( xAddr )
|
||||
#define portOUTPUT_WORD( xAddr, usValue ) outpw( xAddr, usValue )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,289 +1,288 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V2.6.1
|
||||
|
||||
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
|
||||
macro to be consistent with the later ports.
|
||||
|
||||
Changes from V4.0.1
|
||||
|
||||
+ Add function prvSetTickFrequencyDefault() to set the DOS tick back to
|
||||
its proper value when the scheduler exits.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <dos.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "portasm.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the industrial
|
||||
* PC port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/*lint -e950 Non ANSI reserved words okay in this file only. */
|
||||
|
||||
#define portTIMER_INT_NUMBER 0x08
|
||||
|
||||
/* Setup hardware for required tick interrupt rate. */
|
||||
static void prvSetTickFrequency( uint32_t ulTickRateHz );
|
||||
|
||||
/* Restore hardware to as it was prior to starting the scheduler. */
|
||||
static void prvExitFunction( void );
|
||||
|
||||
/* Either chain to the DOS tick (which itself clears the PIC) or clear the PIC
|
||||
directly. We chain to the DOS tick as close as possible to the standard DOS
|
||||
tick rate. */
|
||||
static void prvPortResetPIC( void );
|
||||
|
||||
/* The ISR used depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
/* Tick service routine used by the scheduler when preemptive scheduling is
|
||||
being used. */
|
||||
static void __interrupt __far prvPreemptiveTick( void );
|
||||
#else
|
||||
/* Tick service routine used by the scheduler when cooperative scheduling is
|
||||
being used. */
|
||||
static void __interrupt __far prvNonPreemptiveTick( void );
|
||||
#endif
|
||||
|
||||
/* Trap routine used by taskYIELD() to manually cause a context switch. */
|
||||
static void __interrupt __far prvYieldProcessor( void );
|
||||
|
||||
/* Set the tick frequency back so the floppy drive works correctly when the
|
||||
scheduler exits. */
|
||||
static void prvSetTickFrequencyDefault( void );
|
||||
|
||||
/*lint -e956 File scopes necessary here. */
|
||||
|
||||
/* Used to signal when to chain to the DOS tick, and when to just clear the PIC ourselves. */
|
||||
static int16_t sDOSTickCounter;
|
||||
|
||||
/* Set true when the vectors are set so the scheduler will service the tick. */
|
||||
static BaseType_t xSchedulerRunning = pdFALSE;
|
||||
|
||||
/* Points to the original routine installed on the vector we use for manual context switches. This is then used to restore the original routine during prvExitFunction(). */
|
||||
static void ( __interrupt __far *pxOldSwitchISR )();
|
||||
|
||||
/* Points to the original routine installed on the vector we use to chain to the DOS tick. This is then used to restore the original routine during prvExitFunction(). */
|
||||
static void ( __interrupt __far *pxOldSwitchISRPlus1 )();
|
||||
|
||||
/* Used to restore the original DOS context when the scheduler is ended. */
|
||||
static jmp_buf xJumpBuf;
|
||||
|
||||
/*lint +e956 */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
pxISR pxOriginalTickISR;
|
||||
|
||||
/* This is called with interrupts already disabled. */
|
||||
|
||||
/* Remember what was on the interrupts we are going to use
|
||||
so we can put them back later if required. */
|
||||
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
|
||||
pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER );
|
||||
pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
|
||||
|
||||
prvSetTickFrequency( configTICK_RATE_HZ );
|
||||
|
||||
/* Put our manual switch (yield) function on a known
|
||||
vector. */
|
||||
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
|
||||
|
||||
/* Put the old tick on a different interrupt number so we can
|
||||
call it when we want. */
|
||||
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR );
|
||||
|
||||
/* The ISR used depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
{
|
||||
/* Put our tick switch function on the timer interrupt. */
|
||||
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* We want the timer interrupt to just increment the tick count. */
|
||||
_dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup a counter that is used to call the DOS interrupt as close
|
||||
to it's original frequency as can be achieved given our chosen tick
|
||||
frequency. */
|
||||
sDOSTickCounter = portTICKS_PER_DOS_TICK;
|
||||
|
||||
/* Clean up function if we want to return to DOS. */
|
||||
if( setjmp( xJumpBuf ) != 0 )
|
||||
{
|
||||
prvExitFunction();
|
||||
xSchedulerRunning = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xSchedulerRunning = pdTRUE;
|
||||
|
||||
/* Kick off the scheduler by setting up the context of the first task. */
|
||||
portFIRST_CONTEXT();
|
||||
}
|
||||
|
||||
return xSchedulerRunning;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The ISR used depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
static void __interrupt __far prvPreemptiveTick( void )
|
||||
{
|
||||
/* Get the scheduler to update the task states following the tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Switch in the context of the next task to be run. */
|
||||
portSWITCH_CONTEXT();
|
||||
}
|
||||
|
||||
/* Reset the PIC ready for the next time. */
|
||||
prvPortResetPIC();
|
||||
}
|
||||
#else
|
||||
static void __interrupt __far prvNonPreemptiveTick( void )
|
||||
{
|
||||
/* Same as preemptive tick, but the cooperative scheduler is being used
|
||||
so we don't have to switch in the context of the next task. */
|
||||
xTaskIncrementTick();
|
||||
prvPortResetPIC();
|
||||
}
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void __interrupt __far prvYieldProcessor( void )
|
||||
{
|
||||
/* Switch in the context of the next task to be run. */
|
||||
portSWITCH_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvPortResetPIC( void )
|
||||
{
|
||||
/* We are going to call the DOS tick interrupt at as close a
|
||||
frequency to the normal DOS tick as possible. */
|
||||
|
||||
/* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */
|
||||
--sDOSTickCounter;
|
||||
if( sDOSTickCounter <= 0 )
|
||||
{
|
||||
sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK;
|
||||
__asm{ int portSWITCH_INT_NUMBER + 1 };
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset the PIC as the DOS tick is not being called to
|
||||
do it. */
|
||||
__asm
|
||||
{
|
||||
mov al, 20H
|
||||
out 20H, al
|
||||
};
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Jump back to the processor state prior to starting the
|
||||
scheduler. This means we are not going to be using a
|
||||
task stack frame so the task can be deleted. */
|
||||
longjmp( xJumpBuf, 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvExitFunction( void )
|
||||
{
|
||||
void ( __interrupt __far *pxOriginalTickISR )();
|
||||
|
||||
/* Interrupts should be disabled here anyway - but no
|
||||
harm in making sure. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
if( xSchedulerRunning == pdTRUE )
|
||||
{
|
||||
/* Set the DOS tick back onto the timer ticker. */
|
||||
pxOriginalTickISR = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
|
||||
_dos_setvect( portTIMER_INT_NUMBER, pxOriginalTickISR );
|
||||
prvSetTickFrequencyDefault();
|
||||
|
||||
/* Put back the switch interrupt routines that was in place
|
||||
before the scheduler started. */
|
||||
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
|
||||
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 );
|
||||
}
|
||||
/* The tick timer is back how DOS wants it. We can re-enable
|
||||
interrupts without the scheduler being called. */
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetTickFrequency( uint32_t ulTickRateHz )
|
||||
{
|
||||
const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
|
||||
const uint16_t usPIT0 = ( uint16_t ) 0x40;
|
||||
const uint32_t ulPIT_CONST = ( uint32_t ) 1193180UL;
|
||||
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
|
||||
uint32_t ulOutput;
|
||||
|
||||
/* Setup the 8245 to tick at the wanted frequency. */
|
||||
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
|
||||
ulOutput = ulPIT_CONST / ulTickRateHz;
|
||||
portOUTPUT_BYTE( usPIT0, ( uint16_t )( ulOutput & ( uint32_t ) 0xff ) );
|
||||
ulOutput >>= 8;
|
||||
portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetTickFrequencyDefault( void )
|
||||
{
|
||||
const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
|
||||
const uint16_t usPIT0 = ( uint16_t ) 0x40;
|
||||
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
|
||||
|
||||
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
|
||||
portOUTPUT_BYTE( usPIT0,0 );
|
||||
portOUTPUT_BYTE( usPIT0,0 );
|
||||
}
|
||||
|
||||
|
||||
/*lint +e950 */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V2.6.1
|
||||
|
||||
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
|
||||
macro to be consistent with the later ports.
|
||||
|
||||
Changes from V4.0.1
|
||||
|
||||
+ Add function prvSetTickFrequencyDefault() to set the DOS tick back to
|
||||
its proper value when the scheduler exits.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <dos.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "portasm.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the industrial
|
||||
* PC port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/*lint -e950 Non ANSI reserved words okay in this file only. */
|
||||
|
||||
#define portTIMER_INT_NUMBER 0x08
|
||||
|
||||
/* Setup hardware for required tick interrupt rate. */
|
||||
static void prvSetTickFrequency( uint32_t ulTickRateHz );
|
||||
|
||||
/* Restore hardware to as it was prior to starting the scheduler. */
|
||||
static void prvExitFunction( void );
|
||||
|
||||
/* Either chain to the DOS tick (which itself clears the PIC) or clear the PIC
|
||||
directly. We chain to the DOS tick as close as possible to the standard DOS
|
||||
tick rate. */
|
||||
static void prvPortResetPIC( void );
|
||||
|
||||
/* The ISR used depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
/* Tick service routine used by the scheduler when preemptive scheduling is
|
||||
being used. */
|
||||
static void __interrupt __far prvPreemptiveTick( void );
|
||||
#else
|
||||
/* Tick service routine used by the scheduler when cooperative scheduling is
|
||||
being used. */
|
||||
static void __interrupt __far prvNonPreemptiveTick( void );
|
||||
#endif
|
||||
|
||||
/* Trap routine used by taskYIELD() to manually cause a context switch. */
|
||||
static void __interrupt __far prvYieldProcessor( void );
|
||||
|
||||
/* Set the tick frequency back so the floppy drive works correctly when the
|
||||
scheduler exits. */
|
||||
static void prvSetTickFrequencyDefault( void );
|
||||
|
||||
/*lint -e956 File scopes necessary here. */
|
||||
|
||||
/* Used to signal when to chain to the DOS tick, and when to just clear the PIC ourselves. */
|
||||
static int16_t sDOSTickCounter;
|
||||
|
||||
/* Set true when the vectors are set so the scheduler will service the tick. */
|
||||
static BaseType_t xSchedulerRunning = pdFALSE;
|
||||
|
||||
/* Points to the original routine installed on the vector we use for manual context switches. This is then used to restore the original routine during prvExitFunction(). */
|
||||
static void ( __interrupt __far *pxOldSwitchISR )();
|
||||
|
||||
/* Points to the original routine installed on the vector we use to chain to the DOS tick. This is then used to restore the original routine during prvExitFunction(). */
|
||||
static void ( __interrupt __far *pxOldSwitchISRPlus1 )();
|
||||
|
||||
/* Used to restore the original DOS context when the scheduler is ended. */
|
||||
static jmp_buf xJumpBuf;
|
||||
|
||||
/*lint +e956 */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
pxISR pxOriginalTickISR;
|
||||
|
||||
/* This is called with interrupts already disabled. */
|
||||
|
||||
/* Remember what was on the interrupts we are going to use
|
||||
so we can put them back later if required. */
|
||||
pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER );
|
||||
pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER );
|
||||
pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
|
||||
|
||||
prvSetTickFrequency( configTICK_RATE_HZ );
|
||||
|
||||
/* Put our manual switch (yield) function on a known
|
||||
vector. */
|
||||
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
|
||||
|
||||
/* Put the old tick on a different interrupt number so we can
|
||||
call it when we want. */
|
||||
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR );
|
||||
|
||||
/* The ISR used depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
{
|
||||
/* Put our tick switch function on the timer interrupt. */
|
||||
_dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick );
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* We want the timer interrupt to just increment the tick count. */
|
||||
_dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup a counter that is used to call the DOS interrupt as close
|
||||
to it's original frequency as can be achieved given our chosen tick
|
||||
frequency. */
|
||||
sDOSTickCounter = portTICKS_PER_DOS_TICK;
|
||||
|
||||
/* Clean up function if we want to return to DOS. */
|
||||
if( setjmp( xJumpBuf ) != 0 )
|
||||
{
|
||||
prvExitFunction();
|
||||
xSchedulerRunning = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xSchedulerRunning = pdTRUE;
|
||||
|
||||
/* Kick off the scheduler by setting up the context of the first task. */
|
||||
portFIRST_CONTEXT();
|
||||
}
|
||||
|
||||
return xSchedulerRunning;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The ISR used depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
#if( configUSE_PREEMPTION == 1 )
|
||||
static void __interrupt __far prvPreemptiveTick( void )
|
||||
{
|
||||
/* Get the scheduler to update the task states following the tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Switch in the context of the next task to be run. */
|
||||
portSWITCH_CONTEXT();
|
||||
}
|
||||
|
||||
/* Reset the PIC ready for the next time. */
|
||||
prvPortResetPIC();
|
||||
}
|
||||
#else
|
||||
static void __interrupt __far prvNonPreemptiveTick( void )
|
||||
{
|
||||
/* Same as preemptive tick, but the cooperative scheduler is being used
|
||||
so we don't have to switch in the context of the next task. */
|
||||
xTaskIncrementTick();
|
||||
prvPortResetPIC();
|
||||
}
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void __interrupt __far prvYieldProcessor( void )
|
||||
{
|
||||
/* Switch in the context of the next task to be run. */
|
||||
portSWITCH_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvPortResetPIC( void )
|
||||
{
|
||||
/* We are going to call the DOS tick interrupt at as close a
|
||||
frequency to the normal DOS tick as possible. */
|
||||
|
||||
/* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */
|
||||
--sDOSTickCounter;
|
||||
if( sDOSTickCounter <= 0 )
|
||||
{
|
||||
sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK;
|
||||
__asm{ int portSWITCH_INT_NUMBER + 1 };
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset the PIC as the DOS tick is not being called to
|
||||
do it. */
|
||||
__asm
|
||||
{
|
||||
mov al, 20H
|
||||
out 20H, al
|
||||
};
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Jump back to the processor state prior to starting the
|
||||
scheduler. This means we are not going to be using a
|
||||
task stack frame so the task can be deleted. */
|
||||
longjmp( xJumpBuf, 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvExitFunction( void )
|
||||
{
|
||||
void ( __interrupt __far *pxOriginalTickISR )();
|
||||
|
||||
/* Interrupts should be disabled here anyway - but no
|
||||
harm in making sure. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
if( xSchedulerRunning == pdTRUE )
|
||||
{
|
||||
/* Set the DOS tick back onto the timer ticker. */
|
||||
pxOriginalTickISR = _dos_getvect( portSWITCH_INT_NUMBER + 1 );
|
||||
_dos_setvect( portTIMER_INT_NUMBER, pxOriginalTickISR );
|
||||
prvSetTickFrequencyDefault();
|
||||
|
||||
/* Put back the switch interrupt routines that was in place
|
||||
before the scheduler started. */
|
||||
_dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR );
|
||||
_dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 );
|
||||
}
|
||||
/* The tick timer is back how DOS wants it. We can re-enable
|
||||
interrupts without the scheduler being called. */
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetTickFrequency( uint32_t ulTickRateHz )
|
||||
{
|
||||
const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
|
||||
const uint16_t usPIT0 = ( uint16_t ) 0x40;
|
||||
const uint32_t ulPIT_CONST = ( uint32_t ) 1193180UL;
|
||||
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
|
||||
uint32_t ulOutput;
|
||||
|
||||
/* Setup the 8245 to tick at the wanted frequency. */
|
||||
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
|
||||
ulOutput = ulPIT_CONST / ulTickRateHz;
|
||||
portOUTPUT_BYTE( usPIT0, ( uint16_t )( ulOutput & ( uint32_t ) 0xff ) );
|
||||
ulOutput >>= 8;
|
||||
portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetTickFrequencyDefault( void )
|
||||
{
|
||||
const uint16_t usPIT_MODE = ( uint16_t ) 0x43;
|
||||
const uint16_t usPIT0 = ( uint16_t ) 0x40;
|
||||
const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36;
|
||||
|
||||
portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 );
|
||||
portOUTPUT_BYTE( usPIT0,0 );
|
||||
portOUTPUT_BYTE( usPIT0,0 );
|
||||
}
|
||||
|
||||
|
||||
/*lint +e950 */
|
||||
|
|
|
|||
|
|
@ -1,98 +1,97 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT long
|
||||
#define portDOUBLE long
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portSTACK_TYPE uint16_t
|
||||
#define portBASE_TYPE portSHORT
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef short BaseType_t;
|
||||
typedef unsigned short UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
#define portENTER_CRITICAL() __asm{ pushf } \
|
||||
__asm{ cli } \
|
||||
|
||||
#define portEXIT_CRITICAL() __asm{ popf }
|
||||
|
||||
#define portDISABLE_INTERRUPTS() __asm{ cli }
|
||||
|
||||
#define portENABLE_INTERRUPTS() __asm{ sti }
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portNOP() __asm{ nop }
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portSWITCH_INT_NUMBER 0x80
|
||||
#define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
|
||||
#define portDOS_TICK_RATE ( 18.20648 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portTICKS_PER_DOS_TICK ( ( uint16_t ) ( ( ( portDOUBLE ) configTICK_RATE_HZ / portDOS_TICK_RATE ) + 0.5 ) )
|
||||
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
|
||||
#define portBYTE_ALIGNMENT ( 2 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Compiler specifics. */
|
||||
#define portINPUT_BYTE( xAddr ) inp( xAddr )
|
||||
#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT long
|
||||
#define portDOUBLE long
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portSTACK_TYPE uint16_t
|
||||
#define portBASE_TYPE portSHORT
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef short BaseType_t;
|
||||
typedef unsigned short UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
#define portENTER_CRITICAL() __asm{ pushf } \
|
||||
__asm{ cli } \
|
||||
|
||||
#define portEXIT_CRITICAL() __asm{ popf }
|
||||
|
||||
#define portDISABLE_INTERRUPTS() __asm{ cli }
|
||||
|
||||
#define portENABLE_INTERRUPTS() __asm{ sti }
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portNOP() __asm{ nop }
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portSWITCH_INT_NUMBER 0x80
|
||||
#define portYIELD() __asm{ int portSWITCH_INT_NUMBER }
|
||||
#define portDOS_TICK_RATE ( 18.20648 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portTICKS_PER_DOS_TICK ( ( uint16_t ) ( ( ( portDOUBLE ) configTICK_RATE_HZ / portDOS_TICK_RATE ) + 0.5 ) )
|
||||
#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */
|
||||
#define portBYTE_ALIGNMENT ( 2 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Compiler specifics. */
|
||||
#define portINPUT_BYTE( xAddr ) inp( xAddr )
|
||||
#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,88 +1,87 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORT_ASM_H
|
||||
#define PORT_ASM_H
|
||||
|
||||
typedef void TCB_t;
|
||||
extern volatile TCB_t * volatile pxCurrentTCB;
|
||||
extern void vTaskSwitchContext( void );
|
||||
|
||||
/*
|
||||
* Saves the stack pointer for one task into its TCB, calls
|
||||
* vTaskSwitchContext() to update the TCB being used, then restores the stack
|
||||
* from the new TCB read to run the task.
|
||||
*/
|
||||
void portSWITCH_CONTEXT( void );
|
||||
|
||||
/*
|
||||
* Load the stack pointer from the TCB of the task which is going to be first
|
||||
* to execute. Then force an IRET so the registers and IP are popped off the
|
||||
* stack.
|
||||
*/
|
||||
void portFIRST_CONTEXT( void );
|
||||
|
||||
/* There are slightly different versions depending on whether you are building
|
||||
to include debugger information. If debugger information is used then there
|
||||
are a couple of extra bytes left of the ISR stack (presumably for use by the
|
||||
debugger). The true stack pointer is then stored in the bp register. We add
|
||||
2 to the stack pointer to remove the extra bytes before we restore our context. */
|
||||
|
||||
#define portSWITCH_CONTEXT() \
|
||||
asm { mov ax, seg pxCurrentTCB } \
|
||||
asm { mov ds, ax } \
|
||||
asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \
|
||||
asm { mov es:0x2[ bx ], ss } \
|
||||
asm { mov es:[ bx ], sp } \
|
||||
asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \
|
||||
asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \
|
||||
asm { mov ds, ax } \
|
||||
asm { les bx, dword ptr pxCurrentTCB } \
|
||||
asm { mov ss, es:[ bx + 2 ] } \
|
||||
asm { mov sp, es:[ bx ] }
|
||||
|
||||
#define portFIRST_CONTEXT() \
|
||||
__asm { mov ax, seg pxCurrentTCB } \
|
||||
__asm { mov ds, ax } \
|
||||
__asm { les bx, dword ptr pxCurrentTCB } \
|
||||
__asm { mov ss, es:[ bx + 2 ] } \
|
||||
__asm { mov sp, es:[ bx ] } \
|
||||
__asm { pop bp } \
|
||||
__asm { pop di } \
|
||||
__asm { pop si } \
|
||||
__asm { pop ds } \
|
||||
__asm { pop es } \
|
||||
__asm { pop dx } \
|
||||
__asm { pop cx } \
|
||||
__asm { pop bx } \
|
||||
__asm { pop ax } \
|
||||
__asm { iret }
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORT_ASM_H
|
||||
#define PORT_ASM_H
|
||||
|
||||
typedef void TCB_t;
|
||||
extern volatile TCB_t * volatile pxCurrentTCB;
|
||||
extern void vTaskSwitchContext( void );
|
||||
|
||||
/*
|
||||
* Saves the stack pointer for one task into its TCB, calls
|
||||
* vTaskSwitchContext() to update the TCB being used, then restores the stack
|
||||
* from the new TCB read to run the task.
|
||||
*/
|
||||
void portSWITCH_CONTEXT( void );
|
||||
|
||||
/*
|
||||
* Load the stack pointer from the TCB of the task which is going to be first
|
||||
* to execute. Then force an IRET so the registers and IP are popped off the
|
||||
* stack.
|
||||
*/
|
||||
void portFIRST_CONTEXT( void );
|
||||
|
||||
/* There are slightly different versions depending on whether you are building
|
||||
to include debugger information. If debugger information is used then there
|
||||
are a couple of extra bytes left of the ISR stack (presumably for use by the
|
||||
debugger). The true stack pointer is then stored in the bp register. We add
|
||||
2 to the stack pointer to remove the extra bytes before we restore our context. */
|
||||
|
||||
#define portSWITCH_CONTEXT() \
|
||||
asm { mov ax, seg pxCurrentTCB } \
|
||||
asm { mov ds, ax } \
|
||||
asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \
|
||||
asm { mov es:0x2[ bx ], ss } \
|
||||
asm { mov es:[ bx ], sp } \
|
||||
asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \
|
||||
asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \
|
||||
asm { mov ds, ax } \
|
||||
asm { les bx, dword ptr pxCurrentTCB } \
|
||||
asm { mov ss, es:[ bx + 2 ] } \
|
||||
asm { mov sp, es:[ bx ] }
|
||||
|
||||
#define portFIRST_CONTEXT() \
|
||||
__asm { mov ax, seg pxCurrentTCB } \
|
||||
__asm { mov ds, ax } \
|
||||
__asm { les bx, dword ptr pxCurrentTCB } \
|
||||
__asm { mov ss, es:[ bx + 2 ] } \
|
||||
__asm { mov sp, es:[ bx ] } \
|
||||
__asm { pop bp } \
|
||||
__asm { pop di } \
|
||||
__asm { pop si } \
|
||||
__asm { pop ds } \
|
||||
__asm { pop es } \
|
||||
__asm { pop dx } \
|
||||
__asm { pop cx } \
|
||||
__asm { pop bx } \
|
||||
__asm { pop ax } \
|
||||
__asm { iret }
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,121 +1,120 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V1.00:
|
||||
|
||||
+ pxPortInitialiseStack() now initialises the stack of new tasks to the
|
||||
same format used by the compiler. This allows the compiler generated
|
||||
interrupt mechanism to be used for context switches.
|
||||
|
||||
Changes from V2.6.1
|
||||
|
||||
+ Move usPortCheckFreeStackSpace() to tasks.c.
|
||||
*/
|
||||
|
||||
|
||||
#include <dos.h>
|
||||
#include <stdlib.h>
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* See header file for description. */
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t DS_Reg = 0;
|
||||
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
This is just useful for debugging. */
|
||||
|
||||
*pxTopOfStack = 0x1111;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2222;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x3333;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x4444;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x5555;
|
||||
pxTopOfStack--;
|
||||
|
||||
|
||||
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
|
||||
|
||||
/* We are going to start the scheduler using a return from interrupt
|
||||
instruction to load the program counter, so first there would be the
|
||||
function call with parameters preamble. */
|
||||
|
||||
*pxTopOfStack = FP_SEG( pvParameters );
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = FP_OFF( pvParameters );
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = FP_SEG( pxCode );
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = FP_OFF( pxCode );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next the status register and interrupt return address. */
|
||||
*pxTopOfStack = portINITIAL_SW;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = FP_SEG( pxCode );
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = FP_OFF( pxCode );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The remaining registers would be pushed on the stack by our context
|
||||
switch function. These are loaded with values simply to make debugging
|
||||
easier. */
|
||||
*pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xEEEE; /* ES */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* We need the true data segment. */
|
||||
__asm{ MOV DS_Reg, DS };
|
||||
|
||||
*pxTopOfStack = DS_Reg; /* DS */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0123; /* SI */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */
|
||||
|
||||
/*lint +e950 +e611 +e923 */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V1.00:
|
||||
|
||||
+ pxPortInitialiseStack() now initialises the stack of new tasks to the
|
||||
same format used by the compiler. This allows the compiler generated
|
||||
interrupt mechanism to be used for context switches.
|
||||
|
||||
Changes from V2.6.1
|
||||
|
||||
+ Move usPortCheckFreeStackSpace() to tasks.c.
|
||||
*/
|
||||
|
||||
|
||||
#include <dos.h>
|
||||
#include <stdlib.h>
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* See header file for description. */
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t DS_Reg = 0;
|
||||
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
This is just useful for debugging. */
|
||||
|
||||
*pxTopOfStack = 0x1111;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2222;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x3333;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x4444;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x5555;
|
||||
pxTopOfStack--;
|
||||
|
||||
|
||||
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
|
||||
|
||||
/* We are going to start the scheduler using a return from interrupt
|
||||
instruction to load the program counter, so first there would be the
|
||||
function call with parameters preamble. */
|
||||
|
||||
*pxTopOfStack = FP_SEG( pvParameters );
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = FP_OFF( pvParameters );
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = FP_SEG( pxCode );
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = FP_OFF( pxCode );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next the status register and interrupt return address. */
|
||||
*pxTopOfStack = portINITIAL_SW;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = FP_SEG( pxCode );
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = FP_OFF( pxCode );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The remaining registers would be pushed on the stack by our context
|
||||
switch function. These are loaded with values simply to make debugging
|
||||
easier. */
|
||||
*pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xEEEE; /* ES */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* We need the true data segment. */
|
||||
__asm{ MOV DS_Reg, DS };
|
||||
|
||||
*pxTopOfStack = DS_Reg; /* DS */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x0123; /* SI */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */
|
||||
|
||||
/*lint +e950 +e611 +e923 */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,145 +1,144 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * SPDX-License-Identifier: MIT
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
; *
|
||||
; * https://www.FreeRTOS.org
|
||||
; * https://github.com/FreeRTOS
|
||||
; *
|
||||
; */
|
||||
|
||||
.thumb
|
||||
|
||||
.ref pxCurrentTCB
|
||||
.ref vTaskSwitchContext
|
||||
.ref ulMaxSyscallInterruptPriority
|
||||
|
||||
.def xPortPendSVHandler
|
||||
.def ulPortGetIPSR
|
||||
.def vPortSVCHandler
|
||||
.def vPortStartFirstTask
|
||||
|
||||
NVICOffsetConst: .word 0xE000ED08
|
||||
CPACRConst: .word 0xE000ED88
|
||||
pxCurrentTCBConst: .word pxCurrentTCB
|
||||
ulMaxSyscallInterruptPriorityConst: .word ulMaxSyscallInterruptPriority
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
ulPortGetIPSR: .asmfunc
|
||||
mrs r0, ipsr
|
||||
bx r14
|
||||
.endasmfunc
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortSetInterruptMask: .asmfunc
|
||||
push {r0}
|
||||
ldr r0, ulMaxSyscallInterruptPriorityConst
|
||||
msr basepri, r0
|
||||
pop {r0}
|
||||
bx r14
|
||||
.endasmfunc
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
xPortPendSVHandler: .asmfunc
|
||||
mrs r0, psp
|
||||
isb
|
||||
|
||||
;/* Get the location of the current TCB. */
|
||||
ldr r3, pxCurrentTCBConst
|
||||
ldr r2, [r3]
|
||||
|
||||
;/* Save the core registers. */
|
||||
stmdb r0!, {r4-r11}
|
||||
|
||||
;/* Save the new top of stack into the first member of the TCB. */
|
||||
str r0, [r2]
|
||||
|
||||
stmdb sp!, {r3, r14}
|
||||
ldr r0, ulMaxSyscallInterruptPriorityConst
|
||||
ldr r1, [r0]
|
||||
msr basepri, r1
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
ldmia sp!, {r3, r14}
|
||||
|
||||
;/* The first item in pxCurrentTCB is the task top of stack. */
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
|
||||
;/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11}
|
||||
|
||||
msr psp, r0
|
||||
isb
|
||||
bx r14
|
||||
.endasmfunc
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortSVCHandler: .asmfunc
|
||||
;/* Get the location of the current TCB. */
|
||||
ldr r3, pxCurrentTCBConst
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
;/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11}
|
||||
msr psp, r0
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
orr r14, #0xd
|
||||
bx r14
|
||||
.endasmfunc
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortStartFirstTask: .asmfunc
|
||||
;/* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, NVICOffsetConst
|
||||
ldr r0, [r0]
|
||||
ldr r0, [r0]
|
||||
;/* Set the msp back to the start of the stack. */
|
||||
msr msp, r0
|
||||
;/* Clear the bit that indicates the FPU is in use in case the FPU was used
|
||||
;before the scheduler was started - which would otherwise result in the
|
||||
;unnecessary leaving of space in the SVC stack for lazy saving of FPU
|
||||
;registers. */
|
||||
mov r0, #0
|
||||
msr control, r0
|
||||
;/* Call SVC to start the first task. */
|
||||
cpsie i
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc #0
|
||||
.endasmfunc
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
;/*
|
||||
; * FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * SPDX-License-Identifier: MIT
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
; *
|
||||
; * https://www.FreeRTOS.org
|
||||
; * https://github.com/FreeRTOS
|
||||
; *
|
||||
; */
|
||||
|
||||
.thumb
|
||||
|
||||
.ref pxCurrentTCB
|
||||
.ref vTaskSwitchContext
|
||||
.ref ulMaxSyscallInterruptPriority
|
||||
|
||||
.def xPortPendSVHandler
|
||||
.def ulPortGetIPSR
|
||||
.def vPortSVCHandler
|
||||
.def vPortStartFirstTask
|
||||
|
||||
NVICOffsetConst: .word 0xE000ED08
|
||||
CPACRConst: .word 0xE000ED88
|
||||
pxCurrentTCBConst: .word pxCurrentTCB
|
||||
ulMaxSyscallInterruptPriorityConst: .word ulMaxSyscallInterruptPriority
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
ulPortGetIPSR: .asmfunc
|
||||
mrs r0, ipsr
|
||||
bx r14
|
||||
.endasmfunc
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortSetInterruptMask: .asmfunc
|
||||
push {r0}
|
||||
ldr r0, ulMaxSyscallInterruptPriorityConst
|
||||
msr basepri, r0
|
||||
pop {r0}
|
||||
bx r14
|
||||
.endasmfunc
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
xPortPendSVHandler: .asmfunc
|
||||
mrs r0, psp
|
||||
isb
|
||||
|
||||
;/* Get the location of the current TCB. */
|
||||
ldr r3, pxCurrentTCBConst
|
||||
ldr r2, [r3]
|
||||
|
||||
;/* Save the core registers. */
|
||||
stmdb r0!, {r4-r11}
|
||||
|
||||
;/* Save the new top of stack into the first member of the TCB. */
|
||||
str r0, [r2]
|
||||
|
||||
stmdb sp!, {r3, r14}
|
||||
ldr r0, ulMaxSyscallInterruptPriorityConst
|
||||
ldr r1, [r0]
|
||||
msr basepri, r1
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
ldmia sp!, {r3, r14}
|
||||
|
||||
;/* The first item in pxCurrentTCB is the task top of stack. */
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
|
||||
;/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11}
|
||||
|
||||
msr psp, r0
|
||||
isb
|
||||
bx r14
|
||||
.endasmfunc
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortSVCHandler: .asmfunc
|
||||
;/* Get the location of the current TCB. */
|
||||
ldr r3, pxCurrentTCBConst
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
;/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11}
|
||||
msr psp, r0
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
orr r14, #0xd
|
||||
bx r14
|
||||
.endasmfunc
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortStartFirstTask: .asmfunc
|
||||
;/* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, NVICOffsetConst
|
||||
ldr r0, [r0]
|
||||
ldr r0, [r0]
|
||||
;/* Set the msp back to the start of the stack. */
|
||||
msr msp, r0
|
||||
;/* Clear the bit that indicates the FPU is in use in case the FPU was used
|
||||
;before the scheduler was started - which would otherwise result in the
|
||||
;unnecessary leaving of space in the SVC stack for lazy saving of FPU
|
||||
;registers. */
|
||||
mov r0, #0
|
||||
msr control, r0
|
||||
;/* Call SVC to start the first task. */
|
||||
cpsie i
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc #0
|
||||
.endasmfunc
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1,171 +1,171 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Compiler directives. */
|
||||
#define portWEAK_SYMBOL __attribute__( ( weak ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
__asm( " dsb"); \
|
||||
__asm( " isb"); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) portYIELD(); } while( 0 )
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Check the configuration. */
|
||||
#if ( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
{ \
|
||||
_set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
|
||||
__asm( " dsb"); \
|
||||
__asm( " isb"); \
|
||||
}
|
||||
|
||||
#define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb")
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) _set_interrupt_priority( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
* not necessary for to use this port. They are defined so the common demo files
|
||||
* (which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Compiler directives. */
|
||||
#define portWEAK_SYMBOL __attribute__( ( weak ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
__asm( " dsb"); \
|
||||
__asm( " isb"); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) portYIELD(); } while( 0 )
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Check the configuration. */
|
||||
#if ( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
{ \
|
||||
_set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
|
||||
__asm( " dsb"); \
|
||||
__asm( " isb"); \
|
||||
}
|
||||
|
||||
#define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb")
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) _set_interrupt_priority( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
* not necessary for to use this port. They are defined so the common demo files
|
||||
* (which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,172 +1,171 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * SPDX-License-Identifier: MIT
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
; *
|
||||
; * https://www.FreeRTOS.org
|
||||
; * https://github.com/FreeRTOS
|
||||
; *
|
||||
; */
|
||||
|
||||
.thumb
|
||||
|
||||
.ref pxCurrentTCB
|
||||
.ref vTaskSwitchContext
|
||||
.ref ulMaxSyscallInterruptPriority
|
||||
|
||||
.def xPortPendSVHandler
|
||||
.def ulPortGetIPSR
|
||||
.def vPortSVCHandler
|
||||
.def vPortStartFirstTask
|
||||
.def vPortEnableVFP
|
||||
|
||||
NVICOffsetConst: .word 0xE000ED08
|
||||
CPACRConst: .word 0xE000ED88
|
||||
pxCurrentTCBConst: .word pxCurrentTCB
|
||||
ulMaxSyscallInterruptPriorityConst: .word ulMaxSyscallInterruptPriority
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
ulPortGetIPSR: .asmfunc
|
||||
mrs r0, ipsr
|
||||
bx r14
|
||||
.endasmfunc
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortSetInterruptMask: .asmfunc
|
||||
push {r0}
|
||||
ldr r0, ulMaxSyscallInterruptPriorityConst
|
||||
msr basepri, r0
|
||||
pop {r0}
|
||||
bx r14
|
||||
.endasmfunc
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
xPortPendSVHandler: .asmfunc
|
||||
mrs r0, psp
|
||||
isb
|
||||
|
||||
;/* Get the location of the current TCB. */
|
||||
ldr r3, pxCurrentTCBConst
|
||||
ldr r2, [r3]
|
||||
|
||||
;/* Is the task using the FPU context? If so, push high vfp registers. */
|
||||
tst r14, #0x10
|
||||
it eq
|
||||
vstmdbeq r0!, {s16-s31}
|
||||
|
||||
;/* Save the core registers. */
|
||||
stmdb r0!, {r4-r11, r14}
|
||||
|
||||
;/* Save the new top of stack into the first member of the TCB. */
|
||||
str r0, [r2]
|
||||
|
||||
stmdb sp!, {r0, r3}
|
||||
ldr r0, ulMaxSyscallInterruptPriorityConst
|
||||
ldr r1, [r0]
|
||||
msr basepri, r1
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
ldmia sp!, {r0, r3}
|
||||
|
||||
;/* The first item in pxCurrentTCB is the task top of stack. */
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
|
||||
;/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11, r14}
|
||||
|
||||
;/* Is the task using the FPU context? If so, pop the high vfp registers
|
||||
;too. */
|
||||
tst r14, #0x10
|
||||
it eq
|
||||
vldmiaeq r0!, {s16-s31}
|
||||
|
||||
msr psp, r0
|
||||
isb
|
||||
bx r14
|
||||
.endasmfunc
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortSVCHandler: .asmfunc
|
||||
;/* Get the location of the current TCB. */
|
||||
ldr r3, pxCurrentTCBConst
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
;/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11, r14}
|
||||
msr psp, r0
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
bx r14
|
||||
.endasmfunc
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortStartFirstTask: .asmfunc
|
||||
;/* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, NVICOffsetConst
|
||||
ldr r0, [r0]
|
||||
ldr r0, [r0]
|
||||
;/* Set the msp back to the start of the stack. */
|
||||
msr msp, r0
|
||||
;/* Clear the bit that indicates the FPU is in use in case the FPU was used
|
||||
;before the scheduler was started - which would otherwise result in the
|
||||
;unnecessary leaving of space in the SVC stack for lazy saving of FPU
|
||||
;registers. */
|
||||
mov r0, #0
|
||||
msr control, r0
|
||||
;/* Call SVC to start the first task. */
|
||||
cpsie i
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc #0
|
||||
.endasmfunc
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortEnableVFP: .asmfunc
|
||||
;/* The FPU enable bits are in the CPACR. */
|
||||
ldr.w r0, CPACRConst
|
||||
ldr r1, [r0]
|
||||
|
||||
;/* Enable CP10 and CP11 coprocessors, then save back. */
|
||||
orr r1, r1, #( 0xf << 20 )
|
||||
str r1, [r0]
|
||||
bx r14
|
||||
.endasmfunc
|
||||
|
||||
.end
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
;/*
|
||||
; * FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * SPDX-License-Identifier: MIT
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
; *
|
||||
; * https://www.FreeRTOS.org
|
||||
; * https://github.com/FreeRTOS
|
||||
; *
|
||||
; */
|
||||
|
||||
.thumb
|
||||
|
||||
.ref pxCurrentTCB
|
||||
.ref vTaskSwitchContext
|
||||
.ref ulMaxSyscallInterruptPriority
|
||||
|
||||
.def xPortPendSVHandler
|
||||
.def ulPortGetIPSR
|
||||
.def vPortSVCHandler
|
||||
.def vPortStartFirstTask
|
||||
.def vPortEnableVFP
|
||||
|
||||
NVICOffsetConst: .word 0xE000ED08
|
||||
CPACRConst: .word 0xE000ED88
|
||||
pxCurrentTCBConst: .word pxCurrentTCB
|
||||
ulMaxSyscallInterruptPriorityConst: .word ulMaxSyscallInterruptPriority
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
ulPortGetIPSR: .asmfunc
|
||||
mrs r0, ipsr
|
||||
bx r14
|
||||
.endasmfunc
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortSetInterruptMask: .asmfunc
|
||||
push {r0}
|
||||
ldr r0, ulMaxSyscallInterruptPriorityConst
|
||||
msr basepri, r0
|
||||
pop {r0}
|
||||
bx r14
|
||||
.endasmfunc
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
xPortPendSVHandler: .asmfunc
|
||||
mrs r0, psp
|
||||
isb
|
||||
|
||||
;/* Get the location of the current TCB. */
|
||||
ldr r3, pxCurrentTCBConst
|
||||
ldr r2, [r3]
|
||||
|
||||
;/* Is the task using the FPU context? If so, push high vfp registers. */
|
||||
tst r14, #0x10
|
||||
it eq
|
||||
vstmdbeq r0!, {s16-s31}
|
||||
|
||||
;/* Save the core registers. */
|
||||
stmdb r0!, {r4-r11, r14}
|
||||
|
||||
;/* Save the new top of stack into the first member of the TCB. */
|
||||
str r0, [r2]
|
||||
|
||||
stmdb sp!, {r0, r3}
|
||||
ldr r0, ulMaxSyscallInterruptPriorityConst
|
||||
ldr r1, [r0]
|
||||
msr basepri, r1
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
ldmia sp!, {r0, r3}
|
||||
|
||||
;/* The first item in pxCurrentTCB is the task top of stack. */
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
|
||||
;/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11, r14}
|
||||
|
||||
;/* Is the task using the FPU context? If so, pop the high vfp registers
|
||||
;too. */
|
||||
tst r14, #0x10
|
||||
it eq
|
||||
vldmiaeq r0!, {s16-s31}
|
||||
|
||||
msr psp, r0
|
||||
isb
|
||||
bx r14
|
||||
.endasmfunc
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortSVCHandler: .asmfunc
|
||||
;/* Get the location of the current TCB. */
|
||||
ldr r3, pxCurrentTCBConst
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
;/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11, r14}
|
||||
msr psp, r0
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
bx r14
|
||||
.endasmfunc
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortStartFirstTask: .asmfunc
|
||||
;/* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, NVICOffsetConst
|
||||
ldr r0, [r0]
|
||||
ldr r0, [r0]
|
||||
;/* Set the msp back to the start of the stack. */
|
||||
msr msp, r0
|
||||
;/* Clear the bit that indicates the FPU is in use in case the FPU was used
|
||||
;before the scheduler was started - which would otherwise result in the
|
||||
;unnecessary leaving of space in the SVC stack for lazy saving of FPU
|
||||
;registers. */
|
||||
mov r0, #0
|
||||
msr control, r0
|
||||
;/* Call SVC to start the first task. */
|
||||
cpsie i
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc #0
|
||||
.endasmfunc
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
||||
.align 4
|
||||
vPortEnableVFP: .asmfunc
|
||||
;/* The FPU enable bits are in the CPACR. */
|
||||
ldr.w r0, CPACRConst
|
||||
ldr r1, [r0]
|
||||
|
||||
;/* Enable CP10 and CP11 coprocessors, then save back. */
|
||||
orr r1, r1, #( 0xf << 20 )
|
||||
str r1, [r0]
|
||||
bx r14
|
||||
.endasmfunc
|
||||
|
||||
.end
|
||||
|
||||
; -----------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1,165 +1,165 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
__asm( " dsb"); \
|
||||
__asm( " isb"); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) portYIELD(); } while( 0 )
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Check the configuration. */
|
||||
#if ( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
{ \
|
||||
_set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
|
||||
__asm( " dsb"); \
|
||||
__asm( " isb"); \
|
||||
}
|
||||
|
||||
#define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb")
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) _set_interrupt_priority( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
* not necessary for to use this port. They are defined so the common demo files
|
||||
* (which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
__asm( " dsb"); \
|
||||
__asm( " isb"); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) portYIELD(); } while( 0 )
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Check the configuration. */
|
||||
#if ( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
{ \
|
||||
_set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
|
||||
__asm( " dsb"); \
|
||||
__asm( " isb"); \
|
||||
}
|
||||
|
||||
#define portENABLE_INTERRUPTS() _set_interrupt_priority( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() _set_interrupt_priority( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __asm( " dsb" ); __asm( " isb")
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) _set_interrupt_priority( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
* not necessary for to use this port. They are defined so the common demo files
|
||||
* (which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,313 +1,312 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Count of the critical section nesting depth. */
|
||||
uint32_t ulCriticalNesting = 9999;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Registers required to configure the RTI. */
|
||||
#define portRTI_GCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC00 ) )
|
||||
#define portRTI_TBCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC04 ) )
|
||||
#define portRTI_COMPCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC0C ) )
|
||||
#define portRTI_CNT0_FRC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC10 ) )
|
||||
#define portRTI_CNT0_UC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC14 ) )
|
||||
#define portRTI_CNT0_CPUC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC18 ) )
|
||||
#define portRTI_CNT0_COMP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC50 ) )
|
||||
#define portRTI_CNT0_UDCP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC54 ) )
|
||||
#define portRTI_SETINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC80 ) )
|
||||
#define portRTI_CLEARINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC84 ) )
|
||||
#define portRTI_INTFLAG_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC88 ) )
|
||||
|
||||
|
||||
/* Constants required to set up the initial stack of each task. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1F )
|
||||
#define portINITIAL_FPSCR ( ( StackType_t ) 0x00 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 0x04 )
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
|
||||
/* The number of words on the stack frame between the saved Top Of Stack and
|
||||
R0 (in which the parameters are passed. */
|
||||
#define portSPACE_BETWEEN_TOS_AND_PARAMETERS ( 12 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* vPortStartFirstSTask() is defined in portASM.asm */
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Saved as part of the task context. Set to pdFALSE if the task does not
|
||||
require an FPU context. */
|
||||
uint32_t ulTaskHasFPUContext = 0;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
#if __TI_VFP_SUPPORT__
|
||||
{
|
||||
/* Ensure the stack is correctly aligned on exit. */
|
||||
pxTopOfStack--;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* First on the stack is the return address - which is the start of the as
|
||||
the task has not executed yet. The offset is added to make the return
|
||||
address appear as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
|
||||
#ifdef portPRELOAD_TASK_REGISTERS
|
||||
{
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
}
|
||||
#else
|
||||
{
|
||||
pxTopOfStack -= portSPACE_BETWEEN_TOS_AND_PARAMETERS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Function parameters are passed in R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Set the status register for system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) ( ( _get_CPSR() & ~0xFF ) | portINITIAL_SPSR );
|
||||
|
||||
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
|
||||
{
|
||||
/* The task will start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
#ifdef __TI_VFP_SUPPORT__
|
||||
{
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing on the stack is the tasks ulUsingFPU value, which by
|
||||
default is set to indicate that the stack frame does not include FPU
|
||||
registers. */
|
||||
*pxTopOfStack = pdFALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt(void)
|
||||
{
|
||||
/* Disable timer 0. */
|
||||
portRTI_GCTRL_REG &= 0xFFFFFFFEUL;
|
||||
|
||||
/* Use the internal counter. */
|
||||
portRTI_TBCTRL_REG = 0x00000000U;
|
||||
|
||||
/* COMPSEL0 will use the RTIFRC0 counter. */
|
||||
portRTI_COMPCTRL_REG = 0x00000000U;
|
||||
|
||||
/* Initialise the counter and the prescale counter registers. */
|
||||
portRTI_CNT0_UC0_REG = 0x00000000U;
|
||||
portRTI_CNT0_FRC0_REG = 0x00000000U;
|
||||
|
||||
/* Set Prescalar for RTI clock. */
|
||||
portRTI_CNT0_CPUC0_REG = 0x00000001U;
|
||||
portRTI_CNT0_COMP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
|
||||
portRTI_CNT0_UDCP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
|
||||
|
||||
/* Clear interrupts. */
|
||||
portRTI_INTFLAG_REG = 0x0007000FU;
|
||||
portRTI_CLEARINTENA_REG = 0x00070F0FU;
|
||||
|
||||
/* Enable the compare 0 interrupt. */
|
||||
portRTI_SETINTENA_REG = 0x00000001U;
|
||||
portRTI_GCTRL_REG |= 0x00000001U;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler(void)
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Reset the critical section nesting count read to execute the first task. */
|
||||
ulCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. This is done from portASM.asm as ARM mode must be
|
||||
used. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return pdFAIL;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
void vPortEndScheduler(void)
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
* simply increment the system tick. */
|
||||
__interrupt void vPortNonPreemptiveTick( void )
|
||||
{
|
||||
/* clear clock interrupt flag */
|
||||
portRTI_INTFLAG_REG = 0x00000001;
|
||||
|
||||
/* Increment the tick count - this may make a delaying task ready
|
||||
to run - but a context switch is not performed. */
|
||||
xTaskIncrementTick();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
**************************************************************************
|
||||
* The preemptive scheduler ISR is written in assembler and can be found
|
||||
* in the portASM.asm file. This will only get used if portUSE_PREEMPTION
|
||||
* is set to 1 in portmacro.h
|
||||
**************************************************************************
|
||||
*/
|
||||
void vPortPreemptiveTick( void );
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Disable interrupts, and keep a count of the nesting depth.
|
||||
*/
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Decrement the critical nesting count, and if it has reached zero, re-enable
|
||||
* interrupts.
|
||||
*/
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > 0 )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
/* Enable interrupts as per portENABLE_INTERRUPTS(). */
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if __TI_VFP_SUPPORT__
|
||||
|
||||
void vPortTaskUsesFPU( void )
|
||||
{
|
||||
extern void vPortInitialiseFPSCR( void );
|
||||
|
||||
/* A task is registering the fact that it needs an FPU context. Set the
|
||||
FPU flag (saved as part of the task context. */
|
||||
ulTaskHasFPUContext = pdTRUE;
|
||||
|
||||
/* Initialise the floating point status register. */
|
||||
vPortInitialiseFPSCR();
|
||||
}
|
||||
|
||||
#endif /* __TI_VFP_SUPPORT__ */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Count of the critical section nesting depth. */
|
||||
uint32_t ulCriticalNesting = 9999;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Registers required to configure the RTI. */
|
||||
#define portRTI_GCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC00 ) )
|
||||
#define portRTI_TBCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC04 ) )
|
||||
#define portRTI_COMPCTRL_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC0C ) )
|
||||
#define portRTI_CNT0_FRC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC10 ) )
|
||||
#define portRTI_CNT0_UC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC14 ) )
|
||||
#define portRTI_CNT0_CPUC0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC18 ) )
|
||||
#define portRTI_CNT0_COMP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC50 ) )
|
||||
#define portRTI_CNT0_UDCP0_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC54 ) )
|
||||
#define portRTI_SETINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC80 ) )
|
||||
#define portRTI_CLEARINTENA_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC84 ) )
|
||||
#define portRTI_INTFLAG_REG ( * ( ( volatile uint32_t * ) 0xFFFFFC88 ) )
|
||||
|
||||
|
||||
/* Constants required to set up the initial stack of each task. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1F )
|
||||
#define portINITIAL_FPSCR ( ( StackType_t ) 0x00 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 0x04 )
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
|
||||
/* The number of words on the stack frame between the saved Top Of Stack and
|
||||
R0 (in which the parameters are passed. */
|
||||
#define portSPACE_BETWEEN_TOS_AND_PARAMETERS ( 12 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* vPortStartFirstSTask() is defined in portASM.asm */
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Saved as part of the task context. Set to pdFALSE if the task does not
|
||||
require an FPU context. */
|
||||
uint32_t ulTaskHasFPUContext = 0;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
#if __TI_VFP_SUPPORT__
|
||||
{
|
||||
/* Ensure the stack is correctly aligned on exit. */
|
||||
pxTopOfStack--;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* First on the stack is the return address - which is the start of the as
|
||||
the task has not executed yet. The offset is added to make the return
|
||||
address appear as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
|
||||
#ifdef portPRELOAD_TASK_REGISTERS
|
||||
{
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
}
|
||||
#else
|
||||
{
|
||||
pxTopOfStack -= portSPACE_BETWEEN_TOS_AND_PARAMETERS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Function parameters are passed in R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Set the status register for system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) ( ( _get_CPSR() & ~0xFF ) | portINITIAL_SPSR );
|
||||
|
||||
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
|
||||
{
|
||||
/* The task will start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
#ifdef __TI_VFP_SUPPORT__
|
||||
{
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing on the stack is the tasks ulUsingFPU value, which by
|
||||
default is set to indicate that the stack frame does not include FPU
|
||||
registers. */
|
||||
*pxTopOfStack = pdFALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt(void)
|
||||
{
|
||||
/* Disable timer 0. */
|
||||
portRTI_GCTRL_REG &= 0xFFFFFFFEUL;
|
||||
|
||||
/* Use the internal counter. */
|
||||
portRTI_TBCTRL_REG = 0x00000000U;
|
||||
|
||||
/* COMPSEL0 will use the RTIFRC0 counter. */
|
||||
portRTI_COMPCTRL_REG = 0x00000000U;
|
||||
|
||||
/* Initialise the counter and the prescale counter registers. */
|
||||
portRTI_CNT0_UC0_REG = 0x00000000U;
|
||||
portRTI_CNT0_FRC0_REG = 0x00000000U;
|
||||
|
||||
/* Set Prescalar for RTI clock. */
|
||||
portRTI_CNT0_CPUC0_REG = 0x00000001U;
|
||||
portRTI_CNT0_COMP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
|
||||
portRTI_CNT0_UDCP0_REG = ( configCPU_CLOCK_HZ / 2 ) / configTICK_RATE_HZ;
|
||||
|
||||
/* Clear interrupts. */
|
||||
portRTI_INTFLAG_REG = 0x0007000FU;
|
||||
portRTI_CLEARINTENA_REG = 0x00070F0FU;
|
||||
|
||||
/* Enable the compare 0 interrupt. */
|
||||
portRTI_SETINTENA_REG = 0x00000001U;
|
||||
portRTI_GCTRL_REG |= 0x00000001U;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler(void)
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Reset the critical section nesting count read to execute the first task. */
|
||||
ulCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. This is done from portASM.asm as ARM mode must be
|
||||
used. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return pdFAIL;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
void vPortEndScheduler(void)
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
* simply increment the system tick. */
|
||||
__interrupt void vPortNonPreemptiveTick( void )
|
||||
{
|
||||
/* clear clock interrupt flag */
|
||||
portRTI_INTFLAG_REG = 0x00000001;
|
||||
|
||||
/* Increment the tick count - this may make a delaying task ready
|
||||
to run - but a context switch is not performed. */
|
||||
xTaskIncrementTick();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
**************************************************************************
|
||||
* The preemptive scheduler ISR is written in assembler and can be found
|
||||
* in the portASM.asm file. This will only get used if portUSE_PREEMPTION
|
||||
* is set to 1 in portmacro.h
|
||||
**************************************************************************
|
||||
*/
|
||||
void vPortPreemptiveTick( void );
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Disable interrupts, and keep a count of the nesting depth.
|
||||
*/
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Decrement the critical nesting count, and if it has reached zero, re-enable
|
||||
* interrupts.
|
||||
*/
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > 0 )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
/* Enable interrupts as per portENABLE_INTERRUPTS(). */
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if __TI_VFP_SUPPORT__
|
||||
|
||||
void vPortTaskUsesFPU( void )
|
||||
{
|
||||
extern void vPortInitialiseFPSCR( void );
|
||||
|
||||
/* A task is registering the fact that it needs an FPU context. Set the
|
||||
FPU flag (saved as part of the task context. */
|
||||
ulTaskHasFPUContext = pdTRUE;
|
||||
|
||||
/* Initialise the floating point status register. */
|
||||
vPortInitialiseFPSCR();
|
||||
}
|
||||
|
||||
#endif /* __TI_VFP_SUPPORT__ */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,230 +1,229 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * SPDX-License-Identifier: MIT
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
; *
|
||||
; * https://www.FreeRTOS.org
|
||||
; * https://github.com/FreeRTOS
|
||||
; *
|
||||
; */
|
||||
|
||||
.text
|
||||
.arm
|
||||
.ref vTaskSwitchContext
|
||||
.ref xTaskIncrementTick
|
||||
.ref ulTaskHasFPUContext
|
||||
.ref pxCurrentTCB
|
||||
|
||||
;/*-----------------------------------------------------------*/
|
||||
;
|
||||
; Save Task Context
|
||||
;
|
||||
portSAVE_CONTEXT .macro
|
||||
DSB
|
||||
|
||||
; Push R0 as we are going to use it
|
||||
STMDB SP!, {R0}
|
||||
|
||||
; Set R0 to point to the task stack pointer.
|
||||
STMDB SP,{SP}^
|
||||
SUB SP, SP, #4
|
||||
LDMIA SP!,{R0}
|
||||
|
||||
; Push the return address onto the stack.
|
||||
STMDB R0!, {LR}
|
||||
|
||||
; Now LR has been saved, it can be used instead of R0.
|
||||
MOV LR, R0
|
||||
|
||||
; Pop R0 so it can be saved onto the task stack.
|
||||
LDMIA SP!, {R0}
|
||||
|
||||
; Push all the system mode registers onto the task stack.
|
||||
STMDB LR,{R0-LR}^
|
||||
SUB LR, LR, #60
|
||||
|
||||
; Push the SPSR onto the task stack.
|
||||
MRS R0, SPSR
|
||||
STMDB LR!, {R0}
|
||||
|
||||
.if (__TI_VFP_SUPPORT__)
|
||||
;Determine if the task maintains an FPU context.
|
||||
LDR R0, ulFPUContextConst
|
||||
LDR R0, [R0]
|
||||
|
||||
; Test the flag
|
||||
CMP R0, #0
|
||||
|
||||
; If the task is not using a floating point context then skip the
|
||||
; saving of the FPU registers.
|
||||
BEQ $+16
|
||||
FSTMDBD LR!, {D0-D15}
|
||||
FMRX R1, FPSCR
|
||||
STMFD LR!, {R1}
|
||||
|
||||
; Save the flag
|
||||
STMDB LR!, {R0}
|
||||
.endif
|
||||
|
||||
; Store the new top of stack for the task.
|
||||
LDR R0, pxCurrentTCBConst
|
||||
LDR R0, [R0]
|
||||
STR LR, [R0]
|
||||
|
||||
.endm
|
||||
|
||||
;/*-----------------------------------------------------------*/
|
||||
;
|
||||
; Restore Task Context
|
||||
;
|
||||
portRESTORE_CONTEXT .macro
|
||||
LDR R0, pxCurrentTCBConst
|
||||
LDR R0, [R0]
|
||||
LDR LR, [R0]
|
||||
|
||||
.if (__TI_VFP_SUPPORT__)
|
||||
; The floating point context flag is the first thing on the stack.
|
||||
LDR R0, ulFPUContextConst
|
||||
LDMFD LR!, {R1}
|
||||
STR R1, [R0]
|
||||
|
||||
; Test the flag
|
||||
CMP R1, #0
|
||||
|
||||
; If the task is not using a floating point context then skip the
|
||||
; VFP register loads.
|
||||
BEQ $+16
|
||||
|
||||
; Restore the floating point context.
|
||||
LDMFD LR!, {R0}
|
||||
FLDMIAD LR!, {D0-D15}
|
||||
FMXR FPSCR, R0
|
||||
.endif
|
||||
|
||||
; Get the SPSR from the stack.
|
||||
LDMFD LR!, {R0}
|
||||
MSR SPSR_CSXF, R0
|
||||
|
||||
; Restore all system mode registers for the task.
|
||||
LDMFD LR, {R0-R14}^
|
||||
|
||||
; Restore the return address.
|
||||
LDR LR, [LR, #+60]
|
||||
|
||||
; And return - correcting the offset in the LR to obtain the
|
||||
; correct address.
|
||||
SUBS PC, LR, #4
|
||||
.endm
|
||||
|
||||
;/*-----------------------------------------------------------*/
|
||||
; Start the first task by restoring its context.
|
||||
|
||||
.def vPortStartFirstTask
|
||||
|
||||
vPortStartFirstTask:
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;/*-----------------------------------------------------------*/
|
||||
; Yield to another task.
|
||||
|
||||
.def vPortYieldProcessor
|
||||
|
||||
vPortYieldProcessor:
|
||||
; Within an IRQ ISR the link register has an offset from the true return
|
||||
; address. SWI doesn't do this. Add the offset manually so the ISR
|
||||
; return code can be used.
|
||||
ADD LR, LR, #4
|
||||
|
||||
; First save the context of the current task.
|
||||
portSAVE_CONTEXT
|
||||
|
||||
; Select the next task to execute. */
|
||||
BL vTaskSwitchContext
|
||||
|
||||
; Restore the context of the task selected to execute.
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;/*-----------------------------------------------------------*/
|
||||
; Yield to another task from within the FreeRTOS API
|
||||
|
||||
.def vPortYeildWithinAPI
|
||||
|
||||
vPortYeildWithinAPI:
|
||||
; Save the context of the current task.
|
||||
|
||||
portSAVE_CONTEXT
|
||||
; Clear SSI flag.
|
||||
MOVW R0, #0xFFF4
|
||||
MOVT R0, #0xFFFF
|
||||
LDR R0, [R0]
|
||||
|
||||
; Select the next task to execute. */
|
||||
BL vTaskSwitchContext
|
||||
|
||||
; Restore the context of the task selected to execute.
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;/*-----------------------------------------------------------*/
|
||||
; Preemptive Tick
|
||||
|
||||
.def vPortPreemptiveTick
|
||||
|
||||
vPortPreemptiveTick:
|
||||
|
||||
; Save the context of the current task.
|
||||
portSAVE_CONTEXT
|
||||
|
||||
; Clear interrupt flag
|
||||
MOVW R0, #0xFC88
|
||||
MOVT R0, #0xFFFF
|
||||
MOV R1, #1
|
||||
STR R1, [R0]
|
||||
|
||||
; Increment the tick count, making any adjustments to the blocked lists
|
||||
; that may be necessary.
|
||||
BL xTaskIncrementTick
|
||||
|
||||
; Select the next task to execute.
|
||||
CMP R0, #0
|
||||
BLNE vTaskSwitchContext
|
||||
|
||||
; Restore the context of the task selected to execute.
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
|
||||
.if (__TI_VFP_SUPPORT__)
|
||||
|
||||
.def vPortInitialiseFPSCR
|
||||
|
||||
vPortInitialiseFPSCR:
|
||||
|
||||
MOV R0, #0
|
||||
FMXR FPSCR, R0
|
||||
BX LR
|
||||
|
||||
.endif ;__TI_VFP_SUPPORT__
|
||||
|
||||
|
||||
pxCurrentTCBConst .word pxCurrentTCB
|
||||
ulFPUContextConst .word ulTaskHasFPUContext
|
||||
;-------------------------------------------------------------------------------
|
||||
|
||||
;/*
|
||||
; * FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * SPDX-License-Identifier: MIT
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
; *
|
||||
; * https://www.FreeRTOS.org
|
||||
; * https://github.com/FreeRTOS
|
||||
; *
|
||||
; */
|
||||
|
||||
.text
|
||||
.arm
|
||||
.ref vTaskSwitchContext
|
||||
.ref xTaskIncrementTick
|
||||
.ref ulTaskHasFPUContext
|
||||
.ref pxCurrentTCB
|
||||
|
||||
;/*-----------------------------------------------------------*/
|
||||
;
|
||||
; Save Task Context
|
||||
;
|
||||
portSAVE_CONTEXT .macro
|
||||
DSB
|
||||
|
||||
; Push R0 as we are going to use it
|
||||
STMDB SP!, {R0}
|
||||
|
||||
; Set R0 to point to the task stack pointer.
|
||||
STMDB SP,{SP}^
|
||||
SUB SP, SP, #4
|
||||
LDMIA SP!,{R0}
|
||||
|
||||
; Push the return address onto the stack.
|
||||
STMDB R0!, {LR}
|
||||
|
||||
; Now LR has been saved, it can be used instead of R0.
|
||||
MOV LR, R0
|
||||
|
||||
; Pop R0 so it can be saved onto the task stack.
|
||||
LDMIA SP!, {R0}
|
||||
|
||||
; Push all the system mode registers onto the task stack.
|
||||
STMDB LR,{R0-LR}^
|
||||
SUB LR, LR, #60
|
||||
|
||||
; Push the SPSR onto the task stack.
|
||||
MRS R0, SPSR
|
||||
STMDB LR!, {R0}
|
||||
|
||||
.if (__TI_VFP_SUPPORT__)
|
||||
;Determine if the task maintains an FPU context.
|
||||
LDR R0, ulFPUContextConst
|
||||
LDR R0, [R0]
|
||||
|
||||
; Test the flag
|
||||
CMP R0, #0
|
||||
|
||||
; If the task is not using a floating point context then skip the
|
||||
; saving of the FPU registers.
|
||||
BEQ $+16
|
||||
FSTMDBD LR!, {D0-D15}
|
||||
FMRX R1, FPSCR
|
||||
STMFD LR!, {R1}
|
||||
|
||||
; Save the flag
|
||||
STMDB LR!, {R0}
|
||||
.endif
|
||||
|
||||
; Store the new top of stack for the task.
|
||||
LDR R0, pxCurrentTCBConst
|
||||
LDR R0, [R0]
|
||||
STR LR, [R0]
|
||||
|
||||
.endm
|
||||
|
||||
;/*-----------------------------------------------------------*/
|
||||
;
|
||||
; Restore Task Context
|
||||
;
|
||||
portRESTORE_CONTEXT .macro
|
||||
LDR R0, pxCurrentTCBConst
|
||||
LDR R0, [R0]
|
||||
LDR LR, [R0]
|
||||
|
||||
.if (__TI_VFP_SUPPORT__)
|
||||
; The floating point context flag is the first thing on the stack.
|
||||
LDR R0, ulFPUContextConst
|
||||
LDMFD LR!, {R1}
|
||||
STR R1, [R0]
|
||||
|
||||
; Test the flag
|
||||
CMP R1, #0
|
||||
|
||||
; If the task is not using a floating point context then skip the
|
||||
; VFP register loads.
|
||||
BEQ $+16
|
||||
|
||||
; Restore the floating point context.
|
||||
LDMFD LR!, {R0}
|
||||
FLDMIAD LR!, {D0-D15}
|
||||
FMXR FPSCR, R0
|
||||
.endif
|
||||
|
||||
; Get the SPSR from the stack.
|
||||
LDMFD LR!, {R0}
|
||||
MSR SPSR_CSXF, R0
|
||||
|
||||
; Restore all system mode registers for the task.
|
||||
LDMFD LR, {R0-R14}^
|
||||
|
||||
; Restore the return address.
|
||||
LDR LR, [LR, #+60]
|
||||
|
||||
; And return - correcting the offset in the LR to obtain the
|
||||
; correct address.
|
||||
SUBS PC, LR, #4
|
||||
.endm
|
||||
|
||||
;/*-----------------------------------------------------------*/
|
||||
; Start the first task by restoring its context.
|
||||
|
||||
.def vPortStartFirstTask
|
||||
|
||||
vPortStartFirstTask:
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;/*-----------------------------------------------------------*/
|
||||
; Yield to another task.
|
||||
|
||||
.def vPortYieldProcessor
|
||||
|
||||
vPortYieldProcessor:
|
||||
; Within an IRQ ISR the link register has an offset from the true return
|
||||
; address. SWI doesn't do this. Add the offset manually so the ISR
|
||||
; return code can be used.
|
||||
ADD LR, LR, #4
|
||||
|
||||
; First save the context of the current task.
|
||||
portSAVE_CONTEXT
|
||||
|
||||
; Select the next task to execute. */
|
||||
BL vTaskSwitchContext
|
||||
|
||||
; Restore the context of the task selected to execute.
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;/*-----------------------------------------------------------*/
|
||||
; Yield to another task from within the FreeRTOS API
|
||||
|
||||
.def vPortYeildWithinAPI
|
||||
|
||||
vPortYeildWithinAPI:
|
||||
; Save the context of the current task.
|
||||
|
||||
portSAVE_CONTEXT
|
||||
; Clear SSI flag.
|
||||
MOVW R0, #0xFFF4
|
||||
MOVT R0, #0xFFFF
|
||||
LDR R0, [R0]
|
||||
|
||||
; Select the next task to execute. */
|
||||
BL vTaskSwitchContext
|
||||
|
||||
; Restore the context of the task selected to execute.
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;/*-----------------------------------------------------------*/
|
||||
; Preemptive Tick
|
||||
|
||||
.def vPortPreemptiveTick
|
||||
|
||||
vPortPreemptiveTick:
|
||||
|
||||
; Save the context of the current task.
|
||||
portSAVE_CONTEXT
|
||||
|
||||
; Clear interrupt flag
|
||||
MOVW R0, #0xFC88
|
||||
MOVT R0, #0xFFFF
|
||||
MOV R1, #1
|
||||
STR R1, [R0]
|
||||
|
||||
; Increment the tick count, making any adjustments to the blocked lists
|
||||
; that may be necessary.
|
||||
BL xTaskIncrementTick
|
||||
|
||||
; Select the next task to execute.
|
||||
CMP R0, #0
|
||||
BLNE vTaskSwitchContext
|
||||
|
||||
; Restore the context of the task selected to execute.
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
|
||||
.if (__TI_VFP_SUPPORT__)
|
||||
|
||||
.def vPortInitialiseFPSCR
|
||||
|
||||
vPortInitialiseFPSCR:
|
||||
|
||||
MOV R0, #0
|
||||
FMXR FPSCR, R0
|
||||
BX LR
|
||||
|
||||
.endif ;__TI_VFP_SUPPORT__
|
||||
|
||||
|
||||
pxCurrentTCBConst .word pxCurrentTCB
|
||||
ulFPUContextConst .word ulTaskHasFPUContext
|
||||
;-------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1,118 +1,117 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PORTMACRO_H__
|
||||
#define __PORTMACRO_H__
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if (configUSE_16_BIT_TICKS == 1)
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY (TickType_t) 0xFFFF
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY (TickType_t) 0xFFFFFFFFF
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH (-1)
|
||||
#define portTICK_PERIOD_MS ((TickType_t) 1000 / configTICK_RATE_HZ)
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
|
||||
/* Critical section handling. */
|
||||
extern void vPortEnterCritical(void);
|
||||
extern void vPortExitCritical(void);
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portDISABLE_INTERRUPTS() asm( " CPSID I" )
|
||||
#define portENABLE_INTERRUPTS() asm( " CPSIE I" )
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#pragma SWI_ALIAS( vPortYield, 0 )
|
||||
extern void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
#define portSYS_SSIR1_REG ( * ( ( volatile uint32_t * ) 0xFFFFFFB0 ) )
|
||||
#define portSYS_SSIR1_SSKEY ( 0x7500UL )
|
||||
#define portYIELD_WITHIN_API() { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; asm( " DSB " ); asm( " ISB " ); }
|
||||
#define portYIELD_FROM_ISR( x ) do { if( x != pdFALSE ) { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; ( void ) portSYS_SSIR1_REG; } } while( 0 )
|
||||
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Check the configuration. */
|
||||
#if( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters)
|
||||
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)
|
||||
|
||||
#endif /* __PORTMACRO_H__ */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PORTMACRO_H__
|
||||
#define __PORTMACRO_H__
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if (configUSE_16_BIT_TICKS == 1)
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY (TickType_t) 0xFFFF
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY (TickType_t) 0xFFFFFFFFF
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH (-1)
|
||||
#define portTICK_PERIOD_MS ((TickType_t) 1000 / configTICK_RATE_HZ)
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
|
||||
/* Critical section handling. */
|
||||
extern void vPortEnterCritical(void);
|
||||
extern void vPortExitCritical(void);
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portDISABLE_INTERRUPTS() asm( " CPSID I" )
|
||||
#define portENABLE_INTERRUPTS() asm( " CPSIE I" )
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#pragma SWI_ALIAS( vPortYield, 0 )
|
||||
extern void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
#define portSYS_SSIR1_REG ( * ( ( volatile uint32_t * ) 0xFFFFFFB0 ) )
|
||||
#define portSYS_SSIR1_SSKEY ( 0x7500UL )
|
||||
#define portYIELD_WITHIN_API() { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; asm( " DSB " ); asm( " ISB " ); }
|
||||
#define portYIELD_FROM_ISR( x ) do { if( x != pdFALSE ) { portSYS_SSIR1_REG = portSYS_SSIR1_SSKEY; ( void ) portSYS_SSIR1_REG; } } while( 0 )
|
||||
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Check the configuration. */
|
||||
#if( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( ( uxReadyPriorities ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION(vFunction, pvParameters) void vFunction(void *pvParameters)
|
||||
#define portTASK_FUNCTION_PROTO(vFunction, pvParameters) void vFunction(void *pvParameters)
|
||||
|
||||
#endif /* __PORTMACRO_H__ */
|
||||
|
|
|
|||
|
|
@ -1,54 +1,49 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * SPDX-License-Identifier: MIT
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
; *
|
||||
; * https://www.FreeRTOS.org
|
||||
; * https://github.com/FreeRTOS
|
||||
; *
|
||||
; */
|
||||
|
||||
.if $DEFINED( __LARGE_DATA_MODEL__ )
|
||||
.define "pushm.a", pushm_x
|
||||
.define "popm.a", popm_x
|
||||
.define "push.a", push_x
|
||||
.define "pop.a", pop_x
|
||||
.define "mov.a", mov_x
|
||||
.else
|
||||
.define "pushm.w", pushm_x
|
||||
.define "popm.w", popm_x
|
||||
.define "push.w", push_x
|
||||
.define "pop.w", pop_x
|
||||
.define "mov.w", mov_x
|
||||
.endif
|
||||
|
||||
.if $DEFINED( __LARGE_CODE_MODEL__ )
|
||||
.define "calla", call_x
|
||||
.define "reta", ret_x
|
||||
.else
|
||||
.define "call", call_x
|
||||
.define "ret", ret_x
|
||||
.endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;/*
|
||||
; * FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * SPDX-License-Identifier: MIT
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
; *
|
||||
; * https://www.FreeRTOS.org
|
||||
; * https://github.com/FreeRTOS
|
||||
; *
|
||||
; */
|
||||
|
||||
.if $DEFINED( __LARGE_DATA_MODEL__ )
|
||||
.define "pushm.a", pushm_x
|
||||
.define "popm.a", popm_x
|
||||
.define "push.a", push_x
|
||||
.define "pop.a", pop_x
|
||||
.define "mov.a", mov_x
|
||||
.else
|
||||
.define "pushm.w", pushm_x
|
||||
.define "popm.w", popm_x
|
||||
.define "push.w", push_x
|
||||
.define "pop.w", pop_x
|
||||
.define "mov.w", mov_x
|
||||
.endif
|
||||
|
||||
.if $DEFINED( __LARGE_CODE_MODEL__ )
|
||||
.define "calla", call_x
|
||||
.define "reta", ret_x
|
||||
.else
|
||||
.define "call", call_x
|
||||
.define "ret", ret_x
|
||||
.endif
|
||||
|
|
|
|||
|
|
@ -1,188 +1,188 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the MSP430X port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Constants required for hardware setup. The tick ISR runs off the ACLK,
|
||||
not the MCLK. */
|
||||
#define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 )
|
||||
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
|
||||
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 )
|
||||
|
||||
/* We require the address of the pxCurrentTCB variable, but don't want to know
|
||||
any details of its type. */
|
||||
typedef void TCB_t;
|
||||
extern volatile TCB_t * volatile pxCurrentTCB;
|
||||
|
||||
/* Each task maintains a count of the critical section nesting depth. Each
|
||||
time a critical section is entered the count is incremented. Each time a
|
||||
critical section is exited the count is decremented - with interrupts only
|
||||
being re-enabled if the count is zero.
|
||||
|
||||
usCriticalNesting will get set to zero when the scheduler starts, but must
|
||||
not be initialised to zero as this will cause problems during the startup
|
||||
sequence. */
|
||||
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Sets up the periodic ISR used for the RTOS tick. This uses timer 0, but
|
||||
* could have alternatively used the watchdog timer or timer 1.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See the header file portable.h.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
uint16_t *pusTopOfStack;
|
||||
uint32_t *pulTopOfStack, ulTemp;
|
||||
|
||||
/*
|
||||
Place a few bytes of known values on the bottom of the stack.
|
||||
This is just useful for debugging and can be included if required.
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x1111;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x2222;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x3333;
|
||||
pxTopOfStack--;
|
||||
*/
|
||||
|
||||
/* Data types are need either 16 bits or 32 bits depending on the data
|
||||
and code model used. */
|
||||
if( sizeof( pxCode ) == sizeof( uint16_t ) )
|
||||
{
|
||||
pusTopOfStack = ( uint16_t * ) pxTopOfStack;
|
||||
ulTemp = ( uint32_t ) pxCode;
|
||||
*pusTopOfStack = ( uint16_t ) ulTemp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make room for a 20 bit value stored as a 32 bit value. */
|
||||
pusTopOfStack = ( uint16_t * ) pxTopOfStack;
|
||||
pusTopOfStack--;
|
||||
pulTopOfStack = ( uint32_t * ) pusTopOfStack;
|
||||
*pulTopOfStack = ( uint32_t ) pxCode;
|
||||
}
|
||||
|
||||
pusTopOfStack--;
|
||||
*pusTopOfStack = portFLAGS_INT_ENABLED;
|
||||
pusTopOfStack -= ( sizeof( StackType_t ) / 2 );
|
||||
|
||||
/* From here on the size of stacked items depends on the memory model. */
|
||||
pxTopOfStack = ( StackType_t * ) pusTopOfStack;
|
||||
|
||||
/* Next the general purpose registers. */
|
||||
#ifdef PRELOAD_REGISTER_VALUES
|
||||
*pxTopOfStack = ( StackType_t ) 0xffff;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xeeee;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xdddd;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xbbbb;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaa;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x9999;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x8888;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x5555;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x6666;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x5555;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x4444;
|
||||
pxTopOfStack--;
|
||||
#else
|
||||
pxTopOfStack -= 3;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack -= 9;
|
||||
#endif
|
||||
|
||||
/* A variable is used to keep track of the critical section nesting.
|
||||
This variable has to be stored as part of the task context and is
|
||||
initially set to zero. */
|
||||
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
/* Return a pointer to the top of the stack we have generated so this can
|
||||
be stored in the task control block for the task. */
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the MSP430 port will get stopped. If required simply
|
||||
disable the tick interrupt here. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Hardware initialisation to generate the RTOS tick.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
vApplicationSetupTimerInterrupt();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#pragma vector=configTICK_VECTOR
|
||||
interrupt void vTickISREntry( void )
|
||||
{
|
||||
extern void vPortTickISR( void );
|
||||
|
||||
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
|
||||
#if configUSE_PREEMPTION == 1
|
||||
extern void vPortPreemptiveTickISR( void );
|
||||
vPortPreemptiveTickISR();
|
||||
#else
|
||||
extern void vPortCooperativeTickISR( void );
|
||||
vPortCooperativeTickISR();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the MSP430X port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Constants required for hardware setup. The tick ISR runs off the ACLK,
|
||||
not the MCLK. */
|
||||
#define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 )
|
||||
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
|
||||
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 )
|
||||
|
||||
/* We require the address of the pxCurrentTCB variable, but don't want to know
|
||||
any details of its type. */
|
||||
typedef void TCB_t;
|
||||
extern volatile TCB_t * volatile pxCurrentTCB;
|
||||
|
||||
/* Each task maintains a count of the critical section nesting depth. Each
|
||||
time a critical section is entered the count is incremented. Each time a
|
||||
critical section is exited the count is decremented - with interrupts only
|
||||
being re-enabled if the count is zero.
|
||||
|
||||
usCriticalNesting will get set to zero when the scheduler starts, but must
|
||||
not be initialised to zero as this will cause problems during the startup
|
||||
sequence. */
|
||||
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Sets up the periodic ISR used for the RTOS tick. This uses timer 0, but
|
||||
* could have alternatively used the watchdog timer or timer 1.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See the header file portable.h.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
uint16_t *pusTopOfStack;
|
||||
uint32_t *pulTopOfStack, ulTemp;
|
||||
|
||||
/*
|
||||
Place a few bytes of known values on the bottom of the stack.
|
||||
This is just useful for debugging and can be included if required.
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x1111;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x2222;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x3333;
|
||||
pxTopOfStack--;
|
||||
*/
|
||||
|
||||
/* Data types are need either 16 bits or 32 bits depending on the data
|
||||
and code model used. */
|
||||
if( sizeof( pxCode ) == sizeof( uint16_t ) )
|
||||
{
|
||||
pusTopOfStack = ( uint16_t * ) pxTopOfStack;
|
||||
ulTemp = ( uint32_t ) pxCode;
|
||||
*pusTopOfStack = ( uint16_t ) ulTemp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make room for a 20 bit value stored as a 32 bit value. */
|
||||
pusTopOfStack = ( uint16_t * ) pxTopOfStack;
|
||||
pusTopOfStack--;
|
||||
pulTopOfStack = ( uint32_t * ) pusTopOfStack;
|
||||
*pulTopOfStack = ( uint32_t ) pxCode;
|
||||
}
|
||||
|
||||
pusTopOfStack--;
|
||||
*pusTopOfStack = portFLAGS_INT_ENABLED;
|
||||
pusTopOfStack -= ( sizeof( StackType_t ) / 2 );
|
||||
|
||||
/* From here on the size of stacked items depends on the memory model. */
|
||||
pxTopOfStack = ( StackType_t * ) pusTopOfStack;
|
||||
|
||||
/* Next the general purpose registers. */
|
||||
#ifdef PRELOAD_REGISTER_VALUES
|
||||
*pxTopOfStack = ( StackType_t ) 0xffff;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xeeee;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xdddd;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xbbbb;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaa;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x9999;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x8888;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x5555;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x6666;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x5555;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x4444;
|
||||
pxTopOfStack--;
|
||||
#else
|
||||
pxTopOfStack -= 3;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack -= 9;
|
||||
#endif
|
||||
|
||||
/* A variable is used to keep track of the critical section nesting.
|
||||
This variable has to be stored as part of the task context and is
|
||||
initially set to zero. */
|
||||
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
/* Return a pointer to the top of the stack we have generated so this can
|
||||
be stored in the task control block for the task. */
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the MSP430 port will get stopped. If required simply
|
||||
disable the tick interrupt here. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Hardware initialisation to generate the RTOS tick.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
vApplicationSetupTimerInterrupt();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#pragma vector=configTICK_VECTOR
|
||||
interrupt void vTickISREntry( void )
|
||||
{
|
||||
extern void vPortTickISR( void );
|
||||
|
||||
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
|
||||
#if configUSE_PREEMPTION == 1
|
||||
extern void vPortPreemptiveTickISR( void );
|
||||
vPortPreemptiveTickISR();
|
||||
#else
|
||||
extern void vPortCooperativeTickISR( void );
|
||||
vPortCooperativeTickISR();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,160 +1,159 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * SPDX-License-Identifier: MIT
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
; *
|
||||
; * https://www.FreeRTOS.org
|
||||
; * https://github.com/FreeRTOS
|
||||
; *
|
||||
; */
|
||||
|
||||
; * The definition of the "register test" tasks, as described at the top of
|
||||
; * main.c
|
||||
|
||||
.include data_model.h
|
||||
|
||||
.global xTaskIncrementTick
|
||||
.global vTaskSwitchContext
|
||||
.global vPortSetupTimerInterrupt
|
||||
.global pxCurrentTCB
|
||||
.global usCriticalNesting
|
||||
|
||||
.def vPortPreemptiveTickISR
|
||||
.def vPortCooperativeTickISR
|
||||
.def vPortYield
|
||||
.def xPortStartScheduler
|
||||
|
||||
;-----------------------------------------------------------
|
||||
|
||||
portSAVE_CONTEXT .macro
|
||||
|
||||
;Save the remaining registers.
|
||||
pushm_x #12, r15
|
||||
mov.w &usCriticalNesting, r14
|
||||
push_x r14
|
||||
mov_x &pxCurrentTCB, r12
|
||||
mov_x sp, 0( r12 )
|
||||
.endm
|
||||
;-----------------------------------------------------------
|
||||
|
||||
portRESTORE_CONTEXT .macro
|
||||
|
||||
mov_x &pxCurrentTCB, r12
|
||||
mov_x @r12, sp
|
||||
pop_x r15
|
||||
mov.w r15, &usCriticalNesting
|
||||
popm_x #12, r15
|
||||
nop
|
||||
pop.w sr
|
||||
nop
|
||||
ret_x
|
||||
.endm
|
||||
;-----------------------------------------------------------
|
||||
|
||||
;*
|
||||
;* The RTOS tick ISR.
|
||||
;*
|
||||
;* If the cooperative scheduler is in use this simply increments the tick
|
||||
;* count.
|
||||
;*
|
||||
;* If the preemptive scheduler is in use a context switch can also occur.
|
||||
;*/
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
vPortPreemptiveTickISR: .asmfunc
|
||||
|
||||
; The sr is not saved in portSAVE_CONTEXT() because vPortYield() needs
|
||||
;to save it manually before it gets modified (interrupts get disabled).
|
||||
push.w sr
|
||||
portSAVE_CONTEXT
|
||||
|
||||
call_x #xTaskIncrementTick
|
||||
call_x #vTaskSwitchContext
|
||||
|
||||
portRESTORE_CONTEXT
|
||||
.endasmfunc
|
||||
;-----------------------------------------------------------
|
||||
|
||||
.align 2
|
||||
|
||||
vPortCooperativeTickISR: .asmfunc
|
||||
|
||||
; The sr is not saved in portSAVE_CONTEXT() because vPortYield() needs
|
||||
;to save it manually before it gets modified (interrupts get disabled).
|
||||
push.w sr
|
||||
portSAVE_CONTEXT
|
||||
|
||||
call_x #xTaskIncrementTick
|
||||
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
.endasmfunc
|
||||
;-----------------------------------------------------------
|
||||
|
||||
;
|
||||
; Manual context switch called by the portYIELD() macro.
|
||||
;
|
||||
|
||||
.align 2
|
||||
|
||||
vPortYield: .asmfunc
|
||||
|
||||
; The sr needs saving before it is modified.
|
||||
push.w sr
|
||||
|
||||
; Now the SR is stacked we can disable interrupts.
|
||||
dint
|
||||
nop
|
||||
|
||||
; Save the context of the current task.
|
||||
portSAVE_CONTEXT
|
||||
|
||||
; Select the next task to run.
|
||||
call_x #vTaskSwitchContext
|
||||
|
||||
; Restore the context of the new task.
|
||||
portRESTORE_CONTEXT
|
||||
.endasmfunc
|
||||
;-----------------------------------------------------------
|
||||
|
||||
|
||||
;
|
||||
; Start off the scheduler by initialising the RTOS tick timer, then restoring
|
||||
; the context of the first task.
|
||||
;
|
||||
|
||||
.align 2
|
||||
|
||||
xPortStartScheduler: .asmfunc
|
||||
|
||||
; Setup the hardware to generate the tick. Interrupts are disabled
|
||||
; when this function is called.
|
||||
call_x #vPortSetupTimerInterrupt
|
||||
|
||||
; Restore the context of the first task that is going to run.
|
||||
portRESTORE_CONTEXT
|
||||
.endasmfunc
|
||||
;-----------------------------------------------------------
|
||||
|
||||
.end
|
||||
|
||||
;/*
|
||||
; * FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
; * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * SPDX-License-Identifier: MIT
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
; * the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
; *
|
||||
; * https://www.FreeRTOS.org
|
||||
; * https://github.com/FreeRTOS
|
||||
; *
|
||||
; */
|
||||
|
||||
; * The definition of the "register test" tasks, as described at the top of
|
||||
; * main.c
|
||||
|
||||
.include data_model.h
|
||||
|
||||
.global xTaskIncrementTick
|
||||
.global vTaskSwitchContext
|
||||
.global vPortSetupTimerInterrupt
|
||||
.global pxCurrentTCB
|
||||
.global usCriticalNesting
|
||||
|
||||
.def vPortPreemptiveTickISR
|
||||
.def vPortCooperativeTickISR
|
||||
.def vPortYield
|
||||
.def xPortStartScheduler
|
||||
|
||||
;-----------------------------------------------------------
|
||||
|
||||
portSAVE_CONTEXT .macro
|
||||
|
||||
;Save the remaining registers.
|
||||
pushm_x #12, r15
|
||||
mov.w &usCriticalNesting, r14
|
||||
push_x r14
|
||||
mov_x &pxCurrentTCB, r12
|
||||
mov_x sp, 0( r12 )
|
||||
.endm
|
||||
;-----------------------------------------------------------
|
||||
|
||||
portRESTORE_CONTEXT .macro
|
||||
|
||||
mov_x &pxCurrentTCB, r12
|
||||
mov_x @r12, sp
|
||||
pop_x r15
|
||||
mov.w r15, &usCriticalNesting
|
||||
popm_x #12, r15
|
||||
nop
|
||||
pop.w sr
|
||||
nop
|
||||
ret_x
|
||||
.endm
|
||||
;-----------------------------------------------------------
|
||||
|
||||
;*
|
||||
;* The RTOS tick ISR.
|
||||
;*
|
||||
;* If the cooperative scheduler is in use this simply increments the tick
|
||||
;* count.
|
||||
;*
|
||||
;* If the preemptive scheduler is in use a context switch can also occur.
|
||||
;*/
|
||||
|
||||
.text
|
||||
.align 2
|
||||
|
||||
vPortPreemptiveTickISR: .asmfunc
|
||||
|
||||
; The sr is not saved in portSAVE_CONTEXT() because vPortYield() needs
|
||||
;to save it manually before it gets modified (interrupts get disabled).
|
||||
push.w sr
|
||||
portSAVE_CONTEXT
|
||||
|
||||
call_x #xTaskIncrementTick
|
||||
call_x #vTaskSwitchContext
|
||||
|
||||
portRESTORE_CONTEXT
|
||||
.endasmfunc
|
||||
;-----------------------------------------------------------
|
||||
|
||||
.align 2
|
||||
|
||||
vPortCooperativeTickISR: .asmfunc
|
||||
|
||||
; The sr is not saved in portSAVE_CONTEXT() because vPortYield() needs
|
||||
;to save it manually before it gets modified (interrupts get disabled).
|
||||
push.w sr
|
||||
portSAVE_CONTEXT
|
||||
|
||||
call_x #xTaskIncrementTick
|
||||
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
.endasmfunc
|
||||
;-----------------------------------------------------------
|
||||
|
||||
;
|
||||
; Manual context switch called by the portYIELD() macro.
|
||||
;
|
||||
|
||||
.align 2
|
||||
|
||||
vPortYield: .asmfunc
|
||||
|
||||
; The sr needs saving before it is modified.
|
||||
push.w sr
|
||||
|
||||
; Now the SR is stacked we can disable interrupts.
|
||||
dint
|
||||
nop
|
||||
|
||||
; Save the context of the current task.
|
||||
portSAVE_CONTEXT
|
||||
|
||||
; Select the next task to run.
|
||||
call_x #vTaskSwitchContext
|
||||
|
||||
; Restore the context of the new task.
|
||||
portRESTORE_CONTEXT
|
||||
.endasmfunc
|
||||
;-----------------------------------------------------------
|
||||
|
||||
|
||||
;
|
||||
; Start off the scheduler by initialising the RTOS tick timer, then restoring
|
||||
; the context of the first task.
|
||||
;
|
||||
|
||||
.align 2
|
||||
|
||||
xPortStartScheduler: .asmfunc
|
||||
|
||||
; Setup the hardware to generate the tick. Interrupts are disabled
|
||||
; when this function is called.
|
||||
call_x #vPortSetupTimerInterrupt
|
||||
|
||||
; Restore the context of the first task that is going to run.
|
||||
portRESTORE_CONTEXT
|
||||
.endasmfunc
|
||||
;-----------------------------------------------------------
|
||||
|
||||
.end
|
||||
|
|
|
|||
|
|
@ -1,144 +1,143 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Hardware includes. */
|
||||
#include "msp430.h"
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portBASE_TYPE portSHORT
|
||||
|
||||
/* The stack type changes depending on the data model. */
|
||||
#ifdef __LARGE_DATA_MODEL__
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#else
|
||||
#define portSTACK_TYPE uint16_t
|
||||
#define portPOINTER_SIZE_TYPE uint16_t
|
||||
#endif
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef short BaseType_t;
|
||||
typedef unsigned short UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Interrupt control macros. */
|
||||
#define portDISABLE_INTERRUPTS() _disable_interrupt(); _nop()
|
||||
#define portENABLE_INTERRUPTS() _enable_interrupt(); _nop()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section control macros. */
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
|
||||
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
\
|
||||
/* Now interrupts are disabled usCriticalNesting can be accessed */ \
|
||||
/* directly. Increment ulCriticalNesting to keep a count of how many */ \
|
||||
/* times portENTER_CRITICAL() has been called. */ \
|
||||
usCriticalNesting++; \
|
||||
}
|
||||
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
/* Decrement the nesting count as we are leaving a critical section. */ \
|
||||
usCriticalNesting--; \
|
||||
\
|
||||
/* If the nesting level has reached zero then interrupts should be */ \
|
||||
/* re-enabled. */ \
|
||||
if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/*
|
||||
* Manual context switch called by portYIELD or taskYIELD.
|
||||
*/
|
||||
extern void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 2
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portNOP() __no_operation()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
extern void vTaskSwitchContext( void );
|
||||
#define portYIELD_FROM_ISR( x ) do { if( x ) vPortYield(); } while( 0 )
|
||||
|
||||
void vApplicationSetupTimerInterrupt( void );
|
||||
|
||||
/* sizeof( int ) != sizeof( long ) so a full printf() library is required if
|
||||
run time stats information is to be displayed. */
|
||||
#define portLU_PRINTF_SPECIFIER_REQUIRED
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Hardware includes. */
|
||||
#include "msp430.h"
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portBASE_TYPE portSHORT
|
||||
|
||||
/* The stack type changes depending on the data model. */
|
||||
#ifdef __LARGE_DATA_MODEL__
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#else
|
||||
#define portSTACK_TYPE uint16_t
|
||||
#define portPOINTER_SIZE_TYPE uint16_t
|
||||
#endif
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef short BaseType_t;
|
||||
typedef unsigned short UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Interrupt control macros. */
|
||||
#define portDISABLE_INTERRUPTS() _disable_interrupt(); _nop()
|
||||
#define portENABLE_INTERRUPTS() _enable_interrupt(); _nop()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section control macros. */
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
|
||||
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
\
|
||||
/* Now interrupts are disabled usCriticalNesting can be accessed */ \
|
||||
/* directly. Increment ulCriticalNesting to keep a count of how many */ \
|
||||
/* times portENTER_CRITICAL() has been called. */ \
|
||||
usCriticalNesting++; \
|
||||
}
|
||||
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
/* Decrement the nesting count as we are leaving a critical section. */ \
|
||||
usCriticalNesting--; \
|
||||
\
|
||||
/* If the nesting level has reached zero then interrupts should be */ \
|
||||
/* re-enabled. */ \
|
||||
if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/*
|
||||
* Manual context switch called by portYIELD or taskYIELD.
|
||||
*/
|
||||
extern void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 2
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portNOP() __no_operation()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
extern void vTaskSwitchContext( void );
|
||||
#define portYIELD_FROM_ISR( x ) do { if( x ) vPortYield(); } while( 0 )
|
||||
|
||||
void vApplicationSetupTimerInterrupt( void );
|
||||
|
||||
/* sizeof( int ) != sizeof( long ) so a full printf() library is required if
|
||||
run time stats information is to be displayed. */
|
||||
#define portLU_PRINTF_SPECIFIER_REQUIRED
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,184 +1,183 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
#define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 )
|
||||
|
||||
/* Supervisor mode set. */
|
||||
#define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000)
|
||||
|
||||
/* The clock prescale into the timer peripheral. */
|
||||
#define portPRESCALE_VALUE ( ( uint8_t ) 10 )
|
||||
|
||||
/* The clock frequency into the RTC. */
|
||||
#define portRTC_CLOCK_HZ ( ( uint32_t ) 1000 )
|
||||
|
||||
asm void interrupt VectorNumber_VL1swi vPortYieldISR( void );
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This
|
||||
will be set to 0 prior to the first task being started. */
|
||||
static uint32_t ulCriticalNesting = 0x9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
|
||||
uint32_t ulOriginalA5;
|
||||
|
||||
__asm{ MOVE.L A5, ulOriginalA5 };
|
||||
|
||||
|
||||
*pxTopOfStack = (StackType_t) 0xDEADBEEF;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Exception stack frame starts with the return address. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( portINITIAL_FORMAT_VECTOR << 16UL ) | ( portINITIAL_STATUS_REGISTER );
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x0; /*FP*/
|
||||
pxTopOfStack -= 14; /* A5 to D0. */
|
||||
|
||||
/* Parameter in A0. */
|
||||
*( pxTopOfStack + 8 ) = ( StackType_t ) pvParameters;
|
||||
|
||||
/* A5 must be maintained as it is resurved by the compiler. */
|
||||
*( pxTopOfStack + 13 ) = ulOriginalA5;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
ulCriticalNesting = 0UL;
|
||||
|
||||
/* Configure a timer to generate the tick interrupt. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task executing. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Prescale by 1 - ie no prescale. */
|
||||
RTCSC |= 8;
|
||||
|
||||
/* Compare match value. */
|
||||
RTCMOD = portRTC_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* Enable the RTC to generate interrupts - interrupts are already disabled
|
||||
when this code executes. */
|
||||
RTCSC_RTIE = 1;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented as there is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting == 0UL )
|
||||
{
|
||||
/* Guard against context switches being pended simultaneously with a
|
||||
critical section being entered. */
|
||||
do
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
if( INTC_FRC == 0UL )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
} while( 1 );
|
||||
}
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYieldHandler( void )
|
||||
{
|
||||
uint32_t ulSavedInterruptMask;
|
||||
|
||||
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Note this will clear all forced interrupts - this is done for speed. */
|
||||
INTC_CFRC = 0x3E;
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void interrupt VectorNumber_Vrtc vPortTickISR( void )
|
||||
{
|
||||
uint32_t ulSavedInterruptMask;
|
||||
|
||||
/* Clear the interrupt. */
|
||||
RTCSC |= RTCSC_RTIF_MASK;
|
||||
|
||||
/* Increment the RTOS tick. */
|
||||
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
taskYIELD();
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
|
||||
}
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
#define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 )
|
||||
|
||||
/* Supervisor mode set. */
|
||||
#define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000)
|
||||
|
||||
/* The clock prescale into the timer peripheral. */
|
||||
#define portPRESCALE_VALUE ( ( uint8_t ) 10 )
|
||||
|
||||
/* The clock frequency into the RTC. */
|
||||
#define portRTC_CLOCK_HZ ( ( uint32_t ) 1000 )
|
||||
|
||||
asm void interrupt VectorNumber_VL1swi vPortYieldISR( void );
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This
|
||||
will be set to 0 prior to the first task being started. */
|
||||
static uint32_t ulCriticalNesting = 0x9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
|
||||
uint32_t ulOriginalA5;
|
||||
|
||||
__asm{ MOVE.L A5, ulOriginalA5 };
|
||||
|
||||
|
||||
*pxTopOfStack = (StackType_t) 0xDEADBEEF;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Exception stack frame starts with the return address. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( portINITIAL_FORMAT_VECTOR << 16UL ) | ( portINITIAL_STATUS_REGISTER );
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x0; /*FP*/
|
||||
pxTopOfStack -= 14; /* A5 to D0. */
|
||||
|
||||
/* Parameter in A0. */
|
||||
*( pxTopOfStack + 8 ) = ( StackType_t ) pvParameters;
|
||||
|
||||
/* A5 must be maintained as it is resurved by the compiler. */
|
||||
*( pxTopOfStack + 13 ) = ulOriginalA5;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
ulCriticalNesting = 0UL;
|
||||
|
||||
/* Configure a timer to generate the tick interrupt. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task executing. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Prescale by 1 - ie no prescale. */
|
||||
RTCSC |= 8;
|
||||
|
||||
/* Compare match value. */
|
||||
RTCMOD = portRTC_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* Enable the RTC to generate interrupts - interrupts are already disabled
|
||||
when this code executes. */
|
||||
RTCSC_RTIE = 1;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented as there is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting == 0UL )
|
||||
{
|
||||
/* Guard against context switches being pended simultaneously with a
|
||||
critical section being entered. */
|
||||
do
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
if( INTC_FRC == 0UL )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
} while( 1 );
|
||||
}
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYieldHandler( void )
|
||||
{
|
||||
uint32_t ulSavedInterruptMask;
|
||||
|
||||
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Note this will clear all forced interrupts - this is done for speed. */
|
||||
INTC_CFRC = 0x3E;
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void interrupt VectorNumber_Vrtc vPortTickISR( void )
|
||||
{
|
||||
uint32_t ulSavedInterruptMask;
|
||||
|
||||
/* Clear the interrupt. */
|
||||
RTCSC |= RTCSC_RTIF_MASK;
|
||||
|
||||
/* Increment the RTOS tick. */
|
||||
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
taskYIELD();
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,131 +1,129 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Purpose: Lowest level routines for all ColdFire processors.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* ulPortSetIPL() and mcf5xxx_wr_cacr() copied with permission from FreeScale
|
||||
* supplied source files.
|
||||
*/
|
||||
|
||||
.global ulPortSetIPL
|
||||
.global _ulPortSetIPL
|
||||
.global mcf5xxx_wr_cacrx
|
||||
.global _mcf5xxx_wr_cacrx
|
||||
.global vPortYieldISR
|
||||
.global _vPortYieldISR
|
||||
.global vPortStartFirstTask
|
||||
.global _vPortStartFirstTask
|
||||
.extern _pxCurrentTCB
|
||||
.extern _vPortYieldHandler
|
||||
|
||||
.text
|
||||
|
||||
.macro portSAVE_CONTEXT
|
||||
|
||||
lea.l (-60, sp), sp
|
||||
movem.l d0-a6, (sp)
|
||||
move.l _pxCurrentTCB, a0
|
||||
move.l sp, (a0)
|
||||
|
||||
.endm
|
||||
|
||||
.macro portRESTORE_CONTEXT
|
||||
|
||||
move.l _pxCurrentTCB, a0
|
||||
move.l (a0), sp
|
||||
movem.l (sp), d0-a6
|
||||
lea.l (60, sp), sp
|
||||
rte
|
||||
|
||||
.endm
|
||||
|
||||
/********************************************************************/
|
||||
/*
|
||||
* This routines changes the IPL to the value passed into the routine.
|
||||
* It also returns the old IPL value back.
|
||||
* Calling convention from C:
|
||||
* old_ipl = asm_set_ipl(new_ipl);
|
||||
* For the Diab Data C compiler, it passes return value thru D0.
|
||||
* Note that only the least significant three bits of the passed
|
||||
* value are used.
|
||||
*/
|
||||
|
||||
ulPortSetIPL:
|
||||
_ulPortSetIPL:
|
||||
link A6,#-8
|
||||
movem.l D6-D7,(SP)
|
||||
|
||||
move.w SR,D7 /* current sr */
|
||||
|
||||
move.l D7,D6 /* prepare return value */
|
||||
andi.l #0x0700,D6 /* mask out IPL */
|
||||
lsr.l #8,D6 /* IPL */
|
||||
|
||||
andi.l #0x07,D0 /* least significant three bits */
|
||||
lsl.l #8,D0 /* move over to make mask */
|
||||
|
||||
andi.l #0x0000F8FF,D7 /* zero out current IPL */
|
||||
or.l D0,D7 /* place new IPL in sr */
|
||||
move.w D7,SR
|
||||
|
||||
move.l D6, D0 /* Return value in D0. */
|
||||
movem.l (SP),D6-D7
|
||||
lea 8(SP),SP
|
||||
unlk A6
|
||||
rts
|
||||
/********************************************************************/
|
||||
|
||||
mcf5xxx_wr_cacrx:
|
||||
_mcf5xxx_wr_cacrx:
|
||||
move.l 4(sp),d0
|
||||
.long 0x4e7b0002 /* movec d0,cacr */
|
||||
nop
|
||||
rts
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
/* Yield interrupt. */
|
||||
_vPortYieldISR:
|
||||
vPortYieldISR:
|
||||
portSAVE_CONTEXT
|
||||
jsr _vPortYieldHandler
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
vPortStartFirstTask:
|
||||
_vPortStartFirstTask:
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
.end
|
||||
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Purpose: Lowest level routines for all ColdFire processors.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* ulPortSetIPL() and mcf5xxx_wr_cacr() copied with permission from FreeScale
|
||||
* supplied source files.
|
||||
*/
|
||||
|
||||
.global ulPortSetIPL
|
||||
.global _ulPortSetIPL
|
||||
.global mcf5xxx_wr_cacrx
|
||||
.global _mcf5xxx_wr_cacrx
|
||||
.global vPortYieldISR
|
||||
.global _vPortYieldISR
|
||||
.global vPortStartFirstTask
|
||||
.global _vPortStartFirstTask
|
||||
.extern _pxCurrentTCB
|
||||
.extern _vPortYieldHandler
|
||||
|
||||
.text
|
||||
|
||||
.macro portSAVE_CONTEXT
|
||||
|
||||
lea.l (-60, sp), sp
|
||||
movem.l d0-a6, (sp)
|
||||
move.l _pxCurrentTCB, a0
|
||||
move.l sp, (a0)
|
||||
|
||||
.endm
|
||||
|
||||
.macro portRESTORE_CONTEXT
|
||||
|
||||
move.l _pxCurrentTCB, a0
|
||||
move.l (a0), sp
|
||||
movem.l (sp), d0-a6
|
||||
lea.l (60, sp), sp
|
||||
rte
|
||||
|
||||
.endm
|
||||
|
||||
/********************************************************************/
|
||||
/*
|
||||
* This routines changes the IPL to the value passed into the routine.
|
||||
* It also returns the old IPL value back.
|
||||
* Calling convention from C:
|
||||
* old_ipl = asm_set_ipl(new_ipl);
|
||||
* For the Diab Data C compiler, it passes return value thru D0.
|
||||
* Note that only the least significant three bits of the passed
|
||||
* value are used.
|
||||
*/
|
||||
|
||||
ulPortSetIPL:
|
||||
_ulPortSetIPL:
|
||||
link A6,#-8
|
||||
movem.l D6-D7,(SP)
|
||||
|
||||
move.w SR,D7 /* current sr */
|
||||
|
||||
move.l D7,D6 /* prepare return value */
|
||||
andi.l #0x0700,D6 /* mask out IPL */
|
||||
lsr.l #8,D6 /* IPL */
|
||||
|
||||
andi.l #0x07,D0 /* least significant three bits */
|
||||
lsl.l #8,D0 /* move over to make mask */
|
||||
|
||||
andi.l #0x0000F8FF,D7 /* zero out current IPL */
|
||||
or.l D0,D7 /* place new IPL in sr */
|
||||
move.w D7,SR
|
||||
|
||||
move.l D6, D0 /* Return value in D0. */
|
||||
movem.l (SP),D6-D7
|
||||
lea 8(SP),SP
|
||||
unlk A6
|
||||
rts
|
||||
/********************************************************************/
|
||||
|
||||
mcf5xxx_wr_cacrx:
|
||||
_mcf5xxx_wr_cacrx:
|
||||
move.l 4(sp),d0
|
||||
.long 0x4e7b0002 /* movec d0,cacr */
|
||||
nop
|
||||
rts
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
/* Yield interrupt. */
|
||||
_vPortYieldISR:
|
||||
vPortYieldISR:
|
||||
portSAVE_CONTEXT
|
||||
jsr _vPortYieldHandler
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
vPortStartFirstTask:
|
||||
_vPortStartFirstTask:
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
.end
|
||||
|
|
|
|||
|
|
@ -1,113 +1,112 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH -1
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulPortSetIPL( uint32_t );
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define portENABLE_INTERRUPTS() ulPortSetIPL( 0 )
|
||||
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
extern UBaseType_t uxPortSetInterruptMaskFromISR( void );
|
||||
extern void vPortClearInterruptMaskFromISR( UBaseType_t );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
#define portNOP() asm volatile ( "nop" )
|
||||
|
||||
/* Context switches are requested using the force register. */
|
||||
#define portYIELD() INTC_SFRC = 0x3E; portNOP(); portNOP(); portNOP(); portNOP(); portNOP()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn))
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) { portYIELD(); } } while( 0 )
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH -1
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulPortSetIPL( uint32_t );
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define portENABLE_INTERRUPTS() ulPortSetIPL( 0 )
|
||||
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
extern UBaseType_t uxPortSetInterruptMaskFromISR( void );
|
||||
extern void vPortClearInterruptMaskFromISR( UBaseType_t );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
#define portNOP() asm volatile ( "nop" )
|
||||
|
||||
/* Context switches are requested using the force register. */
|
||||
#define portYIELD() INTC_SFRC = 0x3E; portNOP(); portNOP(); portNOP(); portNOP(); portNOP()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn))
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) { portYIELD(); } } while( 0 )
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,148 +1,147 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
#define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 )
|
||||
|
||||
/* Supervisor mode set. */
|
||||
#define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000)
|
||||
|
||||
/* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This
|
||||
will be set to 0 prior to the first task being started. */
|
||||
static uint32_t ulCriticalNesting = 0x9999UL;
|
||||
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
lea.l (-60, %sp), %sp; \
|
||||
movem.l %d0-%fp, (%sp); \
|
||||
move.l pxCurrentTCB, %a0; \
|
||||
move.l %sp, (%a0);
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
move.l pxCurrentTCB, %a0; \
|
||||
move.l (%a0), %sp; \
|
||||
movem.l (%sp), %d0-%fp; \
|
||||
lea.l %sp@(60), %sp; \
|
||||
rte
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = (StackType_t) 0xDEADBEEF;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Exception stack frame starts with the return address. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( portINITIAL_FORMAT_VECTOR << 16UL ) | ( portINITIAL_STATUS_REGISTER );
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x0; /*FP*/
|
||||
pxTopOfStack -= 14; /* A5 to D0. */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
ulCriticalNesting = 0UL;
|
||||
|
||||
/* Configure the interrupts used by this port. */
|
||||
vApplicationSetupInterrupts();
|
||||
|
||||
/* Start the first task executing. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented as there is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting == 0UL )
|
||||
{
|
||||
/* Guard against context switches being pended simultaneously with a
|
||||
critical section being entered. */
|
||||
do
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
if( MCF_INTC0_INTFRCH == 0UL )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
} while( 1 );
|
||||
}
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYieldHandler( void )
|
||||
{
|
||||
uint32_t ulSavedInterruptMask;
|
||||
|
||||
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
/* Note this will clear all forced interrupts - this is done for speed. */
|
||||
MCF_INTC0_INTFRCL = 0;
|
||||
vTaskSwitchContext();
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
#define portINITIAL_FORMAT_VECTOR ( ( StackType_t ) 0x4000 )
|
||||
|
||||
/* Supervisor mode set. */
|
||||
#define portINITIAL_STATUS_REGISTER ( ( StackType_t ) 0x2000)
|
||||
|
||||
/* Used to keep track of the number of nested calls to taskENTER_CRITICAL(). This
|
||||
will be set to 0 prior to the first task being started. */
|
||||
static uint32_t ulCriticalNesting = 0x9999UL;
|
||||
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
lea.l (-60, %sp), %sp; \
|
||||
movem.l %d0-%fp, (%sp); \
|
||||
move.l pxCurrentTCB, %a0; \
|
||||
move.l %sp, (%a0);
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
move.l pxCurrentTCB, %a0; \
|
||||
move.l (%a0), %sp; \
|
||||
movem.l (%sp), %d0-%fp; \
|
||||
lea.l %sp@(60), %sp; \
|
||||
rte
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
StackType_t *pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = (StackType_t) 0xDEADBEEF;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Exception stack frame starts with the return address. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( portINITIAL_FORMAT_VECTOR << 16UL ) | ( portINITIAL_STATUS_REGISTER );
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x0; /*FP*/
|
||||
pxTopOfStack -= 14; /* A5 to D0. */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
ulCriticalNesting = 0UL;
|
||||
|
||||
/* Configure the interrupts used by this port. */
|
||||
vApplicationSetupInterrupts();
|
||||
|
||||
/* Start the first task executing. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented as there is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting == 0UL )
|
||||
{
|
||||
/* Guard against context switches being pended simultaneously with a
|
||||
critical section being entered. */
|
||||
do
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
if( MCF_INTC0_INTFRCH == 0UL )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
} while( 1 );
|
||||
}
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYieldHandler( void )
|
||||
{
|
||||
uint32_t ulSavedInterruptMask;
|
||||
|
||||
ulSavedInterruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
/* Note this will clear all forced interrupts - this is done for speed. */
|
||||
MCF_INTC0_INTFRCL = 0;
|
||||
vTaskSwitchContext();
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulSavedInterruptMask );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,131 +1,129 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Purpose: Lowest level routines for all ColdFire processors.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* ulPortSetIPL() and mcf5xxx_wr_cacr() copied with permission from FreeScale
|
||||
* supplied source files.
|
||||
*/
|
||||
|
||||
.global ulPortSetIPL
|
||||
.global _ulPortSetIPL
|
||||
.global mcf5xxx_wr_cacrx
|
||||
.global _mcf5xxx_wr_cacrx
|
||||
.global vPortYieldISR
|
||||
.global _vPortYieldISR
|
||||
.global vPortStartFirstTask
|
||||
.global _vPortStartFirstTask
|
||||
.extern _pxCurrentTCB
|
||||
.extern _vPortYieldHandler
|
||||
|
||||
.text
|
||||
|
||||
.macro portSAVE_CONTEXT
|
||||
|
||||
lea.l (-60, sp), sp
|
||||
movem.l d0-a6, (sp)
|
||||
move.l _pxCurrentTCB, a0
|
||||
move.l sp, (a0)
|
||||
|
||||
.endm
|
||||
|
||||
.macro portRESTORE_CONTEXT
|
||||
|
||||
move.l _pxCurrentTCB, a0
|
||||
move.l (a0), sp
|
||||
movem.l (sp), d0-a6
|
||||
lea.l (60, sp), sp
|
||||
rte
|
||||
|
||||
.endm
|
||||
|
||||
/********************************************************************/
|
||||
/*
|
||||
* This routines changes the IPL to the value passed into the routine.
|
||||
* It also returns the old IPL value back.
|
||||
* Calling convention from C:
|
||||
* old_ipl = asm_set_ipl(new_ipl);
|
||||
* For the Diab Data C compiler, it passes return value thru D0.
|
||||
* Note that only the least significant three bits of the passed
|
||||
* value are used.
|
||||
*/
|
||||
|
||||
ulPortSetIPL:
|
||||
_ulPortSetIPL:
|
||||
link A6,#-8
|
||||
movem.l D6-D7,(SP)
|
||||
|
||||
move.w SR,D7 /* current sr */
|
||||
|
||||
move.l D7,D0 /* prepare return value */
|
||||
andi.l #0x0700,D0 /* mask out IPL */
|
||||
lsr.l #8,D0 /* IPL */
|
||||
|
||||
move.l 8(A6),D6 /* get argument */
|
||||
andi.l #0x07,D6 /* least significant three bits */
|
||||
lsl.l #8,D6 /* move over to make mask */
|
||||
|
||||
andi.l #0x0000F8FF,D7 /* zero out current IPL */
|
||||
or.l D6,D7 /* place new IPL in sr */
|
||||
move.w D7,SR
|
||||
|
||||
movem.l (SP),D6-D7
|
||||
lea 8(SP),SP
|
||||
unlk A6
|
||||
rts
|
||||
/********************************************************************/
|
||||
|
||||
mcf5xxx_wr_cacrx:
|
||||
_mcf5xxx_wr_cacrx:
|
||||
move.l 4(sp),d0
|
||||
.long 0x4e7b0002 /* movec d0,cacr */
|
||||
nop
|
||||
rts
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
/* Yield interrupt. */
|
||||
_vPortYieldISR:
|
||||
vPortYieldISR:
|
||||
portSAVE_CONTEXT
|
||||
jsr _vPortYieldHandler
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
vPortStartFirstTask:
|
||||
_vPortStartFirstTask:
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
.end
|
||||
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Purpose: Lowest level routines for all ColdFire processors.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* ulPortSetIPL() and mcf5xxx_wr_cacr() copied with permission from FreeScale
|
||||
* supplied source files.
|
||||
*/
|
||||
|
||||
.global ulPortSetIPL
|
||||
.global _ulPortSetIPL
|
||||
.global mcf5xxx_wr_cacrx
|
||||
.global _mcf5xxx_wr_cacrx
|
||||
.global vPortYieldISR
|
||||
.global _vPortYieldISR
|
||||
.global vPortStartFirstTask
|
||||
.global _vPortStartFirstTask
|
||||
.extern _pxCurrentTCB
|
||||
.extern _vPortYieldHandler
|
||||
|
||||
.text
|
||||
|
||||
.macro portSAVE_CONTEXT
|
||||
|
||||
lea.l (-60, sp), sp
|
||||
movem.l d0-a6, (sp)
|
||||
move.l _pxCurrentTCB, a0
|
||||
move.l sp, (a0)
|
||||
|
||||
.endm
|
||||
|
||||
.macro portRESTORE_CONTEXT
|
||||
|
||||
move.l _pxCurrentTCB, a0
|
||||
move.l (a0), sp
|
||||
movem.l (sp), d0-a6
|
||||
lea.l (60, sp), sp
|
||||
rte
|
||||
|
||||
.endm
|
||||
|
||||
/********************************************************************/
|
||||
/*
|
||||
* This routines changes the IPL to the value passed into the routine.
|
||||
* It also returns the old IPL value back.
|
||||
* Calling convention from C:
|
||||
* old_ipl = asm_set_ipl(new_ipl);
|
||||
* For the Diab Data C compiler, it passes return value thru D0.
|
||||
* Note that only the least significant three bits of the passed
|
||||
* value are used.
|
||||
*/
|
||||
|
||||
ulPortSetIPL:
|
||||
_ulPortSetIPL:
|
||||
link A6,#-8
|
||||
movem.l D6-D7,(SP)
|
||||
|
||||
move.w SR,D7 /* current sr */
|
||||
|
||||
move.l D7,D0 /* prepare return value */
|
||||
andi.l #0x0700,D0 /* mask out IPL */
|
||||
lsr.l #8,D0 /* IPL */
|
||||
|
||||
move.l 8(A6),D6 /* get argument */
|
||||
andi.l #0x07,D6 /* least significant three bits */
|
||||
lsl.l #8,D6 /* move over to make mask */
|
||||
|
||||
andi.l #0x0000F8FF,D7 /* zero out current IPL */
|
||||
or.l D6,D7 /* place new IPL in sr */
|
||||
move.w D7,SR
|
||||
|
||||
movem.l (SP),D6-D7
|
||||
lea 8(SP),SP
|
||||
unlk A6
|
||||
rts
|
||||
/********************************************************************/
|
||||
|
||||
mcf5xxx_wr_cacrx:
|
||||
_mcf5xxx_wr_cacrx:
|
||||
move.l 4(sp),d0
|
||||
.long 0x4e7b0002 /* movec d0,cacr */
|
||||
nop
|
||||
rts
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
/* Yield interrupt. */
|
||||
_vPortYieldISR:
|
||||
vPortYieldISR:
|
||||
portSAVE_CONTEXT
|
||||
jsr _vPortYieldHandler
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
/********************************************************************/
|
||||
|
||||
|
||||
vPortStartFirstTask:
|
||||
_vPortStartFirstTask:
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
.end
|
||||
|
|
|
|||
|
|
@ -1,112 +1,111 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH -1
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
/*-----------------------------------------------------------*/
|
||||
uint32_t ulPortSetIPL( uint32_t );
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define portENABLE_INTERRUPTS() ulPortSetIPL( 0 )
|
||||
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
extern UBaseType_t uxPortSetInterruptMaskFromISR( void );
|
||||
extern void vPortClearInterruptMaskFromISR( UBaseType_t );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
#define portNOP() asm volatile ( "nop" )
|
||||
|
||||
/* Note this will overwrite all other bits in the force register, it is done this way for speed. */
|
||||
#define portYIELD() MCF_INTC0_INTFRCL = ( 1UL << configYIELD_INTERRUPT_VECTOR ); portNOP(); portNOP() /* -32 as we are using the high word of the 64bit mask. */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn))
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) { portYIELD(); } } while( 0 )
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portSTACK_GROWTH -1
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
/*-----------------------------------------------------------*/
|
||||
uint32_t ulPortSetIPL( uint32_t );
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define portENABLE_INTERRUPTS() ulPortSetIPL( 0 )
|
||||
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
extern UBaseType_t uxPortSetInterruptMaskFromISR( void );
|
||||
extern void vPortClearInterruptMaskFromISR( UBaseType_t );
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetIPL( configMAX_SYSCALL_INTERRUPT_PRIORITY )
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) ulPortSetIPL( uxSavedStatusRegister )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
#define portNOP() asm volatile ( "nop" )
|
||||
|
||||
/* Note this will overwrite all other bits in the force register, it is done this way for speed. */
|
||||
#define portYIELD() MCF_INTC0_INTFRCL = ( 1UL << configYIELD_INTERRUPT_VECTOR ); portNOP(); portNOP() /* -32 as we are using the high word of the 64bit mask. */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn))
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) { portYIELD(); } } while( 0 )
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,238 +1,236 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the HCS12 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Configure a timer to generate the RTOS tick at the frequency specified
|
||||
* within FreeRTOSConfig.h.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/* Interrupt service routines have to be in non-banked memory - as does the
|
||||
scheduler startup function. */
|
||||
#pragma CODE_SEG __NEAR_SEG NON_BANKED
|
||||
|
||||
/* Manual context switch function. This is the SWI ISR. */
|
||||
void interrupt vPortYield( void );
|
||||
|
||||
/* Tick context switch function. This is the timer ISR. */
|
||||
void interrupt vPortTickInterrupt( void );
|
||||
|
||||
/* Simply called by xPortStartScheduler(). xPortStartScheduler() does not
|
||||
start the scheduler directly because the header file containing the
|
||||
xPortStartScheduler() prototype is part of the common kernel code, and
|
||||
therefore cannot use the CODE_SEG pragma. */
|
||||
static BaseType_t xBankedStartScheduler( void );
|
||||
|
||||
#pragma CODE_SEG DEFAULT
|
||||
|
||||
/* Calls to portENTER_CRITICAL() can be nested. When they are nested the
|
||||
critical section should not be left (i.e. interrupts should not be re-enabled)
|
||||
until the nesting depth reaches 0. This variable simply tracks the nesting
|
||||
depth. Each task maintains it's own critical nesting depth variable so
|
||||
uxCriticalNesting is saved and restored from the task stack during a context
|
||||
switch. */
|
||||
volatile UBaseType_t uxCriticalNesting = 0xff;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/*
|
||||
Place a few bytes of known values on the bottom of the stack.
|
||||
This can be uncommented to provide useful stack markers when debugging.
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x11;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x22;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x33;
|
||||
pxTopOfStack--;
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. In this case the stack as
|
||||
expected by the HCS12 RTI instruction. */
|
||||
|
||||
|
||||
/* The address of the task function is placed in the stack byte at a time. */
|
||||
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 1 );
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 0 );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next are all the registers that form part of the task context. */
|
||||
|
||||
/* Y register */
|
||||
*pxTopOfStack = ( StackType_t ) 0xff;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xee;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* X register */
|
||||
*pxTopOfStack = ( StackType_t ) 0xdd;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xcc;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* A register contains parameter high byte. */
|
||||
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 0 );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* B register contains parameter low byte. */
|
||||
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 1 );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* CCR: Note that when the task starts interrupts will be enabled since
|
||||
"I" bit of CCR is cleared */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00;
|
||||
pxTopOfStack--;
|
||||
|
||||
#ifdef BANKED_MODEL
|
||||
/* The page of the task. */
|
||||
*pxTopOfStack = ( StackType_t ) ( ( int ) pxCode );
|
||||
pxTopOfStack--;
|
||||
#endif
|
||||
|
||||
/* Finally the critical nesting depth is initialised with 0 (not within
|
||||
a critical section). */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the HCS12 port will get stopped. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
TickTimer_SetFreqHz( configTICK_RATE_HZ );
|
||||
TickTimer_Enable();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* xPortStartScheduler() does not start the scheduler directly because
|
||||
the header file containing the xPortStartScheduler() prototype is part
|
||||
of the common kernel code, and therefore cannot use the CODE_SEG pragma.
|
||||
Instead it simply calls the locally defined xBankedStartScheduler() -
|
||||
which does use the CODE_SEG pragma. */
|
||||
|
||||
return xBankedStartScheduler();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#pragma CODE_SEG __NEAR_SEG NON_BANKED
|
||||
|
||||
static BaseType_t xBankedStartScheduler( void )
|
||||
{
|
||||
/* Configure the timer that will generate the RTOS tick. Interrupts are
|
||||
disabled when this function is called. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Restore the context of the first task. */
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
/* Simulate the end of an interrupt to start the scheduler off. */
|
||||
__asm( "rti" );
|
||||
|
||||
/* Should not get here! */
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Context switch functions. These are both interrupt service routines.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Manual context switch forced by calling portYIELD(). This is the SWI
|
||||
* handler.
|
||||
*/
|
||||
void interrupt vPortYield( void )
|
||||
{
|
||||
portSAVE_CONTEXT();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* RTOS tick interrupt service routine. If the cooperative scheduler is
|
||||
* being used then this simply increments the tick count. If the
|
||||
* preemptive scheduler is being used a context switch can occur.
|
||||
*/
|
||||
void interrupt vPortTickInterrupt( void )
|
||||
{
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
/* A context switch might happen so save the context. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the tick ... */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
TFLG1 = 1;
|
||||
|
||||
/* Restore the context of a task - which may be a different task
|
||||
to that interrupted. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
#else
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
TFLG1 = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma CODE_SEG DEFAULT
|
||||
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the HCS12 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Configure a timer to generate the RTOS tick at the frequency specified
|
||||
* within FreeRTOSConfig.h.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/* Interrupt service routines have to be in non-banked memory - as does the
|
||||
scheduler startup function. */
|
||||
#pragma CODE_SEG __NEAR_SEG NON_BANKED
|
||||
|
||||
/* Manual context switch function. This is the SWI ISR. */
|
||||
void interrupt vPortYield( void );
|
||||
|
||||
/* Tick context switch function. This is the timer ISR. */
|
||||
void interrupt vPortTickInterrupt( void );
|
||||
|
||||
/* Simply called by xPortStartScheduler(). xPortStartScheduler() does not
|
||||
start the scheduler directly because the header file containing the
|
||||
xPortStartScheduler() prototype is part of the common kernel code, and
|
||||
therefore cannot use the CODE_SEG pragma. */
|
||||
static BaseType_t xBankedStartScheduler( void );
|
||||
|
||||
#pragma CODE_SEG DEFAULT
|
||||
|
||||
/* Calls to portENTER_CRITICAL() can be nested. When they are nested the
|
||||
critical section should not be left (i.e. interrupts should not be re-enabled)
|
||||
until the nesting depth reaches 0. This variable simply tracks the nesting
|
||||
depth. Each task maintains it's own critical nesting depth variable so
|
||||
uxCriticalNesting is saved and restored from the task stack during a context
|
||||
switch. */
|
||||
volatile UBaseType_t uxCriticalNesting = 0xff;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/*
|
||||
Place a few bytes of known values on the bottom of the stack.
|
||||
This can be uncommented to provide useful stack markers when debugging.
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x11;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x22;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x33;
|
||||
pxTopOfStack--;
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. In this case the stack as
|
||||
expected by the HCS12 RTI instruction. */
|
||||
|
||||
|
||||
/* The address of the task function is placed in the stack byte at a time. */
|
||||
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 1 );
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pxCode) ) + 0 );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next are all the registers that form part of the task context. */
|
||||
|
||||
/* Y register */
|
||||
*pxTopOfStack = ( StackType_t ) 0xff;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xee;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* X register */
|
||||
*pxTopOfStack = ( StackType_t ) 0xdd;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xcc;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* A register contains parameter high byte. */
|
||||
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 0 );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* B register contains parameter low byte. */
|
||||
*pxTopOfStack = ( StackType_t ) *( ((StackType_t *) (&pvParameters) ) + 1 );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* CCR: Note that when the task starts interrupts will be enabled since
|
||||
"I" bit of CCR is cleared */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00;
|
||||
pxTopOfStack--;
|
||||
|
||||
#ifdef BANKED_MODEL
|
||||
/* The page of the task. */
|
||||
*pxTopOfStack = ( StackType_t ) ( ( int ) pxCode );
|
||||
pxTopOfStack--;
|
||||
#endif
|
||||
|
||||
/* Finally the critical nesting depth is initialised with 0 (not within
|
||||
a critical section). */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the HCS12 port will get stopped. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
TickTimer_SetFreqHz( configTICK_RATE_HZ );
|
||||
TickTimer_Enable();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* xPortStartScheduler() does not start the scheduler directly because
|
||||
the header file containing the xPortStartScheduler() prototype is part
|
||||
of the common kernel code, and therefore cannot use the CODE_SEG pragma.
|
||||
Instead it simply calls the locally defined xBankedStartScheduler() -
|
||||
which does use the CODE_SEG pragma. */
|
||||
|
||||
return xBankedStartScheduler();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#pragma CODE_SEG __NEAR_SEG NON_BANKED
|
||||
|
||||
static BaseType_t xBankedStartScheduler( void )
|
||||
{
|
||||
/* Configure the timer that will generate the RTOS tick. Interrupts are
|
||||
disabled when this function is called. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Restore the context of the first task. */
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
/* Simulate the end of an interrupt to start the scheduler off. */
|
||||
__asm( "rti" );
|
||||
|
||||
/* Should not get here! */
|
||||
return pdFALSE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Context switch functions. These are both interrupt service routines.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Manual context switch forced by calling portYIELD(). This is the SWI
|
||||
* handler.
|
||||
*/
|
||||
void interrupt vPortYield( void )
|
||||
{
|
||||
portSAVE_CONTEXT();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* RTOS tick interrupt service routine. If the cooperative scheduler is
|
||||
* being used then this simply increments the tick count. If the
|
||||
* preemptive scheduler is being used a context switch can occur.
|
||||
*/
|
||||
void interrupt vPortTickInterrupt( void )
|
||||
{
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
/* A context switch might happen so save the context. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the tick ... */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
TFLG1 = 1;
|
||||
|
||||
/* Restore the context of a task - which may be a different task
|
||||
to that interrupted. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
#else
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
TFLG1 = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma CODE_SEG DEFAULT
|
||||
|
|
|
|||
|
|
@ -1,203 +1,202 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint8_t
|
||||
#define portBASE_TYPE char
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef signed char BaseType_t;
|
||||
typedef unsigned char UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 1
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portYIELD() __asm( "swi" );
|
||||
#define portNOP() __asm( "nop" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section handling. */
|
||||
#define portENABLE_INTERRUPTS() __asm( "cli" )
|
||||
#define portDISABLE_INTERRUPTS() __asm( "sei" )
|
||||
|
||||
/*
|
||||
* Disable interrupts before incrementing the count of critical section nesting.
|
||||
* The nesting count is maintained so we know when interrupts should be
|
||||
* re-enabled. Once interrupts are disabled the nesting count can be accessed
|
||||
* directly. Each task maintains its own nesting count.
|
||||
*/
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
uxCriticalNesting++; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupts are disabled so we can access the nesting count directly. If the
|
||||
* nesting is found to be 0 (no nesting) then we are leaving the critical
|
||||
* section and interrupts can be re-enabled.
|
||||
*/
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
uxCriticalNesting--; \
|
||||
if( uxCriticalNesting == 0 ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/*
|
||||
* These macros are very simple as the processor automatically saves and
|
||||
* restores its registers as interrupts are entered and exited. In
|
||||
* addition to the (automatically stacked) registers we also stack the
|
||||
* critical nesting count. Each task maintains its own critical nesting
|
||||
* count as it is legitimate for a task to yield from within a critical
|
||||
* section. If the banked memory model is being used then the PPAGE
|
||||
* register is also stored as part of the tasks context.
|
||||
*/
|
||||
|
||||
#ifdef BANKED_MODEL
|
||||
/*
|
||||
* Load the stack pointer for the task, then pull the critical nesting
|
||||
* count and PPAGE register from the stack. The remains of the
|
||||
* context are restored by the RTI instruction.
|
||||
*/
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * pxCurrentTCB; \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
__asm( "ldx pxCurrentTCB" ); \
|
||||
__asm( "lds 0, x" ); \
|
||||
__asm( "pula" ); \
|
||||
__asm( "staa uxCriticalNesting" ); \
|
||||
__asm( "pula" ); \
|
||||
__asm( "staa 0x30" ); /* 0x30 = PPAGE */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* By the time this macro is called the processor has already stacked the
|
||||
* registers. Simply stack the nesting count and PPAGE value, then save
|
||||
* the task stack pointer.
|
||||
*/
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * pxCurrentTCB; \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
__asm( "ldaa 0x30" ); /* 0x30 = PPAGE */ \
|
||||
__asm( "psha" ); \
|
||||
__asm( "ldaa uxCriticalNesting" ); \
|
||||
__asm( "psha" ); \
|
||||
__asm( "ldx pxCurrentTCB" ); \
|
||||
__asm( "sts 0, x" ); \
|
||||
}
|
||||
#else
|
||||
|
||||
/*
|
||||
* These macros are as per the BANKED versions above, but without saving
|
||||
* and restoring the PPAGE register.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * pxCurrentTCB; \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
__asm( "ldx pxCurrentTCB" ); \
|
||||
__asm( "lds 0, x" ); \
|
||||
__asm( "pula" ); \
|
||||
__asm( "staa uxCriticalNesting" ); \
|
||||
}
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * pxCurrentTCB; \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
__asm( "ldaa uxCriticalNesting" ); \
|
||||
__asm( "psha" ); \
|
||||
__asm( "ldx pxCurrentTCB" ); \
|
||||
__asm( "sts 0, x" ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Utility macro to call macros above in correct order in order to perform a
|
||||
* task switch from within a standard ISR. This macro can only be used if
|
||||
* the ISR does not use any local (stack) variables. If the ISR uses stack
|
||||
* variables portYIELD() should be used in it's place.
|
||||
*/
|
||||
#define portTASK_SWITCH_FROM_ISR() \
|
||||
portSAVE_CONTEXT(); \
|
||||
vTaskSwitchContext(); \
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint8_t
|
||||
#define portBASE_TYPE char
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef signed char BaseType_t;
|
||||
typedef unsigned char UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 1
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portYIELD() __asm( "swi" );
|
||||
#define portNOP() __asm( "nop" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section handling. */
|
||||
#define portENABLE_INTERRUPTS() __asm( "cli" )
|
||||
#define portDISABLE_INTERRUPTS() __asm( "sei" )
|
||||
|
||||
/*
|
||||
* Disable interrupts before incrementing the count of critical section nesting.
|
||||
* The nesting count is maintained so we know when interrupts should be
|
||||
* re-enabled. Once interrupts are disabled the nesting count can be accessed
|
||||
* directly. Each task maintains its own nesting count.
|
||||
*/
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
uxCriticalNesting++; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupts are disabled so we can access the nesting count directly. If the
|
||||
* nesting is found to be 0 (no nesting) then we are leaving the critical
|
||||
* section and interrupts can be re-enabled.
|
||||
*/
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
uxCriticalNesting--; \
|
||||
if( uxCriticalNesting == 0 ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/*
|
||||
* These macros are very simple as the processor automatically saves and
|
||||
* restores its registers as interrupts are entered and exited. In
|
||||
* addition to the (automatically stacked) registers we also stack the
|
||||
* critical nesting count. Each task maintains its own critical nesting
|
||||
* count as it is legitimate for a task to yield from within a critical
|
||||
* section. If the banked memory model is being used then the PPAGE
|
||||
* register is also stored as part of the tasks context.
|
||||
*/
|
||||
|
||||
#ifdef BANKED_MODEL
|
||||
/*
|
||||
* Load the stack pointer for the task, then pull the critical nesting
|
||||
* count and PPAGE register from the stack. The remains of the
|
||||
* context are restored by the RTI instruction.
|
||||
*/
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * pxCurrentTCB; \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
__asm( "ldx pxCurrentTCB" ); \
|
||||
__asm( "lds 0, x" ); \
|
||||
__asm( "pula" ); \
|
||||
__asm( "staa uxCriticalNesting" ); \
|
||||
__asm( "pula" ); \
|
||||
__asm( "staa 0x30" ); /* 0x30 = PPAGE */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* By the time this macro is called the processor has already stacked the
|
||||
* registers. Simply stack the nesting count and PPAGE value, then save
|
||||
* the task stack pointer.
|
||||
*/
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * pxCurrentTCB; \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
__asm( "ldaa 0x30" ); /* 0x30 = PPAGE */ \
|
||||
__asm( "psha" ); \
|
||||
__asm( "ldaa uxCriticalNesting" ); \
|
||||
__asm( "psha" ); \
|
||||
__asm( "ldx pxCurrentTCB" ); \
|
||||
__asm( "sts 0, x" ); \
|
||||
}
|
||||
#else
|
||||
|
||||
/*
|
||||
* These macros are as per the BANKED versions above, but without saving
|
||||
* and restoring the PPAGE register.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * pxCurrentTCB; \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
__asm( "ldx pxCurrentTCB" ); \
|
||||
__asm( "lds 0, x" ); \
|
||||
__asm( "pula" ); \
|
||||
__asm( "staa uxCriticalNesting" ); \
|
||||
}
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * pxCurrentTCB; \
|
||||
extern volatile UBaseType_t uxCriticalNesting; \
|
||||
\
|
||||
__asm( "ldaa uxCriticalNesting" ); \
|
||||
__asm( "psha" ); \
|
||||
__asm( "ldx pxCurrentTCB" ); \
|
||||
__asm( "sts 0, x" ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Utility macro to call macros above in correct order in order to perform a
|
||||
* task switch from within a standard ISR. This macro can only be used if
|
||||
* the ISR does not use any local (stack) variables. If the ISR uses stack
|
||||
* variables portYIELD() should be used in it's place.
|
||||
*/
|
||||
#define portTASK_SWITCH_FROM_ISR() \
|
||||
portSAVE_CONTEXT(); \
|
||||
vTaskSwitchContext(); \
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,239 +1,238 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the Atmel AT91R40008
|
||||
* port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Hardware specific definitions. */
|
||||
#include "AT91R40008.h"
|
||||
#include "pio.h"
|
||||
#include "aic.h"
|
||||
#include "tc.h"
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
#define portTICK_PRIORITY_6 ( 6 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
*/
|
||||
extern void vPortISRStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
start of the task. The offset is added to make the return address appear
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
means the interrupt flags cannot always be stored on the stack and will
|
||||
instead be stored in a variable, which is then saved as part of the
|
||||
tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the tick timer to generate the tick interrupts at the required frequency.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
volatile uint32_t ulDummy;
|
||||
|
||||
/* Enable clock to the tick timer... */
|
||||
AT91C_BASE_PS->PS_PCER = portTIMER_CLK_ENABLE_BIT;
|
||||
|
||||
/* Stop the tick timer... */
|
||||
portTIMER_REG_BASE_PTR->TC_CCR = TC_CLKDIS;
|
||||
|
||||
/* Start with tick timer interrupts disabled... */
|
||||
portTIMER_REG_BASE_PTR->TC_IDR = 0xFFFFFFFF;
|
||||
|
||||
/* Clear any pending tick timer interrupts... */
|
||||
ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
|
||||
|
||||
/* Store interrupt handler function address in tick timer vector register...
|
||||
The ISR installed depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
extern void ( vPreemptiveTick )( void );
|
||||
AT91C_BASE_AIC->AIC_SVR[portTIMER_AIC_CHANNEL] = ( uint32_t ) vPreemptiveTick;
|
||||
}
|
||||
#else // else use cooperative scheduler
|
||||
{
|
||||
extern void ( vNonPreemptiveTick )( void );
|
||||
AT91C_BASE_AIC->AIC_SVR[portTIMER_AIC_CHANNEL] = ( uint32_t ) vNonPreemptiveTick;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Tick timer interrupt level-sensitive, priority 6... */
|
||||
AT91C_BASE_AIC->AIC_SMR[ portTIMER_AIC_CHANNEL ] = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | portTICK_PRIORITY_6;
|
||||
|
||||
/* Enable the tick timer interrupt...
|
||||
|
||||
First at timer level */
|
||||
portTIMER_REG_BASE_PTR->TC_IER = TC_CPCS;
|
||||
|
||||
/* Then at the AIC level. */
|
||||
AT91C_BASE_AIC->AIC_IECR = (1 << portTIMER_AIC_CHANNEL);
|
||||
|
||||
/* Calculate timer compare value to achieve the desired tick rate... */
|
||||
if( (configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 2) ) <= 0xFFFF )
|
||||
{
|
||||
/* The tick rate is fast enough for us to use the faster timer input
|
||||
clock (main clock / 2). */
|
||||
portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK2 | TC_BURST_NONE | TC_CPCTRG;
|
||||
portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We must use a slower timer input clock (main clock / 8) because the
|
||||
tick rate is too slow for the faster input clock. */
|
||||
portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK8 | TC_BURST_NONE | TC_CPCTRG;
|
||||
portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 8);
|
||||
}
|
||||
|
||||
/* Start tick timer... */
|
||||
portTIMER_REG_BASE_PTR->TC_CCR = TC_SWTRG | TC_CLKEN;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the Atmel AT91R40008
|
||||
* port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Hardware specific definitions. */
|
||||
#include "AT91R40008.h"
|
||||
#include "pio.h"
|
||||
#include "aic.h"
|
||||
#include "tc.h"
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
#define portTICK_PRIORITY_6 ( 6 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
*/
|
||||
extern void vPortISRStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
start of the task. The offset is added to make the return address appear
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
means the interrupt flags cannot always be stored on the stack and will
|
||||
instead be stored in a variable, which is then saved as part of the
|
||||
tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the tick timer to generate the tick interrupts at the required frequency.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
volatile uint32_t ulDummy;
|
||||
|
||||
/* Enable clock to the tick timer... */
|
||||
AT91C_BASE_PS->PS_PCER = portTIMER_CLK_ENABLE_BIT;
|
||||
|
||||
/* Stop the tick timer... */
|
||||
portTIMER_REG_BASE_PTR->TC_CCR = TC_CLKDIS;
|
||||
|
||||
/* Start with tick timer interrupts disabled... */
|
||||
portTIMER_REG_BASE_PTR->TC_IDR = 0xFFFFFFFF;
|
||||
|
||||
/* Clear any pending tick timer interrupts... */
|
||||
ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
|
||||
|
||||
/* Store interrupt handler function address in tick timer vector register...
|
||||
The ISR installed depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
extern void ( vPreemptiveTick )( void );
|
||||
AT91C_BASE_AIC->AIC_SVR[portTIMER_AIC_CHANNEL] = ( uint32_t ) vPreemptiveTick;
|
||||
}
|
||||
#else // else use cooperative scheduler
|
||||
{
|
||||
extern void ( vNonPreemptiveTick )( void );
|
||||
AT91C_BASE_AIC->AIC_SVR[portTIMER_AIC_CHANNEL] = ( uint32_t ) vNonPreemptiveTick;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Tick timer interrupt level-sensitive, priority 6... */
|
||||
AT91C_BASE_AIC->AIC_SMR[ portTIMER_AIC_CHANNEL ] = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | portTICK_PRIORITY_6;
|
||||
|
||||
/* Enable the tick timer interrupt...
|
||||
|
||||
First at timer level */
|
||||
portTIMER_REG_BASE_PTR->TC_IER = TC_CPCS;
|
||||
|
||||
/* Then at the AIC level. */
|
||||
AT91C_BASE_AIC->AIC_IECR = (1 << portTIMER_AIC_CHANNEL);
|
||||
|
||||
/* Calculate timer compare value to achieve the desired tick rate... */
|
||||
if( (configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 2) ) <= 0xFFFF )
|
||||
{
|
||||
/* The tick rate is fast enough for us to use the faster timer input
|
||||
clock (main clock / 2). */
|
||||
portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK2 | TC_BURST_NONE | TC_CPCTRG;
|
||||
portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We must use a slower timer input clock (main clock / 8) because the
|
||||
tick rate is too slow for the faster input clock. */
|
||||
portTIMER_REG_BASE_PTR->TC_CMR = TC_WAVE | TC_CLKS_MCK8 | TC_BURST_NONE | TC_CPCTRG;
|
||||
portTIMER_REG_BASE_PTR->TC_RC = configCPU_CLOCK_HZ / (configTICK_RATE_HZ * 8);
|
||||
}
|
||||
|
||||
/* Start tick timer... */
|
||||
portTIMER_REG_BASE_PTR->TC_CCR = TC_SWTRG | TC_CLKEN;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,234 +1,233 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.4
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
*/
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portCLEAR_AIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ISR to handle manual context switches (from a call to taskYIELD()). */
|
||||
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||||
* function here.
|
||||
*/
|
||||
void vPortISRStartFirstTask( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortISRStartFirstTask( void )
|
||||
{
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Called by portYIELD() or taskYIELD() to manually force a context switch.
|
||||
*
|
||||
* When a context switch is performed from the task level the saved task
|
||||
* context is made to look as if it occurred from within the tick ISR. This
|
||||
* way the same restore context function can be used when restoring the context
|
||||
* saved from the ISR or that saved from a call to vPortYieldProcessor.
|
||||
*/
|
||||
void vPortYieldProcessor( void )
|
||||
{
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
address, but an SWI ISR does not. Add the offset manually so the same
|
||||
ISR return code can be used in both cases. */
|
||||
asm volatile ( "ADD LR, LR, #4" );
|
||||
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The ISR used for the scheduler tick depends on whether the cooperative or
|
||||
* the preemptive scheduler is being used.
|
||||
*/
|
||||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
|
||||
void vNonPreemptiveTick( void )
|
||||
{
|
||||
static volatile uint32_t ulDummy;
|
||||
|
||||
/* Clear tick timer interrupt indication. */
|
||||
ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
|
||||
|
||||
xTaskIncrementTick();
|
||||
|
||||
/* Acknowledge the interrupt at AIC level... */
|
||||
AT91C_BASE_AIC->AIC_EOICR = portCLEAR_AIC_INTERRUPT;
|
||||
}
|
||||
|
||||
#else /* else preemption is turned on */
|
||||
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is
|
||||
saved on entry as part of the context switch. */
|
||||
void vPreemptiveTick( void ) __attribute__((naked));
|
||||
void vPreemptiveTick( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* WARNING - Do not use local (stack) variables here. Use globals
|
||||
if you must! */
|
||||
static volatile uint32_t ulDummy;
|
||||
|
||||
/* Clear tick timer interrupt indication. */
|
||||
ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
|
||||
|
||||
/* Increment the RTOS tick count, then look for the highest priority
|
||||
task that is ready to run. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* Acknowledge the interrupt at AIC level... */
|
||||
AT91C_BASE_AIC->AIC_EOICR = portCLEAR_AIC_INTERRUPT;
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions here to
|
||||
* ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then
|
||||
* the utilities are defined as macros in portmacro.h - as per other ports.
|
||||
*/
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.4
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
*/
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portCLEAR_AIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ISR to handle manual context switches (from a call to taskYIELD()). */
|
||||
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||||
* function here.
|
||||
*/
|
||||
void vPortISRStartFirstTask( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortISRStartFirstTask( void )
|
||||
{
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Called by portYIELD() or taskYIELD() to manually force a context switch.
|
||||
*
|
||||
* When a context switch is performed from the task level the saved task
|
||||
* context is made to look as if it occurred from within the tick ISR. This
|
||||
* way the same restore context function can be used when restoring the context
|
||||
* saved from the ISR or that saved from a call to vPortYieldProcessor.
|
||||
*/
|
||||
void vPortYieldProcessor( void )
|
||||
{
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
address, but an SWI ISR does not. Add the offset manually so the same
|
||||
ISR return code can be used in both cases. */
|
||||
asm volatile ( "ADD LR, LR, #4" );
|
||||
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The ISR used for the scheduler tick depends on whether the cooperative or
|
||||
* the preemptive scheduler is being used.
|
||||
*/
|
||||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
|
||||
void vNonPreemptiveTick( void )
|
||||
{
|
||||
static volatile uint32_t ulDummy;
|
||||
|
||||
/* Clear tick timer interrupt indication. */
|
||||
ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
|
||||
|
||||
xTaskIncrementTick();
|
||||
|
||||
/* Acknowledge the interrupt at AIC level... */
|
||||
AT91C_BASE_AIC->AIC_EOICR = portCLEAR_AIC_INTERRUPT;
|
||||
}
|
||||
|
||||
#else /* else preemption is turned on */
|
||||
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is
|
||||
saved on entry as part of the context switch. */
|
||||
void vPreemptiveTick( void ) __attribute__((naked));
|
||||
void vPreemptiveTick( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* WARNING - Do not use local (stack) variables here. Use globals
|
||||
if you must! */
|
||||
static volatile uint32_t ulDummy;
|
||||
|
||||
/* Clear tick timer interrupt indication. */
|
||||
ulDummy = portTIMER_REG_BASE_PTR->TC_SR;
|
||||
|
||||
/* Increment the RTOS tick count, then look for the highest priority
|
||||
task that is ready to run. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* Acknowledge the interrupt at AIC level... */
|
||||
AT91C_BASE_AIC->AIC_EOICR = portCLEAR_AIC_INTERRUPT;
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions here to
|
||||
* ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then
|
||||
* the utilities are defined as macros in portmacro.h - as per other ports.
|
||||
*/
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,256 +1,255 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.3
|
||||
|
||||
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ Removed the use of the %0 parameter within the assembler macros and
|
||||
replaced them with hard coded registers. This will ensure the
|
||||
assembler does not select the link register as the temp register as
|
||||
was occasionally happening previously.
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
|
||||
Changes from V4.5.0
|
||||
|
||||
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
|
||||
and replaced them with portYIELD_FROM_ISR() macro. Application code
|
||||
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
|
||||
macros as per the V4.5.1 demo code.
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portYIELD() asm volatile ( "SWI 0" )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
|
||||
/*
|
||||
* These define the timer to use for generating the tick interrupt.
|
||||
* They are put in this file so they can be shared between "port.c"
|
||||
* and "portisr.c".
|
||||
*/
|
||||
#define portTIMER_REG_BASE_PTR AT91C_BASE_TC0
|
||||
#define portTIMER_CLK_ENABLE_BIT AT91C_PS_TC0
|
||||
#define portTIMER_AIC_CHANNEL ( ( uint32_t ) 4 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/*
|
||||
* portRESTORE_CONTEXT, portRESTORE_CONTEXT, portENTER_SWITCHING_ISR
|
||||
* and portEXIT_SWITCHING_ISR can only be called from ARM mode, but
|
||||
* are included here for efficiency. An attempt to call one from
|
||||
* THUMB mode code will result in a compile time error.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"LDR LR, [R0] \n\t" \
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDMFD LR!, {R1} \n\t" \
|
||||
"STR R1, [R0] \n\t" \
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t" \
|
||||
"MSR SPSR, R0 \n\t" \
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t" \
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB SP, SP, #4 \n\t" \
|
||||
"LDMIA SP!,{R0} \n\t" \
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t" \
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t" \
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB LR, LR, #60 \n\t" \
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STR LR, [R0] \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
|
||||
/* Critical section handling. */
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions in
|
||||
* portISR.c to ensure a switch to ARM mode. When THUMB_INTERWORK is not
|
||||
* defined then the utilities are defined as macros here - as per other ports.
|
||||
*/
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
|
||||
#else
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.3
|
||||
|
||||
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ Removed the use of the %0 parameter within the assembler macros and
|
||||
replaced them with hard coded registers. This will ensure the
|
||||
assembler does not select the link register as the temp register as
|
||||
was occasionally happening previously.
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
|
||||
Changes from V4.5.0
|
||||
|
||||
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
|
||||
and replaced them with portYIELD_FROM_ISR() macro. Application code
|
||||
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
|
||||
macros as per the V4.5.1 demo code.
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portYIELD() asm volatile ( "SWI 0" )
|
||||
#define portNOP() asm volatile ( "NOP" )
|
||||
|
||||
/*
|
||||
* These define the timer to use for generating the tick interrupt.
|
||||
* They are put in this file so they can be shared between "port.c"
|
||||
* and "portisr.c".
|
||||
*/
|
||||
#define portTIMER_REG_BASE_PTR AT91C_BASE_TC0
|
||||
#define portTIMER_CLK_ENABLE_BIT AT91C_PS_TC0
|
||||
#define portTIMER_AIC_CHANNEL ( ( uint32_t ) 4 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/*
|
||||
* portRESTORE_CONTEXT, portRESTORE_CONTEXT, portENTER_SWITCHING_ISR
|
||||
* and portEXIT_SWITCHING_ISR can only be called from ARM mode, but
|
||||
* are included here for efficiency. An attempt to call one from
|
||||
* THUMB mode code will result in a compile time error.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"LDR LR, [R0] \n\t" \
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDMFD LR!, {R1} \n\t" \
|
||||
"STR R1, [R0] \n\t" \
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t" \
|
||||
"MSR SPSR, R0 \n\t" \
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t" \
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB SP, SP, #4 \n\t" \
|
||||
"LDMIA SP!,{R0} \n\t" \
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t" \
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t" \
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB LR, LR, #60 \n\t" \
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STR LR, [R0] \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
|
||||
/* Critical section handling. */
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions in
|
||||
* portISR.c to ensure a switch to ARM mode. When THUMB_INTERWORK is not
|
||||
* defined then the utilities are defined as macros here - as per other ports.
|
||||
*/
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
|
||||
#else
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,51 +1,50 @@
|
|||
//* ----------------------------------------------------------------------------
|
||||
//* ATMEL Microcontroller Software Support - ROUSSET -
|
||||
//* ----------------------------------------------------------------------------
|
||||
//* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
//* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
//* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
//* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
//* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
//* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
//* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
//* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//* ----------------------------------------------------------------------------
|
||||
//* File Name : lib_AT91SAM7X256.h
|
||||
//* Object : AT91SAM7X256 inlined functions
|
||||
//* Generated : AT91 SW Application Group 05/20/2005 (16:22:29)
|
||||
//*
|
||||
//* CVS Reference : /lib_dbgu.h/1.1/Fri Jan 31 12:18:40 2003//
|
||||
//* CVS Reference : /lib_pmc_SAM7X.h/1.1/Tue Feb 1 08:32:10 2005//
|
||||
//* CVS Reference : /lib_VREG_6085B.h/1.1/Tue Feb 1 16:20:47 2005//
|
||||
//* CVS Reference : /lib_rstc_6098A.h/1.1/Wed Oct 6 10:39:20 2004//
|
||||
//* CVS Reference : /lib_ssc.h/1.4/Fri Jan 31 12:19:20 2003//
|
||||
//* CVS Reference : /lib_wdtc_6080A.h/1.1/Wed Oct 6 10:38:30 2004//
|
||||
//* CVS Reference : /lib_usart.h/1.5/Thu Nov 21 16:01:54 2002//
|
||||
//* CVS Reference : /lib_spi2.h/1.1/Mon Aug 25 14:23:52 2003//
|
||||
//* CVS Reference : /lib_pitc_6079A.h/1.2/Tue Nov 9 14:43:56 2004//
|
||||
//* CVS Reference : /lib_aic_6075b.h/1.1/Fri May 20 14:01:19 2005//
|
||||
//* CVS Reference : /lib_aes_6149a.h/1.1/Mon Jan 17 07:43:09 2005//
|
||||
//* CVS Reference : /lib_twi.h/1.3/Mon Jul 19 14:27:58 2004//
|
||||
//* CVS Reference : /lib_adc.h/1.6/Fri Oct 17 09:12:38 2003//
|
||||
//* CVS Reference : /lib_rttc_6081A.h/1.1/Wed Oct 6 10:39:38 2004//
|
||||
//* CVS Reference : /lib_udp.h/1.4/Wed Feb 16 08:39:34 2005//
|
||||
//* CVS Reference : /lib_des3_6150a.h/1.1/Mon Jan 17 09:19:19 2005//
|
||||
//* CVS Reference : /lib_tc_1753b.h/1.1/Fri Jan 31 12:20:02 2003//
|
||||
//* CVS Reference : /lib_MC_SAM7X.h/1.1/Thu Mar 25 15:19:14 2004//
|
||||
//* CVS Reference : /lib_pio.h/1.3/Fri Jan 31 12:18:56 2003//
|
||||
//* CVS Reference : /lib_can_AT91.h/1.4/Fri Oct 17 09:12:50 2003//
|
||||
//* CVS Reference : /lib_PWM_SAM.h/1.3/Thu Jan 22 10:10:50 2004//
|
||||
//* CVS Reference : /lib_pdc.h/1.2/Tue Jul 2 13:29:40 2002//
|
||||
//* ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_AIC_ConfigureIt
|
||||
//* \brief Interrupt Handler Initialization
|
||||
//*----------------------------------------------------------------------------
|
||||
|
||||
//* ----------------------------------------------------------------------------
|
||||
//* ATMEL Microcontroller Software Support - ROUSSET -
|
||||
//* ----------------------------------------------------------------------------
|
||||
//* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
//* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
//* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
//* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
//* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
//* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
//* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
//* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
//* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
//* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//* ----------------------------------------------------------------------------
|
||||
//* File Name : lib_AT91SAM7X256.h
|
||||
//* Object : AT91SAM7X256 inlined functions
|
||||
//* Generated : AT91 SW Application Group 05/20/2005 (16:22:29)
|
||||
//*
|
||||
//* CVS Reference : /lib_dbgu.h/1.1/Fri Jan 31 12:18:40 2003//
|
||||
//* CVS Reference : /lib_pmc_SAM7X.h/1.1/Tue Feb 1 08:32:10 2005//
|
||||
//* CVS Reference : /lib_VREG_6085B.h/1.1/Tue Feb 1 16:20:47 2005//
|
||||
//* CVS Reference : /lib_rstc_6098A.h/1.1/Wed Oct 6 10:39:20 2004//
|
||||
//* CVS Reference : /lib_ssc.h/1.4/Fri Jan 31 12:19:20 2003//
|
||||
//* CVS Reference : /lib_wdtc_6080A.h/1.1/Wed Oct 6 10:38:30 2004//
|
||||
//* CVS Reference : /lib_usart.h/1.5/Thu Nov 21 16:01:54 2002//
|
||||
//* CVS Reference : /lib_spi2.h/1.1/Mon Aug 25 14:23:52 2003//
|
||||
//* CVS Reference : /lib_pitc_6079A.h/1.2/Tue Nov 9 14:43:56 2004//
|
||||
//* CVS Reference : /lib_aic_6075b.h/1.1/Fri May 20 14:01:19 2005//
|
||||
//* CVS Reference : /lib_aes_6149a.h/1.1/Mon Jan 17 07:43:09 2005//
|
||||
//* CVS Reference : /lib_twi.h/1.3/Mon Jul 19 14:27:58 2004//
|
||||
//* CVS Reference : /lib_adc.h/1.6/Fri Oct 17 09:12:38 2003//
|
||||
//* CVS Reference : /lib_rttc_6081A.h/1.1/Wed Oct 6 10:39:38 2004//
|
||||
//* CVS Reference : /lib_udp.h/1.4/Wed Feb 16 08:39:34 2005//
|
||||
//* CVS Reference : /lib_des3_6150a.h/1.1/Mon Jan 17 09:19:19 2005//
|
||||
//* CVS Reference : /lib_tc_1753b.h/1.1/Fri Jan 31 12:20:02 2003//
|
||||
//* CVS Reference : /lib_MC_SAM7X.h/1.1/Thu Mar 25 15:19:14 2004//
|
||||
//* CVS Reference : /lib_pio.h/1.3/Fri Jan 31 12:18:56 2003//
|
||||
//* CVS Reference : /lib_can_AT91.h/1.4/Fri Oct 17 09:12:50 2003//
|
||||
//* CVS Reference : /lib_PWM_SAM.h/1.3/Thu Jan 22 10:10:50 2004//
|
||||
//* CVS Reference : /lib_pdc.h/1.2/Tue Jul 2 13:29:40 2002//
|
||||
//* ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
|
||||
//*----------------------------------------------------------------------------
|
||||
//* \fn AT91F_AIC_ConfigureIt
|
||||
//* \brief Interrupt Handler Initialization
|
||||
//*----------------------------------------------------------------------------
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,214 +1,211 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM7 port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Processor constants. */
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the tick ISR. */
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
|
||||
/* Constants required to setup the PIT. */
|
||||
#define portPIT_CLOCK_DIVISOR ( ( uint32_t ) 16 )
|
||||
#define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_PERIOD_MS )
|
||||
|
||||
#define portINT_LEVEL_SENSITIVE 0
|
||||
#define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 )
|
||||
#define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
*/
|
||||
extern void vPortISRStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
start of the task. The offset is added to make the return address appear
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
means the interrupt flags cannot always be stored on the stack and will
|
||||
instead be stored in a variable, which is then saved as part of the
|
||||
tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the timer 0 to generate the tick interrupts at the required frequency.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
AT91PS_PITC pxPIT = AT91C_BASE_PITC;
|
||||
|
||||
/* Setup the AIC for PIT interrupts. The interrupt routine chosen depends
|
||||
on whether the preemptive or cooperative scheduler is being used. */
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
extern void ( vNonPreemptiveTick ) ( void );
|
||||
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vNonPreemptiveTick );
|
||||
|
||||
#else
|
||||
|
||||
extern void ( vPreemptiveTick )( void );
|
||||
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPreemptiveTick );
|
||||
|
||||
#endif
|
||||
|
||||
/* Configure the PIT period. */
|
||||
pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE;
|
||||
|
||||
/* Enable the interrupt. Global interrupts are disables at this point so
|
||||
this is safe. */
|
||||
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_SYS;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM7 port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Processor constants. */
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the tick ISR. */
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
|
||||
/* Constants required to setup the PIT. */
|
||||
#define portPIT_CLOCK_DIVISOR ( ( uint32_t ) 16 )
|
||||
#define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_PERIOD_MS )
|
||||
|
||||
#define portINT_LEVEL_SENSITIVE 0
|
||||
#define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 )
|
||||
#define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
*/
|
||||
extern void vPortISRStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
start of the task. The offset is added to make the return address appear
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
means the interrupt flags cannot always be stored on the stack and will
|
||||
instead be stored in a variable, which is then saved as part of the
|
||||
tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the timer 0 to generate the tick interrupts at the required frequency.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
AT91PS_PITC pxPIT = AT91C_BASE_PITC;
|
||||
|
||||
/* Setup the AIC for PIT interrupts. The interrupt routine chosen depends
|
||||
on whether the preemptive or cooperative scheduler is being used. */
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
extern void ( vNonPreemptiveTick ) ( void );
|
||||
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vNonPreemptiveTick );
|
||||
|
||||
#else
|
||||
|
||||
extern void ( vPreemptiveTick )( void );
|
||||
AT91F_AIC_ConfigureIt( AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPreemptiveTick );
|
||||
|
||||
#endif
|
||||
|
||||
/* Configure the PIT period. */
|
||||
pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE;
|
||||
|
||||
/* Enable the interrupt. Global interrupts are disables at this point so
|
||||
this is safe. */
|
||||
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_SYS;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,228 +1,227 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.4
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ISR to handle manual context switches (from a call to taskYIELD()). */
|
||||
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||||
* function here.
|
||||
*/
|
||||
void vPortISRStartFirstTask( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortISRStartFirstTask( void )
|
||||
{
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Called by portYIELD() or taskYIELD() to manually force a context switch.
|
||||
*
|
||||
* When a context switch is performed from the task level the saved task
|
||||
* context is made to look as if it occurred from within the tick ISR. This
|
||||
* way the same restore context function can be used when restoring the context
|
||||
* saved from the ISR or that saved from a call to vPortYieldProcessor.
|
||||
*/
|
||||
void vPortYieldProcessor( void )
|
||||
{
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
address, but an SWI ISR does not. Add the offset manually so the same
|
||||
ISR return code can be used in both cases. */
|
||||
__asm volatile ( "ADD LR, LR, #4" );
|
||||
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The ISR used for the scheduler tick depends on whether the cooperative or
|
||||
* the preemptive scheduler is being used.
|
||||
*/
|
||||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
|
||||
void vNonPreemptiveTick( void )
|
||||
{
|
||||
uint32_t ulDummy;
|
||||
|
||||
/* Increment the tick count - which may wake some tasks but as the
|
||||
preemptive scheduler is not being used any woken task is not given
|
||||
processor time no matter what its priority. */
|
||||
xTaskIncrementTick();
|
||||
|
||||
/* Clear the PIT interrupt. */
|
||||
ulDummy = AT91C_BASE_PITC->PITC_PIVR;
|
||||
|
||||
/* End the interrupt in the AIC. */
|
||||
AT91C_BASE_AIC->AIC_EOICR = ulDummy;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is
|
||||
saved on entry as part of the context switch. */
|
||||
void vPreemptiveTick( void ) __attribute__((naked));
|
||||
void vPreemptiveTick( void )
|
||||
{
|
||||
/* Save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the tick count - this may wake a task. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* End the interrupt in the AIC. */
|
||||
AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_PITC->PITC_PIVR;
|
||||
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions here to
|
||||
* ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then
|
||||
* the utilities are defined as macros in portmacro.h - as per other ports.
|
||||
*/
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.4
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "AT91SAM7X256.h"
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ISR to handle manual context switches (from a call to taskYIELD()). */
|
||||
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||||
* function here.
|
||||
*/
|
||||
void vPortISRStartFirstTask( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortISRStartFirstTask( void )
|
||||
{
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Called by portYIELD() or taskYIELD() to manually force a context switch.
|
||||
*
|
||||
* When a context switch is performed from the task level the saved task
|
||||
* context is made to look as if it occurred from within the tick ISR. This
|
||||
* way the same restore context function can be used when restoring the context
|
||||
* saved from the ISR or that saved from a call to vPortYieldProcessor.
|
||||
*/
|
||||
void vPortYieldProcessor( void )
|
||||
{
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
address, but an SWI ISR does not. Add the offset manually so the same
|
||||
ISR return code can be used in both cases. */
|
||||
__asm volatile ( "ADD LR, LR, #4" );
|
||||
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The ISR used for the scheduler tick depends on whether the cooperative or
|
||||
* the preemptive scheduler is being used.
|
||||
*/
|
||||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
|
||||
void vNonPreemptiveTick( void )
|
||||
{
|
||||
uint32_t ulDummy;
|
||||
|
||||
/* Increment the tick count - which may wake some tasks but as the
|
||||
preemptive scheduler is not being used any woken task is not given
|
||||
processor time no matter what its priority. */
|
||||
xTaskIncrementTick();
|
||||
|
||||
/* Clear the PIT interrupt. */
|
||||
ulDummy = AT91C_BASE_PITC->PITC_PIVR;
|
||||
|
||||
/* End the interrupt in the AIC. */
|
||||
AT91C_BASE_AIC->AIC_EOICR = ulDummy;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is
|
||||
saved on entry as part of the context switch. */
|
||||
void vPreemptiveTick( void ) __attribute__((naked));
|
||||
void vPreemptiveTick( void )
|
||||
{
|
||||
/* Save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the tick count - this may wake a task. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* End the interrupt in the AIC. */
|
||||
AT91C_BASE_AIC->AIC_EOICR = AT91C_BASE_PITC->PITC_PIVR;
|
||||
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions here to
|
||||
* ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then
|
||||
* the utilities are defined as macros in portmacro.h - as per other ports.
|
||||
*/
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,250 +1,249 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.3
|
||||
|
||||
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ Removed the use of the %0 parameter within the assembler macros and
|
||||
replaced them with hard coded registers. This will ensure the
|
||||
assembler does not select the link register as the temp register as
|
||||
was occasionally happening previously.
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
|
||||
Changes from V4.5.0
|
||||
|
||||
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
|
||||
and replaced them with portYIELD_FROM_ISR() macro. Application code
|
||||
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
|
||||
macros as per the V4.5.1 demo code.
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE portLONG
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP() __asm volatile ( "NOP" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
|
||||
/*
|
||||
* portRESTORE_CONTEXT, portRESTORE_CONTEXT, portENTER_SWITCHING_ISR
|
||||
* and portEXIT_SWITCHING_ISR can only be called from ARM mode, but
|
||||
* are included here for efficiency. An attempt to call one from
|
||||
* THUMB mode code will result in a compile time error.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
__asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"LDR LR, [R0] \n\t" \
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDMFD LR!, {R1} \n\t" \
|
||||
"STR R1, [R0] \n\t" \
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t" \
|
||||
"MSR SPSR, R0 \n\t" \
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t" \
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB SP, SP, #4 \n\t" \
|
||||
"LDMIA SP!,{R0} \n\t" \
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t" \
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t" \
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB LR, LR, #60 \n\t" \
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STR LR, [R0] \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
|
||||
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD() __asm volatile ( "SWI 0" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions in
|
||||
* portISR.c to ensure a switch to ARM mode. When THUMB_INTERWORK is not
|
||||
* defined then the utilities are defined as macros here - as per other ports.
|
||||
*/
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
|
||||
#else
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.3
|
||||
|
||||
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ Removed the use of the %0 parameter within the assembler macros and
|
||||
replaced them with hard coded registers. This will ensure the
|
||||
assembler does not select the link register as the temp register as
|
||||
was occasionally happening previously.
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
|
||||
Changes from V4.5.0
|
||||
|
||||
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
|
||||
and replaced them with portYIELD_FROM_ISR() macro. Application code
|
||||
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
|
||||
macros as per the V4.5.1 demo code.
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE portLONG
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP() __asm volatile ( "NOP" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
|
||||
/*
|
||||
* portRESTORE_CONTEXT, portRESTORE_CONTEXT, portENTER_SWITCHING_ISR
|
||||
* and portEXIT_SWITCHING_ISR can only be called from ARM mode, but
|
||||
* are included here for efficiency. An attempt to call one from
|
||||
* THUMB mode code will result in a compile time error.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
__asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"LDR LR, [R0] \n\t" \
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDMFD LR!, {R1} \n\t" \
|
||||
"STR R1, [R0] \n\t" \
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t" \
|
||||
"MSR SPSR, R0 \n\t" \
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t" \
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB SP, SP, #4 \n\t" \
|
||||
"LDMIA SP!,{R0} \n\t" \
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t" \
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t" \
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB LR, LR, #60 \n\t" \
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STR LR, [R0] \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
|
||||
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD() __asm volatile ( "SWI 0" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions in
|
||||
* portISR.c to ensure a switch to ARM mode. When THUMB_INTERWORK is not
|
||||
* defined then the utilities are defined as macros here - as per other ports.
|
||||
*/
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
|
||||
#else
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,222 +1,219 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM7 port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the tick ISR. */
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
|
||||
/* Constants required to setup the VIC for the tick ISR. */
|
||||
#define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 )
|
||||
#define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 )
|
||||
#define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
*/
|
||||
extern void vPortISRStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
start of the task. The offset is added to make the return address appear
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
means the interrupt flags cannot always be stored on the stack and will
|
||||
instead be stored in a variable, which is then saved as part of the
|
||||
tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the timer 0 to generate the tick interrupts at the required frequency.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
uint32_t ulCompareMatch;
|
||||
extern void ( vTickISR )( void );
|
||||
|
||||
/* A 1ms tick does not require the use of the timer prescale. This is
|
||||
defaulted to zero but can be used if necessary. */
|
||||
T0_PR = portPRESCALE_VALUE;
|
||||
|
||||
/* Calculate the match value required for our wanted tick rate. */
|
||||
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* Protect against divide by zero. Using an if() statement still results
|
||||
in a warning - hence the #if. */
|
||||
#if portPRESCALE_VALUE != 0
|
||||
{
|
||||
ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
|
||||
}
|
||||
#endif
|
||||
T0_MR0 = ulCompareMatch;
|
||||
|
||||
/* Generate tick with timer 0 compare match. */
|
||||
T0_MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH;
|
||||
|
||||
/* Setup the VIC for the timer. */
|
||||
VICIntSelect &= ~( portTIMER_VIC_CHANNEL_BIT );
|
||||
VICIntEnable |= portTIMER_VIC_CHANNEL_BIT;
|
||||
|
||||
/* The ISR installed depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
|
||||
VICVectAddr0 = ( int32_t ) vTickISR;
|
||||
VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE;
|
||||
|
||||
/* Start the timer - interrupts are disabled when this function is called
|
||||
so it is okay to do this here. */
|
||||
T0_TCR = portENABLE_TIMER;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM7 port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the tick ISR. */
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
|
||||
/* Constants required to setup the VIC for the tick ISR. */
|
||||
#define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 )
|
||||
#define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 )
|
||||
#define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
*/
|
||||
extern void vPortISRStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
start of the task. The offset is added to make the return address appear
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
means the interrupt flags cannot always be stored on the stack and will
|
||||
instead be stored in a variable, which is then saved as part of the
|
||||
tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the timer 0 to generate the tick interrupts at the required frequency.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
uint32_t ulCompareMatch;
|
||||
extern void ( vTickISR )( void );
|
||||
|
||||
/* A 1ms tick does not require the use of the timer prescale. This is
|
||||
defaulted to zero but can be used if necessary. */
|
||||
T0_PR = portPRESCALE_VALUE;
|
||||
|
||||
/* Calculate the match value required for our wanted tick rate. */
|
||||
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* Protect against divide by zero. Using an if() statement still results
|
||||
in a warning - hence the #if. */
|
||||
#if portPRESCALE_VALUE != 0
|
||||
{
|
||||
ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
|
||||
}
|
||||
#endif
|
||||
T0_MR0 = ulCompareMatch;
|
||||
|
||||
/* Generate tick with timer 0 compare match. */
|
||||
T0_MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH;
|
||||
|
||||
/* Setup the VIC for the timer. */
|
||||
VICIntSelect &= ~( portTIMER_VIC_CHANNEL_BIT );
|
||||
VICIntEnable |= portTIMER_VIC_CHANNEL_BIT;
|
||||
|
||||
/* The ISR installed depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
|
||||
VICVectAddr0 = ( int32_t ) vTickISR;
|
||||
VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE;
|
||||
|
||||
/* Start the timer - interrupts are disabled when this function is called
|
||||
so it is okay to do this here. */
|
||||
T0_TCR = portENABLE_TIMER;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,216 +1,216 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Changes from V2.5.2
|
||||
|
||||
+ The critical section management functions have been changed. These no
|
||||
longer modify the stack and are safe to use at all optimisation levels.
|
||||
The functions are now also the same for both ARM and THUMB modes.
|
||||
|
||||
Changes from V2.6.0
|
||||
|
||||
+ Removed the 'static' from the definition of vNonPreemptiveTick() to
|
||||
allow the demo to link when using the cooperative scheduler.
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
*/
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ISR to handle manual context switches (from a call to taskYIELD()). */
|
||||
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||||
* function here.
|
||||
*/
|
||||
void vPortISRStartFirstTask( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortISRStartFirstTask( void )
|
||||
{
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Called by portYIELD() or taskYIELD() to manually force a context switch.
|
||||
*
|
||||
* When a context switch is performed from the task level the saved task
|
||||
* context is made to look as if it occurred from within the tick ISR. This
|
||||
* way the same restore context function can be used when restoring the context
|
||||
* saved from the ISR or that saved from a call to vPortYieldProcessor.
|
||||
*/
|
||||
void vPortYieldProcessor( void )
|
||||
{
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
address, but an SWI ISR does not. Add the offset manually so the same
|
||||
ISR return code can be used in both cases. */
|
||||
__asm volatile ( "ADD LR, LR, #4" );
|
||||
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
__asm volatile ( "bl vTaskSwitchContext" );
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The ISR used for the scheduler tick.
|
||||
*/
|
||||
void vTickISR( void ) __attribute__((naked));
|
||||
void vTickISR( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the RTOS tick count, then look for the highest priority
|
||||
task that is ready to run. */
|
||||
__asm volatile
|
||||
(
|
||||
" bl xTaskIncrementTick \t\n" \
|
||||
" cmp r0, #0 \t\n" \
|
||||
" beq SkipContextSwitch \t\n" \
|
||||
" bl vTaskSwitchContext \t\n" \
|
||||
"SkipContextSwitch: \t\n"
|
||||
);
|
||||
|
||||
/* Ready for the next interrupt. */
|
||||
T0_IR = portTIMER_MATCH_ISR_BIT;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions here to
|
||||
* ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then
|
||||
* the utilities are defined as macros in portmacro.h - as per other ports.
|
||||
*/
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Changes from V2.5.2
|
||||
|
||||
+ The critical section management functions have been changed. These no
|
||||
longer modify the stack and are safe to use at all optimisation levels.
|
||||
The functions are now also the same for both ARM and THUMB modes.
|
||||
|
||||
Changes from V2.6.0
|
||||
|
||||
+ Removed the 'static' from the definition of vNonPreemptiveTick() to
|
||||
allow the demo to link when using the cooperative scheduler.
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
*/
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ISR to handle manual context switches (from a call to taskYIELD()). */
|
||||
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||||
* function here.
|
||||
*/
|
||||
void vPortISRStartFirstTask( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortISRStartFirstTask( void )
|
||||
{
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Called by portYIELD() or taskYIELD() to manually force a context switch.
|
||||
*
|
||||
* When a context switch is performed from the task level the saved task
|
||||
* context is made to look as if it occurred from within the tick ISR. This
|
||||
* way the same restore context function can be used when restoring the context
|
||||
* saved from the ISR or that saved from a call to vPortYieldProcessor.
|
||||
*/
|
||||
void vPortYieldProcessor( void )
|
||||
{
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
address, but an SWI ISR does not. Add the offset manually so the same
|
||||
ISR return code can be used in both cases. */
|
||||
__asm volatile ( "ADD LR, LR, #4" );
|
||||
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
__asm volatile ( "bl vTaskSwitchContext" );
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The ISR used for the scheduler tick.
|
||||
*/
|
||||
void vTickISR( void ) __attribute__((naked));
|
||||
void vTickISR( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the RTOS tick count, then look for the highest priority
|
||||
task that is ready to run. */
|
||||
__asm volatile
|
||||
(
|
||||
" bl xTaskIncrementTick \t\n" \
|
||||
" cmp r0, #0 \t\n" \
|
||||
" beq SkipContextSwitch \t\n" \
|
||||
" bl vTaskSwitchContext \t\n" \
|
||||
"SkipContextSwitch: \t\n"
|
||||
);
|
||||
|
||||
/* Ready for the next interrupt. */
|
||||
T0_IR = portTIMER_MATCH_ISR_BIT;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions here to
|
||||
* ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then
|
||||
* the utilities are defined as macros in portmacro.h - as per other ports.
|
||||
*/
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,227 +1,226 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE portLONG
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP() __asm volatile ( "NOP" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
|
||||
/*
|
||||
* portRESTORE_CONTEXT, portRESTORE_CONTEXT, portENTER_SWITCHING_ISR
|
||||
* and portEXIT_SWITCHING_ISR can only be called from ARM mode, but
|
||||
* are included here for efficiency. An attempt to call one from
|
||||
* THUMB mode code will result in a compile time error.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
__asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"LDR LR, [R0] \n\t" \
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDMFD LR!, {R1} \n\t" \
|
||||
"STR R1, [R0] \n\t" \
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t" \
|
||||
"MSR SPSR, R0 \n\t" \
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t" \
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB SP, SP, #4 \n\t" \
|
||||
"LDMIA SP!,{R0} \n\t" \
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t" \
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t" \
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB LR, LR, #60 \n\t" \
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STR LR, [R0] \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
|
||||
extern void vTaskSwitchContext( void );
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD() __asm volatile ( "SWI 0" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions in
|
||||
* portISR.c to ensure a switch to ARM mode. When THUMB_INTERWORK is not
|
||||
* defined then the utilities are defined as macros here - as per other ports.
|
||||
*/
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
|
||||
#else
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE portLONG
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP() __asm volatile ( "NOP" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
|
||||
/*
|
||||
* portRESTORE_CONTEXT, portRESTORE_CONTEXT, portENTER_SWITCHING_ISR
|
||||
* and portEXIT_SWITCHING_ISR can only be called from ARM mode, but
|
||||
* are included here for efficiency. An attempt to call one from
|
||||
* THUMB mode code will result in a compile time error.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
__asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"LDR LR, [R0] \n\t" \
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDMFD LR!, {R1} \n\t" \
|
||||
"STR R1, [R0] \n\t" \
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t" \
|
||||
"MSR SPSR, R0 \n\t" \
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t" \
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB SP, SP, #4 \n\t" \
|
||||
"LDMIA SP!,{R0} \n\t" \
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t" \
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t" \
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB LR, LR, #60 \n\t" \
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STR LR, [R0] \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
|
||||
extern void vTaskSwitchContext( void );
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD() __asm volatile ( "SWI 0" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions in
|
||||
* portISR.c to ensure a switch to ARM mode. When THUMB_INTERWORK is not
|
||||
* defined then the utilities are defined as macros here - as per other ports.
|
||||
*/
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
|
||||
#else
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,234 +1,231 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM7 port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the tick ISR. */
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
|
||||
/* Constants required to setup the VIC for the tick ISR. */
|
||||
#define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 )
|
||||
#define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 )
|
||||
#define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
*/
|
||||
extern void vPortISRStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
start of the task. The offset is added to make the return address appear
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
means the interrupt flags cannot always be stored on the stack and will
|
||||
instead be stored in a variable, which is then saved as part of the
|
||||
tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the timer 0 to generate the tick interrupts at the required frequency.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
uint32_t ulCompareMatch;
|
||||
|
||||
PCLKSEL0 = (PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2);
|
||||
T0TCR = 2; /* Stop and reset the timer */
|
||||
T0CTCR = 0; /* Timer mode */
|
||||
|
||||
/* A 1ms tick does not require the use of the timer prescale. This is
|
||||
defaulted to zero but can be used if necessary. */
|
||||
T0PR = portPRESCALE_VALUE;
|
||||
|
||||
/* Calculate the match value required for our wanted tick rate. */
|
||||
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* Protect against divide by zero. Using an if() statement still results
|
||||
in a warning - hence the #if. */
|
||||
#if portPRESCALE_VALUE != 0
|
||||
{
|
||||
ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
|
||||
}
|
||||
#endif
|
||||
T0MR1 = ulCompareMatch;
|
||||
|
||||
/* Generate tick with timer 0 compare match. */
|
||||
T0MCR = (3 << 3); /* Reset timer on match and generate interrupt */
|
||||
|
||||
/* Setup the VIC for the timer. */
|
||||
VICIntEnable = 0x00000010;
|
||||
|
||||
/* The ISR installed depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
extern void ( vPreemptiveTick )( void );
|
||||
VICVectAddr4 = ( int32_t ) vPreemptiveTick;
|
||||
}
|
||||
#else
|
||||
{
|
||||
extern void ( vNonPreemptiveTick )( void );
|
||||
VICVectAddr4 = ( int32_t ) vNonPreemptiveTick;
|
||||
}
|
||||
#endif
|
||||
|
||||
VICVectCntl4 = 1;
|
||||
|
||||
/* Start the timer - interrupts are disabled when this function is called
|
||||
so it is okay to do this here. */
|
||||
T0TCR = portENABLE_TIMER;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM7 port.
|
||||
*
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in this file. The ISR routines, which can only be compiled
|
||||
* to ARM mode are contained in portISR.c.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the tick ISR. */
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
|
||||
/* Constants required to setup the VIC for the tick ISR. */
|
||||
#define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 )
|
||||
#define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 )
|
||||
#define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, so
|
||||
* vPortISRStartFirstSTask() is defined in portISR.c.
|
||||
*/
|
||||
extern void vPortISRStartFirstTask( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* First on the stack is the return address - which in this case is the
|
||||
start of the task. The offset is added to make the return address appear
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x00000000; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The last thing onto the stack is the status register, which is set for
|
||||
system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00 )
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Some optimisation levels use the stack differently to others. This
|
||||
means the interrupt flags cannot always be stored on the stack and will
|
||||
instead be stored in a variable, which is then saved as part of the
|
||||
tasks context. */
|
||||
*pxTopOfStack = portNO_CRITICAL_SECTION_NESTING;
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortISRStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the timer 0 to generate the tick interrupts at the required frequency.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
uint32_t ulCompareMatch;
|
||||
|
||||
PCLKSEL0 = (PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2);
|
||||
T0TCR = 2; /* Stop and reset the timer */
|
||||
T0CTCR = 0; /* Timer mode */
|
||||
|
||||
/* A 1ms tick does not require the use of the timer prescale. This is
|
||||
defaulted to zero but can be used if necessary. */
|
||||
T0PR = portPRESCALE_VALUE;
|
||||
|
||||
/* Calculate the match value required for our wanted tick rate. */
|
||||
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* Protect against divide by zero. Using an if() statement still results
|
||||
in a warning - hence the #if. */
|
||||
#if portPRESCALE_VALUE != 0
|
||||
{
|
||||
ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
|
||||
}
|
||||
#endif
|
||||
T0MR1 = ulCompareMatch;
|
||||
|
||||
/* Generate tick with timer 0 compare match. */
|
||||
T0MCR = (3 << 3); /* Reset timer on match and generate interrupt */
|
||||
|
||||
/* Setup the VIC for the timer. */
|
||||
VICIntEnable = 0x00000010;
|
||||
|
||||
/* The ISR installed depends on whether the preemptive or cooperative
|
||||
scheduler is being used. */
|
||||
#if configUSE_PREEMPTION == 1
|
||||
{
|
||||
extern void ( vPreemptiveTick )( void );
|
||||
VICVectAddr4 = ( int32_t ) vPreemptiveTick;
|
||||
}
|
||||
#else
|
||||
{
|
||||
extern void ( vNonPreemptiveTick )( void );
|
||||
VICVectAddr4 = ( int32_t ) vNonPreemptiveTick;
|
||||
}
|
||||
#endif
|
||||
|
||||
VICVectCntl4 = 1;
|
||||
|
||||
/* Start the timer - interrupts are disabled when this function is called
|
||||
so it is okay to do this here. */
|
||||
T0TCR = portENABLE_TIMER;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,219 +1,219 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ISR to handle manual context switches (from a call to taskYIELD()). */
|
||||
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||||
* function here.
|
||||
*/
|
||||
void vPortISRStartFirstTask( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortISRStartFirstTask( void )
|
||||
{
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Called by portYIELD() or taskYIELD() to manually force a context switch.
|
||||
*
|
||||
* When a context switch is performed from the task level the saved task
|
||||
* context is made to look as if it occurred from within the tick ISR. This
|
||||
* way the same restore context function can be used when restoring the context
|
||||
* saved from the ISR or that saved from a call to vPortYieldProcessor.
|
||||
*/
|
||||
void vPortYieldProcessor( void )
|
||||
{
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
address, but an SWI ISR does not. Add the offset manually so the same
|
||||
ISR return code can be used in both cases. */
|
||||
__asm volatile ( "ADD LR, LR, #4" );
|
||||
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
__asm volatile( "bl vTaskSwitchContext" );
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The ISR used for the scheduler tick depends on whether the cooperative or
|
||||
* the preemptive scheduler is being used.
|
||||
*/
|
||||
|
||||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
|
||||
void vNonPreemptiveTick( void )
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
T0IR = 2;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is
|
||||
saved on entry as part of the context switch. */
|
||||
void vPreemptiveTick( void ) __attribute__((naked));
|
||||
void vPreemptiveTick( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the RTOS tick count, then look for the highest priority
|
||||
task that is ready to run. */
|
||||
__asm volatile
|
||||
(
|
||||
" bl xTaskIncrementTick \t\n" \
|
||||
" cmp r0, #0 \t\n" \
|
||||
" beq SkipContextSwitch \t\n" \
|
||||
" bl vTaskSwitchContext \t\n" \
|
||||
"SkipContextSwitch: \t\n"
|
||||
);
|
||||
|
||||
/* Ready for the next interrupt. */
|
||||
T0IR = 2;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions here to
|
||||
* ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then
|
||||
* the utilities are defined as macros in portmacro.h - as per other ports.
|
||||
*/
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Components that can be compiled to either ARM or THUMB mode are
|
||||
* contained in port.c The ISR routines, which can only be compiled
|
||||
* to ARM mode, are contained in this file.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* ISR to handle manual context switches (from a call to taskYIELD()). */
|
||||
void vPortYieldProcessor( void ) __attribute__((interrupt("SWI"), naked));
|
||||
|
||||
/*
|
||||
* The scheduler can only be started from ARM mode, hence the inclusion of this
|
||||
* function here.
|
||||
*/
|
||||
void vPortISRStartFirstTask( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortISRStartFirstTask( void )
|
||||
{
|
||||
/* Simply start the scheduler. This is included here as it can only be
|
||||
called from ARM mode. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Called by portYIELD() or taskYIELD() to manually force a context switch.
|
||||
*
|
||||
* When a context switch is performed from the task level the saved task
|
||||
* context is made to look as if it occurred from within the tick ISR. This
|
||||
* way the same restore context function can be used when restoring the context
|
||||
* saved from the ISR or that saved from a call to vPortYieldProcessor.
|
||||
*/
|
||||
void vPortYieldProcessor( void )
|
||||
{
|
||||
/* Within an IRQ ISR the link register has an offset from the true return
|
||||
address, but an SWI ISR does not. Add the offset manually so the same
|
||||
ISR return code can be used in both cases. */
|
||||
__asm volatile ( "ADD LR, LR, #4" );
|
||||
|
||||
/* Perform the context switch. First save the context of the current task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Find the highest priority task that is ready to run. */
|
||||
__asm volatile( "bl vTaskSwitchContext" );
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The ISR used for the scheduler tick depends on whether the cooperative or
|
||||
* the preemptive scheduler is being used.
|
||||
*/
|
||||
|
||||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
void vNonPreemptiveTick( void ) __attribute__ ((interrupt ("IRQ")));
|
||||
void vNonPreemptiveTick( void )
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
T0IR = 2;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is
|
||||
saved on entry as part of the context switch. */
|
||||
void vPreemptiveTick( void ) __attribute__((naked));
|
||||
void vPreemptiveTick( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Increment the RTOS tick count, then look for the highest priority
|
||||
task that is ready to run. */
|
||||
__asm volatile
|
||||
(
|
||||
" bl xTaskIncrementTick \t\n" \
|
||||
" cmp r0, #0 \t\n" \
|
||||
" beq SkipContextSwitch \t\n" \
|
||||
" bl vTaskSwitchContext \t\n" \
|
||||
"SkipContextSwitch: \t\n"
|
||||
);
|
||||
|
||||
/* Ready for the next interrupt. */
|
||||
T0IR = 2;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions here to
|
||||
* ensure a switch to ARM mode. When THUMB_INTERWORK is not defined then
|
||||
* the utilities are defined as macros in portmacro.h - as per other ports.
|
||||
*/
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
void vPortDisableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
void vPortEnableInterruptsFromThumb( void )
|
||||
{
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0} \n\t" /* Pop R0. */
|
||||
"BX R14" ); /* Return back to thumb. */
|
||||
}
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
be saved to the stack. Instead the critical section nesting level is stored
|
||||
in a variable, which is then saved as part of the stack context. */
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable interrupts as per portEXIT_CRITICAL(). */
|
||||
__asm volatile (
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */
|
||||
"LDMIA SP!, {R0}" ); /* Pop R0. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,250 +1,249 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.3
|
||||
|
||||
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ Removed the use of the %0 parameter within the assembler macros and
|
||||
replaced them with hard coded registers. This will ensure the
|
||||
assembler does not select the link register as the temp register as
|
||||
was occasionally happening previously.
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
|
||||
Changes from V4.5.0
|
||||
|
||||
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
|
||||
and replaced them with portYIELD_FROM_ISR() macro. Application code
|
||||
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
|
||||
macros as per the V4.5.1 demo code.
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE portLONG
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP() __asm volatile ( "NOP" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
|
||||
/*
|
||||
* portRESTORE_CONTEXT, portRESTORE_CONTEXT, portENTER_SWITCHING_ISR
|
||||
* and portEXIT_SWITCHING_ISR can only be called from ARM mode, but
|
||||
* are included here for efficiency. An attempt to call one from
|
||||
* THUMB mode code will result in a compile time error.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
__asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"LDR LR, [R0] \n\t" \
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDMFD LR!, {R1} \n\t" \
|
||||
"STR R1, [R0] \n\t" \
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t" \
|
||||
"MSR SPSR, R0 \n\t" \
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t" \
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB SP, SP, #4 \n\t" \
|
||||
"LDMIA SP!,{R0} \n\t" \
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t" \
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t" \
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB LR, LR, #60 \n\t" \
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STR LR, [R0] \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
|
||||
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD() __asm volatile ( "SWI 0" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions in
|
||||
* portISR.c to ensure a switch to ARM mode. When THUMB_INTERWORK is not
|
||||
* defined then the utilities are defined as macros here - as per other ports.
|
||||
*/
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
|
||||
#else
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.3
|
||||
|
||||
+ Modified portENTER_SWITCHING_ISR() to allow use with GCC V4.0.1.
|
||||
|
||||
Changes from V3.2.4
|
||||
|
||||
+ Removed the use of the %0 parameter within the assembler macros and
|
||||
replaced them with hard coded registers. This will ensure the
|
||||
assembler does not select the link register as the temp register as
|
||||
was occasionally happening previously.
|
||||
|
||||
+ The assembler statements are now included in a single asm block rather
|
||||
than each line having its own asm block.
|
||||
|
||||
Changes from V4.5.0
|
||||
|
||||
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
|
||||
and replaced them with portYIELD_FROM_ISR() macro. Application code
|
||||
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
|
||||
macros as per the V4.5.1 demo code.
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE portLONG
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP() __asm volatile ( "NOP" );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
|
||||
/*
|
||||
* portRESTORE_CONTEXT, portRESTORE_CONTEXT, portENTER_SWITCHING_ISR
|
||||
* and portEXIT_SWITCHING_ISR can only be called from ARM mode, but
|
||||
* are included here for efficiency. An attempt to call one from
|
||||
* THUMB mode code will result in a compile time error.
|
||||
*/
|
||||
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Set the LR to the task stack. */ \
|
||||
__asm volatile ( \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"LDR LR, [R0] \n\t" \
|
||||
\
|
||||
/* The critical nesting depth is the first item on the stack. */ \
|
||||
/* Load it into the ulCriticalNesting variable. */ \
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDMFD LR!, {R1} \n\t" \
|
||||
"STR R1, [R0] \n\t" \
|
||||
\
|
||||
/* Get the SPSR from the stack. */ \
|
||||
"LDMFD LR!, {R0} \n\t" \
|
||||
"MSR SPSR, R0 \n\t" \
|
||||
\
|
||||
/* Restore all system mode registers for the task. */ \
|
||||
"LDMFD LR, {R0-R14}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
\
|
||||
/* Restore the return address. */ \
|
||||
"LDR LR, [LR, #+60] \n\t" \
|
||||
\
|
||||
/* And return - correcting the offset in the LR to obtain the */ \
|
||||
/* correct address. */ \
|
||||
"SUBS PC, LR, #4 \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portSAVE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile void * volatile pxCurrentTCB; \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
\
|
||||
/* Push R0 as we are going to use the register. */ \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Set R0 to point to the task stack pointer. */ \
|
||||
"STMDB SP,{SP}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB SP, SP, #4 \n\t" \
|
||||
"LDMIA SP!,{R0} \n\t" \
|
||||
\
|
||||
/* Push the return address onto the stack. */ \
|
||||
"STMDB R0!, {LR} \n\t" \
|
||||
\
|
||||
/* Now we have saved LR we can use it instead of R0. */ \
|
||||
"MOV LR, R0 \n\t" \
|
||||
\
|
||||
/* Pop R0 so we can save it onto the system mode stack. */ \
|
||||
"LDMIA SP!, {R0} \n\t" \
|
||||
\
|
||||
/* Push all the system mode registers onto the task stack. */ \
|
||||
"STMDB LR,{R0-LR}^ \n\t" \
|
||||
"NOP \n\t" \
|
||||
"SUB LR, LR, #60 \n\t" \
|
||||
\
|
||||
/* Push the SPSR onto the task stack. */ \
|
||||
"MRS R0, SPSR \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
"LDR R0, =ulCriticalNesting \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STMDB LR!, {R0} \n\t" \
|
||||
\
|
||||
/* Store the new top of stack for the task. */ \
|
||||
"LDR R0, =pxCurrentTCB \n\t" \
|
||||
"LDR R0, [R0] \n\t" \
|
||||
"STR LR, [R0] \n\t" \
|
||||
); \
|
||||
( void ) ulCriticalNesting; \
|
||||
( void ) pxCurrentTCB; \
|
||||
}
|
||||
|
||||
|
||||
#define portYIELD_FROM_ISR() vTaskSwitchContext()
|
||||
#define portYIELD() __asm volatile ( "SWI 0" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
|
||||
/*
|
||||
* The interrupt management utilities can only be called from ARM mode. When
|
||||
* THUMB_INTERWORK is defined the utilities are defined as functions in
|
||||
* portISR.c to ensure a switch to ARM mode. When THUMB_INTERWORK is not
|
||||
* defined then the utilities are defined as macros here - as per other ports.
|
||||
*/
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
|
||||
extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));
|
||||
|
||||
#define portDISABLE_INTERRUPTS() vPortDisableInterruptsFromThumb()
|
||||
#define portENABLE_INTERRUPTS() vPortEnableInterruptsFromThumb()
|
||||
|
||||
#else
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"ORR R0, R0, #0xC0 \n\t" /* Disable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( \
|
||||
"STMDB SP!, {R0} \n\t" /* Push R0. */ \
|
||||
"MRS R0, CPSR \n\t" /* Get CPSR. */ \
|
||||
"BIC R0, R0, #0xC0 \n\t" /* Enable IRQ, FIQ. */ \
|
||||
"MSR CPSR, R0 \n\t" /* Write back modified value. */ \
|
||||
"LDMIA SP!, {R0} " ) /* Pop R0. */
|
||||
|
||||
#endif /* THUMB_INTERWORK */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,432 +1,427 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
.text
|
||||
|
||||
/* Variables and functions. */
|
||||
.extern ullMaxAPIPriorityMask
|
||||
.extern pxCurrentTCB
|
||||
.extern vTaskSwitchContext
|
||||
.extern vApplicationIRQHandler
|
||||
.extern ullPortInterruptNesting
|
||||
.extern ullPortTaskHasFPUContext
|
||||
.extern ullCriticalNesting
|
||||
.extern ullPortYieldRequired
|
||||
.extern ullICCEOIR
|
||||
.extern ullICCIAR
|
||||
.extern _freertos_vector_table
|
||||
|
||||
.global FreeRTOS_IRQ_Handler
|
||||
.global FreeRTOS_SWI_Handler
|
||||
.global vPortRestoreTaskContext
|
||||
|
||||
|
||||
.macro portSAVE_CONTEXT
|
||||
|
||||
/* Switch to use the EL0 stack pointer. */
|
||||
MSR SPSEL, #0
|
||||
|
||||
/* Save the entire context. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X4, X5, [SP, #-0x10]!
|
||||
STP X6, X7, [SP, #-0x10]!
|
||||
STP X8, X9, [SP, #-0x10]!
|
||||
STP X10, X11, [SP, #-0x10]!
|
||||
STP X12, X13, [SP, #-0x10]!
|
||||
STP X14, X15, [SP, #-0x10]!
|
||||
STP X16, X17, [SP, #-0x10]!
|
||||
STP X18, X19, [SP, #-0x10]!
|
||||
STP X20, X21, [SP, #-0x10]!
|
||||
STP X22, X23, [SP, #-0x10]!
|
||||
STP X24, X25, [SP, #-0x10]!
|
||||
STP X26, X27, [SP, #-0x10]!
|
||||
STP X28, X29, [SP, #-0x10]!
|
||||
STP X30, XZR, [SP, #-0x10]!
|
||||
|
||||
/* Save the SPSR. */
|
||||
#if defined( GUEST )
|
||||
MRS X3, SPSR_EL1
|
||||
MRS X2, ELR_EL1
|
||||
#else
|
||||
MRS X3, SPSR_EL3
|
||||
/* Save the ELR. */
|
||||
MRS X2, ELR_EL3
|
||||
#endif
|
||||
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
|
||||
/* Save the critical section nesting depth. */
|
||||
LDR X0, ullCriticalNestingConst
|
||||
LDR X3, [X0]
|
||||
|
||||
/* Save the FPU context indicator. */
|
||||
LDR X0, ullPortTaskHasFPUContextConst
|
||||
LDR X2, [X0]
|
||||
|
||||
/* Save the FPU context, if any (32 128-bit registers). */
|
||||
CMP X2, #0
|
||||
B.EQ 1f
|
||||
STP Q0, Q1, [SP,#-0x20]!
|
||||
STP Q2, Q3, [SP,#-0x20]!
|
||||
STP Q4, Q5, [SP,#-0x20]!
|
||||
STP Q6, Q7, [SP,#-0x20]!
|
||||
STP Q8, Q9, [SP,#-0x20]!
|
||||
STP Q10, Q11, [SP,#-0x20]!
|
||||
STP Q12, Q13, [SP,#-0x20]!
|
||||
STP Q14, Q15, [SP,#-0x20]!
|
||||
STP Q16, Q17, [SP,#-0x20]!
|
||||
STP Q18, Q19, [SP,#-0x20]!
|
||||
STP Q20, Q21, [SP,#-0x20]!
|
||||
STP Q22, Q23, [SP,#-0x20]!
|
||||
STP Q24, Q25, [SP,#-0x20]!
|
||||
STP Q26, Q27, [SP,#-0x20]!
|
||||
STP Q28, Q29, [SP,#-0x20]!
|
||||
STP Q30, Q31, [SP,#-0x20]!
|
||||
|
||||
1:
|
||||
/* Store the critical nesting count and FPU context indicator. */
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
|
||||
LDR X0, pxCurrentTCBConst
|
||||
LDR X1, [X0]
|
||||
MOV X0, SP /* Move SP into X0 for saving. */
|
||||
STR X0, [X1]
|
||||
|
||||
/* Switch to use the ELx stack pointer. */
|
||||
MSR SPSEL, #1
|
||||
|
||||
.endm
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
.macro portRESTORE_CONTEXT
|
||||
|
||||
/* Switch to use the EL0 stack pointer. */
|
||||
MSR SPSEL, #0
|
||||
|
||||
/* Set the SP to point to the stack of the task being restored. */
|
||||
LDR X0, pxCurrentTCBConst
|
||||
LDR X1, [X0]
|
||||
LDR X0, [X1]
|
||||
MOV SP, X0
|
||||
|
||||
LDP X2, X3, [SP], #0x10 /* Critical nesting and FPU context. */
|
||||
|
||||
/* Set the PMR register to be correct for the current critical nesting
|
||||
depth. */
|
||||
LDR X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */
|
||||
MOV X1, #255 /* X1 holds the unmask value. */
|
||||
LDR X4, ullICCPMRConst /* X4 holds the address of the ICCPMR constant. */
|
||||
CMP X3, #0
|
||||
LDR X5, [X4] /* X5 holds the address of the ICCPMR register. */
|
||||
B.EQ 1f
|
||||
LDR X6, ullMaxAPIPriorityMaskConst
|
||||
LDR X1, [X6] /* X1 holds the mask value. */
|
||||
1:
|
||||
STR W1, [X5] /* Write the mask value to ICCPMR. */
|
||||
DSB SY /* _RB_Barriers probably not required here. */
|
||||
ISB SY
|
||||
STR X3, [X0] /* Restore the task's critical nesting count. */
|
||||
|
||||
/* Restore the FPU context indicator. */
|
||||
LDR X0, ullPortTaskHasFPUContextConst
|
||||
STR X2, [X0]
|
||||
|
||||
/* Restore the FPU context, if any. */
|
||||
CMP X2, #0
|
||||
B.EQ 1f
|
||||
LDP Q30, Q31, [SP], #0x20
|
||||
LDP Q28, Q29, [SP], #0x20
|
||||
LDP Q26, Q27, [SP], #0x20
|
||||
LDP Q24, Q25, [SP], #0x20
|
||||
LDP Q22, Q23, [SP], #0x20
|
||||
LDP Q20, Q21, [SP], #0x20
|
||||
LDP Q18, Q19, [SP], #0x20
|
||||
LDP Q16, Q17, [SP], #0x20
|
||||
LDP Q14, Q15, [SP], #0x20
|
||||
LDP Q12, Q13, [SP], #0x20
|
||||
LDP Q10, Q11, [SP], #0x20
|
||||
LDP Q8, Q9, [SP], #0x20
|
||||
LDP Q6, Q7, [SP], #0x20
|
||||
LDP Q4, Q5, [SP], #0x20
|
||||
LDP Q2, Q3, [SP], #0x20
|
||||
LDP Q0, Q1, [SP], #0x20
|
||||
1:
|
||||
LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
|
||||
|
||||
#if defined( GUEST )
|
||||
/* Restore the SPSR. */
|
||||
MSR SPSR_EL1, X3
|
||||
/* Restore the ELR. */
|
||||
MSR ELR_EL1, X2
|
||||
#else
|
||||
/* Restore the SPSR. */
|
||||
MSR SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */
|
||||
/* Restore the ELR. */
|
||||
MSR ELR_EL3, X2
|
||||
#endif
|
||||
|
||||
LDP X30, XZR, [SP], #0x10
|
||||
LDP X28, X29, [SP], #0x10
|
||||
LDP X26, X27, [SP], #0x10
|
||||
LDP X24, X25, [SP], #0x10
|
||||
LDP X22, X23, [SP], #0x10
|
||||
LDP X20, X21, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
/* Switch to use the ELx stack pointer. _RB_ Might not be required. */
|
||||
MSR SPSEL, #1
|
||||
|
||||
ERET
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FreeRTOS_SWI_Handler handler is used to perform a context switch.
|
||||
*****************************************************************************/
|
||||
.align 8
|
||||
.type FreeRTOS_SWI_Handler, %function
|
||||
FreeRTOS_SWI_Handler:
|
||||
/* Save the context of the current task and select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
#if defined( GUEST )
|
||||
MRS X0, ESR_EL1
|
||||
#else
|
||||
MRS X0, ESR_EL3
|
||||
#endif
|
||||
|
||||
LSR X1, X0, #26
|
||||
|
||||
#if defined( GUEST )
|
||||
CMP X1, #0x15 /* 0x15 = SVC instruction. */
|
||||
#else
|
||||
CMP X1, #0x17 /* 0x17 = SMC instruction. */
|
||||
#endif
|
||||
B.NE FreeRTOS_Abort
|
||||
BL vTaskSwitchContext
|
||||
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
FreeRTOS_Abort:
|
||||
/* Full ESR is in X0, exception class code is in X1. */
|
||||
B .
|
||||
|
||||
/******************************************************************************
|
||||
* vPortRestoreTaskContext is used to start the scheduler.
|
||||
*****************************************************************************/
|
||||
.align 8
|
||||
.type vPortRestoreTaskContext, %function
|
||||
vPortRestoreTaskContext:
|
||||
.set freertos_vector_base, _freertos_vector_table
|
||||
|
||||
/* Install the FreeRTOS interrupt handlers. */
|
||||
LDR X1, =freertos_vector_base
|
||||
#if defined( GUEST )
|
||||
MSR VBAR_EL1, X1
|
||||
#else
|
||||
MSR VBAR_EL3, X1
|
||||
#endif
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
/* Start the first task. */
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FreeRTOS_IRQ_Handler handles IRQ entry and exit.
|
||||
*****************************************************************************/
|
||||
.align 8
|
||||
.type FreeRTOS_IRQ_Handler, %function
|
||||
FreeRTOS_IRQ_Handler:
|
||||
/* Save volatile registers. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X4, X5, [SP, #-0x10]!
|
||||
STP X6, X7, [SP, #-0x10]!
|
||||
STP X8, X9, [SP, #-0x10]!
|
||||
STP X10, X11, [SP, #-0x10]!
|
||||
STP X12, X13, [SP, #-0x10]!
|
||||
STP X14, X15, [SP, #-0x10]!
|
||||
STP X16, X17, [SP, #-0x10]!
|
||||
STP X18, X19, [SP, #-0x10]!
|
||||
STP X29, X30, [SP, #-0x10]!
|
||||
|
||||
/* Save the SPSR and ELR. */
|
||||
#if defined( GUEST )
|
||||
MRS X3, SPSR_EL1
|
||||
MRS X2, ELR_EL1
|
||||
#else
|
||||
MRS X3, SPSR_EL3
|
||||
MRS X2, ELR_EL3
|
||||
#endif
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
|
||||
/* Increment the interrupt nesting counter. */
|
||||
LDR X5, ullPortInterruptNestingConst
|
||||
LDR X1, [X5] /* Old nesting count in X1. */
|
||||
ADD X6, X1, #1
|
||||
STR X6, [X5] /* Address of nesting count variable in X5. */
|
||||
|
||||
/* Maintain the interrupt nesting information across the function call. */
|
||||
STP X1, X5, [SP, #-0x10]!
|
||||
|
||||
/* Read value from the interrupt acknowledge register, which is stored in W0
|
||||
for future parameter and interrupt clearing use. */
|
||||
LDR X2, ullICCIARConst
|
||||
LDR X3, [X2]
|
||||
LDR W0, [X3] /* ICCIAR in W0 as parameter. */
|
||||
|
||||
/* Maintain the ICCIAR value across the function call. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
|
||||
/* Call the C handler. */
|
||||
BL vApplicationIRQHandler
|
||||
|
||||
/* Disable interrupts. */
|
||||
MSR DAIFSET, #2
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
/* Restore the ICCIAR value. */
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
/* End IRQ processing by writing ICCIAR to the EOI register. */
|
||||
LDR X4, ullICCEOIRConst
|
||||
LDR X4, [X4]
|
||||
STR W0, [X4]
|
||||
|
||||
/* Restore the critical nesting count. */
|
||||
LDP X1, X5, [SP], #0x10
|
||||
STR X1, [X5]
|
||||
|
||||
/* Has interrupt nesting unwound? */
|
||||
CMP X1, #0
|
||||
B.NE Exit_IRQ_No_Context_Switch
|
||||
|
||||
/* Is a context switch required? */
|
||||
LDR X0, ullPortYieldRequiredConst
|
||||
LDR X1, [X0]
|
||||
CMP X1, #0
|
||||
B.EQ Exit_IRQ_No_Context_Switch
|
||||
|
||||
/* Reset ullPortYieldRequired to 0. */
|
||||
MOV X2, #0
|
||||
STR X2, [X0]
|
||||
|
||||
/* Restore volatile registers. */
|
||||
LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
|
||||
#if defined( GUEST )
|
||||
MSR SPSR_EL1, X5
|
||||
MSR ELR_EL1, X4
|
||||
#else
|
||||
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
|
||||
MSR ELR_EL3, X4
|
||||
#endif
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
LDP X29, X30, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
/* Save the context of the current task and select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
BL vTaskSwitchContext
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
Exit_IRQ_No_Context_Switch:
|
||||
/* Restore volatile registers. */
|
||||
LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
|
||||
#if defined( GUEST )
|
||||
MSR SPSR_EL1, X5
|
||||
MSR ELR_EL1, X4
|
||||
#else
|
||||
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
|
||||
MSR ELR_EL3, X4
|
||||
#endif
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
LDP X29, X30, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
ERET
|
||||
|
||||
|
||||
|
||||
|
||||
.align 8
|
||||
pxCurrentTCBConst: .dword pxCurrentTCB
|
||||
ullCriticalNestingConst: .dword ullCriticalNesting
|
||||
ullPortTaskHasFPUContextConst: .dword ullPortTaskHasFPUContext
|
||||
|
||||
ullICCPMRConst: .dword ullICCPMR
|
||||
ullMaxAPIPriorityMaskConst: .dword ullMaxAPIPriorityMask
|
||||
ullPortInterruptNestingConst: .dword ullPortInterruptNesting
|
||||
ullPortYieldRequiredConst: .dword ullPortYieldRequired
|
||||
ullICCIARConst: .dword ullICCIAR
|
||||
ullICCEOIRConst: .dword ullICCEOIR
|
||||
vApplicationIRQHandlerConst: .word vApplicationIRQHandler
|
||||
|
||||
|
||||
|
||||
.end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
.text
|
||||
|
||||
/* Variables and functions. */
|
||||
.extern ullMaxAPIPriorityMask
|
||||
.extern pxCurrentTCB
|
||||
.extern vTaskSwitchContext
|
||||
.extern vApplicationIRQHandler
|
||||
.extern ullPortInterruptNesting
|
||||
.extern ullPortTaskHasFPUContext
|
||||
.extern ullCriticalNesting
|
||||
.extern ullPortYieldRequired
|
||||
.extern ullICCEOIR
|
||||
.extern ullICCIAR
|
||||
.extern _freertos_vector_table
|
||||
|
||||
.global FreeRTOS_IRQ_Handler
|
||||
.global FreeRTOS_SWI_Handler
|
||||
.global vPortRestoreTaskContext
|
||||
|
||||
|
||||
.macro portSAVE_CONTEXT
|
||||
|
||||
/* Switch to use the EL0 stack pointer. */
|
||||
MSR SPSEL, #0
|
||||
|
||||
/* Save the entire context. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X4, X5, [SP, #-0x10]!
|
||||
STP X6, X7, [SP, #-0x10]!
|
||||
STP X8, X9, [SP, #-0x10]!
|
||||
STP X10, X11, [SP, #-0x10]!
|
||||
STP X12, X13, [SP, #-0x10]!
|
||||
STP X14, X15, [SP, #-0x10]!
|
||||
STP X16, X17, [SP, #-0x10]!
|
||||
STP X18, X19, [SP, #-0x10]!
|
||||
STP X20, X21, [SP, #-0x10]!
|
||||
STP X22, X23, [SP, #-0x10]!
|
||||
STP X24, X25, [SP, #-0x10]!
|
||||
STP X26, X27, [SP, #-0x10]!
|
||||
STP X28, X29, [SP, #-0x10]!
|
||||
STP X30, XZR, [SP, #-0x10]!
|
||||
|
||||
/* Save the SPSR. */
|
||||
#if defined( GUEST )
|
||||
MRS X3, SPSR_EL1
|
||||
MRS X2, ELR_EL1
|
||||
#else
|
||||
MRS X3, SPSR_EL3
|
||||
/* Save the ELR. */
|
||||
MRS X2, ELR_EL3
|
||||
#endif
|
||||
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
|
||||
/* Save the critical section nesting depth. */
|
||||
LDR X0, ullCriticalNestingConst
|
||||
LDR X3, [X0]
|
||||
|
||||
/* Save the FPU context indicator. */
|
||||
LDR X0, ullPortTaskHasFPUContextConst
|
||||
LDR X2, [X0]
|
||||
|
||||
/* Save the FPU context, if any (32 128-bit registers). */
|
||||
CMP X2, #0
|
||||
B.EQ 1f
|
||||
STP Q0, Q1, [SP,#-0x20]!
|
||||
STP Q2, Q3, [SP,#-0x20]!
|
||||
STP Q4, Q5, [SP,#-0x20]!
|
||||
STP Q6, Q7, [SP,#-0x20]!
|
||||
STP Q8, Q9, [SP,#-0x20]!
|
||||
STP Q10, Q11, [SP,#-0x20]!
|
||||
STP Q12, Q13, [SP,#-0x20]!
|
||||
STP Q14, Q15, [SP,#-0x20]!
|
||||
STP Q16, Q17, [SP,#-0x20]!
|
||||
STP Q18, Q19, [SP,#-0x20]!
|
||||
STP Q20, Q21, [SP,#-0x20]!
|
||||
STP Q22, Q23, [SP,#-0x20]!
|
||||
STP Q24, Q25, [SP,#-0x20]!
|
||||
STP Q26, Q27, [SP,#-0x20]!
|
||||
STP Q28, Q29, [SP,#-0x20]!
|
||||
STP Q30, Q31, [SP,#-0x20]!
|
||||
|
||||
1:
|
||||
/* Store the critical nesting count and FPU context indicator. */
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
|
||||
LDR X0, pxCurrentTCBConst
|
||||
LDR X1, [X0]
|
||||
MOV X0, SP /* Move SP into X0 for saving. */
|
||||
STR X0, [X1]
|
||||
|
||||
/* Switch to use the ELx stack pointer. */
|
||||
MSR SPSEL, #1
|
||||
|
||||
.endm
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
.macro portRESTORE_CONTEXT
|
||||
|
||||
/* Switch to use the EL0 stack pointer. */
|
||||
MSR SPSEL, #0
|
||||
|
||||
/* Set the SP to point to the stack of the task being restored. */
|
||||
LDR X0, pxCurrentTCBConst
|
||||
LDR X1, [X0]
|
||||
LDR X0, [X1]
|
||||
MOV SP, X0
|
||||
|
||||
LDP X2, X3, [SP], #0x10 /* Critical nesting and FPU context. */
|
||||
|
||||
/* Set the PMR register to be correct for the current critical nesting
|
||||
depth. */
|
||||
LDR X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */
|
||||
MOV X1, #255 /* X1 holds the unmask value. */
|
||||
LDR X4, ullICCPMRConst /* X4 holds the address of the ICCPMR constant. */
|
||||
CMP X3, #0
|
||||
LDR X5, [X4] /* X5 holds the address of the ICCPMR register. */
|
||||
B.EQ 1f
|
||||
LDR X6, ullMaxAPIPriorityMaskConst
|
||||
LDR X1, [X6] /* X1 holds the mask value. */
|
||||
1:
|
||||
STR W1, [X5] /* Write the mask value to ICCPMR. */
|
||||
DSB SY /* _RB_Barriers probably not required here. */
|
||||
ISB SY
|
||||
STR X3, [X0] /* Restore the task's critical nesting count. */
|
||||
|
||||
/* Restore the FPU context indicator. */
|
||||
LDR X0, ullPortTaskHasFPUContextConst
|
||||
STR X2, [X0]
|
||||
|
||||
/* Restore the FPU context, if any. */
|
||||
CMP X2, #0
|
||||
B.EQ 1f
|
||||
LDP Q30, Q31, [SP], #0x20
|
||||
LDP Q28, Q29, [SP], #0x20
|
||||
LDP Q26, Q27, [SP], #0x20
|
||||
LDP Q24, Q25, [SP], #0x20
|
||||
LDP Q22, Q23, [SP], #0x20
|
||||
LDP Q20, Q21, [SP], #0x20
|
||||
LDP Q18, Q19, [SP], #0x20
|
||||
LDP Q16, Q17, [SP], #0x20
|
||||
LDP Q14, Q15, [SP], #0x20
|
||||
LDP Q12, Q13, [SP], #0x20
|
||||
LDP Q10, Q11, [SP], #0x20
|
||||
LDP Q8, Q9, [SP], #0x20
|
||||
LDP Q6, Q7, [SP], #0x20
|
||||
LDP Q4, Q5, [SP], #0x20
|
||||
LDP Q2, Q3, [SP], #0x20
|
||||
LDP Q0, Q1, [SP], #0x20
|
||||
1:
|
||||
LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
|
||||
|
||||
#if defined( GUEST )
|
||||
/* Restore the SPSR. */
|
||||
MSR SPSR_EL1, X3
|
||||
/* Restore the ELR. */
|
||||
MSR ELR_EL1, X2
|
||||
#else
|
||||
/* Restore the SPSR. */
|
||||
MSR SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */
|
||||
/* Restore the ELR. */
|
||||
MSR ELR_EL3, X2
|
||||
#endif
|
||||
|
||||
LDP X30, XZR, [SP], #0x10
|
||||
LDP X28, X29, [SP], #0x10
|
||||
LDP X26, X27, [SP], #0x10
|
||||
LDP X24, X25, [SP], #0x10
|
||||
LDP X22, X23, [SP], #0x10
|
||||
LDP X20, X21, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
/* Switch to use the ELx stack pointer. _RB_ Might not be required. */
|
||||
MSR SPSEL, #1
|
||||
|
||||
ERET
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FreeRTOS_SWI_Handler handler is used to perform a context switch.
|
||||
*****************************************************************************/
|
||||
.align 8
|
||||
.type FreeRTOS_SWI_Handler, %function
|
||||
FreeRTOS_SWI_Handler:
|
||||
/* Save the context of the current task and select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
#if defined( GUEST )
|
||||
MRS X0, ESR_EL1
|
||||
#else
|
||||
MRS X0, ESR_EL3
|
||||
#endif
|
||||
|
||||
LSR X1, X0, #26
|
||||
|
||||
#if defined( GUEST )
|
||||
CMP X1, #0x15 /* 0x15 = SVC instruction. */
|
||||
#else
|
||||
CMP X1, #0x17 /* 0x17 = SMC instruction. */
|
||||
#endif
|
||||
B.NE FreeRTOS_Abort
|
||||
BL vTaskSwitchContext
|
||||
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
FreeRTOS_Abort:
|
||||
/* Full ESR is in X0, exception class code is in X1. */
|
||||
B .
|
||||
|
||||
/******************************************************************************
|
||||
* vPortRestoreTaskContext is used to start the scheduler.
|
||||
*****************************************************************************/
|
||||
.align 8
|
||||
.type vPortRestoreTaskContext, %function
|
||||
vPortRestoreTaskContext:
|
||||
.set freertos_vector_base, _freertos_vector_table
|
||||
|
||||
/* Install the FreeRTOS interrupt handlers. */
|
||||
LDR X1, =freertos_vector_base
|
||||
#if defined( GUEST )
|
||||
MSR VBAR_EL1, X1
|
||||
#else
|
||||
MSR VBAR_EL3, X1
|
||||
#endif
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
/* Start the first task. */
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FreeRTOS_IRQ_Handler handles IRQ entry and exit.
|
||||
*****************************************************************************/
|
||||
.align 8
|
||||
.type FreeRTOS_IRQ_Handler, %function
|
||||
FreeRTOS_IRQ_Handler:
|
||||
/* Save volatile registers. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X4, X5, [SP, #-0x10]!
|
||||
STP X6, X7, [SP, #-0x10]!
|
||||
STP X8, X9, [SP, #-0x10]!
|
||||
STP X10, X11, [SP, #-0x10]!
|
||||
STP X12, X13, [SP, #-0x10]!
|
||||
STP X14, X15, [SP, #-0x10]!
|
||||
STP X16, X17, [SP, #-0x10]!
|
||||
STP X18, X19, [SP, #-0x10]!
|
||||
STP X29, X30, [SP, #-0x10]!
|
||||
|
||||
/* Save the SPSR and ELR. */
|
||||
#if defined( GUEST )
|
||||
MRS X3, SPSR_EL1
|
||||
MRS X2, ELR_EL1
|
||||
#else
|
||||
MRS X3, SPSR_EL3
|
||||
MRS X2, ELR_EL3
|
||||
#endif
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
|
||||
/* Increment the interrupt nesting counter. */
|
||||
LDR X5, ullPortInterruptNestingConst
|
||||
LDR X1, [X5] /* Old nesting count in X1. */
|
||||
ADD X6, X1, #1
|
||||
STR X6, [X5] /* Address of nesting count variable in X5. */
|
||||
|
||||
/* Maintain the interrupt nesting information across the function call. */
|
||||
STP X1, X5, [SP, #-0x10]!
|
||||
|
||||
/* Read value from the interrupt acknowledge register, which is stored in W0
|
||||
for future parameter and interrupt clearing use. */
|
||||
LDR X2, ullICCIARConst
|
||||
LDR X3, [X2]
|
||||
LDR W0, [X3] /* ICCIAR in W0 as parameter. */
|
||||
|
||||
/* Maintain the ICCIAR value across the function call. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
|
||||
/* Call the C handler. */
|
||||
BL vApplicationIRQHandler
|
||||
|
||||
/* Disable interrupts. */
|
||||
MSR DAIFSET, #2
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
/* Restore the ICCIAR value. */
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
/* End IRQ processing by writing ICCIAR to the EOI register. */
|
||||
LDR X4, ullICCEOIRConst
|
||||
LDR X4, [X4]
|
||||
STR W0, [X4]
|
||||
|
||||
/* Restore the critical nesting count. */
|
||||
LDP X1, X5, [SP], #0x10
|
||||
STR X1, [X5]
|
||||
|
||||
/* Has interrupt nesting unwound? */
|
||||
CMP X1, #0
|
||||
B.NE Exit_IRQ_No_Context_Switch
|
||||
|
||||
/* Is a context switch required? */
|
||||
LDR X0, ullPortYieldRequiredConst
|
||||
LDR X1, [X0]
|
||||
CMP X1, #0
|
||||
B.EQ Exit_IRQ_No_Context_Switch
|
||||
|
||||
/* Reset ullPortYieldRequired to 0. */
|
||||
MOV X2, #0
|
||||
STR X2, [X0]
|
||||
|
||||
/* Restore volatile registers. */
|
||||
LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
|
||||
#if defined( GUEST )
|
||||
MSR SPSR_EL1, X5
|
||||
MSR ELR_EL1, X4
|
||||
#else
|
||||
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
|
||||
MSR ELR_EL3, X4
|
||||
#endif
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
LDP X29, X30, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
/* Save the context of the current task and select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
BL vTaskSwitchContext
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
Exit_IRQ_No_Context_Switch:
|
||||
/* Restore volatile registers. */
|
||||
LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
|
||||
#if defined( GUEST )
|
||||
MSR SPSR_EL1, X5
|
||||
MSR ELR_EL1, X4
|
||||
#else
|
||||
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
|
||||
MSR ELR_EL3, X4
|
||||
#endif
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
LDP X29, X30, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
ERET
|
||||
|
||||
|
||||
|
||||
|
||||
.align 8
|
||||
pxCurrentTCBConst: .dword pxCurrentTCB
|
||||
ullCriticalNestingConst: .dword ullCriticalNesting
|
||||
ullPortTaskHasFPUContextConst: .dword ullPortTaskHasFPUContext
|
||||
|
||||
ullICCPMRConst: .dword ullICCPMR
|
||||
ullMaxAPIPriorityMaskConst: .dword ullMaxAPIPriorityMask
|
||||
ullPortInterruptNestingConst: .dword ullPortInterruptNesting
|
||||
ullPortYieldRequiredConst: .dword ullPortYieldRequired
|
||||
ullICCIARConst: .dword ullICCIAR
|
||||
ullICCEOIRConst: .dword ullICCEOIR
|
||||
vApplicationIRQHandlerConst: .word vApplicationIRQHandler
|
||||
|
||||
|
||||
|
||||
.end
|
||||
|
|
|
|||
|
|
@ -1,212 +1,211 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE size_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef portBASE_TYPE BaseType_t;
|
||||
typedef uint64_t UBaseType_t;
|
||||
|
||||
typedef uint64_t TickType_t;
|
||||
#define portMAX_DELAY ( ( TickType_t ) 0xffffffffffffffff )
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 16
|
||||
#define portPOINTER_SIZE_TYPE uint64_t
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired )\
|
||||
{ \
|
||||
extern uint64_t ullPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ullPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#if defined( GUEST )
|
||||
#define portYIELD() __asm volatile ( "SVC 0" ::: "memory" )
|
||||
#else
|
||||
#define portYIELD() __asm volatile ( "SMC 0" ::: "memory" )
|
||||
#endif
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern UBaseType_t uxPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \
|
||||
__asm volatile ( "DSB SY" ); \
|
||||
__asm volatile ( "ISB SY" );
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \
|
||||
__asm volatile ( "DSB SY" ); \
|
||||
__asm volatile ( "ISB SY" );
|
||||
|
||||
|
||||
/* These macros do not globally disable/enable interrupts. They do mask off
|
||||
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not required for this port but included in case common demo code that uses these
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
/* Prototype of the FreeRTOS tick handler. This must be installed as the
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
|
||||
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
|
||||
before any floating point instructions are executed. */
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
|
||||
/* The number of bits to shift for an interrupt priority is dependent on the
|
||||
number of bits implemented by the interrupt controller. */
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif
|
||||
|
||||
/* Interrupt controller access addresses. */
|
||||
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
|
||||
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
|
||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
|
||||
|
||||
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
|
||||
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
|
||||
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE size_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef portBASE_TYPE BaseType_t;
|
||||
typedef uint64_t UBaseType_t;
|
||||
|
||||
typedef uint64_t TickType_t;
|
||||
#define portMAX_DELAY ( ( TickType_t ) 0xffffffffffffffff )
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 16
|
||||
#define portPOINTER_SIZE_TYPE uint64_t
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired )\
|
||||
{ \
|
||||
extern uint64_t ullPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ullPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#if defined( GUEST )
|
||||
#define portYIELD() __asm volatile ( "SVC 0" ::: "memory" )
|
||||
#else
|
||||
#define portYIELD() __asm volatile ( "SMC 0" ::: "memory" )
|
||||
#endif
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern UBaseType_t uxPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \
|
||||
__asm volatile ( "DSB SY" ); \
|
||||
__asm volatile ( "ISB SY" );
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \
|
||||
__asm volatile ( "DSB SY" ); \
|
||||
__asm volatile ( "ISB SY" );
|
||||
|
||||
|
||||
/* These macros do not globally disable/enable interrupts. They do mask off
|
||||
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not required for this port but included in case common demo code that uses these
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
/* Prototype of the FreeRTOS tick handler. This must be installed as the
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
|
||||
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
|
||||
before any floating point instructions are executed. */
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
|
||||
/* The number of bits to shift for an interrupt priority is dependent on the
|
||||
number of bits implemented by the interrupt controller. */
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif
|
||||
|
||||
/* Interrupt controller access addresses. */
|
||||
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
|
||||
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
|
||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
|
||||
|
||||
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
|
||||
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
|
||||
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -34,91 +34,91 @@
|
|||
#include "task.h"
|
||||
|
||||
#ifndef configUNIQUE_INTERRUPT_PRIORITIES
|
||||
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#endif
|
||||
|
||||
#ifndef configSETUP_TICK_INTERRUPT
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#endif /* configSETUP_TICK_INTERRUPT */
|
||||
|
||||
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See https://www.FreeRTOS.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#endif
|
||||
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
|
||||
#endif
|
||||
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
/* Check the configuration. */
|
||||
#if( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
/* Check the configuration. */
|
||||
#if( configMAX_PRIORITIES > 32 )
|
||||
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
|
||||
#endif
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/* In case security extensions are implemented. */
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#endif
|
||||
|
||||
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
|
||||
portmacro.h. */
|
||||
#ifndef configCLEAR_TICK_INTERRUPT
|
||||
#define configCLEAR_TICK_INTERRUPT()
|
||||
#define configCLEAR_TICK_INTERRUPT()
|
||||
#endif
|
||||
|
||||
/* A critical section is exited when the critical section nesting count reaches
|
||||
this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( size_t ) 0 )
|
||||
#define portNO_CRITICAL_NESTING ( ( size_t ) 0 )
|
||||
|
||||
/* In all GICs 255 can be written to the priority mask register to unmask all
|
||||
(but the lowest) interrupt priority. */
|
||||
#define portUNMASK_VALUE ( 0xFFUL )
|
||||
#define portUNMASK_VALUE ( 0xFFUL )
|
||||
|
||||
/* Tasks are not created with a floating point context, but can be given a
|
||||
floating point context after they have been created. A variable is stored as
|
||||
part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
|
||||
does not have an FPU context, or any other value if the task does have an FPU
|
||||
context. */
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the initial task context. */
|
||||
#define portSP_ELx ( ( StackType_t ) 0x01 )
|
||||
#define portSP_EL0 ( ( StackType_t ) 0x00 )
|
||||
#define portSP_ELx ( ( StackType_t ) 0x01 )
|
||||
#define portSP_EL0 ( ( StackType_t ) 0x00 )
|
||||
|
||||
#if defined( GUEST )
|
||||
#define portEL1 ( ( StackType_t ) 0x04 )
|
||||
#define portINITIAL_PSTATE ( portEL1 | portSP_EL0 )
|
||||
#define portEL1 ( ( StackType_t ) 0x04 )
|
||||
#define portINITIAL_PSTATE ( portEL1 | portSP_EL0 )
|
||||
#else
|
||||
#define portEL3 ( ( StackType_t ) 0x0c )
|
||||
/* At the time of writing, the BSP only supports EL3. */
|
||||
#define portINITIAL_PSTATE ( portEL3 | portSP_EL0 )
|
||||
#define portEL3 ( ( StackType_t ) 0x0c )
|
||||
/* At the time of writing, the BSP only supports EL3. */
|
||||
#define portINITIAL_PSTATE ( portEL3 | portSP_EL0 )
|
||||
#endif
|
||||
|
||||
/* Masks all bits in the APSR other than the mode bits. */
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x0C )
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x0C )
|
||||
|
||||
/* The I bit in the DAIF bits. */
|
||||
#define portDAIF_I ( 0x80 )
|
||||
#define portDAIF_I ( 0x80 )
|
||||
|
||||
/* Macro to unmask all interrupt priorities. */
|
||||
/* s3_0_c4_c6_0 is ICC_PMR_EL1. */
|
||||
#define portCLEAR_INTERRUPT_MASK() \
|
||||
{ \
|
||||
__asm volatile ( "MSR DAIFSET, #2 \n" \
|
||||
"DSB SY \n" \
|
||||
"ISB SY \n" \
|
||||
"MSR s3_0_c4_c6_0, %0 \n" \
|
||||
"DSB SY \n" \
|
||||
"ISB SY \n" \
|
||||
"MSR DAIFCLR, #2 \n" \
|
||||
"DSB SY \n" \
|
||||
"ISB SY \n" \
|
||||
::"r"( portUNMASK_VALUE ) ); \
|
||||
#define portCLEAR_INTERRUPT_MASK() \
|
||||
{ \
|
||||
__asm volatile ( "MSR DAIFSET, #2 \n" \
|
||||
"DSB SY \n" \
|
||||
"ISB SY \n" \
|
||||
"MSR s3_0_c4_c6_0, %0 \n" \
|
||||
"DSB SY \n" \
|
||||
"ISB SY \n" \
|
||||
"MSR DAIFCLR, #2 \n" \
|
||||
"DSB SY \n" \
|
||||
"ISB SY \n" \
|
||||
::"r"( portUNMASK_VALUE ) ); \
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
@ -159,93 +159,93 @@ __attribute__(( used )) const uint64_t ullMaxAPIPriorityMask = ( configMAX_API_C
|
|||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* First all the general purpose registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0101010101010101ULL; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0303030303030303ULL; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0202020202020202ULL; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0505050505050505ULL; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0404040404040404ULL; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0707070707070707ULL; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0606060606060606ULL; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0909090909090909ULL; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0808080808080808ULL; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1111111111111111ULL; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1010101010101010ULL; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1313131313131313ULL; /* R13 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1212121212121212ULL; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1515151515151515ULL; /* R15 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1414141414141414ULL; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1717171717171717ULL; /* R17 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1616161616161616ULL; /* R16 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1919191919191919ULL; /* R19 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1818181818181818ULL; /* R18 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2121212121212121ULL; /* R21 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2020202020202020ULL; /* R20 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2323232323232323ULL; /* R23 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2222222222222222ULL; /* R22 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2525252525252525ULL; /* R25 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2424242424242424ULL; /* R24 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2727272727272727ULL; /* R27 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2626262626262626ULL; /* R26 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2929292929292929ULL; /* R29 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2828282828282828ULL; /* R28 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */
|
||||
pxTopOfStack--;
|
||||
/* First all the general purpose registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0101010101010101ULL; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0303030303030303ULL; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0202020202020202ULL; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0505050505050505ULL; /* R5 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0404040404040404ULL; /* R4 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0707070707070707ULL; /* R7 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0606060606060606ULL; /* R6 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0909090909090909ULL; /* R9 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x0808080808080808ULL; /* R8 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1111111111111111ULL; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1010101010101010ULL; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1313131313131313ULL; /* R13 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1212121212121212ULL; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1515151515151515ULL; /* R15 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1414141414141414ULL; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1717171717171717ULL; /* R17 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1616161616161616ULL; /* R16 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1919191919191919ULL; /* R19 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x1818181818181818ULL; /* R18 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2121212121212121ULL; /* R21 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2020202020202020ULL; /* R20 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2323232323232323ULL; /* R23 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2222222222222222ULL; /* R22 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2525252525252525ULL; /* R25 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2424242424242424ULL; /* R24 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2727272727272727ULL; /* R27 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2626262626262626ULL; /* R26 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2929292929292929ULL; /* R29 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x2828282828282828ULL; /* R28 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* XZR - has no effect, used so there are an even number of registers. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R30 - procedure call link register. */
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = portINITIAL_PSTATE;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_PSTATE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* Exception return address. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The task will start with a critical nesting count of 0 as interrupts are
|
||||
enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
pxTopOfStack--;
|
||||
/* The task will start with a critical nesting count of 0 as interrupts are
|
||||
enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The task will start without a floating point context. A task that uses
|
||||
the floating point hardware must call vPortTaskUsesFPU() before executing
|
||||
any floating point instructions. */
|
||||
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
|
||||
/* The task will start without a floating point context. A task that uses
|
||||
the floating point hardware must call vPortTaskUsesFPU() before executing
|
||||
any floating point instructions. */
|
||||
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
|
||||
|
||||
return pxTopOfStack;
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -253,149 +253,149 @@ BaseType_t xPortStartScheduler( void )
|
|||
{
|
||||
uint32_t ulAPSR;
|
||||
|
||||
__asm volatile ( "MRS %0, CurrentEL" : "=r" ( ulAPSR ) );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
__asm volatile ( "MRS %0, CurrentEL" : "=r" ( ulAPSR ) );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
|
||||
#if defined( GUEST )
|
||||
configASSERT( ulAPSR == portEL1 );
|
||||
if( ulAPSR == portEL1 )
|
||||
configASSERT( ulAPSR == portEL1 );
|
||||
if( ulAPSR == portEL1 )
|
||||
#else
|
||||
configASSERT( ulAPSR == portEL3 );
|
||||
if( ulAPSR == portEL3 )
|
||||
configASSERT( ulAPSR == portEL3 );
|
||||
if( ulAPSR == portEL3 )
|
||||
#endif
|
||||
{
|
||||
/* Interrupts are turned off in the CPU itself to ensure a tick does
|
||||
not execute while the scheduler is being started. Interrupts are
|
||||
automatically turned back on in the CPU when the first task starts
|
||||
executing. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
/* Interrupts are turned off in the CPU itself to ensure a tick does
|
||||
not execute while the scheduler is being started. Interrupts are
|
||||
automatically turned back on in the CPU when the first task starts
|
||||
executing. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
|
||||
/* Start the first task executing. */
|
||||
vPortRestoreTaskContext();
|
||||
}
|
||||
/* Start the first task executing. */
|
||||
vPortRestoreTaskContext();
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( ullCriticalNesting == 1000ULL );
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( ullCriticalNesting == 1000ULL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Mask interrupts up to the max syscall interrupt priority. */
|
||||
uxPortSetInterruptMask();
|
||||
/* Mask interrupts up to the max syscall interrupt priority. */
|
||||
uxPortSetInterruptMask();
|
||||
|
||||
/* Now interrupts are disabled ullCriticalNesting can be accessed
|
||||
directly. Increment ullCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ullCriticalNesting++;
|
||||
/* Now interrupts are disabled ullCriticalNesting can be accessed
|
||||
directly. Increment ullCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ullCriticalNesting++;
|
||||
|
||||
/* This is not the interrupt safe version of the enter critical function so
|
||||
assert() if it is being called from an interrupt context. Only API
|
||||
functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||
the critical nesting count is 1 to protect against recursive calls if the
|
||||
assert function also uses a critical section. */
|
||||
if( ullCriticalNesting == 1ULL )
|
||||
{
|
||||
configASSERT( ullPortInterruptNesting == 0 );
|
||||
}
|
||||
/* This is not the interrupt safe version of the enter critical function so
|
||||
assert() if it is being called from an interrupt context. Only API
|
||||
functions that end in "FromISR" can be used in an interrupt. Only assert if
|
||||
the critical nesting count is 1 to protect against recursive calls if the
|
||||
assert function also uses a critical section. */
|
||||
if( ullCriticalNesting == 1ULL )
|
||||
{
|
||||
configASSERT( ullPortInterruptNesting == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ullCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
exited. */
|
||||
ullCriticalNesting--;
|
||||
if( ullCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
exited. */
|
||||
ullCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
priorities must be re-enabled. */
|
||||
if( ullCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
should be unmasked. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
priorities must be re-enabled. */
|
||||
if( ullCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
should be unmasked. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_Tick_Handler( void )
|
||||
{
|
||||
/* Must be the lowest possible priority. */
|
||||
#if !defined( QEMU )
|
||||
{
|
||||
uint64_t ullRunningInterruptPriority;
|
||||
/* s3_0_c12_c11_3 is ICC_RPR_EL1. */
|
||||
__asm volatile ( "MRS %0, s3_0_c12_c11_3" : "=r" ( ullRunningInterruptPriority ) );
|
||||
configASSERT( ullRunningInterruptPriority == ( portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
}
|
||||
#endif
|
||||
/* Must be the lowest possible priority. */
|
||||
#if !defined( QEMU )
|
||||
{
|
||||
uint64_t ullRunningInterruptPriority;
|
||||
/* s3_0_c12_c11_3 is ICC_RPR_EL1. */
|
||||
__asm volatile ( "MRS %0, s3_0_c12_c11_3" : "=r" ( ullRunningInterruptPriority ) );
|
||||
configASSERT( ullRunningInterruptPriority == ( portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Interrupts should not be enabled before this point. */
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
uint32_t ulMaskBits;
|
||||
/* Interrupts should not be enabled before this point. */
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
uint32_t ulMaskBits;
|
||||
|
||||
__asm volatile( "MRS %0, DAIF" : "=r"( ulMaskBits ) :: "memory" );
|
||||
configASSERT( ( ulMaskBits & portDAIF_I ) != 0 );
|
||||
}
|
||||
#endif /* configASSERT_DEFINED */
|
||||
__asm volatile( "MRS %0, DAIF" : "=r"( ulMaskBits ) :: "memory" );
|
||||
configASSERT( ( ulMaskBits & portDAIF_I ) != 0 );
|
||||
}
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/* Set interrupt mask before altering scheduler structures. The tick
|
||||
handler runs at the lowest priority, so interrupts cannot already be masked,
|
||||
so there is no need to save and restore the current mask value. It is
|
||||
necessary to turn off interrupts in the CPU itself while the ICCPMR is being
|
||||
updated. */
|
||||
/* s3_0_c4_c6_0 is ICC_PMR_EL1. */
|
||||
__asm volatile ( "MSR s3_0_c4_c6_0, %0 \n"
|
||||
"DSB SY \n"
|
||||
"ISB SY \n"
|
||||
:: "r" ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) : "memory" );
|
||||
/* Set interrupt mask before altering scheduler structures. The tick
|
||||
handler runs at the lowest priority, so interrupts cannot already be masked,
|
||||
so there is no need to save and restore the current mask value. It is
|
||||
necessary to turn off interrupts in the CPU itself while the ICCPMR is being
|
||||
updated. */
|
||||
/* s3_0_c4_c6_0 is ICC_PMR_EL1. */
|
||||
__asm volatile ( "MSR s3_0_c4_c6_0, %0 \n"
|
||||
"DSB SY \n"
|
||||
"ISB SY \n"
|
||||
:: "r" ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) : "memory" );
|
||||
|
||||
/* Ok to enable interrupts after the interrupt source has been cleared. */
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
portENABLE_INTERRUPTS();
|
||||
/* Ok to enable interrupts after the interrupt source has been cleared. */
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ullPortYieldRequired = pdTRUE;
|
||||
}
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ullPortYieldRequired = pdTRUE;
|
||||
}
|
||||
|
||||
/* Ensure all interrupt priorities are active again. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
/* Ensure all interrupt priorities are active again. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortTaskUsesFPU( void )
|
||||
{
|
||||
/* A task is registering the fact that it needs an FPU context. Set the
|
||||
FPU flag (which is saved as part of the task context). */
|
||||
ullPortTaskHasFPUContext = pdTRUE;
|
||||
/* A task is registering the fact that it needs an FPU context. Set the
|
||||
FPU flag (which is saved as part of the task context). */
|
||||
ullPortTaskHasFPUContext = pdTRUE;
|
||||
|
||||
/* Consider initialising the FPSR here - but probably not necessary in
|
||||
AArch64. */
|
||||
/* Consider initialising the FPSR here - but probably not necessary in
|
||||
AArch64. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortClearInterruptMask( UBaseType_t uxNewMaskValue )
|
||||
{
|
||||
if( uxNewMaskValue == pdFALSE )
|
||||
{
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
if( uxNewMaskValue == pdFALSE )
|
||||
{
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -404,56 +404,55 @@ UBaseType_t uxPortSetInterruptMask( void )
|
|||
uint32_t ulReturn;
|
||||
uint64_t ullPMRValue;
|
||||
|
||||
/* Interrupt in the CPU must be turned off while the ICCPMR is being
|
||||
updated. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
/* s3_0_c4_c6_0 is ICC_PMR_EL1. */
|
||||
__asm volatile ( "MRS %0, s3_0_c4_c6_0" : "=r" ( ullPMRValue ) );
|
||||
if( ullPMRValue == ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
|
||||
{
|
||||
/* Interrupts were already masked. */
|
||||
ulReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturn = pdFALSE;
|
||||
/* s3_0_c4_c6_0 is ICC_PMR_EL1. */
|
||||
__asm volatile ( "MSR s3_0_c4_c6_0, %0 \n"
|
||||
"DSB SY \n"
|
||||
"ISB SY \n"
|
||||
:: "r" ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) : "memory" );
|
||||
}
|
||||
/* Interrupt in the CPU must be turned off while the ICCPMR is being
|
||||
updated. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
/* s3_0_c4_c6_0 is ICC_PMR_EL1. */
|
||||
__asm volatile ( "MRS %0, s3_0_c4_c6_0" : "=r" ( ullPMRValue ) );
|
||||
if( ullPMRValue == ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
|
||||
{
|
||||
/* Interrupts were already masked. */
|
||||
ulReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturn = pdFALSE;
|
||||
/* s3_0_c4_c6_0 is ICC_PMR_EL1. */
|
||||
__asm volatile ( "MSR s3_0_c4_c6_0, %0 \n"
|
||||
"DSB SY \n"
|
||||
"ISB SY \n"
|
||||
:: "r" ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) : "memory" );
|
||||
}
|
||||
|
||||
portENABLE_INTERRUPTS();
|
||||
portENABLE_INTERRUPTS();
|
||||
|
||||
return ulReturn;
|
||||
return ulReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
Numerically low interrupt priority numbers represent logically high
|
||||
interrupt priorities, therefore the priority of the interrupt must
|
||||
be set to a value equal to or numerically *higher* than
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
Numerically low interrupt priority numbers represent logically high
|
||||
interrupt priorities, therefore the priority of the interrupt must
|
||||
be set to a value equal to or numerically *higher* than
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
|
||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
interrupt entry is as fast and simple as possible. */
|
||||
uint64_t ullRunningInterruptPriority;
|
||||
/* s3_0_c12_c11_3 is ICC_RPR_EL1. */
|
||||
__asm volatile ( "MRS %0, s3_0_c12_c11_3" : "=r" ( ullRunningInterruptPriority ) );
|
||||
configASSERT( ullRunningInterruptPriority >= ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
}
|
||||
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||
interrupt entry is as fast and simple as possible. */
|
||||
uint64_t ullRunningInterruptPriority;
|
||||
/* s3_0_c12_c11_3 is ICC_RPR_EL1. */
|
||||
__asm volatile ( "MRS %0, s3_0_c12_c11_3" : "=r" ( ullRunningInterruptPriority ) );
|
||||
configASSERT( ullRunningInterruptPriority >= ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
|
|||
|
|
@ -26,191 +26,191 @@
|
|||
*
|
||||
*/
|
||||
|
||||
.text
|
||||
.text
|
||||
|
||||
/* Variables and functions. */
|
||||
.extern ullMaxAPIPriorityMask
|
||||
.extern pxCurrentTCB
|
||||
.extern vTaskSwitchContext
|
||||
.extern vApplicationIRQHandler
|
||||
.extern ullPortInterruptNesting
|
||||
.extern ullPortTaskHasFPUContext
|
||||
.extern ullCriticalNesting
|
||||
.extern ullPortYieldRequired
|
||||
.extern _freertos_vector_table
|
||||
/* Variables and functions. */
|
||||
.extern ullMaxAPIPriorityMask
|
||||
.extern pxCurrentTCB
|
||||
.extern vTaskSwitchContext
|
||||
.extern vApplicationIRQHandler
|
||||
.extern ullPortInterruptNesting
|
||||
.extern ullPortTaskHasFPUContext
|
||||
.extern ullCriticalNesting
|
||||
.extern ullPortYieldRequired
|
||||
.extern _freertos_vector_table
|
||||
|
||||
.global FreeRTOS_IRQ_Handler
|
||||
.global FreeRTOS_SWI_Handler
|
||||
.global vPortRestoreTaskContext
|
||||
.global FreeRTOS_IRQ_Handler
|
||||
.global FreeRTOS_SWI_Handler
|
||||
.global vPortRestoreTaskContext
|
||||
|
||||
|
||||
.macro portSAVE_CONTEXT
|
||||
|
||||
/* Switch to use the EL0 stack pointer. */
|
||||
MSR SPSEL, #0
|
||||
/* Switch to use the EL0 stack pointer. */
|
||||
MSR SPSEL, #0
|
||||
|
||||
/* Save the entire context. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X4, X5, [SP, #-0x10]!
|
||||
STP X6, X7, [SP, #-0x10]!
|
||||
STP X8, X9, [SP, #-0x10]!
|
||||
STP X10, X11, [SP, #-0x10]!
|
||||
STP X12, X13, [SP, #-0x10]!
|
||||
STP X14, X15, [SP, #-0x10]!
|
||||
STP X16, X17, [SP, #-0x10]!
|
||||
STP X18, X19, [SP, #-0x10]!
|
||||
STP X20, X21, [SP, #-0x10]!
|
||||
STP X22, X23, [SP, #-0x10]!
|
||||
STP X24, X25, [SP, #-0x10]!
|
||||
STP X26, X27, [SP, #-0x10]!
|
||||
STP X28, X29, [SP, #-0x10]!
|
||||
STP X30, XZR, [SP, #-0x10]!
|
||||
/* Save the entire context. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X4, X5, [SP, #-0x10]!
|
||||
STP X6, X7, [SP, #-0x10]!
|
||||
STP X8, X9, [SP, #-0x10]!
|
||||
STP X10, X11, [SP, #-0x10]!
|
||||
STP X12, X13, [SP, #-0x10]!
|
||||
STP X14, X15, [SP, #-0x10]!
|
||||
STP X16, X17, [SP, #-0x10]!
|
||||
STP X18, X19, [SP, #-0x10]!
|
||||
STP X20, X21, [SP, #-0x10]!
|
||||
STP X22, X23, [SP, #-0x10]!
|
||||
STP X24, X25, [SP, #-0x10]!
|
||||
STP X26, X27, [SP, #-0x10]!
|
||||
STP X28, X29, [SP, #-0x10]!
|
||||
STP X30, XZR, [SP, #-0x10]!
|
||||
|
||||
/* Save the SPSR. */
|
||||
/* Save the SPSR. */
|
||||
#if defined( GUEST )
|
||||
MRS X3, SPSR_EL1
|
||||
MRS X2, ELR_EL1
|
||||
MRS X3, SPSR_EL1
|
||||
MRS X2, ELR_EL1
|
||||
#else
|
||||
MRS X3, SPSR_EL3
|
||||
/* Save the ELR. */
|
||||
MRS X2, ELR_EL3
|
||||
MRS X3, SPSR_EL3
|
||||
/* Save the ELR. */
|
||||
MRS X2, ELR_EL3
|
||||
#endif
|
||||
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
|
||||
/* Save the critical section nesting depth. */
|
||||
LDR X0, ullCriticalNestingConst
|
||||
LDR X3, [X0]
|
||||
/* Save the critical section nesting depth. */
|
||||
LDR X0, ullCriticalNestingConst
|
||||
LDR X3, [X0]
|
||||
|
||||
/* Save the FPU context indicator. */
|
||||
LDR X0, ullPortTaskHasFPUContextConst
|
||||
LDR X2, [X0]
|
||||
/* Save the FPU context indicator. */
|
||||
LDR X0, ullPortTaskHasFPUContextConst
|
||||
LDR X2, [X0]
|
||||
|
||||
/* Save the FPU context, if any (32 128-bit registers). */
|
||||
CMP X2, #0
|
||||
B.EQ 1f
|
||||
STP Q0, Q1, [SP,#-0x20]!
|
||||
STP Q2, Q3, [SP,#-0x20]!
|
||||
STP Q4, Q5, [SP,#-0x20]!
|
||||
STP Q6, Q7, [SP,#-0x20]!
|
||||
STP Q8, Q9, [SP,#-0x20]!
|
||||
STP Q10, Q11, [SP,#-0x20]!
|
||||
STP Q12, Q13, [SP,#-0x20]!
|
||||
STP Q14, Q15, [SP,#-0x20]!
|
||||
STP Q16, Q17, [SP,#-0x20]!
|
||||
STP Q18, Q19, [SP,#-0x20]!
|
||||
STP Q20, Q21, [SP,#-0x20]!
|
||||
STP Q22, Q23, [SP,#-0x20]!
|
||||
STP Q24, Q25, [SP,#-0x20]!
|
||||
STP Q26, Q27, [SP,#-0x20]!
|
||||
STP Q28, Q29, [SP,#-0x20]!
|
||||
STP Q30, Q31, [SP,#-0x20]!
|
||||
/* Save the FPU context, if any (32 128-bit registers). */
|
||||
CMP X2, #0
|
||||
B.EQ 1f
|
||||
STP Q0, Q1, [SP,#-0x20]!
|
||||
STP Q2, Q3, [SP,#-0x20]!
|
||||
STP Q4, Q5, [SP,#-0x20]!
|
||||
STP Q6, Q7, [SP,#-0x20]!
|
||||
STP Q8, Q9, [SP,#-0x20]!
|
||||
STP Q10, Q11, [SP,#-0x20]!
|
||||
STP Q12, Q13, [SP,#-0x20]!
|
||||
STP Q14, Q15, [SP,#-0x20]!
|
||||
STP Q16, Q17, [SP,#-0x20]!
|
||||
STP Q18, Q19, [SP,#-0x20]!
|
||||
STP Q20, Q21, [SP,#-0x20]!
|
||||
STP Q22, Q23, [SP,#-0x20]!
|
||||
STP Q24, Q25, [SP,#-0x20]!
|
||||
STP Q26, Q27, [SP,#-0x20]!
|
||||
STP Q28, Q29, [SP,#-0x20]!
|
||||
STP Q30, Q31, [SP,#-0x20]!
|
||||
|
||||
1:
|
||||
/* Store the critical nesting count and FPU context indicator. */
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
/* Store the critical nesting count and FPU context indicator. */
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
|
||||
LDR X0, pxCurrentTCBConst
|
||||
LDR X1, [X0]
|
||||
MOV X0, SP /* Move SP into X0 for saving. */
|
||||
STR X0, [X1]
|
||||
LDR X0, pxCurrentTCBConst
|
||||
LDR X1, [X0]
|
||||
MOV X0, SP /* Move SP into X0 for saving. */
|
||||
STR X0, [X1]
|
||||
|
||||
/* Switch to use the ELx stack pointer. */
|
||||
MSR SPSEL, #1
|
||||
/* Switch to use the ELx stack pointer. */
|
||||
MSR SPSEL, #1
|
||||
|
||||
.endm
|
||||
.endm
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
.macro portRESTORE_CONTEXT
|
||||
|
||||
/* Switch to use the EL0 stack pointer. */
|
||||
MSR SPSEL, #0
|
||||
/* Switch to use the EL0 stack pointer. */
|
||||
MSR SPSEL, #0
|
||||
|
||||
/* Set the SP to point to the stack of the task being restored. */
|
||||
LDR X0, pxCurrentTCBConst
|
||||
LDR X1, [X0]
|
||||
LDR X0, [X1]
|
||||
MOV SP, X0
|
||||
/* Set the SP to point to the stack of the task being restored. */
|
||||
LDR X0, pxCurrentTCBConst
|
||||
LDR X1, [X0]
|
||||
LDR X0, [X1]
|
||||
MOV SP, X0
|
||||
|
||||
LDP X2, X3, [SP], #0x10 /* Critical nesting and FPU context. */
|
||||
LDP X2, X3, [SP], #0x10 /* Critical nesting and FPU context. */
|
||||
|
||||
/* Set the PMR register to be correct for the current critical nesting
|
||||
depth. */
|
||||
LDR X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */
|
||||
MOV X1, #255 /* X1 holds the unmask value. */
|
||||
CMP X3, #0
|
||||
B.EQ 1f
|
||||
LDR X6, ullMaxAPIPriorityMaskConst
|
||||
LDR X1, [X6] /* X1 holds the mask value. */
|
||||
/* Set the PMR register to be correct for the current critical nesting
|
||||
depth. */
|
||||
LDR X0, ullCriticalNestingConst /* X0 holds the address of ullCriticalNesting. */
|
||||
MOV X1, #255 /* X1 holds the unmask value. */
|
||||
CMP X3, #0
|
||||
B.EQ 1f
|
||||
LDR X6, ullMaxAPIPriorityMaskConst
|
||||
LDR X1, [X6] /* X1 holds the mask value. */
|
||||
1:
|
||||
MSR s3_0_c4_c6_0, X1 /* Write the mask value to ICCPMR. s3_0_c4_c6_0 is ICC_PMR_EL1. */
|
||||
DSB SY /* _RB_Barriers probably not required here. */
|
||||
ISB SY
|
||||
STR X3, [X0] /* Restore the task's critical nesting count. */
|
||||
MSR s3_0_c4_c6_0, X1 /* Write the mask value to ICCPMR. s3_0_c4_c6_0 is ICC_PMR_EL1. */
|
||||
DSB SY /* _RB_Barriers probably not required here. */
|
||||
ISB SY
|
||||
STR X3, [X0] /* Restore the task's critical nesting count. */
|
||||
|
||||
/* Restore the FPU context indicator. */
|
||||
LDR X0, ullPortTaskHasFPUContextConst
|
||||
STR X2, [X0]
|
||||
/* Restore the FPU context indicator. */
|
||||
LDR X0, ullPortTaskHasFPUContextConst
|
||||
STR X2, [X0]
|
||||
|
||||
/* Restore the FPU context, if any. */
|
||||
CMP X2, #0
|
||||
B.EQ 1f
|
||||
LDP Q30, Q31, [SP], #0x20
|
||||
LDP Q28, Q29, [SP], #0x20
|
||||
LDP Q26, Q27, [SP], #0x20
|
||||
LDP Q24, Q25, [SP], #0x20
|
||||
LDP Q22, Q23, [SP], #0x20
|
||||
LDP Q20, Q21, [SP], #0x20
|
||||
LDP Q18, Q19, [SP], #0x20
|
||||
LDP Q16, Q17, [SP], #0x20
|
||||
LDP Q14, Q15, [SP], #0x20
|
||||
LDP Q12, Q13, [SP], #0x20
|
||||
LDP Q10, Q11, [SP], #0x20
|
||||
LDP Q8, Q9, [SP], #0x20
|
||||
LDP Q6, Q7, [SP], #0x20
|
||||
LDP Q4, Q5, [SP], #0x20
|
||||
LDP Q2, Q3, [SP], #0x20
|
||||
LDP Q0, Q1, [SP], #0x20
|
||||
/* Restore the FPU context, if any. */
|
||||
CMP X2, #0
|
||||
B.EQ 1f
|
||||
LDP Q30, Q31, [SP], #0x20
|
||||
LDP Q28, Q29, [SP], #0x20
|
||||
LDP Q26, Q27, [SP], #0x20
|
||||
LDP Q24, Q25, [SP], #0x20
|
||||
LDP Q22, Q23, [SP], #0x20
|
||||
LDP Q20, Q21, [SP], #0x20
|
||||
LDP Q18, Q19, [SP], #0x20
|
||||
LDP Q16, Q17, [SP], #0x20
|
||||
LDP Q14, Q15, [SP], #0x20
|
||||
LDP Q12, Q13, [SP], #0x20
|
||||
LDP Q10, Q11, [SP], #0x20
|
||||
LDP Q8, Q9, [SP], #0x20
|
||||
LDP Q6, Q7, [SP], #0x20
|
||||
LDP Q4, Q5, [SP], #0x20
|
||||
LDP Q2, Q3, [SP], #0x20
|
||||
LDP Q0, Q1, [SP], #0x20
|
||||
1:
|
||||
LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
|
||||
LDP X2, X3, [SP], #0x10 /* SPSR and ELR. */
|
||||
|
||||
#if defined( GUEST )
|
||||
/* Restore the SPSR. */
|
||||
MSR SPSR_EL1, X3
|
||||
/* Restore the ELR. */
|
||||
MSR ELR_EL1, X2
|
||||
/* Restore the SPSR. */
|
||||
MSR SPSR_EL1, X3
|
||||
/* Restore the ELR. */
|
||||
MSR ELR_EL1, X2
|
||||
#else
|
||||
/* Restore the SPSR. */
|
||||
MSR SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */
|
||||
/* Restore the ELR. */
|
||||
MSR ELR_EL3, X2
|
||||
/* Restore the SPSR. */
|
||||
MSR SPSR_EL3, X3 /*_RB_ Assumes started in EL3. */
|
||||
/* Restore the ELR. */
|
||||
MSR ELR_EL3, X2
|
||||
#endif
|
||||
|
||||
LDP X30, XZR, [SP], #0x10
|
||||
LDP X28, X29, [SP], #0x10
|
||||
LDP X26, X27, [SP], #0x10
|
||||
LDP X24, X25, [SP], #0x10
|
||||
LDP X22, X23, [SP], #0x10
|
||||
LDP X20, X21, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
LDP X30, XZR, [SP], #0x10
|
||||
LDP X28, X29, [SP], #0x10
|
||||
LDP X26, X27, [SP], #0x10
|
||||
LDP X24, X25, [SP], #0x10
|
||||
LDP X22, X23, [SP], #0x10
|
||||
LDP X20, X21, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
/* Switch to use the ELx stack pointer. _RB_ Might not be required. */
|
||||
MSR SPSEL, #1
|
||||
/* Switch to use the ELx stack pointer. _RB_ Might not be required. */
|
||||
MSR SPSEL, #1
|
||||
|
||||
ERET
|
||||
ERET
|
||||
|
||||
.endm
|
||||
.endm
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
|
|
@ -219,29 +219,29 @@
|
|||
.align 8
|
||||
.type FreeRTOS_SWI_Handler, %function
|
||||
FreeRTOS_SWI_Handler:
|
||||
/* Save the context of the current task and select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
/* Save the context of the current task and select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
#if defined( GUEST )
|
||||
MRS X0, ESR_EL1
|
||||
MRS X0, ESR_EL1
|
||||
#else
|
||||
MRS X0, ESR_EL3
|
||||
MRS X0, ESR_EL3
|
||||
#endif
|
||||
|
||||
LSR X1, X0, #26
|
||||
LSR X1, X0, #26
|
||||
|
||||
#if defined( GUEST )
|
||||
CMP X1, #0x15 /* 0x15 = SVC instruction. */
|
||||
CMP X1, #0x15 /* 0x15 = SVC instruction. */
|
||||
#else
|
||||
CMP X1, #0x17 /* 0x17 = SMC instruction. */
|
||||
CMP X1, #0x17 /* 0x17 = SMC instruction. */
|
||||
#endif
|
||||
B.NE FreeRTOS_Abort
|
||||
BL vTaskSwitchContext
|
||||
B.NE FreeRTOS_Abort
|
||||
BL vTaskSwitchContext
|
||||
|
||||
portRESTORE_CONTEXT
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
FreeRTOS_Abort:
|
||||
/* Full ESR is in X0, exception class code is in X1. */
|
||||
B .
|
||||
/* Full ESR is in X0, exception class code is in X1. */
|
||||
B .
|
||||
|
||||
/******************************************************************************
|
||||
* vPortRestoreTaskContext is used to start the scheduler.
|
||||
|
|
@ -249,20 +249,20 @@ FreeRTOS_Abort:
|
|||
.align 8
|
||||
.type vPortRestoreTaskContext, %function
|
||||
vPortRestoreTaskContext:
|
||||
.set freertos_vector_base, _freertos_vector_table
|
||||
.set freertos_vector_base, _freertos_vector_table
|
||||
|
||||
/* Install the FreeRTOS interrupt handlers. */
|
||||
LDR X1, =freertos_vector_base
|
||||
/* Install the FreeRTOS interrupt handlers. */
|
||||
LDR X1, =freertos_vector_base
|
||||
#if defined( GUEST )
|
||||
MSR VBAR_EL1, X1
|
||||
MSR VBAR_EL1, X1
|
||||
#else
|
||||
MSR VBAR_EL3, X1
|
||||
MSR VBAR_EL3, X1
|
||||
#endif
|
||||
DSB SY
|
||||
ISB SY
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
/* Start the first task. */
|
||||
portRESTORE_CONTEXT
|
||||
/* Start the first task. */
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
|
|
@ -279,132 +279,132 @@ vPortRestoreTaskContext:
|
|||
.align 8
|
||||
.type FreeRTOS_IRQ_Handler, %function
|
||||
FreeRTOS_IRQ_Handler:
|
||||
/* Save volatile registers. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X4, X5, [SP, #-0x10]!
|
||||
STP X6, X7, [SP, #-0x10]!
|
||||
STP X8, X9, [SP, #-0x10]!
|
||||
STP X10, X11, [SP, #-0x10]!
|
||||
STP X12, X13, [SP, #-0x10]!
|
||||
STP X14, X15, [SP, #-0x10]!
|
||||
STP X16, X17, [SP, #-0x10]!
|
||||
STP X18, X19, [SP, #-0x10]!
|
||||
STP X29, X30, [SP, #-0x10]!
|
||||
/* Save volatile registers. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X4, X5, [SP, #-0x10]!
|
||||
STP X6, X7, [SP, #-0x10]!
|
||||
STP X8, X9, [SP, #-0x10]!
|
||||
STP X10, X11, [SP, #-0x10]!
|
||||
STP X12, X13, [SP, #-0x10]!
|
||||
STP X14, X15, [SP, #-0x10]!
|
||||
STP X16, X17, [SP, #-0x10]!
|
||||
STP X18, X19, [SP, #-0x10]!
|
||||
STP X29, X30, [SP, #-0x10]!
|
||||
|
||||
/* Save the SPSR and ELR. */
|
||||
/* Save the SPSR and ELR. */
|
||||
#if defined( GUEST )
|
||||
MRS X3, SPSR_EL1
|
||||
MRS X2, ELR_EL1
|
||||
MRS X3, SPSR_EL1
|
||||
MRS X2, ELR_EL1
|
||||
#else
|
||||
MRS X3, SPSR_EL3
|
||||
MRS X2, ELR_EL3
|
||||
MRS X3, SPSR_EL3
|
||||
MRS X2, ELR_EL3
|
||||
#endif
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
STP X2, X3, [SP, #-0x10]!
|
||||
|
||||
/* Increment the interrupt nesting counter. */
|
||||
LDR X5, ullPortInterruptNestingConst
|
||||
LDR X1, [X5] /* Old nesting count in X1. */
|
||||
ADD X6, X1, #1
|
||||
STR X6, [X5] /* Address of nesting count variable in X5. */
|
||||
/* Increment the interrupt nesting counter. */
|
||||
LDR X5, ullPortInterruptNestingConst
|
||||
LDR X1, [X5] /* Old nesting count in X1. */
|
||||
ADD X6, X1, #1
|
||||
STR X6, [X5] /* Address of nesting count variable in X5. */
|
||||
|
||||
/* Maintain the interrupt nesting information across the function call. */
|
||||
STP X1, X5, [SP, #-0x10]!
|
||||
/* Maintain the interrupt nesting information across the function call. */
|
||||
STP X1, X5, [SP, #-0x10]!
|
||||
|
||||
/* Read interrupt ID from the interrupt acknowledge register and store it
|
||||
in X0 for future parameter and interrupt clearing use. */
|
||||
MRS X0, S3_0_C12_C12_0 /* S3_0_C12_C12_0 is ICC_IAR1_EL1. */
|
||||
/* Read interrupt ID from the interrupt acknowledge register and store it
|
||||
in X0 for future parameter and interrupt clearing use. */
|
||||
MRS X0, S3_0_C12_C12_0 /* S3_0_C12_C12_0 is ICC_IAR1_EL1. */
|
||||
|
||||
/* Maintain the interrupt ID value across the function call. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
/* Maintain the interrupt ID value across the function call. */
|
||||
STP X0, X1, [SP, #-0x10]!
|
||||
|
||||
/* Call the C handler. */
|
||||
BL vApplicationIRQHandler
|
||||
/* Call the C handler. */
|
||||
BL vApplicationIRQHandler
|
||||
|
||||
/* Disable interrupts. */
|
||||
MSR DAIFSET, #2
|
||||
DSB SY
|
||||
ISB SY
|
||||
/* Disable interrupts. */
|
||||
MSR DAIFSET, #2
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
/* Restore the interrupt ID value. */
|
||||
LDP X0, X1, [SP], #0x10
|
||||
/* Restore the interrupt ID value. */
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
/* End IRQ processing by writing interrupt ID value to the EOI register. */
|
||||
MSR S3_0_C12_C12_1, X0 /* S3_0_C12_C12_1 is ICC_EOIR1_EL1. */
|
||||
/* End IRQ processing by writing interrupt ID value to the EOI register. */
|
||||
MSR S3_0_C12_C12_1, X0 /* S3_0_C12_C12_1 is ICC_EOIR1_EL1. */
|
||||
|
||||
/* Restore the critical nesting count. */
|
||||
LDP X1, X5, [SP], #0x10
|
||||
STR X1, [X5]
|
||||
/* Restore the critical nesting count. */
|
||||
LDP X1, X5, [SP], #0x10
|
||||
STR X1, [X5]
|
||||
|
||||
/* Has interrupt nesting unwound? */
|
||||
CMP X1, #0
|
||||
B.NE Exit_IRQ_No_Context_Switch
|
||||
/* Has interrupt nesting unwound? */
|
||||
CMP X1, #0
|
||||
B.NE Exit_IRQ_No_Context_Switch
|
||||
|
||||
/* Is a context switch required? */
|
||||
LDR X0, ullPortYieldRequiredConst
|
||||
LDR X1, [X0]
|
||||
CMP X1, #0
|
||||
B.EQ Exit_IRQ_No_Context_Switch
|
||||
/* Is a context switch required? */
|
||||
LDR X0, ullPortYieldRequiredConst
|
||||
LDR X1, [X0]
|
||||
CMP X1, #0
|
||||
B.EQ Exit_IRQ_No_Context_Switch
|
||||
|
||||
/* Reset ullPortYieldRequired to 0. */
|
||||
MOV X2, #0
|
||||
STR X2, [X0]
|
||||
/* Reset ullPortYieldRequired to 0. */
|
||||
MOV X2, #0
|
||||
STR X2, [X0]
|
||||
|
||||
/* Restore volatile registers. */
|
||||
LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
|
||||
/* Restore volatile registers. */
|
||||
LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
|
||||
#if defined( GUEST )
|
||||
MSR SPSR_EL1, X5
|
||||
MSR ELR_EL1, X4
|
||||
MSR SPSR_EL1, X5
|
||||
MSR ELR_EL1, X4
|
||||
#else
|
||||
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
|
||||
MSR ELR_EL3, X4
|
||||
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
|
||||
MSR ELR_EL3, X4
|
||||
#endif
|
||||
DSB SY
|
||||
ISB SY
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
LDP X29, X30, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
LDP X29, X30, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
/* Save the context of the current task and select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
BL vTaskSwitchContext
|
||||
portRESTORE_CONTEXT
|
||||
/* Save the context of the current task and select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
BL vTaskSwitchContext
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
Exit_IRQ_No_Context_Switch:
|
||||
/* Restore volatile registers. */
|
||||
LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
|
||||
/* Restore volatile registers. */
|
||||
LDP X4, X5, [SP], #0x10 /* SPSR and ELR. */
|
||||
#if defined( GUEST )
|
||||
MSR SPSR_EL1, X5
|
||||
MSR ELR_EL1, X4
|
||||
MSR SPSR_EL1, X5
|
||||
MSR ELR_EL1, X4
|
||||
#else
|
||||
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
|
||||
MSR ELR_EL3, X4
|
||||
MSR SPSR_EL3, X5 /*_RB_ Assumes started in EL3. */
|
||||
MSR ELR_EL3, X4
|
||||
#endif
|
||||
DSB SY
|
||||
ISB SY
|
||||
DSB SY
|
||||
ISB SY
|
||||
|
||||
LDP X29, X30, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
LDP X29, X30, [SP], #0x10
|
||||
LDP X18, X19, [SP], #0x10
|
||||
LDP X16, X17, [SP], #0x10
|
||||
LDP X14, X15, [SP], #0x10
|
||||
LDP X12, X13, [SP], #0x10
|
||||
LDP X10, X11, [SP], #0x10
|
||||
LDP X8, X9, [SP], #0x10
|
||||
LDP X6, X7, [SP], #0x10
|
||||
LDP X4, X5, [SP], #0x10
|
||||
LDP X2, X3, [SP], #0x10
|
||||
LDP X0, X1, [SP], #0x10
|
||||
|
||||
ERET
|
||||
ERET
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
|
|
@ -44,13 +44,13 @@
|
|||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE size_t
|
||||
#define portBASE_TYPE long
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE size_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef portBASE_TYPE BaseType_t;
|
||||
|
|
@ -66,10 +66,10 @@ not need to be guarded with a critical section. */
|
|||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 16
|
||||
#define portPOINTER_SIZE_TYPE uint64_t
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 16
|
||||
#define portPOINTER_SIZE_TYPE uint64_t
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
@ -77,20 +77,20 @@ not need to be guarded with a critical section. */
|
|||
|
||||
/* Called at the end of an ISR that can cause a context switch. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired )\
|
||||
{ \
|
||||
extern uint64_t ullPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ullPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
{ \
|
||||
extern uint64_t ullPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ullPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#if defined( GUEST )
|
||||
#define portYIELD() __asm volatile ( "SVC 0" ::: "memory" )
|
||||
#define portYIELD() __asm volatile ( "SVC 0" ::: "memory" )
|
||||
#else
|
||||
#define portYIELD() __asm volatile ( "SMC 0" ::: "memory" )
|
||||
#define portYIELD() __asm volatile ( "SMC 0" ::: "memory" )
|
||||
#endif
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
|
|
@ -102,31 +102,31 @@ extern UBaseType_t uxPortSetInterruptMask( void );
|
|||
extern void vPortClearInterruptMask( UBaseType_t uxNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \
|
||||
__asm volatile ( "DSB SY" ); \
|
||||
__asm volatile ( "ISB SY" );
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
__asm volatile ( "MSR DAIFSET, #2" ::: "memory" ); \
|
||||
__asm volatile ( "DSB SY" ); \
|
||||
__asm volatile ( "ISB SY" );
|
||||
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \
|
||||
__asm volatile ( "DSB SY" ); \
|
||||
__asm volatile ( "ISB SY" );
|
||||
#define portENABLE_INTERRUPTS() \
|
||||
__asm volatile ( "MSR DAIFCLR, #2" ::: "memory" ); \
|
||||
__asm volatile ( "DSB SY" ); \
|
||||
__asm volatile ( "ISB SY" );
|
||||
|
||||
|
||||
/* These macros do not globally disable/enable interrupts. They do mask off
|
||||
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not required for this port but included in case common demo code that uses these
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
/* Prototype of the FreeRTOS tick handler. This must be installed as the
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
|
|
@ -142,56 +142,55 @@ void vPortTaskUsesFPU( void );
|
|||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
|
||||
/* The number of bits to shift for an interrupt priority is dependent on the
|
||||
number of bits implemented by the interrupt controller. */
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,324 +1,319 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
.text
|
||||
.arm
|
||||
|
||||
.set SYS_MODE, 0x1f
|
||||
.set SVC_MODE, 0x13
|
||||
.set IRQ_MODE, 0x12
|
||||
|
||||
/* Hardware registers. */
|
||||
.extern ulICCIAR
|
||||
.extern ulICCEOIR
|
||||
.extern ulICCPMR
|
||||
|
||||
/* Variables and functions. */
|
||||
.extern ulMaxAPIPriorityMask
|
||||
.extern _freertos_vector_table
|
||||
.extern pxCurrentTCB
|
||||
.extern vTaskSwitchContext
|
||||
.extern vApplicationIRQHandler
|
||||
.extern ulPortInterruptNesting
|
||||
.extern ulPortTaskHasFPUContext
|
||||
|
||||
.global FreeRTOS_IRQ_Handler
|
||||
.global FreeRTOS_SWI_Handler
|
||||
.global vPortRestoreTaskContext
|
||||
|
||||
|
||||
|
||||
|
||||
.macro portSAVE_CONTEXT
|
||||
|
||||
/* Save the LR and SPSR onto the system mode stack before switching to
|
||||
system mode to save the remaining system mode registers. */
|
||||
SRSDB sp!, #SYS_MODE
|
||||
CPS #SYS_MODE
|
||||
PUSH {R0-R12, R14}
|
||||
|
||||
/* Push the critical nesting count. */
|
||||
LDR R2, ulCriticalNestingConst
|
||||
LDR R1, [R2]
|
||||
PUSH {R1}
|
||||
|
||||
/* Does the task have a floating point context that needs saving? If
|
||||
ulPortTaskHasFPUContext is 0 then no. */
|
||||
LDR R2, ulPortTaskHasFPUContextConst
|
||||
LDR R3, [R2]
|
||||
CMP R3, #0
|
||||
|
||||
/* Save the floating point context, if any. */
|
||||
FMRXNE R1, FPSCR
|
||||
VPUSHNE {D0-D15}
|
||||
VPUSHNE {D16-D31}
|
||||
PUSHNE {R1}
|
||||
|
||||
/* Save ulPortTaskHasFPUContext itself. */
|
||||
PUSH {R3}
|
||||
|
||||
/* Save the stack pointer in the TCB. */
|
||||
LDR R0, pxCurrentTCBConst
|
||||
LDR R1, [R0]
|
||||
STR SP, [R1]
|
||||
|
||||
.endm
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
.macro portRESTORE_CONTEXT
|
||||
|
||||
/* Set the SP to point to the stack of the task being restored. */
|
||||
LDR R0, pxCurrentTCBConst
|
||||
LDR R1, [R0]
|
||||
LDR SP, [R1]
|
||||
|
||||
/* Is there a floating point context to restore? If the restored
|
||||
ulPortTaskHasFPUContext is zero then no. */
|
||||
LDR R0, ulPortTaskHasFPUContextConst
|
||||
POP {R1}
|
||||
STR R1, [R0]
|
||||
CMP R1, #0
|
||||
|
||||
/* Restore the floating point context, if any. */
|
||||
POPNE {R0}
|
||||
VPOPNE {D16-D31}
|
||||
VPOPNE {D0-D15}
|
||||
VMSRNE FPSCR, R0
|
||||
|
||||
/* Restore the critical section nesting depth. */
|
||||
LDR R0, ulCriticalNestingConst
|
||||
POP {R1}
|
||||
STR R1, [R0]
|
||||
|
||||
/* Ensure the priority mask is correct for the critical nesting depth. */
|
||||
LDR R2, ulICCPMRConst
|
||||
LDR R2, [R2]
|
||||
CMP R1, #0
|
||||
MOVEQ R4, #255
|
||||
LDRNE R4, ulMaxAPIPriorityMaskConst
|
||||
LDRNE R4, [R4]
|
||||
STR R4, [R2]
|
||||
|
||||
/* Restore all system mode registers other than the SP (which is already
|
||||
being used). */
|
||||
POP {R0-R12, R14}
|
||||
|
||||
/* Return to the task code, loading CPSR on the way. */
|
||||
RFEIA sp!
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* SVC handler is used to start the scheduler.
|
||||
*****************************************************************************/
|
||||
.align 4
|
||||
.type FreeRTOS_SWI_Handler, %function
|
||||
FreeRTOS_SWI_Handler:
|
||||
/* Save the context of the current task and select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
LDR R0, vTaskSwitchContextConst
|
||||
BLX R0
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* vPortRestoreTaskContext is used to start the scheduler.
|
||||
*****************************************************************************/
|
||||
.type vPortRestoreTaskContext, %function
|
||||
vPortRestoreTaskContext:
|
||||
/* Switch to system mode. */
|
||||
CPS #SYS_MODE
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
.align 4
|
||||
.type FreeRTOS_IRQ_Handler, %function
|
||||
FreeRTOS_IRQ_Handler:
|
||||
/* Return to the interrupted instruction. */
|
||||
SUB lr, lr, #4
|
||||
|
||||
/* Push the return address and SPSR. */
|
||||
PUSH {lr}
|
||||
MRS lr, SPSR
|
||||
PUSH {lr}
|
||||
|
||||
/* Change to supervisor mode to allow reentry. */
|
||||
CPS #SVC_MODE
|
||||
|
||||
/* Push used registers. */
|
||||
PUSH {r0-r4, r12}
|
||||
|
||||
/* Increment nesting count. r3 holds the address of ulPortInterruptNesting
|
||||
for future use. r1 holds the original ulPortInterruptNesting value for
|
||||
future use. */
|
||||
LDR r3, ulPortInterruptNestingConst
|
||||
LDR r1, [r3]
|
||||
ADD r4, r1, #1
|
||||
STR r4, [r3]
|
||||
|
||||
/* Read value from the interrupt acknowledge register, which is stored in r0
|
||||
for future parameter and interrupt clearing use. */
|
||||
LDR r2, ulICCIARConst
|
||||
LDR r2, [r2]
|
||||
LDR r0, [r2]
|
||||
|
||||
/* Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for
|
||||
future use. _RB_ Does this ever actually need to be done provided the start
|
||||
of the stack is 8-byte aligned? */
|
||||
MOV r2, sp
|
||||
AND r2, r2, #4
|
||||
SUB sp, sp, r2
|
||||
|
||||
/* Call the interrupt handler. r4 pushed to maintain alignment. */
|
||||
PUSH {r0-r4, lr}
|
||||
LDR r1, vApplicationIRQHandlerConst
|
||||
BLX r1
|
||||
POP {r0-r4, lr}
|
||||
ADD sp, sp, r2
|
||||
|
||||
CPSID i
|
||||
DSB
|
||||
ISB
|
||||
|
||||
/* Write the value read from ICCIAR to ICCEOIR. */
|
||||
LDR r4, ulICCEOIRConst
|
||||
LDR r4, [r4]
|
||||
STR r0, [r4]
|
||||
|
||||
/* Restore the old nesting count. */
|
||||
STR r1, [r3]
|
||||
|
||||
/* A context switch is never performed if the nesting count is not 0. */
|
||||
CMP r1, #0
|
||||
BNE exit_without_switch
|
||||
|
||||
/* Did the interrupt request a context switch? r1 holds the address of
|
||||
ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
|
||||
use. */
|
||||
LDR r1, =ulPortYieldRequired
|
||||
LDR r0, [r1]
|
||||
CMP r0, #0
|
||||
BNE switch_before_exit
|
||||
|
||||
exit_without_switch:
|
||||
/* No context switch. Restore used registers, LR_irq and SPSR before
|
||||
returning. */
|
||||
POP {r0-r4, r12}
|
||||
CPS #IRQ_MODE
|
||||
POP {LR}
|
||||
MSR SPSR_cxsf, LR
|
||||
POP {LR}
|
||||
MOVS PC, LR
|
||||
|
||||
switch_before_exit:
|
||||
/* A context swtich is to be performed. Clear the context switch pending
|
||||
flag. */
|
||||
MOV r0, #0
|
||||
STR r0, [r1]
|
||||
|
||||
/* Restore used registers, LR-irq and SPSR before saving the context
|
||||
to the task stack. */
|
||||
POP {r0-r4, r12}
|
||||
CPS #IRQ_MODE
|
||||
POP {LR}
|
||||
MSR SPSR_cxsf, LR
|
||||
POP {LR}
|
||||
portSAVE_CONTEXT
|
||||
|
||||
/* Call the function that selects the new task to execute.
|
||||
vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
|
||||
instructions, or 8 byte aligned stack allocated data. LR does not need
|
||||
saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */
|
||||
LDR R0, vTaskSwitchContextConst
|
||||
BLX R0
|
||||
|
||||
/* Restore the context of, and branch to, the task selected to execute
|
||||
next. */
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* If the application provides an implementation of vApplicationIRQHandler(),
|
||||
* then it will get called directly without saving the FPU registers on
|
||||
* interrupt entry, and this weak implementation of
|
||||
* vApplicationIRQHandler() will not get called.
|
||||
*
|
||||
* If the application provides its own implementation of
|
||||
* vApplicationFPUSafeIRQHandler() then this implementation of
|
||||
* vApplicationIRQHandler() will be called, save the FPU registers, and then
|
||||
* call vApplicationFPUSafeIRQHandler().
|
||||
*
|
||||
* Therefore, if the application writer wants FPU registers to be saved on
|
||||
* interrupt entry their IRQ handler must be called
|
||||
* vApplicationFPUSafeIRQHandler(), and if the application writer does not want
|
||||
* FPU registers to be saved on interrupt entry their IRQ handler must be
|
||||
* called vApplicationIRQHandler().
|
||||
*****************************************************************************/
|
||||
|
||||
.align 4
|
||||
.weak vApplicationIRQHandler
|
||||
.type vApplicationIRQHandler, %function
|
||||
vApplicationIRQHandler:
|
||||
PUSH {LR}
|
||||
FMRX R1, FPSCR
|
||||
VPUSH {D0-D15}
|
||||
VPUSH {D16-D31}
|
||||
PUSH {R1}
|
||||
|
||||
LDR r1, vApplicationFPUSafeIRQHandlerConst
|
||||
BLX r1
|
||||
|
||||
POP {R0}
|
||||
VPOP {D16-D31}
|
||||
VPOP {D0-D15}
|
||||
VMSR FPSCR, R0
|
||||
|
||||
POP {PC}
|
||||
|
||||
|
||||
ulICCIARConst: .word ulICCIAR
|
||||
ulICCEOIRConst: .word ulICCEOIR
|
||||
ulICCPMRConst: .word ulICCPMR
|
||||
pxCurrentTCBConst: .word pxCurrentTCB
|
||||
ulCriticalNestingConst: .word ulCriticalNesting
|
||||
ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext
|
||||
ulMaxAPIPriorityMaskConst: .word ulMaxAPIPriorityMask
|
||||
vTaskSwitchContextConst: .word vTaskSwitchContext
|
||||
vApplicationIRQHandlerConst: .word vApplicationIRQHandler
|
||||
ulPortInterruptNestingConst: .word ulPortInterruptNesting
|
||||
vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler
|
||||
|
||||
.end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
.eabi_attribute Tag_ABI_align_preserved, 1
|
||||
.text
|
||||
.arm
|
||||
|
||||
.set SYS_MODE, 0x1f
|
||||
.set SVC_MODE, 0x13
|
||||
.set IRQ_MODE, 0x12
|
||||
|
||||
/* Hardware registers. */
|
||||
.extern ulICCIAR
|
||||
.extern ulICCEOIR
|
||||
.extern ulICCPMR
|
||||
|
||||
/* Variables and functions. */
|
||||
.extern ulMaxAPIPriorityMask
|
||||
.extern _freertos_vector_table
|
||||
.extern pxCurrentTCB
|
||||
.extern vTaskSwitchContext
|
||||
.extern vApplicationIRQHandler
|
||||
.extern ulPortInterruptNesting
|
||||
.extern ulPortTaskHasFPUContext
|
||||
|
||||
.global FreeRTOS_IRQ_Handler
|
||||
.global FreeRTOS_SWI_Handler
|
||||
.global vPortRestoreTaskContext
|
||||
|
||||
|
||||
|
||||
|
||||
.macro portSAVE_CONTEXT
|
||||
|
||||
/* Save the LR and SPSR onto the system mode stack before switching to
|
||||
system mode to save the remaining system mode registers. */
|
||||
SRSDB sp!, #SYS_MODE
|
||||
CPS #SYS_MODE
|
||||
PUSH {R0-R12, R14}
|
||||
|
||||
/* Push the critical nesting count. */
|
||||
LDR R2, ulCriticalNestingConst
|
||||
LDR R1, [R2]
|
||||
PUSH {R1}
|
||||
|
||||
/* Does the task have a floating point context that needs saving? If
|
||||
ulPortTaskHasFPUContext is 0 then no. */
|
||||
LDR R2, ulPortTaskHasFPUContextConst
|
||||
LDR R3, [R2]
|
||||
CMP R3, #0
|
||||
|
||||
/* Save the floating point context, if any. */
|
||||
FMRXNE R1, FPSCR
|
||||
VPUSHNE {D0-D15}
|
||||
VPUSHNE {D16-D31}
|
||||
PUSHNE {R1}
|
||||
|
||||
/* Save ulPortTaskHasFPUContext itself. */
|
||||
PUSH {R3}
|
||||
|
||||
/* Save the stack pointer in the TCB. */
|
||||
LDR R0, pxCurrentTCBConst
|
||||
LDR R1, [R0]
|
||||
STR SP, [R1]
|
||||
|
||||
.endm
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
.macro portRESTORE_CONTEXT
|
||||
|
||||
/* Set the SP to point to the stack of the task being restored. */
|
||||
LDR R0, pxCurrentTCBConst
|
||||
LDR R1, [R0]
|
||||
LDR SP, [R1]
|
||||
|
||||
/* Is there a floating point context to restore? If the restored
|
||||
ulPortTaskHasFPUContext is zero then no. */
|
||||
LDR R0, ulPortTaskHasFPUContextConst
|
||||
POP {R1}
|
||||
STR R1, [R0]
|
||||
CMP R1, #0
|
||||
|
||||
/* Restore the floating point context, if any. */
|
||||
POPNE {R0}
|
||||
VPOPNE {D16-D31}
|
||||
VPOPNE {D0-D15}
|
||||
VMSRNE FPSCR, R0
|
||||
|
||||
/* Restore the critical section nesting depth. */
|
||||
LDR R0, ulCriticalNestingConst
|
||||
POP {R1}
|
||||
STR R1, [R0]
|
||||
|
||||
/* Ensure the priority mask is correct for the critical nesting depth. */
|
||||
LDR R2, ulICCPMRConst
|
||||
LDR R2, [R2]
|
||||
CMP R1, #0
|
||||
MOVEQ R4, #255
|
||||
LDRNE R4, ulMaxAPIPriorityMaskConst
|
||||
LDRNE R4, [R4]
|
||||
STR R4, [R2]
|
||||
|
||||
/* Restore all system mode registers other than the SP (which is already
|
||||
being used). */
|
||||
POP {R0-R12, R14}
|
||||
|
||||
/* Return to the task code, loading CPSR on the way. */
|
||||
RFEIA sp!
|
||||
|
||||
.endm
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* SVC handler is used to start the scheduler.
|
||||
*****************************************************************************/
|
||||
.align 4
|
||||
.type FreeRTOS_SWI_Handler, %function
|
||||
FreeRTOS_SWI_Handler:
|
||||
/* Save the context of the current task and select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
LDR R0, vTaskSwitchContextConst
|
||||
BLX R0
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* vPortRestoreTaskContext is used to start the scheduler.
|
||||
*****************************************************************************/
|
||||
.type vPortRestoreTaskContext, %function
|
||||
vPortRestoreTaskContext:
|
||||
/* Switch to system mode. */
|
||||
CPS #SYS_MODE
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
.align 4
|
||||
.type FreeRTOS_IRQ_Handler, %function
|
||||
FreeRTOS_IRQ_Handler:
|
||||
/* Return to the interrupted instruction. */
|
||||
SUB lr, lr, #4
|
||||
|
||||
/* Push the return address and SPSR. */
|
||||
PUSH {lr}
|
||||
MRS lr, SPSR
|
||||
PUSH {lr}
|
||||
|
||||
/* Change to supervisor mode to allow reentry. */
|
||||
CPS #SVC_MODE
|
||||
|
||||
/* Push used registers. */
|
||||
PUSH {r0-r4, r12}
|
||||
|
||||
/* Increment nesting count. r3 holds the address of ulPortInterruptNesting
|
||||
for future use. r1 holds the original ulPortInterruptNesting value for
|
||||
future use. */
|
||||
LDR r3, ulPortInterruptNestingConst
|
||||
LDR r1, [r3]
|
||||
ADD r4, r1, #1
|
||||
STR r4, [r3]
|
||||
|
||||
/* Read value from the interrupt acknowledge register, which is stored in r0
|
||||
for future parameter and interrupt clearing use. */
|
||||
LDR r2, ulICCIARConst
|
||||
LDR r2, [r2]
|
||||
LDR r0, [r2]
|
||||
|
||||
/* Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for
|
||||
future use. _RB_ Does this ever actually need to be done provided the start
|
||||
of the stack is 8-byte aligned? */
|
||||
MOV r2, sp
|
||||
AND r2, r2, #4
|
||||
SUB sp, sp, r2
|
||||
|
||||
/* Call the interrupt handler. r4 pushed to maintain alignment. */
|
||||
PUSH {r0-r4, lr}
|
||||
LDR r1, vApplicationIRQHandlerConst
|
||||
BLX r1
|
||||
POP {r0-r4, lr}
|
||||
ADD sp, sp, r2
|
||||
|
||||
CPSID i
|
||||
DSB
|
||||
ISB
|
||||
|
||||
/* Write the value read from ICCIAR to ICCEOIR. */
|
||||
LDR r4, ulICCEOIRConst
|
||||
LDR r4, [r4]
|
||||
STR r0, [r4]
|
||||
|
||||
/* Restore the old nesting count. */
|
||||
STR r1, [r3]
|
||||
|
||||
/* A context switch is never performed if the nesting count is not 0. */
|
||||
CMP r1, #0
|
||||
BNE exit_without_switch
|
||||
|
||||
/* Did the interrupt request a context switch? r1 holds the address of
|
||||
ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
|
||||
use. */
|
||||
LDR r1, =ulPortYieldRequired
|
||||
LDR r0, [r1]
|
||||
CMP r0, #0
|
||||
BNE switch_before_exit
|
||||
|
||||
exit_without_switch:
|
||||
/* No context switch. Restore used registers, LR_irq and SPSR before
|
||||
returning. */
|
||||
POP {r0-r4, r12}
|
||||
CPS #IRQ_MODE
|
||||
POP {LR}
|
||||
MSR SPSR_cxsf, LR
|
||||
POP {LR}
|
||||
MOVS PC, LR
|
||||
|
||||
switch_before_exit:
|
||||
/* A context swtich is to be performed. Clear the context switch pending
|
||||
flag. */
|
||||
MOV r0, #0
|
||||
STR r0, [r1]
|
||||
|
||||
/* Restore used registers, LR-irq and SPSR before saving the context
|
||||
to the task stack. */
|
||||
POP {r0-r4, r12}
|
||||
CPS #IRQ_MODE
|
||||
POP {LR}
|
||||
MSR SPSR_cxsf, LR
|
||||
POP {LR}
|
||||
portSAVE_CONTEXT
|
||||
|
||||
/* Call the function that selects the new task to execute.
|
||||
vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
|
||||
instructions, or 8 byte aligned stack allocated data. LR does not need
|
||||
saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */
|
||||
LDR R0, vTaskSwitchContextConst
|
||||
BLX R0
|
||||
|
||||
/* Restore the context of, and branch to, the task selected to execute
|
||||
next. */
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* If the application provides an implementation of vApplicationIRQHandler(),
|
||||
* then it will get called directly without saving the FPU registers on
|
||||
* interrupt entry, and this weak implementation of
|
||||
* vApplicationIRQHandler() will not get called.
|
||||
*
|
||||
* If the application provides its own implementation of
|
||||
* vApplicationFPUSafeIRQHandler() then this implementation of
|
||||
* vApplicationIRQHandler() will be called, save the FPU registers, and then
|
||||
* call vApplicationFPUSafeIRQHandler().
|
||||
*
|
||||
* Therefore, if the application writer wants FPU registers to be saved on
|
||||
* interrupt entry their IRQ handler must be called
|
||||
* vApplicationFPUSafeIRQHandler(), and if the application writer does not want
|
||||
* FPU registers to be saved on interrupt entry their IRQ handler must be
|
||||
* called vApplicationIRQHandler().
|
||||
*****************************************************************************/
|
||||
|
||||
.align 4
|
||||
.weak vApplicationIRQHandler
|
||||
.type vApplicationIRQHandler, %function
|
||||
vApplicationIRQHandler:
|
||||
PUSH {LR}
|
||||
FMRX R1, FPSCR
|
||||
VPUSH {D0-D15}
|
||||
VPUSH {D16-D31}
|
||||
PUSH {R1}
|
||||
|
||||
LDR r1, vApplicationFPUSafeIRQHandlerConst
|
||||
BLX r1
|
||||
|
||||
POP {R0}
|
||||
VPOP {D16-D31}
|
||||
VPOP {D0-D15}
|
||||
VMSR FPSCR, R0
|
||||
|
||||
POP {PC}
|
||||
|
||||
|
||||
ulICCIARConst: .word ulICCIAR
|
||||
ulICCEOIRConst: .word ulICCEOIR
|
||||
ulICCPMRConst: .word ulICCPMR
|
||||
pxCurrentTCBConst: .word pxCurrentTCB
|
||||
ulCriticalNestingConst: .word ulCriticalNesting
|
||||
ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext
|
||||
ulMaxAPIPriorityMaskConst: .word ulMaxAPIPriorityMask
|
||||
vTaskSwitchContextConst: .word vTaskSwitchContext
|
||||
vApplicationIRQHandlerConst: .word vApplicationIRQHandler
|
||||
ulPortInterruptNestingConst: .word ulPortInterruptNesting
|
||||
vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler
|
||||
|
||||
.end
|
||||
|
|
|
|||
|
|
@ -1,209 +1,208 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired )\
|
||||
{ \
|
||||
extern uint32_t ulPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() __asm volatile ( "SWI 0" ::: "memory" );
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
|
||||
/* These macros do not globally disable/enable interrupts. They do mask off
|
||||
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not required for this port but included in case common demo code that uses these
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
/* Prototype of the FreeRTOS tick handler. This must be installed as the
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
|
||||
/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or left undefined) then tasks are
|
||||
created without an FPU context and must call vPortTaskUsesFPU() to give
|
||||
themselves an FPU context before using any FPU instructions. If
|
||||
configUSE_TASK_FPU_SUPPORT is set to 2 then all tasks will have an FPU context
|
||||
by default. */
|
||||
#if( configUSE_TASK_FPU_SUPPORT != 2 )
|
||||
void vPortTaskUsesFPU( void );
|
||||
#else
|
||||
/* Each task has an FPU context already, so define this function away to
|
||||
nothing to prevent it being called accidentally. */
|
||||
#define vPortTaskUsesFPU()
|
||||
#endif
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __builtin_clz( uxReadyPriorities ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
|
||||
/* The number of bits to shift for an interrupt priority is dependent on the
|
||||
number of bits implemented by the interrupt controller. */
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif
|
||||
|
||||
/* Interrupt controller access addresses. */
|
||||
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
|
||||
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
|
||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
|
||||
|
||||
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
|
||||
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
|
||||
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired )\
|
||||
{ \
|
||||
extern uint32_t ulPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() __asm volatile ( "SWI 0" ::: "memory" );
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
|
||||
/* These macros do not globally disable/enable interrupts. They do mask off
|
||||
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. These are
|
||||
not required for this port but included in case common demo code that uses these
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
/* Prototype of the FreeRTOS tick handler. This must be installed as the
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
|
||||
/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or left undefined) then tasks are
|
||||
created without an FPU context and must call vPortTaskUsesFPU() to give
|
||||
themselves an FPU context before using any FPU instructions. If
|
||||
configUSE_TASK_FPU_SUPPORT is set to 2 then all tasks will have an FPU context
|
||||
by default. */
|
||||
#if( configUSE_TASK_FPU_SUPPORT != 2 )
|
||||
void vPortTaskUsesFPU( void );
|
||||
#else
|
||||
/* Each task has an FPU context already, so define this function away to
|
||||
nothing to prevent it being called accidentally. */
|
||||
#define vPortTaskUsesFPU()
|
||||
#endif
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
|
||||
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __builtin_clz( uxReadyPriorities ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
|
||||
/* The number of bits to shift for an interrupt priority is dependent on the
|
||||
number of bits implemented by the interrupt controller. */
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif
|
||||
|
||||
/* Interrupt controller access addresses. */
|
||||
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
|
||||
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
|
||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
|
||||
|
||||
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
|
||||
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
|
||||
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
|
||||
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,125 +1,125 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
extern void vPortYield( void );
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portYIELD() vPortYield()
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 )
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulSetInterruptMaskFromISR( void ) __attribute__( ( naked ) );
|
||||
extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__( ( naked ) );
|
||||
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMaskFromISR( x )
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
#define portNOP()
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if ( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
|
||||
* not need to be guarded with a critical section. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
extern void vPortYield( void );
|
||||
#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portYIELD() vPortYield()
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 )
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulSetInterruptMaskFromISR( void ) __attribute__( ( naked ) );
|
||||
extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__( ( naked ) );
|
||||
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMaskFromISR( x )
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
#define portNOP()
|
||||
|
||||
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -1,478 +1,478 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||
* is defined correctly and privileged functions are placed in correct sections. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" movs r5, #4 \n"/* r5 = 4. */
|
||||
" str r5, [r2] \n"/* Program RNR = 4. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r5, #5 \n"/* r5 = 5. */
|
||||
" str r5, [r2] \n"/* Program RNR = 5. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r5, #6 \n"/* r5 = 6. */
|
||||
" str r5, [r2] \n"/* Program RNR = 6. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r5, #7 \n"/* r5 = 7. */
|
||||
" str r5, [r2] \n"/* Program RNR = 7. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
" ldr r5, xSecureContextConst2 \n"
|
||||
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r3 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r4 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
" ldr r4, xSecureContextConst2 \n"
|
||||
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst2: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
" beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
|
||||
" movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" running_privileged: \n"
|
||||
" movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" bics r0, r1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" orrs r0, r1 \n"/* r0 = r0 | r1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" .extern SecureContext_SaveContext \n"
|
||||
" .extern SecureContext_LoadContext \n"
|
||||
" \n"
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later.*/
|
||||
" mrs r2, psp \n"/* Read PSP in r2. */
|
||||
" \n"
|
||||
" cbz r0, save_ns_context \n"/* No secure context to save. */
|
||||
" push {r0-r2, r14} \n"
|
||||
" bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r0-r3} \n"/* LR is now in r3. */
|
||||
" mov lr, r3 \n"/* LR = r3. */
|
||||
" lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" b select_next_task \n"
|
||||
" \n"
|
||||
" save_ns_context: \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" adds r2, r2, #16 \n"/* r2 = r2 + 16. */
|
||||
" stmia r2!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" subs r2, r2, #48 \n"/* r2 = r2 - 48. */
|
||||
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" select_next_task: \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r3] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r3] \n"/* Program MAIR0. */
|
||||
" ldr r4, xRNRConst \n"/* r4 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" movs r5, #4 \n"/* r5 = 4. */
|
||||
" str r5, [r4] \n"/* Program RNR = 4. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r5, #5 \n"/* r5 = 5. */
|
||||
" str r5, [r4] \n"/* Program RNR = 5. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r5, #6 \n"/* r5 = 6. */
|
||||
" str r5, [r4] \n"/* Program RNR = 6. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r5, #7 \n"/* r5 = 7. */
|
||||
" str r5, [r4] \n"/* Program RNR = 7. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r3] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r3] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" push {r2, r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r2, r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r3] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" push {r2, r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r2, r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" restore_ns_context: \n"
|
||||
" adds r2, r2, #16 \n"/* Move to the high registers. */
|
||||
" ldmia r2!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n"/* r8 = r4. */
|
||||
" mov r9, r5 \n"/* r9 = r5. */
|
||||
" mov r10, r6 \n"/* r10 = r6. */
|
||||
" mov r11, r7 \n"/* r11 = r7. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" subs r2, r2, #32 \n"/* Go back to the low registers. */
|
||||
" ldmia r2!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" movs r0, #4 \n"
|
||||
" mov r1, lr \n"
|
||||
" tst r0, r1 \n"
|
||||
" beq stacking_used_msp \n"
|
||||
" mrs r0, psp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" stacking_used_msp: \n"
|
||||
" mrs r0, msp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" svc %0 \n"/* Secure context is allocated in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */
|
||||
" ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */
|
||||
" cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
|
||||
" bne free_secure_context \n"/* Branch if r1 != 0. */
|
||||
" bx lr \n"/* There is no secure context (xSecureContext is NULL). */
|
||||
" free_secure_context: \n"
|
||||
" svc %0 \n"/* Secure context is freed in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE ensures that PRIVILEGED_FUNCTION
|
||||
* is defined correctly and privileged functions are placed in correct sections. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE is needed to be defined only for the
|
||||
* header files. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r3, [r2] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
" ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r2] \n"/* Program MAIR0. */
|
||||
" ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
" movs r5, #4 \n"/* r5 = 4. */
|
||||
" str r5, [r2] \n"/* Program RNR = 4. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r5, #5 \n"/* r5 = 5. */
|
||||
" str r5, [r2] \n"/* Program RNR = 5. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r5, #6 \n"/* r5 = 6. */
|
||||
" str r5, [r2] \n"/* Program RNR = 6. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r5, #7 \n"/* r5 = 7. */
|
||||
" str r5, [r2] \n"/* Program RNR = 7. */
|
||||
" ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r2] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
" ldr r5, xSecureContextConst2 \n"
|
||||
" str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" msr control, r3 \n"/* Set this task's CONTROL value. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r4 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
" ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
" ldr r4, xSecureContextConst2 \n"
|
||||
" str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */
|
||||
" msr psplim, r2 \n"/* Set this task's PSPLIM value. */
|
||||
" movs r1, #2 \n"/* r1 = 2. */
|
||||
" msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */
|
||||
" adds r0, #32 \n"/* Discard everything up to r0. */
|
||||
" msr psp, r0 \n"/* This is now the new top of stack to use in the task. */
|
||||
" isb \n"
|
||||
" bx r3 \n"/* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst2: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst2: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst2: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const2: .word 0xe000edc0 \n"
|
||||
"xRNRConst2: .word 0xe000ed98 \n"
|
||||
"xRBARConst2: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
" beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */
|
||||
" movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" running_privileged: \n"
|
||||
" movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
" bx lr \n"/* Return. */
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* Read the CONTROL register. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" bics r0, r1 \n"/* Clear the bit 0. */
|
||||
" msr control, r0 \n"/* Write back the new CONTROL value. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vResetPrivilege( void ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, control \n"/* r0 = CONTROL. */
|
||||
" movs r1, #1 \n"/* r1 = 1. */
|
||||
" orrs r0, r1 \n"/* r0 = r0 | r1. */
|
||||
" msr control, r0 \n"/* CONTROL = r0. */
|
||||
" bx lr \n"/* Return to the caller. */
|
||||
::: "r0", "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */
|
||||
" ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */
|
||||
" ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */
|
||||
" msr msp, r0 \n"/* Set the MSP back to the start of the stack. */
|
||||
" cpsie i \n"/* Globally enable interrupts. */
|
||||
" dsb \n"
|
||||
" isb \n"
|
||||
" svc %0 \n"/* System call to start the first task. */
|
||||
" nop \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"xVTORConst: .word 0xe000ed08 \n"
|
||||
::"i" ( portSVC_START_SCHEDULER ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r0, PRIMASK \n"
|
||||
" cpsid i \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" msr PRIMASK, r0 \n"
|
||||
" bx lr \n"
|
||||
::: "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" .extern SecureContext_SaveContext \n"
|
||||
" .extern SecureContext_LoadContext \n"
|
||||
" \n"
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" ldr r0, [r3] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB - Value of pxCurrentTCB must be in r1 as it is used as a parameter later.*/
|
||||
" mrs r2, psp \n"/* Read PSP in r2. */
|
||||
" \n"
|
||||
" cbz r0, save_ns_context \n"/* No secure context to save. */
|
||||
" push {r0-r2, r14} \n"
|
||||
" bl SecureContext_SaveContext \n"/* Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r0-r3} \n"/* LR is now in r3. */
|
||||
" mov lr, r3 \n"/* LR = r3. */
|
||||
" lsls r1, r3, #25 \n"/* r1 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl save_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r2, r2, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r2, r2, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" b select_next_task \n"
|
||||
" \n"
|
||||
" save_ns_context: \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" subs r2, r2, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" adds r2, r2, #16 \n"/* r2 = r2 + 16. */
|
||||
" stmia r2!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mrs r3, control \n"/* r3 = CONTROL. */
|
||||
" mov r4, lr \n"/* r4 = LR/EXC_RETURN. */
|
||||
" subs r2, r2, #48 \n"/* r2 = r2 - 48. */
|
||||
" stmia r2!, {r0, r1, r3, r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" subs r2, r2, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
" str r2, [r1] \n"/* Save the new top of stack in TCB. */
|
||||
" mrs r1, psplim \n"/* r1 = PSPLIM. */
|
||||
" mov r3, lr \n"/* r3 = LR/EXC_RETURN. */
|
||||
" stmia r2!, {r0, r1, r3-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
|
||||
" mov r4, r8 \n"/* r4 = r8. */
|
||||
" mov r5, r9 \n"/* r5 = r9. */
|
||||
" mov r6, r10 \n"/* r6 = r10. */
|
||||
" mov r7, r11 \n"/* r7 = r11. */
|
||||
" stmia r2!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" select_next_task: \n"
|
||||
" cpsid i \n"
|
||||
" bl vTaskSwitchContext \n"
|
||||
" cpsie i \n"
|
||||
" \n"
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" ldr r2, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r2 now points to the top of stack. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" dmb \n"/* Complete outstanding transfers before disabling MPU. */
|
||||
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
" str r4, [r3] \n"/* Disable MPU. */
|
||||
" \n"
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
" ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
" ldr r3, xMAIR0Const \n"/* r3 = 0xe000edc0 [Location of MAIR0]. */
|
||||
" str r4, [r3] \n"/* Program MAIR0. */
|
||||
" ldr r4, xRNRConst \n"/* r4 = 0xe000ed98 [Location of RNR]. */
|
||||
" adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
" movs r5, #4 \n"/* r5 = 4. */
|
||||
" str r5, [r4] \n"/* Program RNR = 4. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */
|
||||
" movs r5, #5 \n"/* r5 = 5. */
|
||||
" str r5, [r4] \n"/* Program RNR = 5. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */
|
||||
" movs r5, #6 \n"/* r5 = 6. */
|
||||
" str r5, [r4] \n"/* Program RNR = 6. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */
|
||||
" movs r5, #7 \n"/* r5 = 7. */
|
||||
" str r5, [r4] \n"/* Program RNR = 7. */
|
||||
" ldmia r1!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */
|
||||
" ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
" stmia r3!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */
|
||||
" \n"
|
||||
" ldr r3, xMPUCTRLConst \n"/* r3 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
" ldr r4, [r3] \n"/* Read the value of MPU_CTRL. */
|
||||
" movs r5, #1 \n"/* r5 = 1. */
|
||||
" orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
" str r4, [r3] \n"/* Enable MPU. */
|
||||
" dsb \n"/* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r2!, {r0, r1, r3, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" msr control, r3 \n"/* Restore the CONTROL register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r3] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" push {r2, r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r2, r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#else /* configENABLE_MPU */
|
||||
" ldmia r2!, {r0, r1, r4} \n"/* Read from stack - r0 = xSecureContext, r1 = PSPLIM and r4 = LR. */
|
||||
" msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" ldr r3, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
" str r0, [r3] \n"/* Restore the task's xSecureContext. */
|
||||
" cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */
|
||||
" ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
" ldr r1, [r3] \n"/* Read pxCurrentTCB. */
|
||||
" push {r2, r4} \n"
|
||||
" bl SecureContext_LoadContext \n"/* Restore the secure context. Params are in r0 and r1. r0 = xSecureContext and r1 = pxCurrentTCB. */
|
||||
" pop {r2, r4} \n"
|
||||
" mov lr, r4 \n"/* LR = r4. */
|
||||
" lsls r1, r4, #25 \n"/* r1 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
" bpl restore_ns_context \n"/* bpl - branch if positive or zero. If r1 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" bx lr \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" restore_ns_context: \n"
|
||||
" adds r2, r2, #16 \n"/* Move to the high registers. */
|
||||
" ldmia r2!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */
|
||||
" mov r8, r4 \n"/* r8 = r4. */
|
||||
" mov r9, r5 \n"/* r9 = r5. */
|
||||
" mov r10, r6 \n"/* r10 = r6. */
|
||||
" mov r11, r7 \n"/* r11 = r7. */
|
||||
" msr psp, r2 \n"/* Remember the new top of stack for the task. */
|
||||
" subs r2, r2, #32 \n"/* Go back to the low registers. */
|
||||
" ldmia r2!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"pxCurrentTCBConst: .word pxCurrentTCB \n"
|
||||
"xSecureContextConst: .word xSecureContext \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
"xMPUCTRLConst: .word 0xe000ed94 \n"
|
||||
"xMAIR0Const: .word 0xe000edc0 \n"
|
||||
"xRNRConst: .word 0xe000ed98 \n"
|
||||
"xRBARConst: .word 0xe000ed9c \n"
|
||||
#endif /* configENABLE_MPU */
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" movs r0, #4 \n"
|
||||
" mov r1, lr \n"
|
||||
" tst r0, r1 \n"
|
||||
" beq stacking_used_msp \n"
|
||||
" mrs r0, psp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" stacking_used_msp: \n"
|
||||
" mrs r0, msp \n"
|
||||
" ldr r2, svchandler_address_const \n"
|
||||
" bx r2 \n"
|
||||
" \n"
|
||||
" .align 4 \n"
|
||||
"svchandler_address_const: .word vPortSVCHandler_C \n"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" svc %0 \n"/* Secure context is allocated in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" ldr r2, [r0] \n"/* The first item in the TCB is the top of the stack. */
|
||||
" ldr r1, [r2] \n"/* The first item on the stack is the task's xSecureContext. */
|
||||
" cmp r1, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */
|
||||
" bne free_secure_context \n"/* Branch if r1 != 0. */
|
||||
" bx lr \n"/* There is no secure context (xSecureContext is NULL). */
|
||||
" free_secure_context: \n"
|
||||
" svc %0 \n"/* Secure context is freed in the supervisor call. */
|
||||
" bx lr \n"/* Return. */
|
||||
::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,114 +1,114 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ASM_H__
|
||||
#define __PORT_ASM_H__
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/**
|
||||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* @note This is a privileged function and should only be called from the kenrel
|
||||
* code.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ASM_H__
|
||||
#define __PORT_ASM_H__
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/**
|
||||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* @note This is a privileged function and should only be called from the kenrel
|
||||
* code.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__( ( naked ) );
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
|
|
|
|||
|
|
@ -1,71 +1,71 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "portmacrocommon.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portDONT_DISCARD __attribute__( ( used ) )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configTOTAL_MPU_REGIONS == 16 )
|
||||
#error 16 MPU regions are not yet supported for this port.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
|
|
|||
|
|
@ -155,9 +155,9 @@
|
|||
* 8-bit values encoded as follows:
|
||||
* Bit[7:4] - 0000 - Device Memory
|
||||
* Bit[3:2] - 00 --> Device-nGnRnE
|
||||
* 01 --> Device-nGnRE
|
||||
* 10 --> Device-nGRE
|
||||
* 11 --> Device-GRE
|
||||
* 01 --> Device-nGnRE
|
||||
* 10 --> Device-nGRE
|
||||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
|
|
|
|||
|
|
@ -1,351 +1,351 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for privileged tasks.
|
||||
*
|
||||
* Bit[0] - 0 --> Thread mode is privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for un-privileged tasks.
|
||||
*
|
||||
* Bit[0] - 1 --> Thread mode is un-privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
|
||||
|
||||
/**
|
||||
* @brief Size of stack seal values in bytes.
|
||||
*/
|
||||
#define securecontextSTACK_SEAL_SIZE 8
|
||||
|
||||
/**
|
||||
* @brief Stack seal value as recommended by ARM.
|
||||
*/
|
||||
#define securecontextSTACK_SEAL_VALUE 0xFEF5EDA5
|
||||
|
||||
/**
|
||||
* @brief Maximum number of secure contexts.
|
||||
*/
|
||||
#ifndef secureconfigMAX_SECURE_CONTEXTS
|
||||
#define secureconfigMAX_SECURE_CONTEXTS 8UL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Pre-allocated array of secure contexts.
|
||||
*/
|
||||
SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Get a free secure context for a task from the secure context pool (xSecureContexts).
|
||||
*
|
||||
* This function ensures that only one secure context is allocated for a task.
|
||||
*
|
||||
* @param[in] pvTaskHandle The task handle for which the secure context is allocated.
|
||||
*
|
||||
* @return Index of a free secure context in the xSecureContexts array.
|
||||
*/
|
||||
static uint32_t ulGetSecureContext( void * pvTaskHandle );
|
||||
|
||||
/**
|
||||
* @brief Return the secure context to the secure context pool (xSecureContexts).
|
||||
*
|
||||
* @param[in] ulSecureContextIndex Index of the context in the xSecureContexts array.
|
||||
*/
|
||||
static void vReturnSecureContext( uint32_t ulSecureContextIndex );
|
||||
|
||||
/* These are implemented in assembly. */
|
||||
extern void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext );
|
||||
extern void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static uint32_t ulGetSecureContext( void * pvTaskHandle )
|
||||
{
|
||||
/* Start with invalid index. */
|
||||
uint32_t i, ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
|
||||
|
||||
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
|
||||
{
|
||||
if( ( xSecureContexts[ i ].pucCurrentStackPointer == NULL ) &&
|
||||
( xSecureContexts[ i ].pucStackLimit == NULL ) &&
|
||||
( xSecureContexts[ i ].pucStackStart == NULL ) &&
|
||||
( xSecureContexts[ i ].pvTaskHandle == NULL ) &&
|
||||
( ulSecureContextIndex == secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = i;
|
||||
}
|
||||
else if( xSecureContexts[ i ].pvTaskHandle == pvTaskHandle )
|
||||
{
|
||||
/* A task can only have one secure context. Do not allocate a second
|
||||
* context for the same task. */
|
||||
ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ulSecureContextIndex;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void vReturnSecureContext( uint32_t ulSecureContextIndex )
|
||||
{
|
||||
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;
|
||||
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
|
||||
{
|
||||
uint32_t ulIPSR, i;
|
||||
static uint32_t ulSecureContextsInitialized = 0;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ( ulIPSR != 0 ) && ( ulSecureContextsInitialized == 0 ) )
|
||||
{
|
||||
/* Ensure to initialize secure contexts only once. */
|
||||
ulSecureContextsInitialized = 1;
|
||||
|
||||
/* No stack for thread mode until a task's context is loaded. */
|
||||
secureportSET_PSPLIM( securecontextNO_STACK );
|
||||
secureportSET_PSP( securecontextNO_STACK );
|
||||
|
||||
/* Initialize all secure contexts. */
|
||||
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
|
||||
{
|
||||
xSecureContexts[ i ].pucCurrentStackPointer = NULL;
|
||||
xSecureContexts[ i ].pucStackLimit = NULL;
|
||||
xSecureContexts[ i ].pucStackStart = NULL;
|
||||
xSecureContexts[ i ].pvTaskHandle = NULL;
|
||||
}
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be unprivileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be privileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
uint32_t ulIsTaskPrivileged,
|
||||
void * pvTaskHandle )
|
||||
#else /* configENABLE_MPU */
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
void * pvTaskHandle )
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
uint8_t * pucStackMemory = NULL;
|
||||
uint8_t * pucStackLimit;
|
||||
uint32_t ulIPSR, ulSecureContextIndex;
|
||||
SecureContextHandle_t xSecureContextHandle = securecontextINVALID_CONTEXT_ID;
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
uint32_t * pulCurrentStackPointer = NULL;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
|
||||
* Register (PSPLIM) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
secureportREAD_PSPLIM( pucStackLimit );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode.
|
||||
* Also do nothing, if a secure context us already loaded. PSPLIM is set to
|
||||
* securecontextNO_STACK when no secure context is loaded. */
|
||||
if( ( ulIPSR != 0 ) && ( pucStackLimit == securecontextNO_STACK ) )
|
||||
{
|
||||
/* Ontain a free secure context. */
|
||||
ulSecureContextIndex = ulGetSecureContext( pvTaskHandle );
|
||||
|
||||
/* Were we able to get a free context? */
|
||||
if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
|
||||
{
|
||||
/* Allocate the stack space. */
|
||||
pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
|
||||
|
||||
if( pucStackMemory != NULL )
|
||||
{
|
||||
/* Since stack grows down, the starting point will be the last
|
||||
* location. Note that this location is next to the last
|
||||
* allocated byte for stack (excluding the space for seal values)
|
||||
* because the hardware decrements the stack pointer before
|
||||
* writing i.e. if stack pointer is 0x2, a push operation will
|
||||
* decrement the stack pointer to 0x1 and then write at 0x1. */
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;
|
||||
|
||||
/* Seal the created secure process stack. */
|
||||
*( uint32_t * )( pucStackMemory + ulSecureStackSize ) = securecontextSTACK_SEAL_VALUE;
|
||||
*( uint32_t * )( pucStackMemory + ulSecureStackSize + 4 ) = securecontextSTACK_SEAL_VALUE;
|
||||
|
||||
/* The stack cannot go beyond this location. This value is
|
||||
* programmed in the PSPLIM register on context switch.*/
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;
|
||||
|
||||
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = pvTaskHandle;
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Store the correct CONTROL value for the task on the stack.
|
||||
* This value is programmed in the CONTROL register on
|
||||
* context switch. */
|
||||
pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;
|
||||
pulCurrentStackPointer--;
|
||||
|
||||
if( ulIsTaskPrivileged )
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
/* Store the current stack pointer. This value is programmed in
|
||||
* the PSP register on context switch. */
|
||||
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Current SP is set to the starting of the stack. This
|
||||
* value programmed in the PSP register on context switch. */
|
||||
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Ensure to never return 0 as a valid context handle. */
|
||||
xSecureContextHandle = ulSecureContextIndex + 1UL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xSecureContextHandle;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
|
||||
{
|
||||
uint32_t ulIPSR, ulSecureContextIndex;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Only free if a valid context handle is passed. */
|
||||
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||
|
||||
/* Ensure that the secure context being deleted is associated with
|
||||
* the task. */
|
||||
if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
|
||||
{
|
||||
/* Free the stack space. */
|
||||
vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
|
||||
|
||||
/* Return the secure context back to the free secure contexts pool. */
|
||||
vReturnSecureContext( ulSecureContextIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
|
||||
{
|
||||
uint8_t * pucStackLimit;
|
||||
uint32_t ulSecureContextIndex;
|
||||
|
||||
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||
|
||||
secureportREAD_PSPLIM( pucStackLimit );
|
||||
|
||||
/* Ensure that no secure context is loaded and the task is loading it's
|
||||
* own context. */
|
||||
if( ( pucStackLimit == securecontextNO_STACK ) &&
|
||||
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
|
||||
{
|
||||
SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
|
||||
{
|
||||
uint8_t * pucStackLimit;
|
||||
uint32_t ulSecureContextIndex;
|
||||
|
||||
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||
|
||||
secureportREAD_PSPLIM( pucStackLimit );
|
||||
|
||||
/* Ensure that task's context is loaded and the task is saving it's own
|
||||
* context. */
|
||||
if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
|
||||
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
|
||||
{
|
||||
SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for privileged tasks.
|
||||
*
|
||||
* Bit[0] - 0 --> Thread mode is privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for un-privileged tasks.
|
||||
*
|
||||
* Bit[0] - 1 --> Thread mode is un-privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
|
||||
|
||||
/**
|
||||
* @brief Size of stack seal values in bytes.
|
||||
*/
|
||||
#define securecontextSTACK_SEAL_SIZE 8
|
||||
|
||||
/**
|
||||
* @brief Stack seal value as recommended by ARM.
|
||||
*/
|
||||
#define securecontextSTACK_SEAL_VALUE 0xFEF5EDA5
|
||||
|
||||
/**
|
||||
* @brief Maximum number of secure contexts.
|
||||
*/
|
||||
#ifndef secureconfigMAX_SECURE_CONTEXTS
|
||||
#define secureconfigMAX_SECURE_CONTEXTS 8UL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Pre-allocated array of secure contexts.
|
||||
*/
|
||||
SecureContext_t xSecureContexts[ secureconfigMAX_SECURE_CONTEXTS ];
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Get a free secure context for a task from the secure context pool (xSecureContexts).
|
||||
*
|
||||
* This function ensures that only one secure context is allocated for a task.
|
||||
*
|
||||
* @param[in] pvTaskHandle The task handle for which the secure context is allocated.
|
||||
*
|
||||
* @return Index of a free secure context in the xSecureContexts array.
|
||||
*/
|
||||
static uint32_t ulGetSecureContext( void * pvTaskHandle );
|
||||
|
||||
/**
|
||||
* @brief Return the secure context to the secure context pool (xSecureContexts).
|
||||
*
|
||||
* @param[in] ulSecureContextIndex Index of the context in the xSecureContexts array.
|
||||
*/
|
||||
static void vReturnSecureContext( uint32_t ulSecureContextIndex );
|
||||
|
||||
/* These are implemented in assembly. */
|
||||
extern void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext );
|
||||
extern void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static uint32_t ulGetSecureContext( void * pvTaskHandle )
|
||||
{
|
||||
/* Start with invalid index. */
|
||||
uint32_t i, ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
|
||||
|
||||
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
|
||||
{
|
||||
if( ( xSecureContexts[ i ].pucCurrentStackPointer == NULL ) &&
|
||||
( xSecureContexts[ i ].pucStackLimit == NULL ) &&
|
||||
( xSecureContexts[ i ].pucStackStart == NULL ) &&
|
||||
( xSecureContexts[ i ].pvTaskHandle == NULL ) &&
|
||||
( ulSecureContextIndex == secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = i;
|
||||
}
|
||||
else if( xSecureContexts[ i ].pvTaskHandle == pvTaskHandle )
|
||||
{
|
||||
/* A task can only have one secure context. Do not allocate a second
|
||||
* context for the same task. */
|
||||
ulSecureContextIndex = secureconfigMAX_SECURE_CONTEXTS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ulSecureContextIndex;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void vReturnSecureContext( uint32_t ulSecureContextIndex )
|
||||
{
|
||||
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = NULL;
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = NULL;
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackStart = NULL;
|
||||
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
|
||||
{
|
||||
uint32_t ulIPSR, i;
|
||||
static uint32_t ulSecureContextsInitialized = 0;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ( ulIPSR != 0 ) && ( ulSecureContextsInitialized == 0 ) )
|
||||
{
|
||||
/* Ensure to initialize secure contexts only once. */
|
||||
ulSecureContextsInitialized = 1;
|
||||
|
||||
/* No stack for thread mode until a task's context is loaded. */
|
||||
secureportSET_PSPLIM( securecontextNO_STACK );
|
||||
secureportSET_PSP( securecontextNO_STACK );
|
||||
|
||||
/* Initialize all secure contexts. */
|
||||
for( i = 0; i < secureconfigMAX_SECURE_CONTEXTS; i++ )
|
||||
{
|
||||
xSecureContexts[ i ].pucCurrentStackPointer = NULL;
|
||||
xSecureContexts[ i ].pucStackLimit = NULL;
|
||||
xSecureContexts[ i ].pucStackStart = NULL;
|
||||
xSecureContexts[ i ].pvTaskHandle = NULL;
|
||||
}
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be unprivileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be privileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
uint32_t ulIsTaskPrivileged,
|
||||
void * pvTaskHandle )
|
||||
#else /* configENABLE_MPU */
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
void * pvTaskHandle )
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
uint8_t * pucStackMemory = NULL;
|
||||
uint8_t * pucStackLimit;
|
||||
uint32_t ulIPSR, ulSecureContextIndex;
|
||||
SecureContextHandle_t xSecureContextHandle = securecontextINVALID_CONTEXT_ID;
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
uint32_t * pulCurrentStackPointer = NULL;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) and Process Stack Limit
|
||||
* Register (PSPLIM) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
secureportREAD_PSPLIM( pucStackLimit );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode.
|
||||
* Also do nothing, if a secure context us already loaded. PSPLIM is set to
|
||||
* securecontextNO_STACK when no secure context is loaded. */
|
||||
if( ( ulIPSR != 0 ) && ( pucStackLimit == securecontextNO_STACK ) )
|
||||
{
|
||||
/* Ontain a free secure context. */
|
||||
ulSecureContextIndex = ulGetSecureContext( pvTaskHandle );
|
||||
|
||||
/* Were we able to get a free context? */
|
||||
if( ulSecureContextIndex < secureconfigMAX_SECURE_CONTEXTS )
|
||||
{
|
||||
/* Allocate the stack space. */
|
||||
pucStackMemory = pvPortMalloc( ulSecureStackSize + securecontextSTACK_SEAL_SIZE );
|
||||
|
||||
if( pucStackMemory != NULL )
|
||||
{
|
||||
/* Since stack grows down, the starting point will be the last
|
||||
* location. Note that this location is next to the last
|
||||
* allocated byte for stack (excluding the space for seal values)
|
||||
* because the hardware decrements the stack pointer before
|
||||
* writing i.e. if stack pointer is 0x2, a push operation will
|
||||
* decrement the stack pointer to 0x1 and then write at 0x1. */
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackStart = pucStackMemory + ulSecureStackSize;
|
||||
|
||||
/* Seal the created secure process stack. */
|
||||
*( uint32_t * )( pucStackMemory + ulSecureStackSize ) = securecontextSTACK_SEAL_VALUE;
|
||||
*( uint32_t * )( pucStackMemory + ulSecureStackSize + 4 ) = securecontextSTACK_SEAL_VALUE;
|
||||
|
||||
/* The stack cannot go beyond this location. This value is
|
||||
* programmed in the PSPLIM register on context switch.*/
|
||||
xSecureContexts[ ulSecureContextIndex ].pucStackLimit = pucStackMemory;
|
||||
|
||||
xSecureContexts[ ulSecureContextIndex ].pvTaskHandle = pvTaskHandle;
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Store the correct CONTROL value for the task on the stack.
|
||||
* This value is programmed in the CONTROL register on
|
||||
* context switch. */
|
||||
pulCurrentStackPointer = ( uint32_t * ) xSecureContexts[ ulSecureContextIndex ].pucStackStart;
|
||||
pulCurrentStackPointer--;
|
||||
|
||||
if( ulIsTaskPrivileged )
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
/* Store the current stack pointer. This value is programmed in
|
||||
* the PSP register on context switch. */
|
||||
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Current SP is set to the starting of the stack. This
|
||||
* value programmed in the PSP register on context switch. */
|
||||
xSecureContexts[ ulSecureContextIndex ].pucCurrentStackPointer = xSecureContexts[ ulSecureContextIndex ].pucStackStart;
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Ensure to never return 0 as a valid context handle. */
|
||||
xSecureContextHandle = ulSecureContextIndex + 1UL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xSecureContextHandle;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
|
||||
{
|
||||
uint32_t ulIPSR, ulSecureContextIndex;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Only free if a valid context handle is passed. */
|
||||
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||
|
||||
/* Ensure that the secure context being deleted is associated with
|
||||
* the task. */
|
||||
if( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle )
|
||||
{
|
||||
/* Free the stack space. */
|
||||
vPortFree( xSecureContexts[ ulSecureContextIndex ].pucStackLimit );
|
||||
|
||||
/* Return the secure context back to the free secure contexts pool. */
|
||||
vReturnSecureContext( ulSecureContextIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
|
||||
{
|
||||
uint8_t * pucStackLimit;
|
||||
uint32_t ulSecureContextIndex;
|
||||
|
||||
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||
|
||||
secureportREAD_PSPLIM( pucStackLimit );
|
||||
|
||||
/* Ensure that no secure context is loaded and the task is loading it's
|
||||
* own context. */
|
||||
if( ( pucStackLimit == securecontextNO_STACK ) &&
|
||||
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
|
||||
{
|
||||
SecureContext_LoadContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle )
|
||||
{
|
||||
uint8_t * pucStackLimit;
|
||||
uint32_t ulSecureContextIndex;
|
||||
|
||||
if( ( xSecureContextHandle > 0UL ) && ( xSecureContextHandle <= secureconfigMAX_SECURE_CONTEXTS ) )
|
||||
{
|
||||
ulSecureContextIndex = xSecureContextHandle - 1UL;
|
||||
|
||||
secureportREAD_PSPLIM( pucStackLimit );
|
||||
|
||||
/* Ensure that task's context is loaded and the task is saving it's own
|
||||
* context. */
|
||||
if( ( xSecureContexts[ ulSecureContextIndex ].pucStackLimit == pucStackLimit ) &&
|
||||
( xSecureContexts[ ulSecureContextIndex ].pvTaskHandle == pvTaskHandle ) )
|
||||
{
|
||||
SecureContext_SaveContextAsm( &( xSecureContexts[ ulSecureContextIndex ] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,135 +1,135 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_CONTEXT_H__
|
||||
#define __SECURE_CONTEXT_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
/**
|
||||
* @brief PSP value when no secure context is loaded.
|
||||
*/
|
||||
#define securecontextNO_STACK 0x0
|
||||
|
||||
/**
|
||||
* @brief Invalid context ID.
|
||||
*/
|
||||
#define securecontextINVALID_CONTEXT_ID 0UL
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Structure to represent a secure context.
|
||||
*
|
||||
* @note Since stack grows down, pucStackStart is the highest address while
|
||||
* pucStackLimit is the first address of the allocated memory.
|
||||
*/
|
||||
typedef struct SecureContext
|
||||
{
|
||||
uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
|
||||
uint8_t * pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
|
||||
uint8_t * pucStackStart; /**< First location of the stack memory. */
|
||||
void * pvTaskHandle; /**< Task handle of the task this context is associated with. */
|
||||
} SecureContext_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Opaque handle for a secure context.
|
||||
*/
|
||||
typedef uint32_t SecureContextHandle_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the secure context management system.
|
||||
*
|
||||
* PSP is set to NULL and therefore a task must allocate and load a context
|
||||
* before calling any secure side function in the thread mode.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureContext_Init( void );
|
||||
|
||||
/**
|
||||
* @brief Allocates a context on the secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] ulSecureStackSize Size of the stack to allocate on secure side.
|
||||
* @param[in] ulIsTaskPrivileged 1 if the calling task is privileged, 0 otherwise.
|
||||
*
|
||||
* @return Opaque context handle if context is successfully allocated, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
uint32_t ulIsTaskPrivileged,
|
||||
void * pvTaskHandle );
|
||||
#else /* configENABLE_MPU */
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
void * pvTaskHandle );
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/**
|
||||
* @brief Frees the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the
|
||||
* context to be freed.
|
||||
*/
|
||||
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
|
||||
|
||||
/**
|
||||
* @brief Loads the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be loaded.
|
||||
*/
|
||||
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
|
||||
|
||||
/**
|
||||
* @brief Saves the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be saved.
|
||||
*/
|
||||
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
|
||||
|
||||
#endif /* __SECURE_CONTEXT_H__ */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_CONTEXT_H__
|
||||
#define __SECURE_CONTEXT_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
/**
|
||||
* @brief PSP value when no secure context is loaded.
|
||||
*/
|
||||
#define securecontextNO_STACK 0x0
|
||||
|
||||
/**
|
||||
* @brief Invalid context ID.
|
||||
*/
|
||||
#define securecontextINVALID_CONTEXT_ID 0UL
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Structure to represent a secure context.
|
||||
*
|
||||
* @note Since stack grows down, pucStackStart is the highest address while
|
||||
* pucStackLimit is the first address of the allocated memory.
|
||||
*/
|
||||
typedef struct SecureContext
|
||||
{
|
||||
uint8_t * pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
|
||||
uint8_t * pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
|
||||
uint8_t * pucStackStart; /**< First location of the stack memory. */
|
||||
void * pvTaskHandle; /**< Task handle of the task this context is associated with. */
|
||||
} SecureContext_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Opaque handle for a secure context.
|
||||
*/
|
||||
typedef uint32_t SecureContextHandle_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the secure context management system.
|
||||
*
|
||||
* PSP is set to NULL and therefore a task must allocate and load a context
|
||||
* before calling any secure side function in the thread mode.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureContext_Init( void );
|
||||
|
||||
/**
|
||||
* @brief Allocates a context on the secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] ulSecureStackSize Size of the stack to allocate on secure side.
|
||||
* @param[in] ulIsTaskPrivileged 1 if the calling task is privileged, 0 otherwise.
|
||||
*
|
||||
* @return Opaque context handle if context is successfully allocated, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
uint32_t ulIsTaskPrivileged,
|
||||
void * pvTaskHandle );
|
||||
#else /* configENABLE_MPU */
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
|
||||
void * pvTaskHandle );
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/**
|
||||
* @brief Frees the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the
|
||||
* context to be freed.
|
||||
*/
|
||||
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
|
||||
|
||||
/**
|
||||
* @brief Loads the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be loaded.
|
||||
*/
|
||||
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
|
||||
|
||||
/**
|
||||
* @brief Saves the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be saved.
|
||||
*/
|
||||
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle, void * pvTaskHandle );
|
||||
|
||||
#endif /* __SECURE_CONTEXT_H__ */
|
||||
|
|
|
|||
|
|
@ -1,99 +1,99 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||
|
||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
|
||||
{
|
||||
/* pxSecureContext value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" ldmia r0!, {r1, r2} \n" /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
" msr control, r3 \n" /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" msr psplim, r2 \n" /* PSPLIM = r2. */
|
||||
" msr psp, r1 \n" /* PSP = r1. */
|
||||
" \n"
|
||||
" load_ctx_therad_mode: \n"
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
::: "r0", "r1", "r2"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )
|
||||
{
|
||||
/* pxSecureContext value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" mrs r1, psp \n" /* r1 = PSP. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||
" subs r1, r1, #4 \n" /* Make space for the CONTROL value on the stack. */
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
" stmia r1!, {r2} \n" /* Store CONTROL value on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */
|
||||
" msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */
|
||||
" msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
" \n"
|
||||
" save_ctx_therad_mode: \n"
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
::"i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
|
||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext ) __attribute__( ( naked ) );
|
||||
|
||||
void SecureContext_LoadContextAsm( SecureContext_t * pxSecureContext )
|
||||
{
|
||||
/* pxSecureContext value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" ldmia r0!, {r1, r2} \n" /* r1 = pxSecureContext->pucCurrentStackPointer, r2 = pxSecureContext->pucStackLimit. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
" msr control, r3 \n" /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" msr psplim, r2 \n" /* PSPLIM = r2. */
|
||||
" msr psp, r1 \n" /* PSP = r1. */
|
||||
" \n"
|
||||
" load_ctx_therad_mode: \n"
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
::: "r0", "r1", "r2"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SecureContext_SaveContextAsm( SecureContext_t * pxSecureContext )
|
||||
{
|
||||
/* pxSecureContext value is in r0. */
|
||||
__asm volatile
|
||||
(
|
||||
" .syntax unified \n"
|
||||
" \n"
|
||||
" mrs r1, ipsr \n" /* r1 = IPSR. */
|
||||
" cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */
|
||||
" mrs r1, psp \n" /* r1 = PSP. */
|
||||
" \n"
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
" mrs r2, control \n" /* r2 = CONTROL. */
|
||||
" subs r1, r1, #4 \n" /* Make space for the CONTROL value on the stack. */
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
" stmia r1!, {r2} \n" /* Store CONTROL value on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
" str r1, [r0] \n" /* Save the top of stack in context. pxSecureContext->pucCurrentStackPointer = r1. */
|
||||
#endif /* configENABLE_MPU */
|
||||
" \n"
|
||||
" movs r1, %0 \n" /* r1 = securecontextNO_STACK. */
|
||||
" msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */
|
||||
" msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
" \n"
|
||||
" save_ctx_therad_mode: \n"
|
||||
" bx lr \n"
|
||||
" \n"
|
||||
::"i" ( securecontextNO_STACK ) : "r1", "memory"
|
||||
);
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,454 +1,454 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Secure context heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Total heap size.
|
||||
*/
|
||||
#ifndef secureconfigTOTAL_HEAP_SIZE
|
||||
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
|
||||
#endif
|
||||
|
||||
/* No test marker by default. */
|
||||
#ifndef mtCOVERAGE_TEST_MARKER
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceMALLOC
|
||||
#define traceMALLOC( pvReturn, xWantedSize )
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceFREE
|
||||
#define traceFREE( pv, xBlockSize )
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#else /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
/**
|
||||
* @brief The linked list structure.
|
||||
*
|
||||
* This is used to link free blocks in order of their memory address.
|
||||
*/
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Called automatically to setup the required heap structures the first
|
||||
* time pvPortMalloc() is called.
|
||||
*/
|
||||
static void prvHeapInit( void );
|
||||
|
||||
/**
|
||||
* @brief Inserts a block of memory that is being freed into the correct
|
||||
* position in the list of free memory blocks.
|
||||
*
|
||||
* The block being freed will be merged with the block in front it and/or the
|
||||
* block behind it if the memory blocks are adjacent to each other.
|
||||
*
|
||||
* @param[in] pxBlockToInsert The block being freed.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief The size of the structure placed at the beginning of each allocated
|
||||
* memory block must by correctly byte aligned.
|
||||
*/
|
||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( secureportBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
|
||||
/**
|
||||
* @brief Create a couple of list links to mark the start and end of the list.
|
||||
*/
|
||||
static BlockLink_t xStart;
|
||||
static BlockLink_t * pxEnd = NULL;
|
||||
|
||||
/**
|
||||
* @brief Keeps track of the number of free bytes remaining, but says nothing
|
||||
* about fragmentation.
|
||||
*/
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
|
||||
/**
|
||||
* @brief Gets set to the top bit of an size_t type.
|
||||
*
|
||||
* When this bit in the xBlockSize member of an BlockLink_t structure is set
|
||||
* then the block belongs to the application. When the bit is free the block is
|
||||
* still part of the free heap space.
|
||||
*/
|
||||
static size_t xBlockAllocatedBit = 0;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHeapInit( void )
|
||||
{
|
||||
BlockLink_t * pxFirstFreeBlock;
|
||||
uint8_t * pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = ( size_t ) ucHeap;
|
||||
|
||||
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
|
||||
}
|
||||
|
||||
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( void * ) uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
|
||||
{
|
||||
BlockLink_t * pxIterator;
|
||||
uint8_t * puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void * pvPortMalloc( size_t xWantedSize )
|
||||
{
|
||||
BlockLink_t * pxBlock;
|
||||
BlockLink_t * pxPreviousBlock;
|
||||
BlockLink_t * pxNewBlockLink;
|
||||
void * pvReturn = NULL;
|
||||
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Check the requested block size is not so large that the top bit is set.
|
||||
* The top bit of the block size member of the BlockLink_t structure is used
|
||||
* to determine who owns the block - the application or the kernel, so it
|
||||
* must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number of
|
||||
* bytes. */
|
||||
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
|
||||
secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size was
|
||||
* not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the single
|
||||
* block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned by
|
||||
* the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
|
||||
#if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
|
||||
|
||||
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
uint8_t * puc = ( uint8_t * ) pv;
|
||||
BlockLink_t * pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
}
|
||||
secureportENABLE_NON_SECURE_INTERRUPTS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Secure context heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Total heap size.
|
||||
*/
|
||||
#ifndef secureconfigTOTAL_HEAP_SIZE
|
||||
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
|
||||
#endif
|
||||
|
||||
/* No test marker by default. */
|
||||
#ifndef mtCOVERAGE_TEST_MARKER
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceMALLOC
|
||||
#define traceMALLOC( pvReturn, xWantedSize )
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceFREE
|
||||
#define traceFREE( pv, xBlockSize )
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if ( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#else /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
/**
|
||||
* @brief The linked list structure.
|
||||
*
|
||||
* This is used to link free blocks in order of their memory address.
|
||||
*/
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Called automatically to setup the required heap structures the first
|
||||
* time pvPortMalloc() is called.
|
||||
*/
|
||||
static void prvHeapInit( void );
|
||||
|
||||
/**
|
||||
* @brief Inserts a block of memory that is being freed into the correct
|
||||
* position in the list of free memory blocks.
|
||||
*
|
||||
* The block being freed will be merged with the block in front it and/or the
|
||||
* block behind it if the memory blocks are adjacent to each other.
|
||||
*
|
||||
* @param[in] pxBlockToInsert The block being freed.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief The size of the structure placed at the beginning of each allocated
|
||||
* memory block must by correctly byte aligned.
|
||||
*/
|
||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( secureportBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
|
||||
/**
|
||||
* @brief Create a couple of list links to mark the start and end of the list.
|
||||
*/
|
||||
static BlockLink_t xStart;
|
||||
static BlockLink_t * pxEnd = NULL;
|
||||
|
||||
/**
|
||||
* @brief Keeps track of the number of free bytes remaining, but says nothing
|
||||
* about fragmentation.
|
||||
*/
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
|
||||
/**
|
||||
* @brief Gets set to the top bit of an size_t type.
|
||||
*
|
||||
* When this bit in the xBlockSize member of an BlockLink_t structure is set
|
||||
* then the block belongs to the application. When the bit is free the block is
|
||||
* still part of the free heap space.
|
||||
*/
|
||||
static size_t xBlockAllocatedBit = 0;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHeapInit( void )
|
||||
{
|
||||
BlockLink_t * pxFirstFreeBlock;
|
||||
uint8_t * pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = ( size_t ) ucHeap;
|
||||
|
||||
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
|
||||
}
|
||||
|
||||
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( void * ) uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert )
|
||||
{
|
||||
BlockLink_t * pxIterator;
|
||||
uint8_t * puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void * pvPortMalloc( size_t xWantedSize )
|
||||
{
|
||||
BlockLink_t * pxBlock;
|
||||
BlockLink_t * pxPreviousBlock;
|
||||
BlockLink_t * pxNewBlockLink;
|
||||
void * pvReturn = NULL;
|
||||
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Check the requested block size is not so large that the top bit is set.
|
||||
* The top bit of the block size member of the BlockLink_t structure is used
|
||||
* to determine who owns the block - the application or the kernel, so it
|
||||
* must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number of
|
||||
* bytes. */
|
||||
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
|
||||
secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size was
|
||||
* not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the single
|
||||
* block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned by
|
||||
* the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
|
||||
#if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
|
||||
|
||||
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void * pv )
|
||||
{
|
||||
uint8_t * puc = ( uint8_t * ) pv;
|
||||
BlockLink_t * pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
}
|
||||
secureportENABLE_NON_SECURE_INTERRUPTS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,66 +1,66 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_HEAP_H__
|
||||
#define __SECURE_HEAP_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from heap.
|
||||
*
|
||||
* @param[in] xWantedSize The size of the memory to be allocated.
|
||||
*
|
||||
* @return Pointer to the memory region if the allocation is successful, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
void * pvPortMalloc( size_t xWantedSize );
|
||||
|
||||
/**
|
||||
* @brief Frees the previously allocated memory.
|
||||
*
|
||||
* @param[in] pv Pointer to the memory to be freed.
|
||||
*/
|
||||
void vPortFree( void * pv );
|
||||
|
||||
/**
|
||||
* @brief Get the free heap size.
|
||||
*
|
||||
* @return Free heap size.
|
||||
*/
|
||||
size_t xPortGetFreeHeapSize( void );
|
||||
|
||||
/**
|
||||
* @brief Get the minimum ever free heap size.
|
||||
*
|
||||
* @return Minimum ever free heap size.
|
||||
*/
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void );
|
||||
|
||||
#endif /* __SECURE_HEAP_H__ */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_HEAP_H__
|
||||
#define __SECURE_HEAP_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from heap.
|
||||
*
|
||||
* @param[in] xWantedSize The size of the memory to be allocated.
|
||||
*
|
||||
* @return Pointer to the memory region if the allocation is successful, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
void * pvPortMalloc( size_t xWantedSize );
|
||||
|
||||
/**
|
||||
* @brief Frees the previously allocated memory.
|
||||
*
|
||||
* @param[in] pv Pointer to the memory to be freed.
|
||||
*/
|
||||
void vPortFree( void * pv );
|
||||
|
||||
/**
|
||||
* @brief Get the free heap size.
|
||||
*
|
||||
* @return Free heap size.
|
||||
*/
|
||||
size_t xPortGetFreeHeapSize( void );
|
||||
|
||||
/**
|
||||
* @brief Get the minimum ever free heap size.
|
||||
*
|
||||
* @return Minimum ever free heap size.
|
||||
*/
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void );
|
||||
|
||||
#endif /* __SECURE_HEAP_H__ */
|
||||
|
|
|
|||
|
|
@ -1,106 +1,106 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Secure init includes. */
|
||||
#include "secure_init.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
|
||||
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
|
||||
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
|
||||
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
|
||||
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define secureinitFPCCR_LSPENS_POS ( 29UL )
|
||||
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
|
||||
#define secureinitFPCCR_TS_POS ( 26UL )
|
||||
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
|
||||
|
||||
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
|
||||
#define secureinitNSACR_CP10_POS ( 10UL )
|
||||
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
|
||||
#define secureinitNSACR_CP11_POS ( 11UL )
|
||||
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
|
||||
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
|
||||
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
|
||||
* permitted. CP11 should be programmed to the same value as CP10. */
|
||||
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
|
||||
|
||||
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
|
||||
* that we can enable/disable lazy stacking in port.c file. */
|
||||
*( secureinitFPCCR ) &= ~( secureinitFPCCR_LSPENS_MASK );
|
||||
|
||||
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
|
||||
* registers (S16-S31) are also pushed to stack on exception entry and
|
||||
* restored on exception return. */
|
||||
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Secure init includes. */
|
||||
#include "secure_init.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
|
||||
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
|
||||
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
|
||||
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
|
||||
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define secureinitFPCCR_LSPENS_POS ( 29UL )
|
||||
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
|
||||
#define secureinitFPCCR_TS_POS ( 26UL )
|
||||
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
|
||||
|
||||
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
|
||||
#define secureinitNSACR_CP10_POS ( 10UL )
|
||||
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
|
||||
#define secureinitNSACR_CP11_POS ( 11UL )
|
||||
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
|
||||
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
|
||||
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
|
||||
* permitted. CP11 should be programmed to the same value as CP10. */
|
||||
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
|
||||
|
||||
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
|
||||
* that we can enable/disable lazy stacking in port.c file. */
|
||||
*( secureinitFPCCR ) &= ~( secureinitFPCCR_LSPENS_MASK );
|
||||
|
||||
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
|
||||
* registers (S16-S31) are also pushed to stack on exception entry and
|
||||
* restored on exception return. */
|
||||
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
|
|
|||
|
|
@ -1,54 +1,54 @@
|
|||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_INIT_H__
|
||||
#define __SECURE_INIT_H__
|
||||
|
||||
/**
|
||||
* @brief De-prioritizes the non-secure exceptions.
|
||||
*
|
||||
* This is needed to ensure that the non-secure PendSV runs at the lowest
|
||||
* priority. Context switch is done in the non-secure PendSV handler.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_DePrioritizeNSExceptions( void );
|
||||
|
||||
/**
|
||||
* @brief Sets up the Floating Point Unit (FPU) for Non-Secure access.
|
||||
*
|
||||
* Also sets FPCCR.TS=1 to ensure that the content of the Floating Point
|
||||
* Registers are not leaked to the non-secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_EnableNSFPUAccess( void );
|
||||
|
||||
#endif /* __SECURE_INIT_H__ */
|
||||
/*
|
||||
* FreeRTOS Kernel <DEVELOPMENT BRANCH>
|
||||
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* https://www.FreeRTOS.org
|
||||
* https://github.com/FreeRTOS
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_INIT_H__
|
||||
#define __SECURE_INIT_H__
|
||||
|
||||
/**
|
||||
* @brief De-prioritizes the non-secure exceptions.
|
||||
*
|
||||
* This is needed to ensure that the non-secure PendSV runs at the lowest
|
||||
* priority. Context switch is done in the non-secure PendSV handler.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_DePrioritizeNSExceptions( void );
|
||||
|
||||
/**
|
||||
* @brief Sets up the Floating Point Unit (FPU) for Non-Secure access.
|
||||
*
|
||||
* Also sets FPCCR.TS=1 to ensure that the content of the Floating Point
|
||||
* Registers are not leaked to the non-secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_EnableNSFPUAccess( void );
|
||||
|
||||
#endif /* __SECURE_INIT_H__ */
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue