creating a task context

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guys, I'm having trouble with floats in my RTOS tht I have ported to SAMA5D44.  I think the error is caused by the function that creates the context for the floating registers.  I have listed it below removing a lot of the code that I feel you do not need to see.

struct task_ctrl_obj * api_program(void(*task)(void), char const * name, void * variable_pass, unsigned int mpu_mem, unsigned char priority, unsigned char ceiling ){

	unsigned int program = (unsigned int)task & ~1u; /* Mask off lower bit in case task is thumb mode        */               					   /* Mask off lower bit in case task is thumb mode        */
	/*
	 * Setup general purpose registers
	 */
     * cpu_core_stack-- = (unsigned int) program;										   /* PC                                                    */
     * cpu_core_stack-- = (unsigned int) internal_task_destructor;		                                   /* LR: Supervisor mode                                       */
     * cpu_core_stack-- = (unsigned int) 0x00000000;                                       /* R12                                                        */
     * cpu_core_stack-- = (unsigned int) 0x00000000;                                       /* R11                                                        */
     * cpu_core_stack-- = (unsigned int) 0x00000000;                                       /* R10				                                           */
     * cpu_core_stack-- = (unsigned int) 0x00000000;		                               /* R9							    		                   */
     * cpu_core_stack-- = (unsigned int) 0x00000000;                                       /* R8                                                        */
     * cpu_core_stack-- = (unsigned int) 0x00000000;									   /* R7				                                           */
     * cpu_core_stack-- = (unsigned int) 0x00000000;                                       /* R6                                                        */
     * cpu_core_stack-- = (unsigned int) 0x00000000;                                       /* R5                                                        */
     * cpu_core_stack-- = (unsigned int) 0x00000000;                                       /* R4                                                        */
     * cpu_core_stack-- = (unsigned int) 0x00000000;                                       /* R3                                                        */
     * cpu_core_stack-- = (unsigned int) 0x00000000;                                       /* R2                                                        */
     * cpu_core_stack-- = (unsigned int) 0x00000000;                                       /* R1                                                        */
     * cpu_core_stack-- = (unsigned int) variable_pass;                                    /* R0 ARGUMENT PASS                                         */


	#define  OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR 0x13u
	#define  OS_CPU_ARM_BIT_CPSR_T (1u << 5u)

     // Setup Status registers
     if (((unsigned int)task & 0x01u) == 0x01u) {                  			/* See if task runs in Thumb or ARM mode                */
            *cpu_core_stack-- = (OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR  		/* Set supervisor mode.                                 */
                     	 	   | OS_CPU_ARM_BIT_CPSR_T);              		/* Set Thumb mode.                                      */
     } else {
            *cpu_core_stack-- = (0x00000100 | OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR);
     }



     {	/*
     	 *	Setup Floating Point registers
     	 **/
    	 *cpu_core_stack-- = 0x00000000;	 	/* Initialise Floating point status & control register  */

    	 for (int i = 0; i < 32; i++)
    		 * cpu_core_stack-- = 0x00000000;	/* Initialise general-purpose Floating point registers  */

    	 * cpu_core_stack = 0x40000000;  	 	/* Initialise Floating-Point Exception Register (Enable)*/
     }

    // Insert Newly created task on to the Kernel
	internal_kernel_insert_task(tcb);											// insert task ctrl block unto Kernel Schedular


	tcb->stack_ptr = (unsigned char *)cpu_core_stack;													// Store Stack pointer unto the task ctrl block
	return(tcb);														// Return Handle to the newly Created Task
}

The part of interest is:

	#define  OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR 0x13u
	#define  OS_CPU_ARM_BIT_CPSR_T (1u << 5u)

     // Setup Status registers
     if (((unsigned int)task & 0x01u) == 0x01u) {                  			/* See if task runs in Thumb or ARM mode                */
            *cpu_core_stack-- = (OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR  		/* Set supervisor mode.                                 */
                     	 	   | OS_CPU_ARM_BIT_CPSR_T);              		/* Set Thumb mode.                                      */
     } else {
            *cpu_core_stack-- = (0x00000100 | OS_CPU_ARM_BIT_CPSR_MODE_SUPERVISOR);
     }



     {	/*
     	 *	Setup Floating Point registers
     	 **/
    	 *cpu_core_stack-- = 0x00000000;	 	/* Initialise Floating point status & control register  */

    	 for (int i = 0; i < 32; i++)
    		 * cpu_core_stack-- = 0x00000000;	/* Initialise general-purpose Floating point registers  */

    	 * cpu_core_stack = 0x40000000;  	 	/* Initialise Floating-Point Exception Register (Enable)*/
     }

Any advise is very much welcome.

 

This topic has a solution.
Last Edited: Tue. Jul 14, 2020 - 05:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Out of interest, we have the following code that loads the first task.  This may be causing the trouble with the floats: see below:

void run (void);
__attribute__((naked))void run (void){

	__asm__ __volatile__(


			"MOV     R0, %[current_tcb]\n\t"
		    "MOV     R1, %[tcb_new]\n\t"
		    "LDR     R2, [R1]\n\t"
		    "STR     R2, [R0]\n\t"

		    "LDR     SP, [R2]\n\t"

			"POP     {r0}\n\t"					// Pop new task's FPEXC
            "FLDMIAS SP!, {S0-S31}\n\t"			//    ... Pop new task's General-Purpose floating point registers.
			"POP     {r0}\n\t"
			"VMSR    FPSCR, r0\n\t"				//    ... Pop new task's FPSCR.



		    "LDMFD   SP!, {R0}\n\t"
			"MSR     SPSR_cxsf, R0\n\t"

		    "LDMFD   SP!, {R0-R12, LR, PC}" :: [current_tcb] "r" (&core_executing_task), [tcb_new] "r" (&OSTCBHighRdy));
}

When I pop the ""POP {r0}\n\t" // Pop new task's FPEXC", I don't see me loading the Floating-Point Exception Register?

Is this the cause of the error????

 

Slán

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Added the following code:

			"POP     {r0}\n\t"					// Pop new task's FPEXC
			"VMSR    FPEXC, r0\n\t"

EDITED: forgot to mention that the floating point error is still there.

Last Edited: Fri. Jun 26, 2020 - 07:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Balls! I have to get the debugger out, never have I been forced to go to the debugger.

 

Slán

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe I will not have to resort to the debugger, I found two or three errors in the function that creates the task.  See below, I'll not be able to test it until tomorrow.  Here's hoping it works.

struct task_ctrl_obj * api_program(void(*task)(void), char const * name, void * variable_pass, unsigned int mpu_mem, unsigned char priority, unsigned char ceiling ){

    api_system_gateway();

    if(priority > 63){
        return(0);
    }

    struct task_ctrl_obj * tcb;

    tcb = safe_malloc(sizeof(struct task_ctrl_obj));            // Allocate Memory for the Task Ctrl Block, used by the Kernel to manage the Task

    memset(tcb, 0x00, sizeof(struct task_ctrl_obj));

    if(tcb == NULL){
        return(NULL);
    }




    unsigned int stack;

    // Allocate Memory for the Stack
    tcb->mpu_base_mem_addr = safe_malloc(mpu_mem * sizeof(int));
    tcb->stack_allocation = (unsigned char *)tcb->mpu_base_mem_addr;


    // find the number of bytes allocated
    stack = mpu_mem * sizeof(int);


    if(tcb->mpu_base_mem_addr == NULL){
        safe_free(tcb);
        return(NULL);
    }

    // PointStack to the end of the memory structure, Stack grows downwards
    unsigned int * cpu_context = (unsigned int *)(stack + tcb->mpu_base_mem_addr);

    /* Align stack pointer.                                 */
    cpu_context = (unsigned int *)((unsigned int)(cpu_context) & 0xFFFFFFF8u);

    tcb->task_status = DORMANT;    // Initial State of all Tasks is DORMANT


    /*
     *    Register task name with operating system
     */
    tcb->name[0] = '\0';

    //if task name has been specified then load the name into the system
    if(strlen(name)){

        struct task_id * log = safe_malloc(sizeof(struct task_id ));
        log->id = tcb;

        int i = 0;    while(* name != '\0'){

                // copy the name
                tcb->name[i] = * name; log->name[i++] = * name; name++;
        }

        // tidy up strings by nulling the end
        tcb->name[i] = '\0'; log->name[i] = '\0';
        add_system_name(log);
    }


    /*
     * Signal Setup
     */
    // Setup Signal Receive Buffer, also associated with TCB
    tcb->signals = safe_malloc(sizeof(struct ipc_signal_sent));
    if(tcb->signals == NULL){

        safe_free(tcb);
        safe_free(tcb->stack_allocation);
        safe_free((struct ipc_signal_obj *)tcb->signal_management);
        return(NULL);
    }

    tcb->signal_management->nr_signal_registered = 0;
    tcb->signals->nr_signal_received = 0;



    /*
     * Setup tcb priority
     */
    tcb->delta_priority   = priority;                                    // Set Task Priority
    tcb->ceiling_priority = ceiling;
    tcb->default_priority = priority;                                    // Set Base Priority, used by the Priority inversion protocol


    unsigned int program = (unsigned int)task & ~1u; /* Mask off lower bit in case task is thumb mode        */                                      /* Mask off lower bit in case task is thumb mode        */
    /*
     * Setup general purpose registers
     */
     * cpu_context-- = (unsigned int) program;                                            /* PC                                                    */
     * cpu_context-- = (unsigned int) internal_task_destructor;                            /* LR: Supervisor mode                                       */
     * cpu_context-- = (unsigned int) 0x00000011;                                       /* R1`                                                        */
     * cpu_context-- = (unsigned int) 0x00000010;                                       /* R10                                                        */
     * cpu_context-- = (unsigned int) 0x00000009;                                       /* R09                                                           */
     * cpu_context-- = (unsigned int) 0x00000008;                                        /* R8                                                           */
     * cpu_context-- = (unsigned int) 0x00000007;                                       /* R7                                                        */
     * cpu_context-- = (unsigned int) 0x00000006;                                        /* R6                                                           */
     * cpu_context-- = (unsigned int) 0x00000005;                                       /* R5                                                        */
     * cpu_context-- = (unsigned int) 0x00000004;                                       /* R4                                                        */
     * cpu_context-- = (unsigned int) 0x00000003;                                       /* R3                                                        */
     * cpu_context-- = (unsigned int) 0x00000002;                                       /* R2                                                        */
     * cpu_context-- = (unsigned int) 0x00000001;                                       /* R1                                                        */
     * cpu_context-- = (unsigned int) 0x00000000;                                       /* R0  ARGUMENT PASS                                                         */
     * cpu_context-- = (unsigned int) variable_pass;                                    /* status regsiter                             */


    #define  ARM_MODE_ARM           0x00000200u
    #define  ARM_MODE_THUMB         0x00000220u

    #define  ARM_SVC_MODE_THUMB    (0x00000013u + ARM_MODE_THUMB)
    #define  ARM_SVC_MODE_ARM      (0x00000013u + ARM_MODE_ARM)


     // Setup Status registers
     if ((task & 0x01u) == 0x01u) {                   /* See if task runs in Thumb or ARM mode                */
        * cpu_context-- = ARM_SVC_MODE_THUMB;                  /* CPSR  (Enable IRQ and FIQ interrupts, THUMB-mode)    */
     }
     else {
        * cpu_context-- = ARM_SVC_MODE_ARM;                    /* CPSR  (Enable IRQ and FIQ interrupts, ARM-mode)      */
     }

     /*
      *    Setup Floating Point registers
      **/
     * cpu_context-- = (unsigned int)0x00000000;         /* Initialise Floating point status & control register  */

     // floating point reegisters
     for (int i = 0; i < 32; i++)
         * cpu_context-- = (unsigned int)0x00000000;    /* Initialise general-purpose Floating point registers  */

     // floating point execution register
     * cpu_context = (unsigned int)0x40000000;           /* Initialise Floating-Point Exception Register (Enable)*/


    // Insert Newly created task on to the Kernel
    internal_kernel_insert_task(tcb);                                            // insert task ctrl block unto Kernel Schedular


    tcb->stack_ptr = (unsigned char *)cpu_context;                                                    // Store Stack pointer unto the task ctrl block
    return(tcb);                                                        // Return Handle to the newly Created Task
}

 

Last Edited: Sun. Jun 28, 2020 - 11:07 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Solution/Error was the way the context switch was built.  See below for the working solution - thankyou freaks.

struct task_ctrl_obj * api_program(void(*task)(void), char const * name, void * variable_pass, unsigned int mpu_mem, unsigned char priority, unsigned char ceiling ){

	api_system_gateway();

	if(priority > 63){
		return(0);
	}

	struct task_ctrl_obj * tcb;

	tcb = safe_malloc(sizeof(struct task_ctrl_obj));			// Allocate Memory for the Task Ctrl Block, used by the Kernel to manage the Task

	memset(tcb, 0x00, sizeof(struct task_ctrl_obj));

	if(tcb == NULL){
		return(NULL);
	}

	unsigned int stack_offset;

	// Allocate Memory for the Stack
	tcb->stack_allocation = (unsigned char *)safe_malloc(mpu_mem * sizeof(int));


	// find the number of bytes allocated
	stack_offset = mpu_mem * sizeof(int);


	if(tcb->stack_allocation == NULL){

		safe_free(tcb);
		return(NULL);
	}

	// PointStack to the end of the memory structure, Stack grows downwards
	unsigned int * cpu_context = (unsigned int *)(stack_offset + tcb->stack_allocation);

	/* Align stack pointer.                                 */
	cpu_context = (unsigned int *)((unsigned int)(cpu_context) & 0xFFFFFFF8u);

	tcb->task_status = DORMANT;	// Initial State of all Tasks is DORMANT


	/*
	 *	Register task name with operating system
	 */
	tcb->name[0] = '\0';

	//if task name has been specified then load the name into the system
	if(strlen(name)){

		struct task_id * log = safe_malloc(sizeof(struct task_id ));
		log->id = tcb;

		int i = 0;	while(* name != '\0'){

				// copy the name
				tcb->name[i] = * name; log->name[i++] = * name; name++;
		}

		// tidy up strings by nulling the end
		tcb->name[i] = '\0'; log->name[i] = '\0';
		add_system_name(log);
	}


	/*
	 * Signal Setup
	 */
	// Setup Signal Receive Buffer, also associated with TCB
	tcb->signals = safe_malloc(sizeof(struct ipc_signal_sent));
	if(tcb->signals == NULL){

		safe_free(tcb);
		safe_free(tcb->stack_allocation);
		safe_free((struct ipc_signal_obj *)tcb->signal_management);
		return(NULL);
	}

	tcb->signal_management->nr_signal_registered = 0;
	tcb->signals->nr_signal_received = 0;



	/*
	 * Setup tcb priority
	 */
	tcb->delta_priority   = priority;		// Set Task Priority
	tcb->ceiling_priority = ceiling;
	tcb->default_priority = priority;		// Set Base Priority, used by the Priority inversion protocol


	unsigned int program = (unsigned int)task & ~1u; /* Mask off lower bit in case task is thumb mode        */               					   /* Mask off lower bit in case task is thumb mode        */
	/*
	 * Setup general purpose registers
	 */
     * --cpu_context = (unsigned int) program;										    /* PC                                                    */
     * --cpu_context = (unsigned int) internal_task_destructor;		                    /* LR: Supervisor mode                                       */
     * --cpu_context = (unsigned int) 0x00000011;                                       /* R1`                                                        */
     * --cpu_context = (unsigned int) 0x00000010;                                       /* R10                                                        */
     * --cpu_context = (unsigned int) 0x00000009;                                       /* R09				                                           */
     * --cpu_context = (unsigned int) 0x00000008;		                                /* R8							    		                   */
     * --cpu_context = (unsigned int) 0x00000007;                                       /* R7                                                        */
     * --cpu_context = (unsigned int) 0x00000006;									    /* R6				                                           */
     * --cpu_context = (unsigned int) 0x00000005;                                       /* R5                                                        */
     * --cpu_context = (unsigned int) 0x00000004;                                       /* R4                                                        */
     * --cpu_context = (unsigned int) 0x00000003;                                       /* R3                                                        */
     * --cpu_context = (unsigned int) 0x00000002;                                       /* R2                                                        */
     * --cpu_context = (unsigned int) 0x00000001;                                       /* R1                                                        */
     * --cpu_context = (unsigned int) 0x00000000;                                       /* R0  ARGUMENT PASS                                                         */
     * --cpu_context = (unsigned int) variable_pass;                                    /* status regsiter                             */

     	/****************************************************************/
        // used for the status register
		#define  ARM_MODE_ARM           0x00000200u
		#define  ARM_MODE_THUMB         0x00000220u

		#define  ARM_SVC_MODE_THUMB    (0x0000001f + ARM_MODE_THUMB)
		#define  ARM_SVC_MODE_ARM      (0x0000001f + ARM_MODE_ARM)
       /*****************************************************************/

     // Setup Status register
     if (((unsigned int)task & 0x01) == 0x01)                   /* See if task arch_sama5d4_context_switch_starts in Thumb or ARM mode                */
        * --cpu_context = ARM_SVC_MODE_THUMB;                   /* CPSR  (Enable IRQ and FIQ interrupts, THUMB-mode)    */
     else
        * --cpu_context = ARM_SVC_MODE_ARM;                     /* CPSR  (Enable IRQ and FIQ interrupts, ARM-mode)      */

     /*
      *	Setup Floating Point registers
      */

     // floating point status register
     * --cpu_context = (unsigned int)0x00000000;	 	/* Initialise Floating point status & control register  */

     // floating point registers
     for (int i = 0; i < 32; i++)
    	 * --cpu_context = (unsigned int)0x00000000;	/* Initialise general-purpose Floating point registers  */

     // floating point execution register
     * --cpu_context = (unsigned int)0x40000000;  	 	/* Initialise Floating-Point Exception Register (Enable)*/


    // Insert Newly created task on to the Kernel
	internal_kernel_insert_task(tcb);					// insert task ctrl block unto Kernel Schedular


	tcb->stack_ptr = (unsigned char *)cpu_context;		// Store Stack pointer unto the task ctrl block
	return(tcb);										// Return Handle to the newly Created Task
}