Zynq 7000:从 cpu0 初始化 cpu1 的最小 asm 代码
Zynq 7000: Minimum asm code to init cpu1 from cpu0
我正在尝试找出在 zynq-7000 的放大器配置中从 cpu0 初始化 cpu1 的最低要求。
我有一个给定的 FSBL,它移交给了 u-boot,我用它把两个程序(cpu0/1)从闪存复制到 ram 中的不同位置(sf read ...
)。
我可以 运行 在 cpu0 上使用 go [adr]
u-boot 上的两个程序,其中 adr 是任一程序的起始地址。我在 uart 上得到了预期的输出。
不起作用的是 cpu0 应该通过将其起始地址写入寄存器 0xffff_fff0
来启动 cpu1,然后发出系统事件 sev
。
我不启用任何高速缓存、MMU 或 SCU,因为我想在我实现启动 cpu1 之前使其尽可能简单(无同步或刷新)。或者这真的是问题所在,我确实需要其中的任何一个?
目前我只初始化向量 table,打印到 uart,另外对于核心 0 尝试启动核心 1:
/* CPU 0 */
.section .vector_table, "x"
.global _init
_init:
b reset /* reset handler */
b . /* software interrupt */
b . /* prefetch abort */
b . /* data abort */
b . /* reserved */
b . /* irq */
b . /* fiq */
/* ASCII control chars */
.equ asciiLF, 0x0a
.equ asciiCR, 0x0d
.section .text
uart1fifo: .word 0xe0001030 /* UART 1 rx/tx fifo register */
reset:
/* Output "0" on UART 1 */
ldr r0, uart1fifo
mov r1, #'0'
str r1, [r0]
mov r1, #asciiCR
str r1, [r0]
mov r1, #asciiLF
str r1, [r0]
/* Set cpu1 start address */
ldr r0, =0x20000000 /* CPU 1 start address */
ldr r1, =0xfffffff0 /* Register to point to the CPU 1 start address */
str r0, [r1]
/* I added a 0.5s wait here which did not help */
sev /* Execute SEV to cause CPU 1 to wake up */
/* Output "." on UART 1 to indicate that we actually went so far */
ldr r0, uart1fifo
mov r1, #'.'
str r1, [r0]
mov r1, #asciiCR
str r1, [r0]
mov r1, #asciiLF
str r1, [r0]
b . /* Endless loop */
我可以看到“0”和“.”在 uart 1 上,当我 运行 上面的代码在 cpu 0.
/* CPU 1 */
.section .vector_table, "x"
.global _init
_init:
b reset /* reset handler */
b . /* software interrupt */
b . /* prefetch abort */
b . /* data abort */
b . /* reserved */
b . /* irq */
b . /* fiq */
/* ASCII control chars */
.equ asciiLF, 0x0a
.equ asciiCR, 0x0d
.section .text
uart0fifo: .word 0xe0000030 /* UART 0 rx/tx fifo register */
reset:
/* Output "1" on UART 0 */
ldr r0, uart0fifo
mov r1, #'1'
str r1, [r0]
mov r1, #asciiCR
str r1, [r0]
mov r1, #asciiLF
str r1, [r0]
b . /* Endless loop */
在这里,当我在 cpu 0 上 运行 时,我可以在 uart 0 上看到 '1'。
我是新手,有点迷茫。我错过了一些基本的东西吗?我该怎么做才能让它发挥作用?
我一直在查看 xapp-1079,但它使用了 Xilinx 的独立库,我很难筛选出实际需要的内容。我需要一个最小的工作示例,以便我可以将它移植到我们在第一个核心上 运行 的异国情调 OS。
原来 cpu1 不在 wfe 状态。我想 u-boot 已经唤醒了它,尽管它没有使用它,即 cpu1 的状态不是 smp.
,我必须在 cpu 1 上执行软件重置并在发出 sev
命令之前将其恢复到 wfe 状态
link 死亡的步骤是:
- 备份后续步骤中覆盖的寄存器。
- 恢复OCM区的WFE(等待事件)代码。 (我使用汇编而不是显示的 xilinx xsct 命令,因为我无权访问它们的 IDE):
mwr 0xFFFFFF00 0xe3e0000f
mwr 0xFFFFFF04 0xe3a01000
mwr 0xFFFFFF08 0xe5801000
mwr 0xFFFFFF0C 0xe320f002
mwr 0xFFFFFF10 0xe5902000
mwr 0xFFFFFF14 0xe1520001
mwr 0xFFFFFF18 0x0afffffb
mwr 0xFFFFFF1C 0xe1a0f002
- 写
0x0
的跳转指令,从0x0
跳cpu1到0xffffff00
处的wfe区:
mwr 0x00000000 0xe3e0f0ff
- 在 cpu1:
上执行软件重置
mwr 0xf8000008 0xdf0d # slcr unlock
mwr 0xf8000244 0x2 # A9_RST1_ASSERT
mwr 0xf8000244 0x22 # A9_RST1_ASSERT | A9_CLKSTOP1
mwr 0xf8000244 0x20 # A9_CLKSTOP1
mwr 0xf8000244 0x0 # de-assert / start all
mwr 0xf8000004 0x767b # slcr lock
- 将cpu1起始地址写入
0xfffffff0
。
- 问题
sev
。
- 确保 cpu1 实际启动或等待几个周期。
- 恢复备份的寄存器。
我正在尝试找出在 zynq-7000 的放大器配置中从 cpu0 初始化 cpu1 的最低要求。
我有一个给定的 FSBL,它移交给了 u-boot,我用它把两个程序(cpu0/1)从闪存复制到 ram 中的不同位置(sf read ...
)。
我可以 运行 在 cpu0 上使用 go [adr]
u-boot 上的两个程序,其中 adr 是任一程序的起始地址。我在 uart 上得到了预期的输出。
不起作用的是 cpu0 应该通过将其起始地址写入寄存器 0xffff_fff0
来启动 cpu1,然后发出系统事件 sev
。
我不启用任何高速缓存、MMU 或 SCU,因为我想在我实现启动 cpu1 之前使其尽可能简单(无同步或刷新)。或者这真的是问题所在,我确实需要其中的任何一个?
目前我只初始化向量 table,打印到 uart,另外对于核心 0 尝试启动核心 1:
/* CPU 0 */
.section .vector_table, "x"
.global _init
_init:
b reset /* reset handler */
b . /* software interrupt */
b . /* prefetch abort */
b . /* data abort */
b . /* reserved */
b . /* irq */
b . /* fiq */
/* ASCII control chars */
.equ asciiLF, 0x0a
.equ asciiCR, 0x0d
.section .text
uart1fifo: .word 0xe0001030 /* UART 1 rx/tx fifo register */
reset:
/* Output "0" on UART 1 */
ldr r0, uart1fifo
mov r1, #'0'
str r1, [r0]
mov r1, #asciiCR
str r1, [r0]
mov r1, #asciiLF
str r1, [r0]
/* Set cpu1 start address */
ldr r0, =0x20000000 /* CPU 1 start address */
ldr r1, =0xfffffff0 /* Register to point to the CPU 1 start address */
str r0, [r1]
/* I added a 0.5s wait here which did not help */
sev /* Execute SEV to cause CPU 1 to wake up */
/* Output "." on UART 1 to indicate that we actually went so far */
ldr r0, uart1fifo
mov r1, #'.'
str r1, [r0]
mov r1, #asciiCR
str r1, [r0]
mov r1, #asciiLF
str r1, [r0]
b . /* Endless loop */
我可以看到“0”和“.”在 uart 1 上,当我 运行 上面的代码在 cpu 0.
/* CPU 1 */
.section .vector_table, "x"
.global _init
_init:
b reset /* reset handler */
b . /* software interrupt */
b . /* prefetch abort */
b . /* data abort */
b . /* reserved */
b . /* irq */
b . /* fiq */
/* ASCII control chars */
.equ asciiLF, 0x0a
.equ asciiCR, 0x0d
.section .text
uart0fifo: .word 0xe0000030 /* UART 0 rx/tx fifo register */
reset:
/* Output "1" on UART 0 */
ldr r0, uart0fifo
mov r1, #'1'
str r1, [r0]
mov r1, #asciiCR
str r1, [r0]
mov r1, #asciiLF
str r1, [r0]
b . /* Endless loop */
在这里,当我在 cpu 0 上 运行 时,我可以在 uart 0 上看到 '1'。
我是新手,有点迷茫。我错过了一些基本的东西吗?我该怎么做才能让它发挥作用?
我一直在查看 xapp-1079,但它使用了 Xilinx 的独立库,我很难筛选出实际需要的内容。我需要一个最小的工作示例,以便我可以将它移植到我们在第一个核心上 运行 的异国情调 OS。
原来 cpu1 不在 wfe 状态。我想 u-boot 已经唤醒了它,尽管它没有使用它,即 cpu1 的状态不是 smp.
,我必须在 cpu 1 上执行软件重置并在发出sev
命令之前将其恢复到 wfe 状态
link 死亡的步骤是:
- 备份后续步骤中覆盖的寄存器。
- 恢复OCM区的WFE(等待事件)代码。 (我使用汇编而不是显示的 xilinx xsct 命令,因为我无权访问它们的 IDE):
mwr 0xFFFFFF00 0xe3e0000f
mwr 0xFFFFFF04 0xe3a01000
mwr 0xFFFFFF08 0xe5801000
mwr 0xFFFFFF0C 0xe320f002
mwr 0xFFFFFF10 0xe5902000
mwr 0xFFFFFF14 0xe1520001
mwr 0xFFFFFF18 0x0afffffb
mwr 0xFFFFFF1C 0xe1a0f002
- 写
0x0
的跳转指令,从0x0
跳cpu1到0xffffff00
处的wfe区:
mwr 0x00000000 0xe3e0f0ff
- 在 cpu1: 上执行软件重置
mwr 0xf8000008 0xdf0d # slcr unlock
mwr 0xf8000244 0x2 # A9_RST1_ASSERT
mwr 0xf8000244 0x22 # A9_RST1_ASSERT | A9_CLKSTOP1
mwr 0xf8000244 0x20 # A9_CLKSTOP1
mwr 0xf8000244 0x0 # de-assert / start all
mwr 0xf8000004 0x767b # slcr lock
- 将cpu1起始地址写入
0xfffffff0
。 - 问题
sev
。 - 确保 cpu1 实际启动或等待几个周期。
- 恢复备份的寄存器。