背景:
使用t113s3芯片,LcTech开发板,此板可以脱离flash,直接从USB烧录bootloader、kernel等文件并直接启动(断电后清零);
使用awboot作为bootloader,经测试可以顺利进入main函数,可以从串口打出提示信息;
bootloader烧录在0x30000,并从0x30000开始启动(xfel write 0x30000 awboot-fel.bin ; xfel exec 0x30000);
问题简述:
阅读反汇编代码,发现逻辑完全符合要求,打印前后包含测试字符串地址的寄存器未变化及修改。
测试字符串的地址0x30050传给打印函数之前,打印发现确实为0x30050,(已给打印函数增加命令:打印之前先输出待打印字符串的地址)传给打印函数后打印地址变为0x20050,并概率触发读地址错误或打印无法显示的字符。给打印函数添加新命令,接到传入地址后,地址增加0x10000,结果全部正确。
后续启动过程也存在访问地址错误的问题,怀疑与字符串显示时的地址偏移有关,所以发帖咨询:rolleyes:
下附部分反汇编代码,及link.ld文件全文。
反汇编代码说明:
前半段说明了访问字符串地址的连续性,即寄存器r0储存的确实为实际字符串ASCII值7265777169757974,即"qwertyuio",且调用函数前后没有变化,后半段为输出函数,经测试可以正常使用。
awboot-fel.elf: file format elf32-littlearm
Disassembly of section .text:
00038000 <__spl_start>:
38000: ea000016 b 38060 <__spl_start+0x60>
38004: 4e4f4765 cdpmi 7, 4, cr4, cr15, cr5, {3}
38008: 3054422e subscc r4, r4, lr, lsr #4
3800c: 12345678 eorsne r5, r4, #120, 12 ; 0x7800000
38010: 0000950c andeq r9, r0, ip, lsl #10
38014: 00000030 andeq r0, r0, r0, lsr r0
38018: 30303033 eorscc r3, r0, r3, lsr r0
.............................
char *str0 = "qwertyuio";
send_string_via_usart((int)str0);
38b3a: 486d ldr r0, [pc, #436] ; (38cf0 <main+0x200>)
38b3c: f000 f92c bl 38d98 <send_string_via_usart>
.............................
38cf0: 0003f88d andeq pc, r3, sp, lsl #17
.............................
0003f88d <.rodata.main.str1.1>:
3f88d: 72657771 rsbvc r7, r5, #29622272 ; 0x1c40000
3f891: 69757974 ldmdbvs r5!, {r2, r4, r5, r6, r8, fp, ip, sp, lr}^
.............................
void send_string_via_usart(int a) {
38d98: b570 push {r4, r5, r6, lr}
int tmp = a+0x18000;
38d9a: f500 34c0 add.w r4, r0, #98304 ; 0x18000
char* str = (char*)tmp;
putint((int)str);
for(int i = 0;i<100;i++){
if(str[i] == '\0')break;
sunxi_usart_putc(&USART_DBG,str[i]);
38d9e: 4e07 ldr r6, [pc, #28] ; (38dbc <send_string_via_usart+0x24>)
putint((int)str);
38da0: 4620 mov r0, r4
38da2: f104 0564 add.w r5, r4, #100 ; 0x64
38da6: f7ff ffcd bl 38d44 <putint>
if(str[i] == '\0')break;
38daa: 7821 ldrb r1, [r4, #0]
38dac: b129 cbz r1, 38dba <send_string_via_usart+0x22>
sunxi_usart_putc(&USART_DBG,str[i]);
38dae: 4630 mov r0, r6
for(int i = 0;i<100;i++){
38db0: 3401 adds r4, #1
sunxi_usart_putc(&USART_DBG,str[i]);
38db2: f001 fadb bl 3a36c <sunxi_usart_putc>
for(int i = 0;i<100;i++){
38db6: 42ac cmp r4, r5
38db8: d1f7 bne.n 38daa <send_string_via_usart+0x12>
}
}
38dba: bd70 pop {r4, r5, r6, pc}
38dbc: 0003f588 andeq pc, r3, r8, lsl #11
.........................
0003a36c <sunxi_usart_putc>:
//uint32_t usart_base = usart->base;
uint32_t usart_base = 0x02501400;
// 等待发送缓冲区准备好
do {
__asm__ volatile (
3a36c: 4b06 ldr r3, [pc, #24] ; (3a388 <sunxi_usart_putc+0x1c>)
3a36e: 6fda ldr r2, [r3, #124] ; 0x7c
3a370: f012 0f02 tst.w r2, #2
"ldr %[status], [%[base], #0x7C] \n" // 读取状态寄存器 (偏移 0x7C)
"tst %[status], #(1 << 1) \n" // 检查第 1 位 (发送缓冲区是否空)
: [status] "=r" (status) // 输出
: [base] "r" (usart_base) // 输入
);
} while ((status & (1 << 1)) == 0);
3a374: 0790 lsls r0, r2, #30
3a376: d5fa bpl.n 3a36e <sunxi_usart_putc+0x2>
// 发送字符
__asm__ volatile (
3a378: 6019 str r1, [r3, #0]
: [ch] "r" ((uint32_t)c), [base] "r" (usart_base)
);
// 等待发送完成
do {
__asm__ volatile (
3a37a: 6fda ldr r2, [r3, #124] ; 0x7c
3a37c: f012 0f01 tst.w r2, #1
"ldr %[status], [%[base], #0x7C] \n" // 读取状态寄存器 (偏移 0x7C)
"tst %[status], #(1 << 0) \n" // 检查第 0 位 (发送是否完成)
: [status] "=r" (status) // 输出
: [base] "r" (usart_base) // 输入
);
} while ((status & (1 << 0)) != 0);
3a380: 07d2 lsls r2, r2, #31
3a382: d4fa bmi.n 3a37a <sunxi_usart_putc+0xe>
}
3a384: 4770 bx lr
3a386: bf00 nop
3a388: 02501400 subseq r1, r0, #0, 8
/**
* \file
*
* \brief Linker script for T113-S3 internal SRAM
*
* based on: Linker script for running in internal FLASH on the SAMD21G17D
* Copyright (c) 2018 Microchip Technology Inc.
*
* \asf_license_start
*
* \page License
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the Licence at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* \asf_license_stop
*
*/
/* This file gets parsed by the preprocessor */
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
ram (rwx) : ORIGIN = __RAM_BASE, LENGTH = 96K /* A1 + DSP0 IRAM + DSP0 DRAM0. 128K on boot mode, 96K on FEL mode */
}
/* The stack size used by the application. NOTE: you need to adjust according to your application. */
STACK_SIZE = 0x1000; /* 4KB */
ENTRY(reset)
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
PROVIDE(__spl_start = .);
*(.text .text.*)
. = ALIGN(4);
} > ram
. = ALIGN(4);
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
__exidx_end = .;
} > ram
PROVIDE(__spl_end = .);
PROVIDE(__spl_size = __spl_end - __spl_start);
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
} > ram
.stack (NOLOAD):
{
. = ALIGN(8);
/* SRV stack section */
__stack_srv_start = .;
. += STACK_SIZE;
__stack_srv_end = .;
} > ram
. = ALIGN(4);
_end = . ;
}
离线