Beispiel #1
0
/*******************************************************************************
* Function Name  : uart_close
* Description    : Close the USART port communication
* Input          : - Uart: Select the USART or the UART peripheral.
* Output         : None
* Return         : 0
*******************************************************************************/
int uart_close(const _Uart_Descriptor *Uart)
{
  /* Disable IT */
  NVIC_DisableIRQ(Uart->IRQn);

  /* Free control variables and buffers */
  if (*Uart->Ctrl)
  {
    if ((*Uart->Ctrl)->DmaBufSize)
    {
      USART_DMACmd(Uart->UARTx, USART_DMAReq_Rx, DISABLE);
      NVIC_DisableIRQ(Uart->DMAx_IRQn);
      DMA_DeInit(Uart->DMAy_Streamx);
    }
    if (((*Uart->Ctrl)->HwCtrl & UART_HW_FLOW_CTRL_RX) || ((*Uart->Ctrl)->HwCtrl & UART_HALF_DUPLEX)) gpio_init((*Uart->Ctrl)->Gpio);
    _sys_free(*Uart->Ctrl);
    *Uart->Ctrl = 0;
  }

  /* Deactivate UART peripheral */
  USART_DeInit(Uart->UARTx);

  /* Disable peripheral clock */
  (*Uart->RCC_APBxPeriphClockCmd)(Uart->RCC_APBxPeriph, DISABLE);

  /* Configure GPIO to default state */
  gpio_init(Uart->TxGpio);
  gpio_init(Uart->RxGpio);

  return(0);
}
/*
    @description:
        Heapify helper for _sort.
*/
void do_heap(uint8_t *base, size_t i, size_t n, size_t size, _cmp_func_t cmp)
{
    /* Not much can be done when size is unknown */
    void *temp = _sys_alloc(size);
    size_t k;

    /* Save the node that's being overwritten below */
    memcpy(temp, &base[i * size], size);

    /* Move all subsequent child nodes into place to maintain the heap property */
    for (k = i * 2 + 1; k < n; k = i * 2 + 1) {
        /* Find the next child node */
        if (k + 1 < n && cmp(&base[k * size], &base[(k + 1) * size]) < 0)
            ++k;

        /* Are we at the saved node's sorted position? */
        if (cmp(temp, &base[k * size]) >= 0)
            break;

        /* Overwrite the parent with one of its children */
        memcpy(&base[i * size], &base[k * size], size);
        i = k;
    }

    /* Copy the saved node into its final resting place */
    memcpy(&base[i * size], temp, size);
    _sys_free(temp);
}
Beispiel #3
0
/*-------------------------------------------
| Name:_syscall_free
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
int _syscall_free(kernel_pthread_t* pthread_ptr, pid_t pid, void* data){
   free_t* free_dt = (free_t*)data;
   _sys_free(free_dt->p);
   __flush_syscall(pthread_ptr);
   __kernel_ret_int(pthread_ptr);
   return 0;
}
Beispiel #4
0
/*-------------------------------------------
| Name:_syscall_closedir
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
int _syscall_closedir(kernel_pthread_t* pthread_ptr, pid_t pid, void* data){
   closedir_t* closedir_dt = (closedir_t*)data;
   desc_t desc = closedir_dt->dir->desc;

   closedir_dt->ret = _vfs_closedir(closedir_dt->dir->desc);

   //free struct dirent (see _syscall_readdir() )
   if(ofile_lst[desc].p)
      _sys_free(ofile_lst[desc].p);

   ofile_lst[desc].p=(void*)0;

   __flush_syscall(pthread_ptr);
   __kernel_ret_int(pthread_ptr);
   return 0;
}
/*
    @description:
        qsort-friendly implementation of heapsort for guaranteed time complexity.
*/
void _sort(void *base, size_t n, size_t size, _cmp_func_t cmp)
{
    /* Not much can be done when size is unknown */
    void *temp = _sys_alloc(size);
    uint8_t *p = (uint8_t*)base;
    int i = n / 2;

    /* Heapify the array */
    while (i-- > 0)
        do_heap(p, i, n, size, cmp);

    /* Extrac the heap max and place it in sorted position */
    while (--n < (size_t)-1) {
        /* Swap the heap max with base[n] */
        memcpy(temp, p, size);
        memcpy(p, &p[n * size], size);
        memcpy(&p[n * size], temp, size);

        /* Re-heapify after removing the heap max */
        do_heap(p, 0, n, size, cmp);
    }

    _sys_free(temp);
}
Beispiel #6
0
/*******************************************************************************
* Function Name  : uart_open
* Description    : Open the UART port communication
* Input          : - Uart: Select the USART or the UART peripheral
*                : - BaudRate: Baud rate configuration
*                : - DmaBufSize: DMA buffer size
*                : - RxBufSize: Receive buffer size
*                : - TxBufSize: Transmit buffer size
*                : - HwCtrl: Hardware control options
*                : - Gpio: GPIO used for hardware control
* Output         : None
* Return         : 0 if OK, -1 in case of error
*******************************************************************************/
int uart_open (const _Uart_Descriptor *Uart, u32 BaudRate, u8 DmaBufSize, u16 RxBufSize, u16 TxBufSize, u8 HwCtrl, const _Gpio_Descriptor *Gpio)
{
  USART_InitTypeDef usart_init_structure;
  DMA_InitTypeDef dma_init_structure;
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Init control variables and bufers */
  if (*Uart->Ctrl) _sys_free(*Uart->Ctrl);
  if ((*Uart->Ctrl = _sys_malloc(sizeof(_Uart_Ctrl) + DmaBufSize + RxBufSize + TxBufSize)) == 0) return(-1);
  memset(*Uart->Ctrl, 0, sizeof(_Uart_Ctrl));
  (*Uart->Ctrl)->DmaBufPtr = (char *)*Uart->Ctrl + sizeof(_Uart_Ctrl);
  (*Uart->Ctrl)->DmaBufSize = DmaBufSize;
  (*Uart->Ctrl)->iDma = DmaBufSize;
  (*Uart->Ctrl)->RxBufSize = RxBufSize;
  (*Uart->Ctrl)->RxBufPtr = (*Uart->Ctrl)->DmaBufPtr + (*Uart->Ctrl)->DmaBufSize;
  (*Uart->Ctrl)->TxBufSize = TxBufSize;
  (*Uart->Ctrl)->TxBufPtr = (*Uart->Ctrl)->RxBufPtr + (*Uart->Ctrl)->RxBufSize;
  (*Uart->Ctrl)->HwCtrl = HwCtrl;
  (*Uart->Ctrl)->Gpio = Gpio;
  #ifdef _UART_OS_SUPPORT
    (*Uart->Ctrl)->Event = SYS_EVT_INCOMING_DATA;
    (*Uart->Ctrl)->Task = sys_task_self();
  #endif

  /* Enable peripheral clock */
  (*Uart->RCC_APBxPeriphClockCmd)(Uart->RCC_APBxPeriph, ENABLE);

  /* Init GPIO */
  gpio_set_function(Uart->TxGpio, Uart->GPIO_AF);
  gpio_set_function(Uart->RxGpio, Uart->GPIO_AF);
  gpio_set_mode(Uart->TxGpio, GPIO_MODE_AF, 0);
  gpio_set_mode(Uart->RxGpio, GPIO_MODE_AF, 0);
  if ((*Uart->Ctrl)->HwCtrl & (UART_HW_FLOW_CTRL_RX | UART_HALF_DUPLEX)) gpio_set_mode((*Uart->Ctrl)->Gpio, GPIO_FCT_OUT, 0);

  /* Init UART peripheral */
  USART_DeInit(Uart->UARTx);
  USART_StructInit(&usart_init_structure);
  usart_init_structure.USART_BaudRate = BaudRate;
  if ((*Uart->Ctrl)->HwCtrl & UART_HW_FLOW_CTRL_TX) usart_init_structure.USART_HardwareFlowControl = USART_HardwareFlowControl_CTS;
  USART_Init(Uart->UARTx, &usart_init_structure);

  /* Configure DMA (if used) */
  if ((*Uart->Ctrl)->DmaBufSize)
  {
    DMA_DeInit(Uart->DMAy_Streamx);
    DMA_StructInit(&dma_init_structure);
    dma_init_structure.DMA_Channel = Uart->DMA_Channel;
    dma_init_structure.DMA_PeripheralBaseAddr = (u32)&Uart->UARTx->DR;
    dma_init_structure.DMA_Memory0BaseAddr = (u32)(*Uart->Ctrl)->DmaBufPtr;
    dma_init_structure.DMA_BufferSize = (*Uart->Ctrl)->DmaBufSize;
    dma_init_structure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    dma_init_structure.DMA_Mode = DMA_Mode_Circular;
    dma_init_structure.DMA_Priority = DMA_Priority_Medium;
    dma_init_structure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_Init(Uart->DMAy_Streamx, &dma_init_structure);
    DMA_ITConfig(Uart->DMAy_Streamx, DMA_IT_TC | DMA_IT_HT, ENABLE);
    DMA_Cmd(Uart->DMAy_Streamx, ENABLE);
    NVIC_EnableIRQ(Uart->DMAx_IRQn);
    //
    //NVIC_SetPriority((IRQn_Type)Uart->DMAx_IRQn, (uint32_t)129);
    NVIC_SetPriority((IRQn_Type)Uart->DMAx_IRQn, (1 << __NVIC_PRIO_BITS) -3);
    //
    USART_DMACmd(Uart->UARTx, USART_DMAReq_Rx, ENABLE);
    USART_ITConfig(Uart->UARTx, USART_IT_IDLE, ENABLE);
  }
  else USART_ITConfig(Uart->UARTx, USART_IT_RXNE, ENABLE);

  /* Enable IT and start peripheral */
  //NVIC_InitStructure.NVIC_IRQChannel = Uart->IRQn;		 // we want to configure the USART1 interrupts
  //NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;// this sets the priority group of the USART1 interrupts
  //NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		 // this sets the subpriority inside the group
  //NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			 // the USART1 interrupts are globally enabled
  //NVIC_Init(&NVIC_InitStructure);	
  //
  //NVIC_SetPriority((IRQn_Type)Uart->IRQn, (uint32_t)129);
  NVIC_SetPriority((IRQn_Type)Uart->IRQn, (1 << __NVIC_PRIO_BITS) -4);
  //
   
  USART_ITConfig(Uart->UARTx, USART_IT_TC, ENABLE);
  NVIC_EnableIRQ(Uart->IRQn);
  USART_Cmd(Uart->UARTx, ENABLE);
  
  
  while (!gpio_read(Uart->TxGpio));

  return(0);
}
/*-------------------------------------------
| Name:_syscall_exit
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
int _syscall_exit(kernel_pthread_t* pthread_ptr, pid_t pid, void* data){
   pid_t ppid = process_lst[pid]->ppid;
   exit_t* exit_dt=(exit_t*)data;

   if(process_lst[pid]->pthread_ptr->parent_pthread_ptr && process_lst[pid]->pthread_ptr->parent_pthread_ptr->stat&PTHREAD_STATUS_FORK ){
      kernel_pthread_t* parent_pthread_ptr= process_lst[pid]->pthread_ptr;
      fork_t* fork_dt;

      //close all process(pid) file descriptor
      //must be execute before __atomic_in() and __stop_sched()
      //because in some _vfs_close() operation on driver, this operation need inter pthread communication to be completed
      //(ex: lwip_sock_close() deadlock risk);
      _close_process_fd(pid);

      //atomic code no task switching
      __atomic_in();

      //wakeup locked process
      _sys_unlockw();

      //warning all!!! micro-kernel operation is not advised.
      __stop_sched();

      fork_dt=(fork_t*)pthread_ptr->parent_pthread_ptr->reg.data;

      //restore father context
      _sys_vfork_exit(pthread_ptr,exit_dt->status);

      //restart father
      fork_dt->pid=pid;

      __flush_syscall(pthread_ptr);

      __restart_sched();

      __flush_syscall(parent_pthread_ptr);
      __kernel_ret_int(parent_pthread_ptr); //father

   }else {

      //close all process(pid) file descriptor
      //must be execute before __atomic_in() and __stop_sched()
      //because in some _vfs_close() operation on driver, this operation need inter pthread communication to be completed
      //(ex: lwip_sock_close() deadlock risk);
      _close_process_fd(exit_dt->pid);

      //atomic code no task switching
      __atomic_in();

      //wakeup locked process
      _sys_unlockw();

      //warning!!! all micro-kernel operation is not advised.
      __stop_sched();
      //
      _sys_exit(exit_dt->pid,exit_dt->status);
      //
      __flush_syscall(pthread_ptr);

      //ppid threads are on waitpid()?
      if( ppid) {
         //get main thread of father process
         kernel_pthread_t* _pthread_ptr=process_lst[ppid]->pthread_ptr;
         //walking on threads chained list in parent process
         while(_pthread_ptr) {
            //is thread blocked on waitpid()?
            if(_pthread_ptr->stat&PTHREAD_STATUS_STOP && _pthread_ptr->reg.syscall==_SYSCALL_WAITPID){
               waitpid_t* waitpid_dt = (waitpid_t*)_pthread_ptr->reg.data;
               //waitpid_dt->pid = pid;
               _syscall_waitpid(_pthread_ptr,ppid,waitpid_dt);
            }else{
               //not then send sig child to all pthread of father processus
               _sys_kill(_pthread_ptr,SIGCHLD,1);
               //send 1 times an only the signal to the first pthread which accept SIGCHLD
               //better conformance with posix specification
               break;
            }
            _pthread_ptr=_pthread_ptr->next;
         }
      }else{
         pid_t _pid;
         //it's a daemon process
         //free process
         _sys_free(process_lst[pid]);
         process_lst[pid]= 0;
         _dbg_printf("free(%d)\n",pid);
         //checkif it's the last process
         for(_pid=1; _pid<=PROCESS_MAX; _pid++)
            if(process_lst[_pid])
               goto end;
         return -1; //in this case stop all
      }
      //
   }
end:
   __restart_sched();
   __atomic_out();
   return 0;
}
/*-------------------------------------------
| Name:_sys_vfork
| Description:
| Parameters:
| Return Type:
| Comments:
| See:
---------------------------------------------*/
pid_t _sys_vfork(kernel_pthread_t* pthread_ptr){

   //to do: copy all father process descriptor
   pid_t pid  = 0;
   pid_t ppid = pthread_ptr->pid;
   char* p;
   struct __timeval tv;
   int argc;

   kernel_pthread_t* backup_parent_pthread_ptr;

   //
#ifdef KERNEL_PROCESS_VFORK_CLRSET_IRQ
   __clr_irq();
#endif
   //profiler
   __kernel_profiler_start();
   //

   //1)process operation
   //pseudo process creation
   if(_nextpid(&pid)==-EAGAIN) {
      //kernel panic!!!
#ifdef KERNEL_PROCESS_VFORK_CLRSET_IRQ
      __set_irq();
#endif
      return (pid_t)-ENOMEM;
   }
   //dynamic allocation:alloc
   p = _sys_malloc(sizeof(process_t));
   if(!p) {
      //kernel panic!!!
#ifdef KERNEL_PROCESS_VFORK_CLRSET_IRQ
      __set_irq();
#endif
      return (pid_t)(-ENOMEM);
   }
   process_lst[pid] = (process_t*)p;
   memset(process_lst[pid],0,sizeof(process_t));
   //
   //_dbg_printf("fork _pid:%d\n",_pid);
   //copy all ppid father process properties to the son (pthread_ptr, ...)
   memcpy(process_lst[pid],process_lst[ppid],sizeof(process_t));

   //modify specific process properties of new process
   _sys_gettimeofday(&tv,NULL);
   process_lst[pid]->pid         = pid;
   process_lst[pid]->ppid        = ppid;
   process_lst[pid]->pgid        = process_lst[ppid]->pgid;
   process_lst[pid]->start_time  = tv.tv_sec;
   //prepare kernel object chained list (see _sys_krnl_exec() )
   process_lst[pid]->kernel_object_head = (kernel_object_t*)0;

   process_lst[pid]->inode_curdir = process_lst[ppid]->inode_curdir;

   //copy argument
   argc=0;
   process_lst[pid]->argc=0;

   process_lst[pid]->argv[argc]=strtok(process_lst[pid]->arg," ");
   while(process_lst[pid]->argv[argc++]) {
      process_lst[pid]->argv[argc]=strtok(0," ");
   }
   process_lst[pid]->argc=argc-1;

   //2)pthread operation
   backup_parent_pthread_ptr=(kernel_pthread_t*)_sys_malloc(sizeof(kernel_pthread_t));
   if(!backup_parent_pthread_ptr) {
      //
      _sys_free(process_lst[pid]);
      //kernel panic!!!
#ifdef KERNEL_PROCESS_VFORK_CLRSET_IRQ
      __set_irq();
#endif
      return -ENOMEM; //kernel panic!!!
   }

   //brutal copy parent pthread in new pthread
   memcpy(backup_parent_pthread_ptr,pthread_ptr,sizeof(kernel_pthread_t));
   //switch pthread_ptr
   process_lst[pid]->pthread_ptr=pthread_ptr;
   process_lst[pid]->pthread_ptr->parent_pthread_ptr = backup_parent_pthread_ptr;

   //back_up calling thread context in parent pthread
   __bckup_context(backup_parent_pthread_ptr->bckup_context,backup_parent_pthread_ptr);
   //back_up ppid  stack in parent pthread
   //must be placed after process_t allocation. heap external fragmentation.
   // see process.c _sys_exec and restore stack
   __bckup_stack(backup_parent_pthread_ptr);

   //to remove:
   _dbg_printf("vfork() pid:%d\n",pid);
   //attach thread with process
   process_lst[pid]->pthread_ptr->pid = pid;
   //reinit status
   process_lst[pid]->pthread_ptr->stat = PTHREAD_STATUS_NULL;
   //
   process_lst[pid]->pthread_ptr->time_out  = (time_t)-1; //for alarm()
   //retinit parent thread status
   process_lst[pid]->pthread_ptr->parent_pthread_ptr->stat |= PTHREAD_STATUS_FORK;

   //remove pthread from the pthread list of father process
   _sys_process_remove_pthread(process_lst[ppid],pthread_ptr);
   //reinit thread chain list in new process container
   process_lst[pid]->pthread_ptr->next = (kernel_pthread_t*)0; //(not need kernel_put_pthread_id() and kernel_get_pthread_id() operation)

   //to do: reinit sigqueue struct
   //thread sigqueue
#ifdef __KERNEL_POSIX_REALTIME_SIGNALS
   memcpy(&process_lst[pid]->pthread_ptr->kernel_sigqueue,&_kernel_sigqueue_initializer,sizeof(kernel_sigqueue_t));
   process_lst[pid]->pthread_ptr->kernel_sigqueue.constructor(&process_lst[pid]->kernel_object_head, &process_lst[pid]->pthread_ptr->kernel_sigqueue);
#endif

   //profiler
   __kernel_profiler_stop(backup_parent_pthread_ptr);
   __profiler_add_result(backup_parent_pthread_ptr,_SYSCALL_VFORK,__kernel_profiler_get_counter(backup_parent_pthread_ptr));
   //
#ifdef KERNEL_PROCESS_VFORK_CLRSET_IRQ
   __set_irq();
#endif

   return pid;
}
/*--------------------------------------------
| Name:        kernel_object_free
| Description:
| Parameters:  none
| Return Type: none
| Comments:
| See:
----------------------------------------------*/
int kernel_object_free(kernel_object_t* p){
   if(!p)
      return -1;
   _sys_free(p);
   return 0;
}