AnsweredAssumed Answered

after i enable interrupt,then i maybe get in usage fault?

Question asked by sheng yang on Apr 21, 2018

nowadays, i try to port uclinux to my board based on stm32f767igt,the uclinux version is uClinux-dist-20160919.tar.bz2.and the u-boot version is U-Boot 2018.03.i compiled u-boot use the compiler arm-none-eabi-gcc (GNU Tools for Arm Embedded Processors 7-2017-q4-major) 7.2.1 20170904 (release) [ARM/embedded-7-branch revision 255204].i can boot u-boot success.

i use compiler arm-uclinuxeabi-tools-20160831.tar.gz to compile uClinux,the gcc version is 

[shengyang@red u-boot]$ arm-uclinuxeabi-gcc -v
Using built-in specs.
COLLECT_GCC=arm-uclinuxeabi-gcc
COLLECT_LTO_WRAPPER=/usr/local/arm-uclinux/bin/../libexec/gcc/arm-uclinuxeabi/5.4.0/lto-wrapper
Target: arm-uclinuxeabi
Configured with: ../configure --target=arm-uclinuxeabi --with-float=hard --enable-multilib --with-system-zlib --disable-libsanitizer --enable-languages=c,c++ --prefix=/usr/local
Thread model: single
gcc version 5.4.0 (GCC)

and the build tool version

[shengyang@red u-boot]$ arm-uclinuxeabi-objdump -v
GNU objdump (GNU Binutils) 2.26.20160125
Copyright (C) 2015 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) any later version.
This program has absolutely no warranty.

after i modified uClinux source code with early printk suppor and change some code with a patch file

diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
old mode 100644
new mode 100755
index f89d1f7..723d842
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -29,7 +29,19 @@

#define DRIVER_NAME "stm32-usart"

+#define CONFIG_STM32F7
/* Register offsets */
+#ifdef CONFIG_STM32F7
+#define USART_SR 0x1c
+#define USART_DR_REC 0x24
+#define USART_DR 0x28
+#define USART_CR1 0x00
+#define USART_CR2 0x04
+#define USART_CR3 0x08
+#define USART_BRR 0x0c
+
+#define USART_GTPR 0x10
+#else
#define USART_SR 0x00
#define USART_DR 0x04
#define USART_BRR 0x08
@@ -37,6 +49,7 @@
#define USART_CR2 0x10
#define USART_CR3 0x14
#define USART_GTPR 0x18
+#endif

/* USART_SR */
#define USART_SR_PE BIT(0)
@@ -76,7 +89,11 @@
#define USART_CR1_PCE BIT(10)
#define USART_CR1_WAKE BIT(11)
#define USART_CR1_M BIT(12)
+#ifdef CONFIG_STM32F7
+#define USART_CR1_UE BIT(0)
+#else
#define USART_CR1_UE BIT(13)
+#endif
#define USART_CR1_OVER8 BIT(15)
#define USART_CR1_IE_MASK GENMASK(8, 4)

@@ -160,7 +177,11 @@ static void stm32_receive_chars(struct uart_port *port)

while ((sr = readl_relaxed(port->membase + USART_SR)) & USART_SR_RXNE) {
sr |= USART_SR_DUMMY_RX;
+ #ifdef CONFIG_STM32F7
+ c = readl_relaxed(port->membase + USART_DR_REC);
+ #else
c = readl_relaxed(port->membase + USART_DR);
+ #endif
flag = TTY_NORMAL;
port->icount.rx++;

@@ -523,7 +544,6 @@ static int stm32_init_port(struct stm32_port *stm32port,
if (IS_ERR(port->membase))
return PTR_ERR(port->membase);
port->mapbase = res->start;
-
spin_lock_init(&port->lock);

stm32port->clk = devm_clk_get(&pdev->dev, NULL);
@@ -538,9 +558,7 @@ static int stm32_init_port(struct stm32_port *stm32port,
stm32port->port.uartclk = clk_get_rate(stm32port->clk);
if (!stm32port->port.uartclk)
ret = -EINVAL;
-
clk_disable_unprepare(stm32port->clk);
-
return ret;
}

@@ -579,19 +597,15 @@ static int stm32_serial_probe(struct platform_device *pdev)
{
int ret;
struct stm32_port *stm32port;
-
stm32port = stm32_of_get_stm32_port(pdev);
if (!stm32port)
return -ENODEV;
-
ret = stm32_init_port(stm32port, pdev);
if (ret)
- return ret;
-
+ return ret;
ret = uart_add_one_port(&stm32_usart_driver, &stm32port->port);
if (ret)
return ret;
-
platform_set_drvdata(pdev, &stm32port->port);

return 0;
@@ -651,7 +665,6 @@ static int stm32_console_setup(struct console *co, char *options)
int bits = 8;
int parity = 'n';
int flow = 'n';
-
if (co->index >= STM32_MAX_PORTS)
return -ENODEV;

@@ -668,7 +681,6 @@ static int stm32_console_setup(struct console *co, char *options)

if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
-
return uart_set_options(&stm32port->port, co, baud, parity, bits, flow);
}

sometimes i can get in kernel success as
[ 0.000000] iysheng start_kernel 00
[ 0.010000] iysheng start_kernel 11
[ 0.010000] Calibrating delay loop... 393.21 BogoMIPS (lpj=1966080)
[ 0.060000] pid_max: default: 4096 minimum: 301
[ 0.060000] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.070000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.080000] iysheng start_kernel 0e10017f 00400000
[ 0.100000] devtmpfs: initialized
[ 0.120000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[ 0.190000] clocksource: Switched to clocksource arm_system_timer
[ 0.420000] iysheng driver_register ***222*** alarmtimer
[ 0.430000] iysheng bus_add_driver ***111
[ 0.430000] iysheng bus_add_driver ***222
[ 0.430000] iysheng bus_for_each_dev
[ 0.440000] iysheng bus_for_each_dev 000 0
[ 0.450000] iysheng bus_for_each_dev 000 0
[ 0.450000] iysheng bus_for_each_dev 000 0
[ 0.450000] iysheng bus_for_each_dev 000 0
[ 0.460000] iysheng bus_for_each_dev 000 0
[ 0.460000] iysheng bus_for_each_dev 000 0
[ 0.460000] iysheng bus_for_each_dev 000 0
[ 0.470000] iysheng bus_for_each_dev 111
[ 0.480000] iysheng bus_for_each_dev 222
[ 0.480000] iysheng bus_add_driver ***333
[ 0.480000] iysheng bus_add_driver ***444
[ 0.490000] iysheng driver_register ***333*** alarmtimer
[ 0.500000] iysheng driver_register ***444*** alarmtimer
[ 0.500000] iysheng driver_register ***555*** alarmtimer
[ 0.500000] iysheng driver_probe_device
[ 0.510000] iysheng really_probe
[ 0.560000] io scheduler noop registered (default)
[ 0.580000] STM32 USART driver initialized
[ 0.580000] iysheng driver_register ***222*** stm32-usart
[ 0.580000] iysheng bus_add_driver ***111
[ 0.590000] iysheng bus_add_driver ***222
[ 0.590000] iysheng bus_for_each_dev
[ 0.600000] iysheng bus_for_each_dev 000 0
[ 0.600000] iysheng bus_for_each_dev 000 0
[ 0.600000] iysheng bus_for_each_dev 000 0
[ 0.610000] iysheng bus_for_each_dev 000 0
[ 0.620000] iysheng driver_probe_device
[ 0.620000] iysheng really_probe
[ 0.620000] iysheng stm32_serial_probe 000
[ 0.630000] iysheng stm32_init_port 000 irq=17 clk=0
[ 0.630000] iysheng stm32_serial_probe 001 ret=0
[ 0.630000] 40011000.serial: ttyS0 at MMIO 0x40011000 (irq = 17, base_baud = 6250000) is a stm32-usart
[ 0.650000] iysheng uart_configure_port 0
[ 0.650000] iysheng register_console 0
[ 0.650000] iysheng register_console 1
[ 0.660000] iysheng stm32_console_setup 0
[ 0.670000] iysheng stm32_console_setup 1
[ 0.670000] iysheng uart_set_options c_cflag=00001cb2 bits=8 parity=n baud=115200
[ 0.670000] iysheng uart_set_options 0
[ 0.680000] iysheng uart_set_options 1
[ 0.680000] iysheng register_console 2
[ 0.690000] console [ttyS0] enabled
0.690000] console [ttyS0] enabled
[ 0.700000] bootconsole [earlycon0] disabled
0.700000] bootconsole [earlycon0] disabled
[ 0.710000] iysheng uart_configure_port 1
[ 0.710000] iysheng bus_for_each_dev 000 0
[ 0.710000] iysheng bus_for_each_dev 000 0
[ 0.720000] iysheng bus_for_each_dev 000 0
[ 0.730000] iysheng bus_for_each_dev 000 0
[ 0.730000] iysheng bus_for_each_dev 111
[ 0.730000] iysheng bus_for_each_dev 222
[ 0.740000] iysheng bus_add_driver ***333
[ 0.740000] iysheng bus_add_driver ***444
[ 0.740000] iysheng driver_register ***333*** stm32-usart
[ 0.750000] iysheng driver_register ***444*** stm32-usart
[ 0.760000] iysheng driver_register ***555*** stm32-usart
[ 0.760000] iysheng usart_init
[ 0.780000] brd: module loaded
[ 0.850000] loop: module loaded
[ 0.870000] Freeing unused kernel memory: 232K (c0112000 - c014c000)
ifconfig: socket: Function not implemented
/ #
/ # ls
bin dev etc init lib proc sbin sys

but sometimes i maybe hung as
[ 0.000000] iysheng start_kernel 00
[ 0.010000]
[ 0.010000] Unhandled exception: IPSR = 00000006 LR = fffffff1
[ 0.010000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.4.0-uc0-gadcec99-dirty #271
[ 0.010000] Hardware name: STM32 (Device Tree Support)
[ 0.010000] task: c014e520 ti: c014c000 task.ti: c014c000
[ 0.010000] PC is at 0xffffffff
[ 0.010000] LR is at reset_devices+0x0/0x4
[ 0.010000] pc : [<ffffffff>] lr : [<c0155ba0>] psr: c014e000
[ 0.010000] sp : c014df78 ip : 00000000 fp : c0112574
[ 0.010000] r10: c0112573 r9 : c014dfc0 r8 : c014df9c
[ 0.010000] r7 : c014e000 r6 : ffffffff r5 : c0155ba0 r4 : 00000000
[ 0.010000] r3 : c014c000 r2 : 00000001 r1 : c0151840 r0 : 00000017
[ 0.010000] xPSR: c014e000
[ 0.010000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.4.0-uc0-gadcec99-dirty #271
[ 0.010000] Hardware name: STM32 (Device Tree Support)
[ 0.010000] [<c000bdf9>] (unwind_backtrace) from [<c000b1ab>] (show_stack+0xb/0xc)
[ 0.010000] [<c000b1ab>] (show_stack) from [<c000b73f>] (__invalid_entry+0x4b/0x4c)
I see lr=c0155ba0, so i look at the asm file of vmlinux,and the addr is bss start as we can see
c0155b95 <__warned.10833>:
450768 ...
450769
450770 c0155b96 <__warned.21182>:
450771 ...
450772
450773 c0155b97 <__warned.6791>:
450774 ...
450775
450776 Disassembly of section .bss:
450777
450778 c0155ba0 <__bss_start>:
450779 c0155ba0: 00000000 andeq r0, r0, r0
and we can see ISPR=6,So I get confused why I may get in Usagefault handler??

i add two line codes with debug around local_irq_enable() in file init/main.c with function start_kernel.

 

printk("iysheng %s 00\n", __func__);
local_irq_enable();

kmem_cache_init_late();
printk("iysheng %s 11\n", __func__);

 

so ,sometimes after i local_irq_enable();then i will get in usagefault soon,and hung with

[ 0.000000] iysheng start_kernel 00

Outcomes