Skip to content
Snippets Groups Projects
Select Git revision
  • 0119fc7532c573bd596fb6173b4d36ef5260027a
  • wip-bootstrap default
  • dualcore
  • ch3/leds
  • ch3/time
  • master
6 results

servo.c

Blame
  • caller.c 2.52 KiB
    #include <stdlib.h>
    #include "sema.h"
    #include "api/caller.h"
    
    #define MXC_ASSERT_ENABLE
    #include "mxc_assert.h"
    
    static uint32_t irq_save = 0;
    
    void *_api_call_start(api_id_t id, uintptr_t size)
    {
    	/*
    	 * Disable all maskable interrupts here, to be turned on again at the
    	 * end of _api_call_transact().
    	 */
    	irq_save = __get_PRIMASK();
    	__set_PRIMASK(1);
    
    	while (SEMA_GetSema(_API_SEMAPHORE) == E_BUSY) {
    	}
    
    	if (API_CALL_MEM->call_flag != _API_FLAG_IDLE) {
    		/*
    		 * The only way this can happen is if a call was issued from an
    		 * interrupt hander while another call is still happening.  This
    		 * has to be prevented at all cost!
    		 */
    		mxc_assert(
    			"API recalled during ongoing call!",
    			__FILE__,
    			__LINE__
    		);
    	}
    
    	API_CALL_MEM->id = id;
    	return API_CALL_MEM->buffer;
    }
    
    void *_api_call_transact(void *buffer)
    {
    	API_CALL_MEM->call_flag = _API_FLAG_CALLING;
    	SEMA_FreeSema(_API_SEMAPHORE);
    
    	/* Notify the dispather of the new call */
    	__SEV();
    	__WFE();
    
    	while (1) {
    		/* Wait for the dispather to return */
    		__WFE();
    
    		while (SEMA_GetSema(_API_SEMAPHORE) == E_BUSY) {
    		}
    		if (API_CALL_MEM->call_flag == _API_FLAG_RETURNED) {
    			break;
    		}
    		SEMA_FreeSema(_API_SEMAPHORE);
    	}
    
    	API_CALL_MEM->call_flag = _API_FLAG_IDLE;
    	SEMA_FreeSema(_API_SEMAPHORE);
    
    	/*
    	 * Re-enable interrupts (if previously enabled) after completing the API
    	 * call.
    	 */
    	__set_PRIMASK(irq_save);
    
    	return API_CALL_MEM->buffer;
    }
    
    __attribute__((noreturn)) void epic_exit(int ret)
    {
    	/*
    	 * Call __epic_exit() and then jump to the reset routine/
    	 */
    	void *buffer;
    
    	buffer         = _api_call_start(API_SYSTEM_EXIT, sizeof(int));
    	*(int *)buffer = ret;
    	_api_call_transact(buffer);
    
    	API_CALL_MEM->reset_stub();
    
    	/* unreachable */
    	while (1)
    		;
    }
    
    int epic_exec(char *name)
    {
    	/*
    	 * Call __epic_exec().  If it succeeds, jump to the reset routine.
    	 * Otherwise, return the error code.
    	 */
    	void *buffer;
    
    	buffer           = _api_call_start(API_SYSTEM_EXEC, sizeof(char *));
    	*(char **)buffer = name;
    	int ret          = *(int *)_api_call_transact(buffer);
    
    	if (ret < 0) {
    		return ret;
    	}
    
    	API_CALL_MEM->reset_stub();
    
    	/* unreachable */
    	while (1)
    		;
    }
    
    int api_fetch_args(char *buf, size_t cnt)
    {
    	if (API_CALL_MEM->id != 0) {
    		/*
    		 * When any call happened before the args are fetched, they are
    		 * overwritten and no longer accessible.
    		 */
    		return (-1);
    	}
    
    	if (API_CALL_MEM->buffer[0x20] == '\0') {
    		return 0;
    	}
    
    	size_t i;
    	for (i = 0; i < cnt && API_CALL_MEM->buffer[i + 0x20] != '\0'; i++) {
    		buf[i] = API_CALL_MEM->buffer[i + 0x20];
    	}
    
    	return i - 1;
    }