Exemplo n.º 1
0
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);
		}
	}
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
/**
 *
 * @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;
}
Exemplo n.º 4
0
/**
 * @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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
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;
}