开发环境
PC:Ubuntu18.04
开发板:tiny4412SDK1611+tiny4412-1412
交叉编译工具:gcc-linaro-6.1.1-2016.08-x86_64_arm-linux-gnueabi
U-boot:u-boot-16.11
Kernel:linux-4.4.0
问题
在Kernel启动后,输入ls、more、cat等需要输出很多内容的命令时出现一下提示:
[root@TINY4412:~]# ls /dev/
autofs ptypf ram6 ttyq0
backlight_1wire ptyq0 r[ 16.570411] dma-pl330 12680000.pdma: Reset Channel-1 CS-20000f FTC-20000
yta
loop6 ptyta tty55 [ 16.577271] dma-pl330 12680000.pdma: Reset Channel-1 CS-20000f FTC-20000
ptyx6 ttyca ttyx7
ptyca ptyx7 ttycb ttyx8
p[ 16.600598] dma-pl330 12680000.pdma: Reset Channel-1 CS-20000f FTC-20000
ttypf
同时输出的内容少时不会出现提示,输出内容多了之后出现问题。
参照网友的方法TINY4412】LINUX移植笔记:(21)常见问题中的解决方法修改kernel配置,只能运行到这里。
[ 2.245907] NET: Registered protocol family 10
[ 2.247915] sit: IPv6 over IPv4 tunneling driver
[ 2.252469] NET: Registered protocol family 17
[ 2.256397] NET: Registered protocol family 15
[ 2.260967] Registering SWP/SWPB emulation handler
[ 2.266803] hctosys: unable to open rtc device (rtc0)
[ 2.282958] ALSA device list:
[ 2.282997] No soundcards found.
[ 2.283666] RAMDISK: gzip image found at block 0
[ 2.433397] VFS: Mounted root (ext2 filesystem) on device 1:0.
[ 2.433545] devtmpfs: mounted
[ d.433821] Freeing unused kernel memory: 420K (c079d000 - c0806000)
并没有出现Please press Enter to activate this console.
但是核心板上的LED任然在有规律的闪烁,说明内核成功启动了,再次猜测可能时ramdisk的制作有问题,又重新制作了一遍ramdisk,最后还是同样的问题。此时可以确定不是ramdisk的问题,而内核已启动,只是没有终端,所以可以判断在Kernel中serial使用了DMA功能,同时数据量大了之后会出现错误。
查看drivers/tty/serial/samsung.c文件发现,当传输数据量小于ourport->min_dma_size时,不使用DMA,大于等于min_mda_size时才是使用DMA,因此可以判断时DMA的问题。
static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport)
{
struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->state->xmit;
unsigned long count;
/* Get data size up to the end of buffer */
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
if (!count) {
s3c24xx_serial_stop_tx(port);
return;
}
if (!ourport->dma || !ourport->dma->tx_chan ||
count < ourport->min_dma_size ||
xmit->tail & (dma_get_cache_alignment() - 1))
s3c24xx_serial_start_tx_pio(ourport);
else
s3c24xx_serial_start_tx_dma(ourport, count);
}
解决方法
查阅资料发现【为了强制执行对非安全世界外设和地址访问的限制,Exynos4412配备了“TrustZone保护控制器”和“TrustZone地址空间控制器”。它们控制是否只有安全世界可访问任何给定的外设或者内存地址或安全和非安全世界。另一个需要注意的重要事项,即使CPU在安全模式下运行,PL330 DMA控制器也始终使用非安全模式,因此,如果尝试使用DMA访问在TZPC中设置为“仅安全”的内容,则会出现故障并且DMA传输将失败。所需要的只是将所有内存标记为非安全可读写,并将所有外设标记为非安全可读写即可。】
具体如下:
diff --git a/arch/arm/mach-exynos/dmc_init_exynos4412.c b/arch/arm/mach-exynos/dmc_init_exynos4412.c
index d35678d..301b282 100644
--- a/arch/arm/mach-exynos/dmc_init_exynos4412.c
+++ b/arch/arm/mach-exynos/dmc_init_exynos4412.c
@@ -28,6 +28,22 @@
#include "common_setup.h"
#include "exynos4412_setup.h"
+#define NR_TZASC_BANKS 4
+
+/* Allow non-secure and secure access to all memory */
+#define RA0_VAL 0xf0000000
+
+static void tzasc_init(void) {
+ unsigned int start = samsung_get_base_dmc_tzasc();
+
+ unsigned int end = start + (DMC_OFFSET * (NR_TZASC_BANKS - 1));
+ for (; start <= end; start += DMC_OFFSET) {
+ struct exynos4412_tzasc *asc = (struct exynos4412_tzasc *)start;
+ writel(RA0_VAL, &asc->region_attributes_0);
+ }
+}
+
+
#ifdef CONFIG_TINY4412
struct mem_timings mem = {
.direct_cmd_msr = {
@@ -248,4 +264,8 @@ void mem_ctrl_init(int reset)
dmc = (struct exynos4_dmc *)(samsung_get_base_dmc_ctrl()
+ DMC_OFFSET);
dmc_init(dmc);
+
+
+ tzasc_init();
+
}
diff --git a/arch/arm/mach-exynos/include/mach/cpu.h b/arch/arm/mach-exynos/include/mach/cpu.h
index 1f722df..babadeb 100644
--- a/arch/arm/mach-exynos/include/mach/cpu.h
+++ b/arch/arm/mach-exynos/include/mach/cpu.h
@@ -70,6 +70,7 @@
#define EXYNOS4X12_TZPC_BASE 0x10110000
#define EXYNOS4X12_DMC_CTRL_BASE 0x10600000
#define EXYNOS4X12_GPIO_PART4_BASE 0x106E0000
+#define EXYNOS4X12_DMC_TZASC_BASE 0x10700000
#define EXYNOS4X12_ACE_SFR_BASE 0x10830000
#define EXYNOS4X12_GPIO_PART2_BASE 0x11000000
#define EXYNOS4X12_GPIO_PART2_0 0x11000000
@@ -101,7 +102,6 @@
#define EXYNOS4X12_AUDIOSS_BASE DEVICE_NOT_AVAILABLE
#define EXYNOS4X12_USB_HOST_XHCI_BASE DEVICE_NOT_AVAILABLE
#define EXYNOS4X12_USB3PHY_BASE DEVICE_NOT_AVAILABLE
-#define EXYNOS4X12_DMC_TZASC_BASE DEVICE_NOT_AVAILABLE
/* EXYNOS5 */
#define EXYNOS5_I2C_SPACING 0x10000
diff --git a/arch/arm/mach-exynos/include/mach/dmc.h b/arch/arm/mach-exynos/include/mach/dmc.h
index 4990a1a..cad4908 100644
--- a/arch/arm/mach-exynos/include/mach/dmc.h
+++ b/arch/arm/mach-exynos/include/mach/dmc.h
@@ -419,6 +419,25 @@ struct exynos5420_phy_control {
unsigned int phy_con42;
};
+struct exynos4412_tzasc {
+ unsigned char res1[0x100];
+ unsigned int region_setup_low_0; // 100
+ unsigned int region_setup_high_0; // 104
+ unsigned int region_attributes_0; // 108
+ unsigned int res2; // 10c
+ unsigned int region_setup_low_1; // 110
+ unsigned int region_setup_high_1; // 114
+ unsigned int region_setup_attributes_1; // 118
+ unsigned int res3;
+ unsigned int region_setup_low_2; // 120
+ unsigned int region_setup_high_2; // 124
+ unsigned int region_setup_attributes_2; // 128
+ unsigned int res4;
+ unsigned int region_setup_low_3; // 130
+ unsigned int region_setup_high_3; // 134
+ unsigned int region_attributes_3; // 138
+};
+
struct exynos5420_tzasc {
unsigned char res1[0xf00];
unsigned int membaseconfig0;
diff --git a/arch/arm/mach-exynos/lowlevel_init.c b/arch/arm/mach-exynos/lowlevel_init.c
index 4aecb7e..5763390 100644
--- a/arch/arm/mach-exynos/lowlevel_init.c
+++ b/arch/arm/mach-exynos/lowlevel_init.c
@@ -225,9 +225,7 @@ int do_lowlevel_init(void)
#endif
mem_ctrl_init(actions & DO_MEM_RESET);
-#ifndef CONFIG_TINY4412
tzpc_init();
-#endif
}
return actions & DO_WAKEUP;
diff --git a/build_tiny4412.sh b/auto_build.sh
similarity index 100%
rename from build_tiny4412.sh
rename to auto_build.sh
diff --git a/sd_fuse/tiny4412/sd_fusing.sh b/sd_fuse/tiny4412/sd_fusing.sh
index d993f6b..2a52404 100755
--- a/sd_fuse/tiny4412/sd_fusing.sh
+++ b/sd_fuse/tiny4412/sd_fusing.sh
@@ -86,9 +86,9 @@ echo "u-boot fusing"
dd iflag=dsync oflag=dsync if=${E4412_UBOOT} of=$1 seek=$uboot_position
#<TrustZone S/W fusing>
-# echo "---------------------------------------"
-# echo "TrustZone S/W fusing"
-# dd iflag=dsync oflag=dsync if=./E4412_tzsw.bin of=$1 seek=$tzsw_position
+echo "---------------------------------------"
+echo "TrustZone S/W fusing"
+dd iflag=dsync oflag=dsync if=./E4412_tzsw.bin of=$1 seek=$tzsw_position
#<flush to disk>
sync
参考
https://blog.forkwhiletrue.me/posts/an-almost-fully-libre-galaxy-s3/