mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-24 22:27:21 -04:00
70 lines
2.7 KiB
C
70 lines
2.7 KiB
C
// ================================================================================ //
|
|
// The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 //
|
|
// Copyright (c) NEORV32 contributors. //
|
|
// Copyright (c) 2020 - 2025 Stephan Nolting. All rights reserved. //
|
|
// Licensed under the BSD-3-Clause license, see LICENSE for details. //
|
|
// SPDX-License-Identifier: BSD-3-Clause //
|
|
// ================================================================================ //
|
|
|
|
/**
|
|
* @file neorv32_smp.c
|
|
* @brief SMP HW driver source file.
|
|
*/
|
|
|
|
#include <neorv32.h>
|
|
|
|
|
|
/**********************************************************************//**
|
|
* Configure and start SMP core.
|
|
*
|
|
* @warning This function can be executed on core 0 only.
|
|
*
|
|
* @param[in] hart_id Hart/core select.
|
|
* @param[in] entry_point Core's main function (must be of type "void entry_point(void)").
|
|
* @param[in] stack_memory Pointer to beginning of core's stack memory array. Should be at least 512 bytes.
|
|
* @param[in] stack_size_bytes Core's stack size in bytes.
|
|
* @return 0 if launching succeeded. -1 if invalid hart ID or CLINT not available. -2 if core is not responding.
|
|
**************************************************************************/
|
|
int neorv32_smp_launch(int hart_id, void (*entry_point)(void), uint8_t* stack_memory, size_t stack_size_bytes) {
|
|
|
|
const uint32_t signature = 0xffab4321u;
|
|
int num_cores = (int)NEORV32_SYSINFO->MISC[SYSINFO_MISC_HART];
|
|
|
|
// sanity checks
|
|
if ((neorv32_cpu_csr_read(CSR_MHARTID) != 0) || // this can be executed on core 0 only
|
|
(hart_id == 0) || // we cannot launch core 0
|
|
(hart_id > (num_cores-1)) || // selected core not available
|
|
(neorv32_clint_available() == 0)) { // we need the CLINT
|
|
return -1;
|
|
}
|
|
|
|
// drain input queue from selected core
|
|
while (neorv32_smp_icc_avail(hart_id)) {
|
|
neorv32_smp_icc_get(hart_id);
|
|
}
|
|
|
|
// align end of stack to 16-bytes according to the RISC-V ABI (#1021)
|
|
uint32_t stack_top = ((uint32_t)stack_memory + (uint32_t)(stack_size_bytes-1)) & 0xfffffff0u;
|
|
|
|
// send launch configuration
|
|
neorv32_smp_icc_put(hart_id, signature); // signature
|
|
neorv32_smp_icc_put(hart_id, stack_top); // top of core's stack
|
|
neorv32_smp_icc_put(hart_id, (uint32_t)entry_point); // entry point
|
|
|
|
// start core by triggering its software interrupt
|
|
neorv32_clint_msi_set(hart_id);
|
|
|
|
// wait for start acknowledge
|
|
int cnt = 0;
|
|
while (1) {
|
|
if (neorv32_smp_icc_avail(hart_id)) {
|
|
if (neorv32_smp_icc_get(hart_id) == signature) {
|
|
return 0;
|
|
}
|
|
}
|
|
if (cnt > 10000) {
|
|
return -2; // timeout; core did not respond
|
|
}
|
|
cnt++;
|
|
}
|
|
}
|