static void dw_dma_isr(void *arg) { struct device *dev = (struct device *)arg; const struct dw_dma_dev_cfg *const dev_cfg = DEV_CFG(dev); struct dw_dma_dev_data *const dev_data = DEV_DATA(dev); struct dma_chan_data *chan_data; u32_t status_tfr = 0; u32_t status_block = 0; u32_t status_err = 0; u32_t status_intr; u32_t channel; status_intr = dw_read(dev_cfg->base, DW_INTR_STATUS); if (!status_intr) { SYS_LOG_ERR("status_intr = %d", status_intr); } /* get the source of our IRQ. */ status_block = dw_read(dev_cfg->base, DW_STATUS_BLOCK); status_tfr = dw_read(dev_cfg->base, DW_STATUS_TFR); /* TODO: handle errors, just clear them atm */ status_err = dw_read(dev_cfg->base, DW_STATUS_ERR); if (status_err) { SYS_LOG_ERR("status_err = %d\n", status_err); dw_write(dev_cfg->base, DW_CLEAR_ERR, status_err); } /* clear interrupts */ dw_write(dev_cfg->base, DW_CLEAR_BLOCK, status_block); dw_write(dev_cfg->base, DW_CLEAR_TFR, status_tfr); /* Dispatch ISRs for channels depending upon the bit set */ while (status_block) { channel = find_lsb_set(status_block) - 1; status_block &= ~(1 << channel); chan_data = &dev_data->chan[channel]; if (chan_data->dma_blkcallback) { /* Ensure the linked list (chan_data->lli) is * freed in the user callback function once * all the blocks are transferred. */ chan_data->dma_blkcallback(dev, channel, 0); } } while (status_tfr) { channel = find_lsb_set(status_tfr) - 1; status_tfr &= ~(1 << channel); chan_data = &dev_data->chan[channel]; k_free(chan_data->lli); chan_data->lli = NULL; if (chan_data->dma_tfrcallback) { chan_data->dma_tfrcallback(dev, channel, 0); } } }
/** * * @brief Set the number of priority groups based on the number of exception * priorities desired * * Exception priorities can be divided in priority groups, inside which there is * no preemption. The priorities inside a group are only used to decide which * exception will run when more than one is ready to be handled. * * The number of priorities has to be a power of two, from 1 to 128. * * @param n the number of priorities * * @return N/A */ void _ScbNumPriGroupSet(unsigned int n) { unsigned int set; union __aircr reg; __ASSERT(is_power_of_two(n) && (n <= 128), "invalid number of priorities"); set = find_lsb_set(n); reg.val = __scs.scb.aircr.val; /* num pri bit set prigroup * --------------------------------- * 1 1 7 * 2 2 6 * 4 3 5 * 8 4 4 * 16 5 3 * 32 6 2 * 64 7 1 * 128 8 0 */ reg.bit.prigroup = 8 - set; reg.bit.vectkey = SCB_AIRCR_VECTKEY_EN_W; __scs.scb.aircr.val = reg.val; }
/** * * @brief Select task to be executed by microkernel * * Locates that highest priority task queue that is non-empty and chooses the * task at the head of that queue. It's guaranteed that there will always be * a non-empty queue, since the idle task is always executable. * * @return pointer to selected task */ static struct k_task *next_task_select(void) { int K_PrioListIdx; #if (CONFIG_NUM_TASK_PRIORITIES <= 32) K_PrioListIdx = find_lsb_set(_k_task_priority_bitmap[0]) - 1; #else int bit_map; int set_bit_pos; K_PrioListIdx = -1; for (bit_map = 0; ; bit_map++) { set_bit_pos = find_lsb_set(_k_task_priority_bitmap[bit_map]); if (set_bit_pos) { K_PrioListIdx += set_bit_pos; break; } K_PrioListIdx += 32; } #endif return _k_task_priority_list[K_PrioListIdx].head; }
/** * @brief Find the currently executing interrupt vector, if any * * This routine finds the vector of the interrupt that is being processed. * The ISR (In-Service Register) register contain the vectors of the interrupts * in service. And the higher vector is the indentification of the interrupt * being currently processed. * * ISR registers' offsets: * -------------------- * | Offset | bits | * -------------------- * | 0100H | 0:31 | * | 0110H | 32:63 | * | 0120H | 64:95 | * | 0130H | 96:127 | * | 0140H | 128:159 | * | 0150H | 160:191 | * | 0160H | 192:223 | * | 0170H | 224:255 | * -------------------- * * @return The vector of the interrupt that is currently being processed. */ int _loapic_isr_vector_get(void) { /* pointer to ISR vector table */ volatile int *pReg; int block = 0; while (block < 8) { pReg = (volatile int *) (CONFIG_LOAPIC_BASE_ADDRESS + LOAPIC_ISR + (block * 0x10)); if (*pReg) { return (block * 32) + (find_lsb_set(*pReg) - 1); } block++; } return 0; }
int _IntVecAlloc(unsigned int requested_priority) { unsigned int key; unsigned int entryToScan; unsigned int fsb; /* first set bit in entry */ unsigned int search_set; int vector_block; int vector; static unsigned int mask[2] = {0x0000ffff, 0xffff0000}; vector_block = requested_priority + 2; __ASSERT(((vector_block << 4) + 15) <= CONFIG_IDT_NUM_VECTORS, "IDT too small (%d entries) to use priority %d", CONFIG_IDT_NUM_VECTORS, requested_priority); /* * Atomically allocate a vector from the _interrupt_vectors_allocated[] * array to prevent race conditions with other tasks/fibers attempting * to allocate an interrupt vector. * * Note: As _interrupt_vectors_allocated[] is initialized by the 'gen_idt' * tool, it is critical that this routine use the same algorithm as the * 'gen_idt' tool for allocating interrupt vectors. */ entryToScan = vector_block >> 1; /* * The _interrupt_vectors_allocated[] entry indexed by 'entryToScan' is a * 32-bit quantity and thus represents the vectors for a pair of priority * levels. Mask out the unwanted priority level and then use find_lsb_set() * to scan for an available vector of the requested priority. * * Note that find_lsb_set() returns bit position from 1 to 32, * or 0 if the argument is zero. */ key = irq_lock(); search_set = mask[vector_block & 1] & _interrupt_vectors_allocated[entryToScan]; fsb = find_lsb_set(search_set); __ASSERT(fsb != 0, "No remaning vectors for priority level %d", requested_priority); /* * An available vector of the requested priority was found. * Mark it as allocated. */ --fsb; _interrupt_vectors_allocated[entryToScan] &= ~(1 << fsb); irq_unlock(key); /* compute vector given allocated bit within the priority level */ vector = (entryToScan << 5) + fsb; return vector; }
static int start_read(struct device *dev, const struct adc_sequence *sequence) { const struct adc_stm32_cfg *config = dev->config->config_info; struct adc_stm32_data *data = dev->driver_data; ADC_TypeDef *adc = (ADC_TypeDef *)config->base; u8_t resolution; int err; switch (sequence->resolution) { #if !defined(CONFIG_SOC_SERIES_STM32F1X) case 6: resolution = table_resolution[0]; break; case 8: resolution = table_resolution[1]; break; case 10: resolution = table_resolution[2]; break; #endif case 12: resolution = table_resolution[3]; break; default: LOG_ERR("Invalid resolution"); return -EINVAL; } u32_t channels = sequence->channels; data->buffer = sequence->buffer; u8_t index; index = find_lsb_set(channels) - 1; u32_t channel = __LL_ADC_DECIMAL_NB_TO_CHANNEL(index); #if defined(CONFIG_SOC_SERIES_STM32F0X) || \ defined(CONFIG_SOC_SERIES_STM32L0X) LL_ADC_REG_SetSequencerChannels(adc, channel); #else LL_ADC_REG_SetSequencerRanks(adc, table_rank[0], channel); LL_ADC_REG_SetSequencerLength(adc, table_seq_len[0]); #endif data->channel_count = 1; err = check_buffer_size(sequence, data->channel_count); if (err) { return err; } #if !defined(CONFIG_SOC_SERIES_STM32F1X) LL_ADC_SetResolution(adc, resolution); #endif #if defined(CONFIG_SOC_SERIES_STM32F0X) || \ defined(CONFIG_SOC_SERIES_STM32F3X) || \ defined(CONFIG_SOC_SERIES_STM32L0X) || \ defined(CONFIG_SOC_SERIES_STM32L4X) LL_ADC_EnableIT_EOC(adc); #elif defined(CONFIG_SOC_SERIES_STM32F1X) LL_ADC_EnableIT_EOS(adc); #else LL_ADC_EnableIT_EOCS(adc); #endif adc_context_start_read(&data->ctx, sequence); return adc_context_wait_for_completion(&data->ctx); }
int pci_legacy_bridge_detect(struct pci_dev_info *dev_info) { union pci_addr_reg pci_ctrl_addr; static union pci_dev pci_dev_header; u32_t pci_data; /* temporary data to read */ u32_t rcba; /* root complex base address */ u32_t rcba_mask; /* bits set for RCBA */ /* initialise the PCI controller address register value */ pci_ctrl_addr.value = 0; pci_ctrl_addr.field.bus = CONFIG_PCI_LEGACY_BRIDGE_BUS; pci_ctrl_addr.field.device = CONFIG_PCI_LEGACY_BRIDGE_DEV; /* verify first if there is a valid device at this point */ pci_ctrl_addr.field.func = 0; pci_read(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr, sizeof(pci_data), &pci_data); if (pci_data == 0xffffffff) { return -1; } /* get the PCI header from the device */ pci_header_get(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr, &pci_dev_header); if (pci_dev_header.field.vendor_id != CONFIG_PCI_LEGACY_BRIDGE_VENDOR_ID || pci_dev_header.field.device_id != CONFIG_PCI_LEGACY_BRIDGE_DEVICE_ID) { return -1; } pci_ctrl_addr.field.reg = PCI_LEGACY_BRIDGE_REG; /* read RCBA PCI register */ pci_read(DEFAULT_PCI_CONTROLLER, pci_ctrl_addr, sizeof(rcba), &rcba); if (pci_rcba_mask_get(pci_ctrl_addr, &rcba_mask) != 0) { return -1; } dev_info->addr = rcba & rcba_mask; if (dev_info->addr != 0) { /* calculate the size of the root complex memory required */ dev_info->size = 1 << (find_lsb_set(rcba_mask) - 1); } dev_info->irq = -1; dev_info->bus = CONFIG_PCI_LEGACY_BRIDGE_BUS; dev_info->dev = CONFIG_PCI_LEGACY_BRIDGE_DEV; dev_info->function = 0; dev_info->mem_type = BAR_SPACE_MEM; dev_info->class_type = pci_dev_header.field.class; dev_info->bar = 0; dev_info->vendor_id = pci_dev_header.field.vendor_id; dev_info->device_id = pci_dev_header.field.device_id; return 0; }
int _IntVecAlloc(unsigned int priority) { unsigned int key; unsigned int entryToScan; unsigned int fsb; /* first set bit in entry */ unsigned int search_set; int vector; static unsigned int mask[2] = {0x0000ffff, 0xffff0000}; #if defined(DEBUG) /* * check whether the IDT was configured with sufficient vectors to * satisfy the priority request. */ if (((priority << 4) + 15) > CONFIG_IDT_NUM_VECTORS) return (-1); #endif /* DEBUG */ /* * Atomically allocate a vector from the _interrupt_vectors_allocated[] * array to prevent race conditions with other tasks/fibers attempting * to allocate an interrupt vector. * * Note: As _interrupt_vectors_allocated[] is initialized by the 'gen_idt' * tool, it is critical that this routine use the same algorithm as the * 'gen_idt' tool for allocating interrupt vectors. */ entryToScan = priority >> 1; /* * The _interrupt_vectors_allocated[] entry indexed by 'entryToScan' is a * 32-bit quantity and thus represents the vectors for a pair of priority * levels. Mask out the unwanted priority level and then use find_lsb_set() * to scan for an available vector of the requested priority. * * Note that find_lsb_set() returns bit position from 1 to 32, * or 0 if the argument is zero. */ key = irq_lock(); search_set = mask[priority & 1] & _interrupt_vectors_allocated[entryToScan]; fsb = find_lsb_set(search_set); #if defined(DEBUG) if (fsb == 0) { /* All vectors for this priority have been allocated. */ irq_unlock(key); return (-1); } #endif /* DEBUG */ /* * An available vector of the requested priority was found. * Mark it as allocated. */ --fsb; _interrupt_vectors_allocated[entryToScan] &= ~(1 << fsb); irq_unlock(key); /* compute vector given allocated bit within the priority level */ vector = (entryToScan << 5) + fsb; return vector; }