예제 #1
0
/*
 * lcd_an_write_register
 * @lcd: LCD driver on which a byte is needed to be written.
 * @rs: Flag to specify if we are writing a data register or command register.
 *  TRUE: If we need to write a data register.
 *  FALSE: If we need to write a command register.
 * @byte: Byte needed to be written.
 * @return: Success will be returned if bytes was successfully written
 *  LCD_AN_TIME_OUT will be returned if timed out waiting for LCD.
 * This function write a register to the LCD.
 */
static int32_t lcd_an_write_register(LCD_AN *lcd, uint8_t rs, uint8_t byte)
{
#ifndef LCD_AN_NO_BUSY_WAIT
    uint8_t cmd_byte;
    uint32_t sys_time = current_system_tick();
#endif /* LCD_AN_NO_BUSY_WAIT */
    int32_t status = SUCCESS;

#ifndef LCD_AN_NO_BUSY_WAIT
    /* Wait for LCD. */
    do
    {
        /* Read command register. */
        lcd_an_read_register(lcd, FALSE, &cmd_byte);

        /* If we are still busy. */
        if (cmd_byte & (1 << 7))
        {
            /* Yield the task. */
            task_yield();
        }

    } while ((current_system_tick() - sys_time) < (MS_TO_TICK(LCD_AN_BUSY_TIMEOUT)) && (cmd_byte & (1 << 7)));

    /* If we did not timeout waiting for the LCD. */
    if (((cmd_byte & (1 << 7)) == 0) || (rs & LCD_IGNORE_WAIT))
#endif /* LCD_AN_NO_BUSY_WAIT */
    {
        /* Select required register. */
        if (rs & LCD_DATA_REG)
        {
            /* Select data register. */
            lcd->set_rs(lcd);
        }
        else
        {
            /* Select command register. */
            lcd->clr_rs(lcd);
        }

        /* We are writing data. */
        lcd->clr_rw(lcd);

        /* Disable the LCD data line. */
        lcd->clr_en(lcd);

        /* Put byte on the LCD. */
        lcd_an_send_nibble(lcd, ((byte >> 4) & 0x0F));
        lcd_an_send_nibble(lcd, (byte & 0x0F));

#ifdef LCD_AN_NO_BUSY_WAIT
        /* Yield the task to put delay in transaction.. */
        task_yield();
#else
    }
    else
    {
예제 #2
0
/*
 * Wait for the byte to be received and return it.
 */
unsigned short
debug_getchar (void)
{
#ifndef DEBUG_SIMULATE
    unsigned char c;
    int x;

    if (debug_char >= 0) {
        c = debug_char;
        debug_char = -1;
        /*debug_printf ("getchar -> 0x%02x\n", c);*/
        return c;
    }
    mips_intr_disable (&x);
    for (;;) {
        /* Wait until receive data available. */
        if (! (MC_LSR & MC_LSR_RXRDY)) {
            /*			watchdog_alive ();*/
            mips_intr_restore (x);
#           ifndef DEBUG_IO_NOCONCURENCE
            task_yield();
#           endif
            mips_intr_disable (&x);
            continue;
        }
        /* TODO: utf8 to unicode conversion. */
        c = MC_RBR;
        break;
    }
    mips_intr_restore (x);
    return c;
#else
    return 0;
#endif// ! DEBUG_SIMULATE
}
예제 #3
0
void iboot_loader_run(void) {
	uint64_t startTime = timer_get_system_microtime();
	// boot iboot when either the up button is pressed or after 10 seconds
	static Boolean buttonPressed = FALSE;
	static Boolean messageShown = FALSE;
	while(1) {
		if (!gpio_pin_state(BUTTONS_VOLUP)
			|| (has_elapsed(startTime, 10 * 1000 * 1000) && !buttonPressed)) {
			load_iboot();
			task_stop();
		}
		if (gpio_pin_state(BUTTONS_HOLD)) {
			buttonPressed = TRUE;
		}
		if (has_elapsed(startTime, 2 * 1000 * 1000) && !messageShown) {
			// show a welcome message after 2 seconds to skip all of the usb spam
			bufferPrintf("===================\r\n");
			bufferPrintf("Welcome to the 2g touch experimental openiBoot!\r\n");
			bufferPrintf("iBoot will be automatically loaded after 10 seconds\r\n");
			bufferPrintf("Press the power button to cancel automatic booting\r\n");
			bufferPrintf("Press the volume up button to load ios\r\n");
			bufferPrintf("===================\r\n");
			bufferPrintf("\r\n\r\n\r\n");
			messageShown = TRUE;
		}
		task_yield();
	}
}
예제 #4
0
// return the byte count received before timeout, or error(<0)
int32_t serial_recv_stream_timeout (serial_t *obj, char *prxbuf, uint32_t len, uint32_t timeout_ms, void *force_cs)
{
    PHAL_RUART_OP      pHalRuartOp;
    PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp);
    uint32_t TimeoutCount=0, StartCount;
    int ret;
    void (*task_yield)(void);

    task_yield = NULL;
    pHalRuartOp = &(obj->hal_uart_op);
    HalRuartEnterCritical(pHalRuartAdapter);
    ret = pHalRuartOp->HalRuartIntRecv(pHalRuartAdapter, (u8*)prxbuf, len);
    HalRuartExitCritical(pHalRuartAdapter);
    if ((ret == HAL_OK) && (timeout_ms > 0)) {
        TimeoutCount = (timeout_ms*1000/TIMER_TICK_US);
        StartCount = HalTimerOp.HalTimerReadCount(1);
        task_yield = (void (*)(void))force_cs;
        while (pHalRuartAdapter->State & HAL_UART_STATE_BUSY_RX) {
            if (HAL_TIMEOUT == RuartIsTimeout(StartCount, TimeoutCount)) {
                ret = pHalRuartOp->HalRuartStopRecv((VOID*)pHalRuartAdapter);
                ret = pHalRuartOp->HalRuartResetRxFifo((VOID*)pHalRuartAdapter);
                pHalRuartAdapter->Status = HAL_UART_STATUS_TIMEOUT;
                break;
            }
            if (NULL != task_yield) {
               task_yield();
            }
        }
        return (len - pHalRuartAdapter->RxCount);
    } else {
        return (-ret);
    }
}
예제 #5
0
/*
 * scheduler_unlock
 * This function will enable preemption for this task so that it can be
 * preempted.
 */
void scheduler_unlock(void)
{
    TASK *tcb = get_current_task();

    /* Check if we have a current task. */
    if (tcb != NULL)
    {
        /* Should never happen. */
        ASSERT(tcb->lock_count == 0);

        /* Decrement the lock count for this task. */
        tcb->lock_count --;

        /* If scheduler is actually unlocked, and we might have missed a
         * context switch because of this lock. */
        if ((tcb->lock_count == 0) && (tcb->flags & TASK_SCHED_DRIFT))
        {
            /* Clear the drift flag. */
            tcb->flags &= (uint8_t)(~(TASK_SCHED_DRIFT));

            /* Try to yield this task. */
            task_yield();
        }
    }

} /* scheduler_unlock */
예제 #6
0
파일: task_yield_test.c 프로젝트: elinx/os
static void task_3_handle(void *argv)
{
        for (;;) {
                for (u32 i = 0; i < 5; ++i)
                        kprintf("C");
                kprintf("\n");
                task_yield();
        }
}
예제 #7
0
파일: task.c 프로젝트: bmeneguele/sist-op
void timer_handler(int signum) 
{
  sys_clk++;

  if (PREEMPTION == 1) {
    if (--ticks == 0)
      task_yield();
  }
}
예제 #8
0
파일: tasks.c 프로젝트: Anon0/openiBoot
void tasks_run()
{
	while(1)
	{
		if(!task_yield())
		{
			//bufferPrintf("WFI\r\n");
			WaitForInterrupt(); // Nothing to do, wait for an interrupt.
		}
	}
}
예제 #9
0
/*
 * sleep_hw_ticks
 * @ticks: Number of hardware ticks for which this task is needed to sleep.
 * This function will busy sleep the current task execution for given number
 * of hardware ticks.
 */
void sleep_hw_ticks(uint64_t ticks)
{
    uint64_t hw_tick;

    /* Wait before reading back from the LCD. */
    hw_tick = current_hardware_tick();
    while ((current_hardware_tick() - hw_tick) < ticks)
    {
        /* Yield current task to execute any high priority task. */
        task_yield();
    }

} /* sleep_hw_ticks */
예제 #10
0
파일: acm.c 프로젝트: boydcase31/openiBoot
static void acm_received(uint32_t _tkn, int32_t _amt)
{
	int attempts;
	for(attempts = 0; attempts < 5; attempts++)
	{
		if(task_start(&acm_parse_task, &acm_parse, (void*)_amt))
			break;

		bufferPrintf("ACM: Worker already running, yielding...\n");

		task_yield();
	}
}
예제 #11
0
int32_t serial_recv_stream_dma_timeout (serial_t *obj, char *prxbuf, uint32_t len, uint32_t timeout_ms, void *force_cs)
{
    PHAL_RUART_OP      pHalRuartOp;
    PHAL_RUART_ADAPTER pHalRuartAdapter=(PHAL_RUART_ADAPTER)&(obj->hal_uart_adp);
    u8  uart_idx = pHalRuartAdapter->UartIndex;
    uint32_t TimeoutCount=0, StartCount;
    int ret;
    void (*task_yield)(void);

    pHalRuartOp = &(obj->hal_uart_op);
    if ((serial_dma_en[uart_idx] & SERIAL_RX_DMA_EN)==0) {
        PUART_DMA_CONFIG   pHalRuartDmaCfg;

        pHalRuartDmaCfg = &obj->uart_gdma_cfg;
        if (HAL_OK == HalRuartRxGdmaInit(pHalRuartOp, pHalRuartAdapter, pHalRuartDmaCfg)) {
            serial_dma_en[uart_idx] |= SERIAL_RX_DMA_EN;
        }
        else {
            return HAL_BUSY;
        }
    }
    HalRuartEnterCritical(pHalRuartAdapter);
    ret = pHalRuartOp->HalRuartDmaRecv(pHalRuartAdapter, (u8*)prxbuf, len);
    HalRuartExitCritical(pHalRuartAdapter);
    
    if ((ret == HAL_OK) && (timeout_ms > 0)) {
        TimeoutCount = (timeout_ms*1000/TIMER_TICK_US);
        StartCount = HalTimerOp.HalTimerReadCount(1);
        task_yield = (void (*)(void))force_cs;
        pHalRuartAdapter->Status = HAL_UART_STATUS_OK;
        while (pHalRuartAdapter->State & HAL_UART_STATE_BUSY_RX) {
            if (HAL_TIMEOUT == RuartIsTimeout(StartCount, TimeoutCount)) {
                ret = pHalRuartOp->HalRuartStopRecv((VOID*)pHalRuartAdapter);
                ret = pHalRuartOp->HalRuartResetRxFifo((VOID*)pHalRuartAdapter);
                pHalRuartAdapter->Status = HAL_UART_STATUS_TIMEOUT;
                break;
            }
            if (NULL != task_yield) {
               task_yield();
            }
        }
        if (pHalRuartAdapter->Status == HAL_UART_STATUS_TIMEOUT) {
            return (len - pHalRuartAdapter->RxCount);
        } else {
            return len;
        }
    } else {
        return (-ret);
    }
//  return (ret);
}
예제 #12
0
/*
 * lcd_an_write_register
 * @lcd: LCD driver on which a byte is needed to be written.
 * @rs: Flag to specify if we are writing a data register or command register.
 *  TRUE: If we need to write a data register.
 *  FALSE: If we need to write a command register.
 * @byte: Byte needed to be written.
 * @return: Success will be returned if bytes was successfully written
 *  LCD_AN_TIME_OUT will be returned if timed out waiting for LCD.
 * This function write a register to the LCD.
 */
int32_t lcd_an_write_register(LCD_AN *lcd, uint8_t rs, uint8_t byte)
{
    uint8_t cmd_byte = 0xFF;
    uint64_t sys_time = current_system_tick();
    int32_t status = SUCCESS;

    /* Wait for LCD. */
    while ((current_system_tick() - sys_time) < (MS_TO_TICK(LCD_AN_BUSY_TIMEOUT)) &&
           (cmd_byte & (1 << 7)))
    {
        /* Read command register. */
        lcd_an_read_register(lcd, FALSE, &cmd_byte);

        /* If we are still busy. */
        if (cmd_byte & (1 << 7))
        {
            /* Yield the task. */
            task_yield();
        }
    }

    /* If we did not timeout waiting for the LCD. */
    if ((cmd_byte & (1 << 7)) == 0)
    {
        /* Select required register. */
        if (rs == TRUE)
        {
            /* Select data register. */
            LCD_AN_TGT_SET_RS(lcd);
        }
        else
        {
            /* Select command register. */
            LCD_AN_TGT_CLR_RS(lcd);
        }

        /* We are writing data. */
        LCD_AN_TGT_CLR_RW(lcd);

        /* Disable the LCD data line. */
        LCD_AN_TGT_CLR_EN(lcd);

        /* Put byte on the LCD. */
        lcd_an_send_nibble(lcd, ((byte >> 4) & 0x0F));
        lcd_an_send_nibble(lcd, (byte & 0x0F));

    }
    else
    {
예제 #13
0
파일: spi.c 프로젝트: chronzz/openiBoot
int spi_tx(int port, const uint8_t* buffer, int len, int block, int unknown)
{
    if(port >= SPICount || port < 0)
        return -1;

    SPIStruct *spi = &SPIData[port];

    SET_REG(spi->registers->control, GET_REG(spi->registers->control) | (1 << 2));
    SET_REG(spi->registers->control, GET_REG(spi->registers->control) | (1 << 3));

    // Set len to number of words.
    len = (len + ((1<<spi->wordSize)-1)) >> spi->wordSize;

    spi->txBuffer = (void*)buffer;
    spi->rxBuffer = NULL;
    spi->txLength = len;

    if(len > MAX_TX_BUFFER)
        spi->txDone = MAX_TX_BUFFER;
    else
        spi->txDone = len;

    if(unknown == 0) {
        SET_REG(spi->registers->rxCount, 0);
    }
    else
    {
        spi->config |= 0x80;
    }

    //bufferPrintf("spi_tx(%d, %p, %d, %d, %d)\n", port, buffer, len, block, unknown);

    spi_txdata(spi, buffer, 0, spi->txDone);

    spi->config |= 0x200100;
    SET_REG(spi->registers->txCount, len);
    SET_REG(spi->registers->config, spi->config);
    SET_REG(spi->registers->control, 1);

    if(block)
    {
        while(spi->txBuffer != NULL || TX_BUFFER_LEFT(GET_REG(spi->registers->status)) > 0)
            task_yield();

        return len;
    }
    else
        return 0;
}
void Body (void * arg)
{
   int i ;

   task_nice (prioridade);
   prioridade += 2 ;

   for (i=0; i<10; i++)
   {
      printf ("%s %d\n", (char *) arg, i) ;
      task_yield ();
   }
   printf ("%s FIM\n", (char *) arg) ;
   task_exit (0) ;
}
예제 #15
0
파일: i2c.c 프로젝트: LILA-99/openiBoot
static I2CError i2c_readwrite(I2CInfo* i2c) { 
	if (i2c->bufferLen > 0x80)
		return 1;

	while (i2c->state != I2CDone) {
		task_yield();
	}

	i2c->state = I2CStart;

	SET_REG(i2c->register_0, i2c->address >> 1);
	SET_REG(i2c->register_14, 0);
	SET_REG(i2c->register_10, *i2c->registers);
	SET_REG(i2c->register_18, i2c->bufferLen);

	if (i2c->is_write) {
		int i = 0;
		while (i < i2c->bufferLen) {
			SET_REG(i2c->register_20, *(i2c->buffer + i++));
		}
	}

	SET_REG(i2c->register_24, i2c->is_write | 4);

	while (!i2c->operation_result) {
		task_yield();
	}

	i2c->operation_result = 0;
	i2c->state = I2CDone;

	if(i2c->operation_result & 0x20)
		return 1;

	return I2CNoError;
}
예제 #16
0
int main (int argc, char *argv[])
{
   printf ("Main INICIO\n");

   task_init () ;

   task_create (&Pang, Body, "    Pang") ;
   task_create (&Peng, Body, "        Peng") ;
   task_create (&Ping, Body, "            Ping") ;
   task_create (&Pong, Body, "                Pong") ;
   task_create (&Pung, Body, "                    Pung") ;

   task_yield () ;

   printf ("Main FIM\n");
   exit (0);
}
예제 #17
0
파일: spi.c 프로젝트: chronzz/openiBoot
int spi_rx(int port, uint8_t* buffer, int len, int block, int noTransmitJunk)
{
    if(port >= SPICount || port < 0)
        return -1;

    SPIStruct *spi = &SPIData[port];

    SET_REG(spi->registers->control, GET_REG(spi->registers->control) | (1 << 2));
    SET_REG(spi->registers->control, GET_REG(spi->registers->control) | (1 << 3));

    // Set len to number of words.
    len = (len + ((1<<spi->wordSize)-1)) >> spi->wordSize;

    spi->txBuffer = NULL;
    spi->rxBuffer = buffer;
    spi->rxDone = 0;
    spi->rxLength = len;

    if(noTransmitJunk == 0)
        spi->config |= 1;
    else
    {
        spi->config |= 0x200000;
        SET_REG(spi->registers->txCount, len);
    }

    //bufferPrintf("spi_rx(%d, %p, %d, %d, %d)\n", port, buffer, len, block, noTransmitJunk);

    SET_REG(spi->registers->rxCount, len);

    spi->config |= 0x180;
    SET_REG(spi->registers->config, spi->config);

    SET_REG(spi->registers->control, 1);

    if(block)
    {
        while(spi->rxBuffer != NULL || spi->txBuffer != NULL)
            task_yield();

        return len;
    }
    else
        return 0;
}
예제 #18
0
/*
 * lcd_an_wait_8bit
 * @lcd: LCD driver on which a command is needed to be sent.
 * @return: Success will be returned if LCD came out of busy successfully
 *  LCD_TIME_OUT will be returned if we timed out waiting for LCD.
 * This function sends a nibble to the LCD.
 */
int32_t lcd_an_wait_8bit(LCD_AN *lcd)
{
#if (LCD_AN_8_BIT_DELAY == 0)
    uint64_t sys_time;
#endif
    int32_t status = SUCCESS;

#if (LCD_AN_8_BIT_DELAY > 0)
    UNUSED_PARAM(lcd);

    /* Rather waiting on status bit just busy wait here. */
    sleep_ms(LCD_AN_8_BIT_DELAY);
#else

    /* Read the command register. */
    LCD_AN_TGT_SET_RW(lcd);
    LCD_AN_TGT_SET_EN(lcd);

    /* Save current system time. */
    sys_time = current_system_tick();

    /* Read the first 4 bit and wait for the busy bit. */
    while ((current_system_tick() - sys_time) < (MS_TO_TICK(LCD_AN_BUSY_TIMEOUT)) &&
           (LCD_AN_TGT_READ_DAT(lcd) & (1 << 3)))
    {
        LCD_AN_TGT_CLR_EN(lcd);
        task_yield();
        LCD_AN_TGT_SET_EN(lcd);
    }

    /* If we timed out waiting for the LCD. */
    if (LCD_AN_TGT_READ_DAT(lcd) & (1 << 3))
    {
        /* Return error to the caller. */
        status = LCD_AN_TIME_OUT;
    }

    /* Clear the enable pin. */
    LCD_AN_TGT_CLR_EN(lcd);
#endif

    /* Return status to the caller. */
    return (status);

} /* lcd_an_wait_8bit */
예제 #19
0
void udp_task (void *data)
{
	int i;
	buf_t *p;
	unsigned old_count = 0;
	unsigned long start, end, elapsed;
	unsigned long long bytes;
	
	start = timer_milliseconds (&timer);

	debug_printf ("Press ENTER to start sending to %d.%d.%d.%d:%d\n", server_ip[0],
		server_ip[1], server_ip[2], server_ip[3], PORT);
	debug_getchar ();
	
	udp_socket (&sock, &ip, PORT);
	trace_udp.udps_ip = (unsigned)sock.ip;

	for (;;) {
		p = buf_alloc (&pool, BUF_SIZE * 4, 42);

		for (i = 0; i < BUF_SIZE; ++i) 
			buf[i] = count++;
		memcpy (p->payload, buf, sizeof(buf));

        if (!udp_sendto (&sock, p, server_ip, PORT)){
            count -= BUF_SIZE;
            debug_printf ("Press ENTER to start sending to %@.4D:%d\n", server_ip, PORT);
            while (debug_peekchar () < 0)
                task_yield();
            debug_getchar ();
        }
		
		if (timer_passed (&timer, start, 1000)) {
			end = timer_milliseconds (&timer);
			elapsed = end - start;
			bytes = (count - old_count) << 2;
			old_count = count;
			debug_printf ("snd rate: %lu (bytes/sec)\n", (unsigned) (bytes * 1000 / elapsed));
			start = end;
		}
	}
}
예제 #20
0
void stat_task(void *argv)
{
    UNUSED_PARAM(argv);
    uint32_t *t = (uint32_t *)argv, i;
    extern MEM_DYNAMIC mem_dynamic;

    while(1)
    {
        util_print_sys_info();
        mem_dynamic_print_usage(&mem_dynamic, (STAT_MEM_GENERAL));

        /* Print time slices for the memory tasks. */
        for (i = 0; i < NUM_DEMO_TASK; i++)
        {
            printf("T%d: %lu ", (i+1), t[i]);
        }
        printf("\r\n");

        task_yield();
    }
}
예제 #21
0
파일: net.c 프로젝트: sillyousu/csocks
static int do_wait_fd(int fd, unsigned events) {
	int needsyscall;
	struct poll_note *note;
	void *current = task_current();
	note = hashmap_get(g_fd_map, &fd, sizeof(int));
	needsyscall = 0;
	/*
	if ((events | POLL_EV_READ) && note->reader && note->reader != current) {
		ERR("dup reader");
		return -1;
	}
	if ((events | POLL_EV_WRITE) && note->writer && note->writer != current) {
		ERR("dup writer");
		return -1;
	}
	*/
	if (events | POLL_EV_READ) {
		note->reader = current;
		needsyscall = (needsyscall || note->reader == NULL);
	}
	if (events | POLL_EV_WRITE) {
		note->writer = current;
		needsyscall = (needsyscall || note->writer == NULL);
	}
	if (note->reader) {
		events |= POLL_EV_READ;
	}
	if (note->writer) {
		events |= POLL_EV_WRITE;
	}

	if (needsyscall && (cs_poll_mod(g_poll_fd, fd, events, (void*)note) == -1)) {
		SYS_ERR("cs_poll_mod failed");
		return -1;
	}
	task_yield(0);
	return 0;
}
예제 #22
0
파일: keyboard.c 프로젝트: Mole23/freewpc
/** Main loop for handling the user interface. */
static void sim_interface_thread (void)
{
	char inbuf[2];
	struct key_binding *kb;
	int simulator_keys = 1;
	int toggle_mode = 1;

#ifndef CONFIG_UI_SDL
	/* Put stdin in raw mode so that 'enter' doesn't have to
	be pressed after each keystroke. */
	keybuffering (0);

	/* Let the system initialize before accepting keystrokes */
	task_sleep_sec (3);
#endif

	if (exec_file && exec_late_flag)
		exec_script_file (exec_file);

	for (;;)
	{
		task_yield ();
#ifdef CONFIG_GTK
		gtk_poll ();
#endif
#ifdef CONFIG_UI_SDL
		ui_refresh_all ();
		*inbuf = ui_poll_events ();
#else
		*inbuf = sim_getchar ();
#endif

		/* Try again if no character was read */
		if (*inbuf == '\0')
			continue;

		/* If switch simulation is turned off, then keystrokes
		are fed into the simulated serial port... meaning it is interpreted
		by the game program itself, and not the simulator.  Use the
		tilde to toggle between the two modes. */
		if (simulator_keys == 0)
		{
			/* Except tilde turns it off as usual. */
			if (*inbuf == '`')
			{
				simlog (SLC_DEBUG, "Input directed to switch matrix.");
				simulator_keys ^= 1;
			}
			else
			{
				wpc_key_press (*inbuf);
			}
			continue;
		}

		switch (*inbuf)
		{
			/* Carriage returns and line feeds are ignored so that you can
			put these commands into a script file. */
			case '\r':
			case '\n':
				break;

			case ':':
			{
				/* Read and execute a script command */
				char cmd[128];
				char *p = cmd;

				memset (p, 0, 128);
				ui_print_command (" ");
				for (;;)
				{
					*p = sim_getchar ();
					if (*p == '\x1B')
					{
						break;
					}
					else if (*p == '\010')
					{
						*p = '\0';
						p--;
					}
					else if ((*p == '\r') || (*p == '\n'))
					{
						*p = '\0';
						exec_script (cmd);
						break;
					}
					ui_print_command (cmd);
					p++;
				}
				ui_print_command ("");
				break;
			}

			case 'C':
				gdb_break ();
				break;

			case '{':
				signal_trace_start (signo_under_trace);
				break;

			case '}':
				signal_trace_stop (signo_under_trace);
				break;

			case 'q':
				node_kick (&open_node);
				break;

			case '`':
				/* The tilde toggles between keystrokes being treated as switches,
				and as input into the runtime debugger. */
				simulator_keys ^= 1;
				simlog (SLC_DEBUG, "Input directed to built-in debugger.");
				break;

			case '\x1b':
				sim_exit (0);
				break;

			case 'T':
				task_dump ();
				break;

			case '#':
				/* Treat '#' as a comment until end of line.
				This is useful for creating scripts. */
				do {
					*inbuf = sim_getchar ();
				} while (*inbuf != '\n');
				break;

			case '"':
				simlog (SLC_DEBUG, "next key will toggle, not press");
				toggle_mode = 0;
				break;

			default:
				/* For all other keystrokes, use the keymap table
				to turn the keystroke into a switch trigger. */
				kb = &keymaps[(int)*inbuf];
#ifdef MACHINE_SHOOTER_SWITCH
				if (kb->flags & KEY_SHOOTER)
				{
					node_kick (&shooter_node);
				}
				else
#endif
				if (kb->flags & KEY_NODE)
				{
					node_move (kb->node, &open_node);
				}
				else if (kb->flags & KEY_SW)
				{
					if ((switch_table[kb->sw].flags & SW_EDGE) || !toggle_mode)
					{
						simlog (SLC_DEBUG, "switch %d toggled", kb->sw);
						sim_switch_toggle (kb->sw);
						toggle_mode = 1;
					}
#if (MACHINE_FLIPTRONIC == 1)
					else if (kb->sw >= 72)
					{
						flipper_button_depress (kb->sw);
					}
#endif
					else
					{
						sim_switch_depress (kb->sw);
					}
				}
				else
					simlog (SLC_DEBUG, "invalid key '%c' pressed (0x%02X)",
						*inbuf, *inbuf);
			}
	}
}
//The main telnet task
void telnet_task_main(void)
{
/*
	commands[0].command="help";
	commands[0].exec = &telnet_help;

	commands[1].command="echo";
	commands[1].exec = &telnet_echo;

	commands[2].command="time";
	commands[2].exec = &telnet_time;

	commands[3].command="quit";
	commands[3].exec = &telnet_quit;

	commands[4].command="memdump";
	commands[4].exec = &telnet_memdump;
*/
	connection_event.event_mask = ReadableOrException;
	telnet_handle = FILE_INVALID_HANDLE;
	socket_listen(HTONS(23), &telnet_connect_accept );

	unsigned short pos = 0;
	while(1)
	{
restart:
		while( ! file_get_next_event( &telnet_handle, 1, &connection_event) )
		{
			task_yield();
		}
		if( connection_event.event & Exception )
		{
//#ifdef __DEBUG
			puts("\r\nTelnet: Closing connection");
//#endif
			file_close( telnet_handle );
			telnet_handle = FILE_INVALID_HANDLE;
			pos = 0;
			optneg_mode = 0;
			goto restart;
		}

		unsigned short avail = buffer_available(&telnet_receive_buffer);
		char* rd_buf = buffer_read_ptr(&telnet_receive_buffer);
		while( pos < avail)//if avail == 1, rd_buf[0] is the last char we can read
		{
			unsigned char c = rd_buf[pos];
			if( pos == REC_BUF_SIZE-1 )
			{
				//buffer is full, but no CR/LF seen yet... what to do?
				//either discard line, or pretend the last char was \r ??
				c = '\r';
			}

			switch(c)
			{
				case TELNET_IAC:
					if( avail - pos > 2 )
					{
						//buf[pos+1] = will/wont/do/dont
						//buf[pos+2] = option
						switch( (unsigned char) rd_buf[pos+2] )
						{
							case TELNET_ECHO:
								switch( (unsigned char) rd_buf[pos+1] )
								{
									case TELNET_DO:
										//other end wants us to echo
										telnet_mode |= MODE_ECHO;
										break;
									case TELNET_DONT:
										//other end demands we don't echo
										telnet_mode &= ~MODE_ECHO;
										break;
								}
								break;
						}
						//remove 3 chars from buffer
						buffer_unwrite(&telnet_receive_buffer, &rd_buf[pos], 3 );
						avail -= 3;
					}
					else
					{
						task_yield();
					}
					break;
				case '\r': // could be \r\n , \r\0 or just \r on its own
					pos++;
					if( telnet_mode & MODE_ECHO)
					{
						file_puts(CRLF, telnet_handle);
					}
					//if there's a following character, and it's \n or \0, chomp it too.
					if( pos < avail && (rd_buf[pos+1] == '\n' || rd_buf[pos+1] == '\0')) pos++; 
					exec_line( rd_buf, rd_buf+pos ); //if read rd_buf[0], pos == 1 -> end = (rd_ptr + 1)

					buffer_seek( &telnet_receive_buffer, pos ); //free buffer
					rd_buf = buffer_read_ptr(&telnet_receive_buffer);

					pos = 0;
					avail = buffer_available(&telnet_receive_buffer);
					file_putchar('>', telnet_handle);
					break;
				case '\b':
				case 0x7f:
					puts("\r\ntel:backspace");
					if( pos > 0 ) //not the first character
					{
						if( telnet_mode & MODE_ECHO)
						{
							file_putchar('\b', telnet_handle);
							file_putchar(' ', telnet_handle);
							file_putchar('\b', telnet_handle);
						}
						buffer_unwrite(&telnet_receive_buffer, &rd_buf[pos-1], 2 );
						avail-=2;
						pos--;
					}
					else
					{
						buffer_unwrite(&telnet_receive_buffer, &rd_buf[pos], 1 );
						avail--;
					}
					break;
				default:
					if( c >= ' ' && c <='~' )
					{
						if( telnet_mode & MODE_ECHO)
						{
							file_putchar(c, telnet_handle);
							pos++;
						}
					}
					else
					{
						buffer_unwrite(&telnet_receive_buffer, &rd_buf[pos], 1 );
						avail--;
					}
			}//end switch
		}//end while loop

		task_yield();
	}//end outer while
}
예제 #24
0
파일: task.c 프로젝트: stevekroh/qnx-pwm
/*
 * Header: Execute provided instruction
 *
 * Params: tsk    - the task in which to execute the instruction
 *         opcode - the opcode dictating which feature to run
 *         params - the parameters to the opcode above
 * Return: 0      - instruction properly executed
 *         ETRPWM - issue with servo targeting
 *         ETRNLP - encountered a nested loop
 *
 * Description: 
 *
 * See project specification for instruction details.
 */
static char task_instr_exe(struct task *tsk, 
	unsigned char opcode, unsigned char params)
{
	char result = 0;
	char pwm_result;

	char cur, mov;
	unsigned char delta; /* Time waiting after MOV is scaled by delta */

	switch(opcode) {
	case MOV:
		/* Grad extension - if transposed, mirror pwm destination */
		tsk->mov_pos = (!tsk->transpose) ? (params) : (PWM_DTY_DIV - params);
		pwm_result = pwm_set(tsk);		

		if(pwm_result > 0) {
			led_set(tsk, LED_RECIPE_CMD_ERROR);
			tsk->state = ST_ERROR;

			result = ETRPWM;
		} else {
			cur = tsk->cur_pos;
			mov = tsk->mov_pos;
			delta = (mov > cur) ? (mov - cur) : (cur - mov);
			
			/* Wait for the servo to get to its target! */
			(void )task_yield(tsk, delta * WAIT_CORRECTION);
		}
		break; 
	case WAI:
		(void )task_yield(tsk, params);
		break; 
	case SLP:
		/* Non-zero lc means we already encountered SLP */
		if(tsk->lc > 0) {
			led_set(tsk, LED_NESTED_LOOP_ERROR);
			tsk->state = ST_ERROR;

			result = ETRNLP;
		} else {
			/*
			 * Mark $ra as addr of this SLP. Upon execution of
			 * next ELP, the next instruction will be $ra + 1.
			 */
			tsk->ra = tsk->pc;
			tsk->lc = params + 1;
		}
		break;
	case ELP:
		/* If there are loops left, go back to $ra */
		if(--tsk->lc > 0) {
			tsk->pc = tsk->ra;
		}
		break;
	case END:
		/* Recipe end */
		led_set(tsk, LED_END_OF_RECIPE);
		tsk->state = ST_END;
		
		result = ETREND;
		break;
	case TTR:
		/* Toggle transpose */
		tsk->transpose = (tsk->transpose) ? (0) : (1);
	}

	/* Defaults to 0. Any error cases should set result themselves */
	return result;
}
예제 #25
0
파일: daemon.C 프로젝트: bjwyman/hostboot
    void Daemon::sendContBuffer(void* i_buffer, size_t i_size)
    {
        // Write debug structure with buffer information.
        g_debugSettings.bufferSize = i_size;
        g_debugSettings.bufferPage = i_buffer;
        // Write scratch register indicating continuous trace is available.
        writeScratchReg(1ull << 32);

        // Signal for simics.
        asm volatile("mr 4, %0; mr 5, %1" ::
                     "r" (i_buffer), "r" (i_size) : "4", "5");
        MAGIC_INSTRUCTION(MAGIC_CONTINUOUS_TRACE);

        TARGETING::Target* sys = NULL;
        TARGETING::targetService().getTopLevelTarget(sys);

        TARGETING::HbSettings hbSettings =
            sys->getAttr<TARGETING::ATTR_HB_SETTINGS>();

        // Determine if continuous trace is currently enabled.
        bool contEnabled = hbSettings.traceContinuous;
        if (g_debugSettings.contTraceOverride !=
                DebugSettings::CONT_TRACE_USE_ATTR)
        {
            contEnabled = (g_debugSettings.contTraceOverride ==
                            DebugSettings::CONT_TRACE_FORCE_ENABLE);
        }

        if (!contEnabled)
        {
            // Trace isn't enabled so just discard the buffer.
            free(i_buffer);
        }
        else
        {
            if (MBOX::mailbox_enabled())
            {
                msg_t* msg = msg_allocate();
                msg->type = DaemonIf::TRACE_CONT_TRACE_BUFFER;
                msg->data[1] = i_size;
                msg->extra_data = MBOX::allocate(i_size);
                memcpy(msg->extra_data,i_buffer,i_size);
                free(i_buffer);

                errlHndl_t l_errl = MBOX::send(MBOX::FSP_TRACE_MSGQ, msg);
                if (l_errl)
                {
                    errlCommit(l_errl, TRACE_COMP_ID);
                    msg_free(msg);
                }
            }
            else
            {
                // Wait for tools to extract the buffer.
                while(0 != readScratchReg())
                {
                    task_yield();
                }
                free(i_buffer);
            }
        }
    }
예제 #26
0
파일: daemon.C 프로젝트: bjwyman/hostboot
    void Daemon::collectTracePages()
    {
        // Clear indication from clients.
        iv_service->iv_daemon->clearSignal();

        // Collect buffer pages from front-end.
        BufferPage* srcPages[BUFFER_COUNT];
        for (size_t i = 0; i < BUFFER_COUNT; i++)
        {
            iv_curPages[i] = srcPages[i] =
                iv_service->iv_buffers[i]->claimPages();

            iv_curOffset[i] = 0;
        }

        char* contBuffer = NULL;
        size_t contBufferSize = 0;

        // Process buffer pages.
        do
        {
            size_t whichBuffer = BUFFER_COUNT;
            Entry* whichEntry = NULL;
            uint64_t minTimeStamp = UINT64_MAX;

            // Find the entry with the earliest timestamp.
            for (size_t i = 0; i < BUFFER_COUNT; i++)
            {
                if (NULL == iv_curPages[i]) continue;

                Entry* entry =
                    reinterpret_cast<Entry*>(
                        &((&(iv_curPages[i]->data[0]))[iv_curOffset[i]])
                    );

                trace_bin_entry_t* binEntry =
                    reinterpret_cast<trace_bin_entry_t*>(
                        &(entry->data[0])
                    );

                // Wait for entry to be committed.
                while(unlikely(entry->committed == 0))
                {
                    task_yield();
                }
                isync();

                uint64_t curTimeStamp =
                    TWO_UINT32_TO_UINT64(binEntry->stamp.tbh,
                                         binEntry->stamp.tbl);

                if (curTimeStamp < minTimeStamp)
                {
                    whichBuffer = i;
                    whichEntry = entry;
                    minTimeStamp = curTimeStamp;
                }
            }

            // Did not find another entry, our work is done.
            if (whichBuffer == BUFFER_COUNT)
            {
                break;
            }

            // Increment pointers to next buffer entry.
            iv_curOffset[whichBuffer] += whichEntry->size + sizeof(Entry);
            if (iv_curOffset[whichBuffer] >= iv_curPages[whichBuffer]->usedSize)
            {
                iv_curPages[whichBuffer] = iv_curPages[whichBuffer]->next;
                iv_curOffset[whichBuffer] = 0;
            }

            trace_bin_entry_t* contEntry =
                reinterpret_cast<trace_bin_entry_t*>(&whichEntry->data[0]);

            // Calculate the sizes of the entry.
            size_t contEntryDataLength = contEntry->head.length +
                                         sizeof(trace_bin_entry_t);

            size_t contEntrySize = whichEntry->comp->iv_compNameLen +
                                   contEntryDataLength;

            // Allocate a new continuous trace page if needed.
            if ((NULL == contBuffer) ||
                ((contBufferSize + contEntrySize) >= PAGESIZE))
            {
                if (NULL != contBuffer)
                {
                    sendContBuffer(contBuffer, contBufferSize);
                    // contBuffer pointer is transfered to mailbox now.
                }

                contBuffer = reinterpret_cast<char*>(malloc(PAGESIZE));
                memset(contBuffer, '\0', PAGESIZE);
                contBuffer[0] = TRACE_BUF_CONT;
                contBufferSize = 1;
            }

            // Add entry to continous trace.
            memcpy(&contBuffer[contBufferSize],
                   whichEntry->comp->iv_compName,
                   whichEntry->comp->iv_compNameLen);
            contBufferSize += whichEntry->comp->iv_compNameLen;

            memcpy(&contBuffer[contBufferSize],
                   &whichEntry->data[0],
                   contEntryDataLength);
            contBufferSize += contEntryDataLength;

            // Allocate a new back-end entry.
            Entry* mainBuffEntry = NULL;
            while (NULL ==
                (mainBuffEntry =
                    iv_last->claimEntry(whichEntry->size + sizeof(Entry))))
            {
                BufferPage* n = BufferPage::allocate(true);

                n->next = iv_last;
                iv_last->prev = n;
                iv_last = n;
            }

            // Move entry from front-end buffer to back-end.
            replaceEntry(whichEntry, mainBuffEntry);

        } while(1);

        // Send remainder of continous trace buffer.
        if (NULL != contBuffer)
        {
            if (contBufferSize > 1)
            {
                sendContBuffer(contBuffer, contBufferSize);
                // contBuffer pointer is transfered to mailbox now.
            }
            else
            {
                free(contBuffer);
            }
        }

        // Release pages.
        for (size_t i = 0; i < BUFFER_COUNT; i++)
        {
            // Toggle lock to ensure no trace extract currently going on.
            iv_service->iv_buffers[i]->consumerOp();

            while(srcPages[i])
            {
                BufferPage* tmp = srcPages[i]->next;
                BufferPage::deallocate(srcPages[i]);
                srcPages[i] = tmp;
            }
        }

    }
예제 #27
0
/// Pass control to next thread that is in state \b READY.
/// \return status code that indicates the execution status of the function.
/// \note MUST REMAIN UNCHANGED: \b osThreadYield shall be consistent in every CMSIS-RTOS.
osStatus osThreadYield (void)
{
    task_yield();

    return osOK;
}
/*
* This is a co-operative task. This function must NEVER return
*/
void uip_task_main(void)
{
    //initialise all the connections to point to the invalid handle
    for( i = 0 ; i  < UIP_CONNS; i++)
    {
        uip_conns[i].appstate[0] = FILE_INVALID_HANDLE;
    }

    while(1) {

        task_yield();

        if( UIP_DMA_RX_PACKET_READY )
        {
            UIP_DMA_RX_PACKET_READY = 0;
            uip_len = uip_dma_rx_last_packet_length;
            // packet received - buffer is already acquired

            // process an IP packet
            if(BUF->type == HTONS(UIP_ETHTYPE_IP)) {
                // add the source to the ARP cache
                // also correctly set the ethernet packet length before processing
                uip_arp_ipin();
                uip_input();

                // transmit a packet, if one is ready
                if(uip_len > 0) {
                    uip_arp_out();
                    nic_send();
                }
                else nic_rx_maybe();
            }
            else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) {

                // process an ARP packet
                uip_arp_arpin();

                // transmit a packet, if one is ready
                if(uip_len > 0) {

                    nic_send();
                }
                else {

                    nic_rx_maybe();
                }
            }
            else //don't know how to process this packet. Discard
            {
                puts("Unknown packet discarded");
                nic_rx_maybe();
            }
        }
        else if(UIP_DMA_PERIODIC_TIMEOUT && uip_acquireBuffer()) {
            if( next_conn_id != UIP_CONNS )
            {
                uip_len = 0;
                while( uip_len == 0 && next_conn_id < UIP_CONNS )
                {
                    uip_periodic( next_conn_id );
                    // transmit a packet, if one is ready
                    if(uip_len > 0) {
                        uip_arp_out();
                        nic_send();
                    }
                    next_conn_id++;
                }
            }
            if( next_conn_id == UIP_CONNS )
            {

                UIP_DMA_PERIODIC_TIMEOUT=0;

                //blink LED to show we're alive
                LD1_O = !LD1_O;
                next_conn_id = 0;

                /* Call the ARP timer function every 10 seconds. */
                if(++arptimer == 20) {
                    uip_arp_timer();
                    arptimer = 0;
                }
                uip_releaseBuffer();
//possibly change test below to if( uip_len == 0)??
                if( ENC_DMACONbits.CHEN == 0 ) nic_rx_maybe();
            }
        }
        else
        {
            //anyone need to send something or close?
            unsigned char loop_end = next_send_id;

            do
            {
                struct uip_conn *connptr = &uip_conns[next_send_id];
                file_handle_t fh = connptr->appstate[0];
                struct file_t *f = file_get_by_handle(fh);
                if(f != NULL &&
                        ( f->state == ClosePending ||
                          (f->write_buffer != NULL && buffer_available( f->write_buffer) > 0 &&
                           connptr->len == 0
                          )
                        )
                  )
                {
#ifdef __DEBUG
                    printf("\n TCP conn id: %hhd state: %hhd. File State: %hhx", next_send_id, connptr->tcpstateflags, f->state);
#endif
                    if(  connptr->tcpstateflags == CLOSED )
                    {
#ifdef __DEBUG
                        puts("\r\nFreed tcp conn and file ");
#endif
                        file_free( fh );
                        connptr->appstate[0] = FILE_INVALID_HANDLE;
                    }
                    if( uip_acquireBuffer() )
                    {
                        uip_periodic_conn(connptr);
                        if(uip_len > 0) {
#ifdef __DEBUG
                            printf("\n id %hhd sending", next_send_id);
#endif
                            uip_arp_out();
                            nic_send();
                            break;
                        }
                        else uip_releaseBuffer();
                    }
                    break; //this connection wants to write. try again later
                }

                next_send_id = ++next_send_id < UIP_CONNS ? next_send_id : 0;

            } while( next_send_id != loop_end );
        }


    } //end while

}
예제 #29
0
void ctx_sample_task(void *argv)
{
    UNUSED_PARAM(argv);
    uint32_t last_tick;
    uint32_t n = 0;
    uint32_t com = 0;
    uint32_t *ret_time = (uint32_t *)argv;
    MEM_TEST_NODE *mem;
    uint32_t mem_size;
    uint32_t total_allocated;
    uint32_t num_allocated, mem_num;
    MEM_TEST_LIST mem_test_list;

    ret_time[0] = 0;

    num_allocated = 0;
    total_allocated = 0;
    mem_test_list.head =
    mem_test_list.tail = NULL;

    /* Initialize random seed. */
    srand(current_hardware_tick());

    while(1)
    {
        n= n + 1;
        last_tick = current_hardware_tick();
        task_yield();

        if (com > 0x0FFFFFFF)
        {
            com = 0;
            n = 1;
        }

        last_tick = current_hardware_tick() - last_tick;
        if (last_tick < MAX_TIMER_TICKS)
        {
            com += last_tick;
            ret_time[0] = (com / n);
        }

        mem_size = (rand() % MAX_ALLOC) + sizeof(MEM_TEST_NODE);
        mem = (MEM_TEST_NODE *)mem_dynamic_alloc(mem_size);

        if (mem)
        {
            total_allocated += mem_size;
            mem->size = mem_size;
            sll_append(&mem_test_list, mem, OFFSETOF(MEM_TEST_NODE, next));
            num_allocated++;
        }

        while ( (total_allocated > MEM_PER_TASK) || (mem == NULL) )
        {
            mem_num = rand() % num_allocated;
            mem = sll_search_pop(&mem_test_list, pop_n, &mem_num, OFFSETOF(MEM_TEST_NODE, next));

            if (mem)
            {
                total_allocated -= mem->size;
                num_allocated --;
                mem_dynamic_dealloc((uint8_t *)mem);
            }
            else
            {
                break;
            }
        }
    }
}
예제 #30
0
파일: drtm.C 프로젝트: wghoffa/hostboot
errlHndl_t initiateDrtm()
{
    SB_ENTER("initiateDrtm");

    errlHndl_t pError = nullptr;

    // For DRTM, the thread has to be pinned to a core (and therefore pinned to
    // a chip)
    task_affinity_pin();

    void* drtmPayloadVirtAddr = nullptr;

    do
    {
        const std::vector<SECUREBOOT::ProcSecurity> LLP {
            SECUREBOOT::ProcSecurity::LLPBit,
        };

        const std::vector<SECUREBOOT::ProcSecurity> LLS {
            SECUREBOOT::ProcSecurity::LLSBit,
        };

        // Determine which fabric group and chip this task is executing on and
        // create a filter to find the matching chip target
        auto cpuId = task_getcpuid();
        auto groupId = PIR_t::groupFromPir(cpuId);
        auto chipId = PIR_t::chipFromPir(cpuId);
        TARGETING::PredicateAttrVal<TARGETING::ATTR_FABRIC_GROUP_ID>
            matchesGroup(groupId);
        TARGETING::PredicateAttrVal<TARGETING::ATTR_FABRIC_CHIP_ID>
            matchesChip(chipId);
        TARGETING::PredicatePostfixExpr matchesGroupAndChip;
        matchesGroupAndChip.push(&matchesGroup).push(&matchesChip).And();

        // Get all the functional proc chips and find the chip we're running on
        TARGETING::TargetHandleList funcProcChips;
        TARGETING::getAllChips(funcProcChips,
                               TARGETING::TYPE_PROC);
        if(funcProcChips.empty())
        {
            // TODO: RTC 167205: GA error handling
            assert(false,"initiateDrtm: BUG! Functional proc chips is empty, "
                "yet this code is running on a functional chip!");
            break;
        }

        // NOTE: std::find_if requires predicates to be copy constructable, but
        // predicates are not; hence use a wrapper lambda function to bypass
        // that limitation
        auto pMatch =
            std::find_if(funcProcChips.begin(),funcProcChips.end(),
                [&matchesGroupAndChip] ( TARGETING::Target* pTarget )
                {
                    return matchesGroupAndChip(pTarget);
                } );

        if(pMatch == funcProcChips.end())
        {
            // TODO: RTC 167205: GA error handling
            assert(false, "initiateDrtm: BUG! No functional chip found "
                "to be running this code");
            break;
        }

        // Move the matching target to the end of the list.
        // NOTE: If reverse iterators were supported, we could have verified the
        // last element of the container is not the match, and done a
        // std::iter_swap of the match and the last element
        TARGETING::Target* const pMatchTarget = *pMatch;
        funcProcChips.erase(pMatch);
        funcProcChips.push_back(pMatchTarget);

        // Map to the DRTM payload area in mainstore
        const uint32_t drtmPayloadPhysAddrMb = DRTM_RIT_PAYLOAD_PHYS_ADDR_MB;
        drtmPayloadVirtAddr = mm_block_map(
            reinterpret_cast<void*>(drtmPayloadPhysAddrMb*BYTES_PER_MEGABYTE),
            PAGESIZE);
        if(drtmPayloadVirtAddr == nullptr)
        {
            // TODO: RTC 167205: GA error handling
            assert(false, "initiateDrtm: BUG! Failed in call to mm_block_map "
                "to map the DRTM payload.");
            break;
        }

        // Copy the DRTM payload to the DRTM payload area
        memcpy(
            reinterpret_cast<uint32_t*>(drtmPayloadVirtAddr),
            DRTM_RIT_PAYLOAD,
            sizeof(DRTM_RIT_PAYLOAD));

        // The required generic sequencing to initiate DRTM is as follows:
        // 1) Initiating task must pin itself to a core (to ensure it
        //     will not be accidentally queisced by SBE)
        // 2) It must set the DRTM payload information in the master processor
        //     mailbox scratch registers (registers 7 and 8) before it goes
        //     offline
        // 3) It must determine the processor it's currently running on
        // 4) It must set the late launch bit (LL) on all other processors
        //     4a) If the given processor is an active master, it must set
        //         late launch primary (LLP) bit
        //     4b) Otherwise it must set late launch secondary (LLS) bit
        // 5) Finally, it must its own processor's LL bit last, according to the
        //     rules of step 4.
        for(auto &pFuncProc :funcProcChips)
        {
            const auto procMasterType = pFuncProc->getAttr<
                TARGETING::ATTR_PROC_MASTER_TYPE>();

            // If master chip, set the DRTM payload address and validity
            if(procMasterType == TARGETING::PROC_MASTER_TYPE_ACTING_MASTER)
            {
                (void)setDrtmPayloadPhysAddrMb(drtmPayloadPhysAddrMb);
            }

            pError = SECUREBOOT::setSecuritySwitchBits(procMasterType ==
                         TARGETING::PROC_MASTER_TYPE_ACTING_MASTER ?
                            LLP : LLS,
                         pFuncProc);
            if(pError)
            {
                SB_ERR("initiateDrtm: setSecuritySwitchBits() failed for proc "
                    "= 0x%08X. Tried to set LLP or LLS.",
                    get_huid(pFuncProc));
                break;
            }
        }

        if(pError)
        {
            break;
        }


        SB_INF("initiateDrtm: SBE should eventually quiesce all cores; until "
            "then, endlessly yield the task");
        while(1)
        {
            task_yield();
        }

    } while(0);

    // If we -do- come back from this function (on error path only), then we
    // should unpin
    task_affinity_unpin();

    if(drtmPayloadVirtAddr)
    {
        auto rc = mm_block_unmap(const_cast<void*>(drtmPayloadVirtAddr));
        if(rc != 0)
        {
            // TODO: RTC 167205: GA error handling
            assert(false,"initiateDrtm: BUG! mm_block_unmap failed for virtual "
                "address 0x%16llX.",
                drtmPayloadVirtAddr);
        }
    }

    if(pError)
    {
        SB_ERR("initiateDrtm: plid=0x%08X, eid=0x%08X, reason=0x%04X",
               ERRL_GETPLID_SAFE(pError),
               ERRL_GETEID_SAFE(pError),
               ERRL_GETRC_SAFE(pError));
    }

    SB_EXIT("initiateDrtm");

    return pError;
}