Discover the Capabilities of Allwinner T153 ARM + RISC-V Heterogeneous Dual-Core Combo!

In this hyper-competitive embedded era defined by performance, responsiveness and power efficiency wars, dual-core collaboration is the only way to break the deadlock.

Traditional Symmetric Multi-Processing (SMP) architectures can no longer cover full-scenario requirements, pushing the Asymmetric Multi-Processing (AMP) heterogeneous architecture to become the new industry mainstream. Against this backdrop, the Allwinner T153 features its ARM + RISC-V dual-core combo: the Cortex-A7 core for high-performance computing runs Linux, while the RISC-V E907 core for hard real-time tasks runs RTOS, forming a perfectly complementary pairing.

System architecture diagram of the Allwinner T153 illustrating the ARM Cortex-A7 and RISC-V E907 heterogeneous dual-core AMP collaboration on the Forlinx Embedded OK153-S development board

This article tests the collaborative capabilities of this dual-core combo on the Forlinx Embedded OK153-S development board. Leveraging the heterogeneous inter-core Inter-Process Communication (IPC) and Suspend/Resume power management mechanisms, we fully validate the A-core & R-core synergy, as well as the data interaction efficiency and intelligent wake-up logic in the heterogeneous multi-core environment.

1. Sleep & Wakeup Function Validation

The pm_test node is used to test the Linux-side sleep and wakeup functionality.

After the device is frozen, it will wait 5 seconds before automatically triggering the wakeup routine.

echo devices > /sys/power/pm_test

Device goes to sleep:

echo mem > /sys/power/state

Once the execute the above command, the device will automatically wake up after 5 seconds.

2. R-Core Wake-up of Sleeping A-Core

Power management is the core competitiveness for product battery life and cost control. The T153’s heterogeneous multi-core architecture delivers a targeted solution:

A-Core Sleep: The ARM core enters deep WFI sleep at idle for minimum power consumption;

R-Core Monitoring: The RISC-V core keeps running to listen for external events;

On-Demand Wakeup: When a sensor is triggered or a scheduled task is pending, the R-Core can wake up the A-Core in one step to process complex tasks.

When the A-core enters WFI mode, the R-core operates on DRAM and acts as the wake-up source.

First, configure the system to disable DRAM self-refresh when the primary core sleeps, so the secondary R-core keeps running on DRAM. Switch this setting by entering the following command in the Linux console:

echo 0 >/sys/class/pm_msgbox/set_dram_refresh

Core A then goes to sleep:

echo mem > /sys/power/state

Wake the A-core via the R-core. Our R-core provides the cpux_resume interface for primary core wakeup. Run the following command on the R-core to activate the A-core:

cpux_resume

In low-power scenarios, the high-performance A-core stays in sleep standby, while the low-power R-core maintains continuous monitoring. When an external event is triggered, the R-core can instantly wake up the A-core to respond to tasks. This “small core on duty, big core on standby” architecture strikes an optimal balance between device battery life and real-time responsiveness.

3. Dual-Core Communication Validation

The Allwinner T153’s ARM Cortex-A7 + RISC-V heterogeneous multi-core architecture equips the system with a specialized “computing cerebrum” and “real-time cerebellum”. The heterogeneous inter-core IPC mechanism acts as the high-speed interconnect between the two cores, enabling seamless dual-core data transmission via the shared memory framework. Here's how to do it:

Enable the R core first before testing:

echo amp_rv0.bin > /sys/class/remoteproc/remoteproc0/firmware
echo start > /sys/class/remoteproc/remoteproc0/state

(1) RISC-V end routine

rtos/lichee/rtos-components/aw/rpbuf/rpbuf_demo/rpbuf_test.c

Command usage:

static void print_help_msg(void)
{
printf("\n");
printf("USAGE:\n");
printf(" rpbuf_test [OPTIONS]\n");
printf("OPTIONS:\n");
printf(" -h : print help message\n");
printf(" -c : create buffer\n");
printf(" -C : Send Cnt(default: 1)\n");
printf(" -d : destory buffer\n");
printf(" -s : send test messagese\n");
printf(" -l : list created buffers\n");
printf(" -a : sync transmit\n");
printf(" -I ID : specify controller ID (default: 0)\n");
printf(" -N NAME : specify buffer name (default: \"%s\")\n",
RPBUF_BUFFER_NAME_DEFAULT);
printf(" -L LENGTH : specify buffer length (default: %d bytes)\n",
RPBUF_BUFFER_LENGTH_DEFAULT);
printf(" -p : print performance data\n");
printf("\n");
printf("e.g.\n");
printf(" First, create a buffer (its name and length should match "
“that of remote rpbuf buffer):\n");
printf(" rpbuf_buffer -N \"xxx\" -L LENGTH -c\n");
printf(" Then if remote sends data to it, the buffer callback will be called.\n");
printf("\n");
printf(" We can send test data to remote:\n");
printf(" rpbuf_test -d 100 -s -L 32\n");
printf("\n");
printf(" If this buffer is no longer in use, destroy it:\n");
printf(" rpbuf_test -N \"xxx\" -d\n");
printf("\n");
}

Parameter Explanation:

-c : Create buffer

-C : Transmission count

-d : Destroy

-i : Specify target node

-a : Enable data synchronization

-N : Define buffer name

-L : Set buffer size

(2) A-Core Routine

Command usage:

static void print_help_msg(void)
{
printf("\n");
printf("USAGE:\n");
printf(" rpbuf_test [OPTIONS]\n");
printf("\n");
printf("OPTIONS:\n");
printf(" -d time : set data sending interval (default: 100 ms)\n");
printf(" -s : send test messages\n");
printf(" -c : send count (default: 10)\n");
printf(" -r : receive messages\n");
printf(" -t time : specifies the time of receive messagess, unit:ms\n");
printf(" -a : sync transmit\n");
printf(" -I ID : specify rpbuf ctrl ID (default: 0)\n");
printf(" -N NAME : specify buffer name (default: \"%s\")\n",
RPBUF_BUFFER_NAME_DEFAULT);
printf(" -L LENGTH : specify buffer length (default: %d bytes)\n",
RPBUF_BUFFER_LENGTH_DEFAULT);
printf(" -p : print performance data\n");
printf("\n");
printf("e.g.\n");
printf(" rpbuf_test -L 0x1000 -c 10 -s : send 10 test data, size=0x1000\n");
printf(" rpbuf_test -L 0x1000 -r : receive test data forever, size=0x1000\n");
printf(" rpbuf_test -L 0x1000 -r -t 1000 : receive test data 1 second, size=0x1000\n");
printf("\n");
}

Parameter Explanation:

-s : Send

-c : Transmission count

-r : Blocking receive

(3) Experimental Results

Take the scenario where the RISC-V core sends data to the A-core as an example: the buffer size is set to 511.875K, with a total of 100 transmission runs.

Allocate a 511.875K buffer, then the A-core will transmit 100 sets of data to the RISC-V core.

Execute the following commands in sequence:

Commands to run on RISC-V core:

rpbuf_test -c -I 0 -N rpbuf_test -L 524160 -a

A-side command:

rpbuf_test -L 524160 -N rpbuf_test -r

RISC-V command:

rpbuf_test -N rpbuf_test -C 100 -s

RISC-V serial port:

cpu0>rpbuf_test -c -I 0 -N rpbuf_test -L 524160 -a
cpu0>[RPBUF_INFO][rpbuf_addr_remap_default:206]reamp pa:0x42144000 -> va:0x42144000
[RPBUF_INFO][rpbuf_service_command_buffer_created_handler:827]buffer "rpbuf_test" (id:0): local_dummy_buffers -> buffers
buffer "rpbuf_test" is available
cpu0>rpbuf_test -N rpbuf_test -C 100 -s
[0]data:21a94801873e262b487f31000da27543... [md5:fd0f42ddde63121837ebcdec775250b9]

A-core Debug Serial Port:

# rpbuf_test -L 524160 -N rpbuf_test -r
ping: 8099.576172ms
bandwidth: 0.517149Mbps
data:21a94801873e262b487f31000da27543... check:fd0f42ddde63121837ebcdec775250b9 success
ping: 14.155000ms
bandwidth: 186.086807Mbps
data:21a94801873e262b487f31000da27543... check:fd0f42ddde63121837ebcdec775250b9 success
ping: 14.721000ms
bandwidth: 181.881592Mbps
data:21a94801873e262b487f31000da27543... check:fd0f42ddde63121837ebcdec775250b9 success
ping: 14.694000ms
bandwidth: 181.992096Mbps
data:21a94801873e262b487f31000da27543... check:fd0f42ddde63121837ebcdec775250b9 success
ping: 14.680000ms
bandwidth: 182.055313Mbps
data:21a94801873e262b487f31000da27543... check:fd0f42ddde63121837ebcdec775250b9 success
ping: 14.712000ms
bandwidth: 181.779083Mbps
data:21a94801873e262b487f31000da27543... check:fd0f42ddde63121837ebcdec775250b9 success
ping: 14.690000ms
bandwidth: 182.276901Mbps
data:21a94801873e262b487f31000da27543... check:fd0f42ddde63121837ebcdec775250b9 success

Test data shows that the average data transmission bandwidth between the ARM and RISC-V dual cores can reach 184Mbps, verifying the high efficiency and stability of the shared memory mechanism.

4. Conclusion

The Allwinner T153 processor, empowered by its heterogeneous multi-core architecture, high-performance heterogeneous Inter-Processor Communication (IPC) mechanism and supporting intelligent sleep/wake-up scheme, enables efficient collaboration between the ARM core and RISC-V core. With Linux handling complex computing tasks and RTOS guaranteeing real-time responsiveness, it integrates three core capabilities: high-performance computing, hard real-time control and ultra-low-power standby, to meet the demands of scenarios such as industrial control. This is far more than a mere technical feature implementation: it serves as a mass-producible, fully functional and reliably performing chip-level solution platform for next-generation smart hardware.




Contact Sales Team

Our sales team will connect you with FAE engineers for one-on-one technical support.

Talk to Our Engineers

Get a Quote

Get pricing and project evaluation support from our team.

Request a Quote

Apply for Samples

Submit your request to receive product samples for evaluation.

Get Samples

Join Facebook Group

Get Forlinx technical updates and hands-on sharing from our experts.

Join Now

Developer Center

Access hardware manuals, software guides, and datasheets.

Read Docs

Developer Community

Connect, share projects, and get technical support.

Explore Community