error_t timer_start (timer_handle_t _handle, msecond_t _duration, expiry_callback_t _cb, void *_arg) { interrupt_level_t level; if (null == _cb) { return ERROR_T (ERROR_TIMER_ALLOC_INVCB); } level = global_interrupt_disable (); if (is_invalid_handle (_handle)) { global_interrupt_enable (level); return ERROR_T (ERROR_TIMER_START_INVHANDLE); } if (TIMER_STARTED == _handle->state_) { g_statistics.abnormal_ ++; global_interrupt_enable (level); return ERROR_T (ERROR_TIMER_START_INVSTATE); } _handle->ticks_ = _duration / CONFIG_TICK_DURATION_IN_MSEC; if (0 == _handle->ticks_) { _handle->ticks_ ++; } _handle->callback_ = _cb; _handle->arg_ = _arg; global_interrupt_enable (level); timer_insert (_handle); return 0; }
static bool mutex_callback_unlock (sync_object_handle_t _handle, error_t *_p_ecode) { mutex_handle_t p_mutex = (mutex_handle_t) _handle; task_handle_t p_task = task_self (); // grab the mutex if (is_in_interrupt () || is_invalid_task (p_task)) { return ERROR_T (ERROR_MUTEX_INVCONTEXT); } if (p_mutex->owner_ != p_task) { *_p_ecode = ERROR_T (ERROR_MUTEX_NOTOWNER); return false; } if (p_mutex->reference_ > 0) { p_mutex->reference_ --; return true; } // restore owner's original priority if (p_mutex->inherited_) { p_mutex->inherited_ = false; task_priority_change (p_mutex->owner_, p_mutex->original_); } if (task_bitmap_is_empty (&p_mutex->object_.pending_bitmap_)) { // no task is pending on this mutex p_mutex->owner_ = null; return true; } return false; }
error_t device_write (device_handle_t _handle, const void *_buf, usize_t _size) { if (is_invalid_handle (_handle)) { return ERROR_T (ERROR_DEVICE_WRITE_INVHANDLE); } if (null == _handle->driver_->operation_.write_) { return ERROR_T (ERROR_DEVICE_WRITE_NOTSUPPORT); } return _handle->driver_->operation_.write_ (_handle, _buf, _size); }
error_t device_read (device_handle_t _handle, void *_buf, usize_t _size) { if (is_invalid_handle (_handle)) { return ERROR_T (ERROR_DEVICE_READ_INVHANDLE); } if (null == _handle->driver_->operation_.read_) { return ERROR_T (ERROR_DEVICE_READ_NOTSUPPORT); } return _handle->driver_->operation_.read_ (_handle, _buf, _size); }
error_t device_control (device_handle_t _handle, control_option_t _option, int _int_arg, void *_ptr_arg) { if (is_invalid_handle (_handle)) { return ERROR_T (ERROR_DEVICE_CONTROL_INVHANDLE); } if (null == _handle->driver_->operation_.control_) { return ERROR_T (ERROR_DEVICE_CONTROL_NOTSUPPORT); } return _handle->driver_->operation_.control_ (_handle, _option, _int_arg, _ptr_arg); }
error_t timer_stop (timer_handle_t _handle, msecond_t *_p_remained) { interrupt_level_t level; timer_handle_t next; bucket_t *p_bucket; level = global_interrupt_disable (); if (is_invalid_handle (_handle)) { global_interrupt_enable (level); return ERROR_T (ERROR_TIMER_STOP_INVHANDLE); } if (_handle->state_ != TIMER_STARTED) { g_statistics.abnormal_ ++; global_interrupt_enable (level); return ERROR_T (ERROR_TIMER_STOP_INVSTATE); } if (g_timer_next == _handle) { g_timer_next = (timer_handle_t) dll_next (&g_bucket_firing->dll_, &_handle->node_); } p_bucket = &g_buckets [_handle->bucket_index_]; if (_p_remained != null) { timer_remained_t remained = {_handle, 0}; (void) dll_traverse (&p_bucket->dll_, timer_calculate_remained, &remained); *_p_remained = remained.remained_round_ * CONFIG_MAX_BUCKET; if (g_cursor > _handle->bucket_index_) { *_p_remained = (*_p_remained) * CONFIG_MAX_BUCKET - (g_cursor - _handle->bucket_index_); } else { *_p_remained = (*_p_remained - 1) * CONFIG_MAX_BUCKET + (g_cursor - _handle->bucket_index_) + 1; } *_p_remained *= CONFIG_TICK_DURATION_IN_MSEC; } _handle->state_ = TIMER_STOPPED; next = (timer_handle_t)dll_next (&p_bucket->dll_, &_handle->node_); if (0 != next) { next->round_ += _handle->round_; } dll_remove (&p_bucket->dll_, &_handle->node_); dll_push_tail (&g_inactive_timer, &_handle->node_); if (p_bucket->reentrance_ > 0) { p_bucket->level_ ++; } global_interrupt_enable (level); return 0; }
error_t event_send (task_handle_t _handle, event_set_t _sent) { interrupt_level_t level; bool wakeup_needed = false; level = global_interrupt_disable (); if (is_invalid_task (_handle)) { global_interrupt_enable (level); return ERROR_T (ERROR_EVENT_RECV_INVRECEIVER); } _handle->event_received_ |= _sent; if (0 == (int)_handle->event_option_) { global_interrupt_enable (level); return 0; } if (EVENT_WAIT_ALL == (_handle->event_option_ & EVENT_WAIT_ALL)) { if ((_handle->event_expected_ & _handle->event_received_) == _handle->event_expected_) { wakeup_needed = true; } } else { if ((_handle->event_expected_ & _handle->event_received_) != 0) { wakeup_needed = true; } } if (!wakeup_needed) { global_interrupt_enable (level); return 0; } (void) task_state_change (_handle, TASK_STATE_READY); global_interrupt_enable (level); task_schedule (null); return 0; }
error_t timer_free (timer_handle_t _handle) { interrupt_level_t level; level = global_interrupt_disable (); if (is_invalid_handle (_handle)) { global_interrupt_enable (level); return ERROR_T (ERROR_TIMER_FREE_INVHANDLE); } if (TIMER_STARTED == _handle->state_) { timer_handle_t next; bucket_t *p_bucket = &g_buckets [_handle->bucket_index_]; if (g_timer_next == _handle) { g_timer_next = (timer_handle_t) dll_next (&g_bucket_firing->dll_, &_handle->node_); } next = (timer_handle_t)dll_next (&p_bucket->dll_, &_handle->node_); if (0 != next) { next->round_ += _handle->round_; } dll_remove (&p_bucket->dll_, &_handle->node_); if (p_bucket->reentrance_ > 0) { g_bucket_firing->level_ ++; } } else { dll_remove (&g_inactive_timer, &_handle->node_); } _handle->magic_number_ = 0; dll_push_tail (&g_free_timer, &_handle->node_); global_interrupt_enable (level); return 0; }
error_t device_open (device_handle_t *_p_handle, const char _name [], open_mode_t _mode) { int idx; driver_handle_t p_driver = null; const char *p_name; device_handle_t handle; error_t ecode; if (null == _name) { return ERROR_T (ERROR_DEVICE_OPEN_INVNAME); } // find the driver for the device for (idx = 0; idx <= DRIVER_LAST_INDEX; idx ++) { if ((MAGIC_NUMBER_DRIVER == g_driver_pool [idx].magic_number_) && (0 == strncmp (g_driver_pool [idx].name_, _name, strlen (g_driver_pool [idx].name_)))) { p_driver = &g_driver_pool [idx]; break; } } if (null == p_driver) { return ERROR_T (ERROR_DEVICE_OPEN_NODRV); } // strip the driver name from device name before passing it into the device // open () operation p_name = &_name [strlen (p_driver->name_)]; // find the device handle = (device_handle_t) dll_traverse (&p_driver->devices_, device_find, (void *)p_name); if (0 == handle) { return ERROR_T (ERROR_DEVICE_OPEN_NODEV); } // we don't need to consider race condition for calling driver's open () // operation, intead, the specific device driver should be responsible. ecode = p_driver->operation_.open_ (handle, _mode); if (0 == ecode) { interrupt_level_t level = global_interrupt_disable (); p_driver->count_opened_ ++; global_interrupt_enable (level); *_p_handle = handle; } return ecode; }
error_t timer_alloc (timer_handle_t *_p_handle, const char *_name, timer_type_t _type) { interrupt_level_t level; static bool initialized = false; timer_handle_t handle; if (0 == _p_handle) { return ERROR_T (ERROR_TIMER_ALLOC_INVHANDLE); } *_p_handle = null; level = global_interrupt_disable (); if (!initialized) { timer_init (); initialized = true; } handle = (timer_handle_t)dll_pop_head (&g_free_timer); if (0 == handle) { g_statistics.notimer_ ++; global_interrupt_enable (level); return ERROR_T (ERROR_TIMER_ALLOC_NOTIMER); } global_interrupt_enable (level); handle->type_ = _type; handle->magic_number_ = MAGIC_NUMBER_TIMER; handle->state_ = TIMER_CREATED; dll_node_init (&handle->node_); if (0 == _name) { handle->name_ [0] = 0; } else { strncpy (handle->name_, _name, (usize_t)sizeof (handle->name_)); handle->name_ [sizeof (handle->name_) - 1] = 0; } level = global_interrupt_disable (); dll_push_tail (&g_inactive_timer, &handle->node_); global_interrupt_enable (level); *_p_handle = handle; return 0; }
error_t driver_install (const char _name [], const device_operation_t *_p_operation, device_mode_t _mode) { int idx; driver_handle_t p_driver = null; const char *dev_root = "/dev/"; if ((null == _name) || (strncmp (_name, dev_root, strlen (dev_root)) != 0)) { // a driver has no name? return ERROR_T (ERROR_DRIVER_INVNAME); } if (null == _p_operation || null == _p_operation->open_ || null == _p_operation->close_) { return ERROR_T (ERROR_DRIVER_INVOPT); } // a driver only can be installed before system is UP if (system_state () > STATE_INITIALIZING) { return ERROR_T (ERROR_DRIVER_INVSTATE); } // check whether the driver is already installed for (idx = 0; idx <= DRIVER_LAST_INDEX; idx ++) { if ((MAGIC_NUMBER_DRIVER == g_driver_pool [idx].magic_number_) && (0 == strncmp (g_driver_pool [idx].name_, _name, strlen (_name)))) { return ERROR_T (ERROR_DRIVER_INSTALLED); } } for (idx = 0; idx <= DRIVER_LAST_INDEX; idx ++) { if (g_driver_pool [idx].magic_number_ != MAGIC_NUMBER_DRIVER) { p_driver = &g_driver_pool [idx]; break; } } if (null == p_driver) { return ERROR_T (ERROR_DRIVER_NODRV); } p_driver->magic_number_ = MAGIC_NUMBER_DRIVER; p_driver->operation_ = *_p_operation; p_driver->mode_ = _mode; strncpy (p_driver->name_, _name, sizeof (p_driver->name_) - 1); p_driver->name_ [sizeof (p_driver->name_) - 1] = 0; dll_init (&p_driver->devices_); return 0; }
error_t timer_restart (timer_handle_t _handle) { interrupt_level_t level; level = global_interrupt_disable (); if (is_invalid_handle (_handle)) { global_interrupt_enable (level); return ERROR_T (ERROR_TIMER_RESTART_INVHANDLE); } if (TIMER_STOPPED != _handle->state_) { g_statistics.abnormal_ ++; global_interrupt_enable (level); return ERROR_T (ERROR_TIMER_RESTART_INVSTATE); } global_interrupt_enable (level); timer_insert (_handle); return 0; }
error_t device_register (const char _name [], device_handle_t _handle) { int idx; driver_handle_t p_driver = null; const char *p_name; if (null == _name) { // a device has no name? return ERROR_T (ERROR_DEVICE_REGISTER_INVNAME); } if (null == _handle) { return ERROR_T (ERROR_DEVICE_REGISTER_INVHANDLE); } // a device only can be registered before system is UP if (system_state () > STATE_INITIALIZING) { return ERROR_T (ERROR_DRIVER_INVSTATE); } // find the driver for the device for (idx = 0; idx <= DRIVER_LAST_INDEX; idx ++) { if ((MAGIC_NUMBER_DRIVER == g_driver_pool [idx].magic_number_) && (0 == strncmp (g_driver_pool [idx].name_, _name, strlen (g_driver_pool [idx].name_)))) { p_driver = &g_driver_pool [idx]; break; } } if (null == p_driver) { return ERROR_T (ERROR_DEVICE_REGISTER_NODRV); } if (_handle->interrupt_vector_ != INTERRUPT_NONE) { g_interrupt_map [_handle->interrupt_vector_] = _handle; } _handle->driver_ = p_driver; // strip the driver name from device name before passing it into the device // open () operation p_name = &_name [strlen (p_driver->name_)]; strncpy (_handle->name_, p_name, sizeof (_handle->name_) - 1); _handle->name_ [sizeof (_handle->name_) - 1] = 0; _handle->magic_number_ = MAGIC_NUMBER_DEVICE; dll_push_tail (&p_driver->devices_, &_handle->node_); return 0; }
static error_t clock_open (device_handle_t _handle, open_mode_t _mode) { clock_handle_t handle = (clock_handle_t)_handle; UNUSED (_mode); if (handle->is_opened_) { return ERROR_T (ERROR_CLOCK_OPEN_OPENED); } handle->is_opened_ = true; return 0; }
error_t event_clear () { interrupt_level_t level; task_handle_t p_task = task_self (); level = global_interrupt_disable (); if (is_invalid_task (p_task)) { global_interrupt_enable (level); return ERROR_T (ERROR_EVENT_CLEAR_INVCONTEXT); } p_task->event_received_ = 0; global_interrupt_enable (level); return 0; }
static error_t ctrlc_open (device_handle_t _handle, open_mode_t _mode) { ctrlc_handle_t handle = (ctrlc_handle_t)_handle; UNUSED (_mode); if (handle->is_opened_) { return ERROR_T (ERROR_CTRLC_OPEN_OPENED); } handle->is_opened_ = true; interrupt_enable (_handle->interrupt_vector_); console_print ("\nInfo: press Ctrl+C to terminate!\n"); return 0; }
error_t device_close (device_handle_t _handle) { error_t ecode; if (is_invalid_handle (_handle)) { return ERROR_T (ERROR_DEVICE_CLOSE_INVHANDLE); } ecode = _handle->driver_->operation_.close_ (_handle); if (0 == ecode) { interrupt_level_t level = global_interrupt_disable (); _handle->driver_->count_opened_ --; global_interrupt_enable (level); } return ecode; }
//lint -e{818} static error_t clock_control (device_handle_t _handle, control_option_t _option, int _int_arg, void *_ptr_arg) { clock_handle_t handle = (clock_handle_t)_handle; switch (_option) { case OPTION_TICK_START: { struct itimerval tv; //lint -e{611} handle->tick_process_ = (interrupt_handler_t) _ptr_arg; tv.it_value.tv_sec = 0; tv.it_value.tv_usec = (long) _int_arg*1000; // msec to usec tv.it_interval.tv_sec = 0; tv.it_interval.tv_usec = (long) _int_arg*1000; // msec to usec (void) setitimer (ITIMER_REAL, &tv, 0); interrupt_enable (_handle->interrupt_vector_); } break; case OPTION_TICK_STOP: { struct itimerval tv; struct sigaction act; interrupt_disable (_handle->interrupt_vector_); memset (&act, 0, sizeof(act)); act.sa_handler = SIG_IGN; (void) sigaction (SIGALRM, &act, 0); memset (&tv, 0, sizeof(tv)); (void) setitimer (ITIMER_REAL, &tv, 0); } break; default: return ERROR_T (ERROR_CLOCK_CONTROL_INVOPT); } return 0; }
error_t event_receive (event_set_t _expected, event_set_handle_t _received, msecond_t _timeout, event_option_t _option) { interrupt_level_t level; event_option_t wait_option = EVENT_WAIT_ALL | EVENT_WAIT_ANY; event_option_t return_option = EVENT_RETURN_ALL | EVENT_RETURN_EXPECTED; task_handle_t p_task; if (is_in_interrupt ()) { return ERROR_T (ERROR_EVENT_RECV_INVCONTEXT); } if (0 == _expected) { return 0; } if (null == _received) { return ERROR_T (ERROR_EVENT_RECV_INVPTR); } if ((wait_option == (wait_option & _option)) || (0 == (int)(wait_option & _option)) || (return_option == (return_option & _option)) || (0 == (int)(return_option & _option))) { return ERROR_T (ERROR_EVENT_RECV_INVOPT); } level = global_interrupt_disable (); p_task = task_self (); if (is_invalid_task (p_task)) { global_interrupt_enable (level); return ERROR_T (ERROR_EVENT_RECV_INVCONTEXT); } again: // if expected event(s) is/are available, return it if (EVENT_WAIT_ALL == (_option & EVENT_WAIT_ALL)) { if ((_expected & p_task->event_received_) == _expected) { if (EVENT_RETURN_ALL == (_option & EVENT_RETURN_ALL)) { *_received = p_task->event_received_; } else { *_received = _expected; p_task->event_received_ &= ~(*_received); } global_interrupt_enable (level); return 0; } } else { if ((_expected & p_task->event_received_) != 0) { if (EVENT_RETURN_ALL == (_option & EVENT_RETURN_ALL)) { *_received = p_task->event_received_; } else { *_received = _expected & p_task->event_received_; p_task->event_received_ &= ~(*_received); } global_interrupt_enable (level); return 0; } } // run here it means we need to block the task p_task->timeout_ = _timeout; (void) task_state_change (p_task, TASK_STATE_WAITING); p_task->ecode_ = 0; p_task->event_expected_ = _expected; p_task->event_option_ = _option; global_interrupt_enable (level); task_schedule (null); level = global_interrupt_disable (); p_task->event_option_ = (event_option_t) 0; if (0 == p_task->ecode_) { // event(s) has/have received and need to return the event(s) expected goto again; } global_interrupt_enable (level); //lint -e{650} if (ERROR_TASK_WAIT_TIMEOUT == MODULE_ERROR (p_task->ecode_)) { p_task->ecode_ = ERROR_T (ERROR_EVENT_RECV_TIMEOUT); } return p_task->ecode_; }
static err_t gpio_init(Drive_Gpio *t) { Drive_Gpio *cthis = ( Drive_Gpio *)t ; uint32_t tmp_reg = 0; gpio_cfg *config = cthis->config; int i = 0; assert( config->intr_line < 2); cthis->gpio_vbase = mmap_device_io( AM335X_GPIO_SIZE, GpioBase[ config->pin_group]); #ifdef DEBUG_GPIO TRACE_INFO("Drive Piling :%s-%s-%d \r\n", __FILE__, __func__, __LINE__); TRACE_INFO("pin config 0x%04x \r\n", rd_pin_conf( config->pin_ctrl_off)); return EXIT_SUCCESS; #else if (cthis->gpio_vbase == MAP_DEVICE_FAILED) { return ERROR_T( gpio_init_mapio_fail); } gpioModuleConfig[ config->pin_group](); GPIOModuleEnable( cthis->gpio_vbase); //配置引脚方向为输入 tmp_reg = in32( cthis->gpio_vbase + GPIO_OE ); tmp_reg |= 1 << config->pin_number; out32( cthis->gpio_vbase + GPIO_OE, tmp_reg ); //使能消抖 tmp_reg=in32( cthis->gpio_vbase + GPIO_DEBOUNCENABLE); tmp_reg &=~( 1 << config->pin_number); tmp_reg |= ( 1 << config->pin_number); out32( cthis->gpio_vbase + GPIO_DEBOUNCENABLE, tmp_reg); //消抖时间 out32( cthis->gpio_vbase + GPIO_DEBOUNCINGTIME, ( config->debou_time )); //配置中断监测类型 for( i = 0; i < 4; i ++) { if( ( ( 1 << i) & config->intr_type) ) { //使能该类型 tmp_reg = in32( cthis->gpio_vbase + GPIO_DETECT(i)); tmp_reg |= 1 << config->pin_number; out32(cthis->gpio_vbase + GPIO_DETECT(i), tmp_reg); } else { //禁止其他类型 tmp_reg = in32( cthis->gpio_vbase + GPIO_DETECT(i)); tmp_reg &= ~(1 << config->pin_number); out32(cthis->gpio_vbase + GPIO_DETECT(i), tmp_reg); } } //使能引脚中断 // tmp_reg = in32( cthis->gpio_vbase + GPIO_IRQSTATUS_SET( config->intr_line)); // tmp_reg |= 1 << config->pin_number; // out32(cthis->gpio_vbase + GPIO_IRQSTATUS_SET( config->intr_line), tmp_reg); #ifdef DEBUG_GPIO dump_gpio_reg( cthis->gpio_vbase); #endif SIGEV_INTR_INIT( &cthis->isr_event ); cthis->irq_id = InterruptAttach_r ( GpioIntNum[ config->intr_line][ config->pin_group], gpioExtInteIsr, cthis, 1, _NTO_INTR_FLAGS_END ); return EXIT_SUCCESS; #endif }