Calling C Functions from Forth and Vice Versa

Register Usage

Procedure Call Standard for the ARM Architecture AAPCS

Register AAPCS Purpose Restore Contents MECRISP Forth Purpose ISR Stacking
xPSR Processor Status Register, Flags N Flags 1
r0 Argument, result, scratch register 1 N Scratch 2
r1 Argument, result, scratch register 2 N Scratch 3
r2 Argument, scratch register 3 N Scratch 4
r3 Argument, scratch register 4 Y Scratch 5
r4 Variable register 1 Y DO Index  
r5 Variable register 2 Y DO Limit  
r6 Variable register 3 Y Top Of Stack TOS  
r7 Variable register 4 Y Data stack pointer SPS  
r8 Variable register 5 Y unused  
r9 Platform register (usage defined by platform in use) Y unused  
r10 Variable register 7 Y unused  
r11 Variable register 8 Y unused  
r12 Intra-procedure-call scratch register N unused 6
r13 Stack pointer (SP) y Stack pointer (SP)  
r14 Link register (LR) N Link register (LR) 7
r15 Program counter (PC) N Program counter (PC) 0

VFP Register Usage

The VFP-v2 co-processor has 32 single-precision registers, s0-s31, which may also be accessed as 16 double-precision registers, d0-d15 (with d0 overlapping s0, s1; d1 overlapping s2, s3; etc).

Calling C Functions from Forth

Word osDelay from rtos.s

// -----------------------------------------------------------------------------
	Wortbirne Flag_visible, "osDelay"
	@ ( u -- n ) Wait for Timeout (Time Delay).
/// \param[in]     ticks         \ref CMSIS_RTOS_TimeOutValue "time ticks" value
/// \return status code that indicates the execution status of the function.
// osStatus_t osDelay (uint32_t ticks);
// -----------------------------------------------------------------------------
	push	{r0-r3, lr}
	movs	r0, tos		// ticks
	bl	osDelay
	movs	tos, r0
	pop	{r0-r3, pc}

If the C function itself calls Forth words the Data Stack Pointer SPS and Top Of Stack TOS registers have to be passed to the Forth words. See below.

Calling Forth Words from C Functions

Data Stack Pointer SPS is in R1 and Top Of Stack TOS is in R0 (first parameter).

C function FS_include() from fs.c calls the Forth words FS_type and FS_evaluate.

 *  @brief
 *      Interprets the content of the file.
 *  @param[in]
 *      forth_stack   TOS (lower word) and SPS (higher word)
 *  @param[in]
 *      str   filename (w/ or w/o null termination)
 *  @param[in]
 *      count string length
 *  @return
 *      TOS (lower word) and SPS (higer word)
uint64_t FS_include(uint64_t forth_stack, uint8_t *str, int count) {
	FIL fil;        /* File object */
	FRESULT fr;     /* FatFs return code */

	uint64_t stack;
	stack = forth_stack;

	memcpy(path, str, count);
	line[count] = 0;

	/* Open a text file */
	fr = f_open(&fil, path, FA_READ);
	if (fr) {
		// open failed
		strcpy(line, "Err: file not found");
		stack = FS_type(stack, (uint8_t*)line, strlen(line));

	/* Read every line and interprets it */
	while (f_gets(line, sizeof line, &fil)) {
		// line without \n
		stack = FS_evaluate(stack, (uint8_t*)line, strlen(line)-1);

	/* Close the file */

	return stack;

Word include from fs.s calls the C function FS_include().

@ -----------------------------------------------------------------------------
		Wortbirne Flag_visible, "include"
		@  ( any "filename" -- any ) Interprets the content of the file.
// uint64_t FS_include  (uint64_t forth_stack, uint8_t *str, int count);
@ -----------------------------------------------------------------------------
	push	{lr}
	bl	token		@ ( -- c-addr len )
	movs	r3, tos		// len -> count
	movs	r2, tos		// c-addr -> str
	movs	r0, tos		// get tos
	movs	r1, psp		// get psp
	bl	FS_include
	movs	tos, r0		// update tos
	movs	psp, r1		// update psp
	pop	{pc}

The C function FS_include() from fs.c calls the Forth word evaluate by the FS_evaluate() function.

// uint64_t FS_evaluate(uint64_t forth_stack, uint8_t* str, int count);
.global		FS_evaluate
	push 	{r4-r7, lr}
	movs	tos, r0		// get tos
	movs	psp, r1		// get psp
	movs	tos, r2		// str
	movs	tos, r3		// count
	bl	evaluate
	movs	r0, tos		// update tos
	movs	r1, psp		// update psp
	pop	{r4-r7, pc}

-- Peter Schmid - 2020-07-13

Creative Commons License
This work by Peter Schmid is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Edit | Attach | Watch | Print version | History: r7 < r6 < r5 < r4 < r3 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r7 - 2021-01-28 - PeterSchmid
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback