mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-11-16 12:34:45 +00:00
Compare commits
10 Commits
contrib/bs
...
5.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61ccb9c05d | ||
|
|
7661402bc2 | ||
|
|
5284e812e2 | ||
|
|
e95c00a79e | ||
|
|
95036a4591 | ||
|
|
534f9dbe13 | ||
|
|
4a2ac5ef8d | ||
|
|
5eb0773159 | ||
|
|
849d741832 | ||
|
|
a1f9265c03 |
@@ -24,44 +24,85 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The SC16IS752 device context.
|
||||||
|
*
|
||||||
|
* All members are private to the device driver.
|
||||||
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
sc16is752_spi_context base;
|
sc16is752_spi_context base;
|
||||||
Pin irq_pin;
|
Pin irq_pin;
|
||||||
rtems_interrupt_server_entry irqs_entry; /* Internal. Don't touch. */
|
rtems_interrupt_server_entry irqs_entry;
|
||||||
rtems_interrupt_server_action irqs_action; /* Internal. Don't touch. */
|
rtems_interrupt_server_action irqs_action;
|
||||||
|
uint32_t irqs_index;
|
||||||
} atsam_sc16is752_spi_context;
|
} atsam_sc16is752_spi_context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The SC16IS752 device configuration.
|
||||||
|
*
|
||||||
|
* @see atsam_sc16is752_spi_create().
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* @brief The device file path for the new device.
|
||||||
|
*/
|
||||||
|
const char *device_path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The SC16IS752 mode.
|
||||||
|
*/
|
||||||
|
sc16is752_mode mode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The input frequency in Hertz of the SC16IS752 chip. See XTAL1 and
|
||||||
|
* XTAL2 pins.
|
||||||
|
*/
|
||||||
|
uint32_t input_frequency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The SPI bus device path.
|
||||||
|
*/
|
||||||
|
const char *spi_path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The SPI chip select (starts with 0, the SPI driver uses
|
||||||
|
* SPI_ChipSelect(1 << spi_chip_select)).
|
||||||
|
*/
|
||||||
|
uint8_t spi_chip_select;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The SPI bus speed in Hertz.
|
||||||
|
*/
|
||||||
|
uint32_t spi_speed_hz;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The interrupt pin, e.g. { PIO_PD28, PIOD, ID_PIOD, PIO_INPUT,
|
||||||
|
* PIO_IT_LOW_LEVEL }.
|
||||||
|
*/
|
||||||
|
const Pin irq_pin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The index to identify the interrupt server used for interrupt
|
||||||
|
* processing.
|
||||||
|
*/
|
||||||
|
uint32_t server_index;
|
||||||
|
} atsam_sc16is752_spi_config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates an SPI connected SC16IS752 device.
|
* @brief Creates an SPI connected SC16IS752 device.
|
||||||
*
|
*
|
||||||
* This devices uses the interrupt server, see
|
* This devices uses the interrupt server, see rtems_interrupt_server_create().
|
||||||
* rtems_interrupt_server_initialize().
|
|
||||||
*
|
*
|
||||||
* The device claims the interrupt of the PIO block.
|
* The device claims the interrupt of the PIO block.
|
||||||
*
|
*
|
||||||
* @param[in] ctx The device context. May have an arbitrary content.
|
* @param[out] ctx is the device context. It may have an arbitrary content.
|
||||||
* @param[in] device_path The device file path for the new device.
|
* @param config is the device configuration.
|
||||||
* @param[in] mode The SC16IS752 mode.
|
|
||||||
* @param[in] input_frequency The input frequency in Hertz of the SC16IS752
|
|
||||||
* chip. See XTAL1 and XTAL2 pins.
|
|
||||||
* @param[in] spi_path The SPI bus device path.
|
|
||||||
* @param[in] spi_chip_select The SPI chip select (starts with 0, the SPI
|
|
||||||
* driver uses SPI_ChipSelect(1 << spi_chip_select)).
|
|
||||||
* @param[in] spi_speed_hz The SPI bus speed in Hertz.
|
|
||||||
* @param[in] irq_pin The interrupt pin, e.g. { PIO_PD28, PIOD, ID_PIOD,
|
|
||||||
* PIO_INPUT, PIO_IT_LOW_LEVEL }.
|
|
||||||
*
|
*
|
||||||
* @return See sc16is752_spi_create().
|
* @return See sc16is752_spi_create().
|
||||||
*/
|
*/
|
||||||
int atsam_sc16is752_spi_create(
|
int atsam_sc16is752_spi_create(
|
||||||
atsam_sc16is752_spi_context *ctx,
|
atsam_sc16is752_spi_context *ctx,
|
||||||
const char *device_path,
|
const atsam_sc16is752_spi_config *config
|
||||||
sc16is752_mode mode,
|
|
||||||
uint32_t input_frequency,
|
|
||||||
const char *spi_path,
|
|
||||||
uint8_t spi_chip_select,
|
|
||||||
uint32_t spi_speed_hz,
|
|
||||||
const Pin *irq_pin
|
|
||||||
);
|
);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ static bool atsam_sc16is752_install_interrupt(sc16is752_context *base)
|
|||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
uint8_t rv;
|
uint8_t rv;
|
||||||
|
|
||||||
sc = rtems_interrupt_server_entry_initialize(RTEMS_INTERRUPT_SERVER_DEFAULT,
|
sc = rtems_interrupt_server_entry_initialize(ctx->irqs_index,
|
||||||
&ctx->irqs_entry);
|
&ctx->irqs_entry);
|
||||||
rtems_interrupt_server_action_prepend(&ctx->irqs_entry,
|
rtems_interrupt_server_action_prepend(&ctx->irqs_entry,
|
||||||
&ctx->irqs_action, atsam_sc16i752_irqs_handler, ctx);
|
&ctx->irqs_action, atsam_sc16i752_irqs_handler, ctx);
|
||||||
@@ -64,24 +64,19 @@ static void atsam_sc16is752_remove_interrupt(sc16is752_context *base)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int atsam_sc16is752_spi_create(
|
int atsam_sc16is752_spi_create(
|
||||||
atsam_sc16is752_spi_context *ctx,
|
atsam_sc16is752_spi_context *ctx,
|
||||||
const char *device_path,
|
const atsam_sc16is752_spi_config *config
|
||||||
sc16is752_mode mode,
|
|
||||||
uint32_t input_frequency,
|
|
||||||
const char *spi_path,
|
|
||||||
uint8_t spi_chip_select,
|
|
||||||
uint32_t spi_speed_hz,
|
|
||||||
const Pin *irq_pin
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ctx->base.base.mode = mode;
|
ctx->base.base.mode = config->mode;
|
||||||
ctx->base.base.input_frequency = input_frequency;
|
ctx->base.base.input_frequency = config->input_frequency;
|
||||||
ctx->base.base.install_irq = atsam_sc16is752_install_interrupt;
|
ctx->base.base.install_irq = atsam_sc16is752_install_interrupt;
|
||||||
ctx->base.base.remove_irq = atsam_sc16is752_remove_interrupt;
|
ctx->base.base.remove_irq = atsam_sc16is752_remove_interrupt;
|
||||||
ctx->base.spi_path = spi_path;
|
ctx->base.spi_path = config->spi_path;
|
||||||
ctx->base.cs = spi_chip_select;
|
ctx->base.cs = config->spi_chip_select;
|
||||||
ctx->base.speed_hz = spi_speed_hz;
|
ctx->base.speed_hz = config->spi_speed_hz;
|
||||||
ctx->irq_pin = *irq_pin;
|
ctx->irq_pin = config->irq_pin;
|
||||||
|
ctx->irqs_index = config->server_index;
|
||||||
|
|
||||||
return sc16is752_spi_create(&ctx->base, device_path);
|
return sc16is752_spi_create(&ctx->base, config->device_path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,6 +122,8 @@ void zynq_uart_initialize(rtems_termios_device_context *base)
|
|||||||
uint32_t brgr = 0x3e;
|
uint32_t brgr = 0x3e;
|
||||||
uint32_t bauddiv = 0x6;
|
uint32_t bauddiv = 0x6;
|
||||||
|
|
||||||
|
zynq_uart_reset_tx_flush(ctx);
|
||||||
|
|
||||||
zynq_cal_baud_rate(ZYNQ_UART_DEFAULT_BAUD, &brgr, &bauddiv, regs->mode);
|
zynq_cal_baud_rate(ZYNQ_UART_DEFAULT_BAUD, &brgr, &bauddiv, regs->mode);
|
||||||
|
|
||||||
regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN);
|
regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN);
|
||||||
|
|||||||
@@ -226,9 +226,11 @@ get_checksum(unsigned start, int length)
|
|||||||
int
|
int
|
||||||
send_ipi(unsigned int dst, unsigned int v)
|
send_ipi(unsigned int dst, unsigned int v)
|
||||||
{
|
{
|
||||||
int to, send_status;
|
int to, send_status, apicid;
|
||||||
|
|
||||||
IMPS_LAPIC_WRITE(LAPIC_ICR+0x10, (dst << 24));
|
apicid = imps_cpu_apic_map[dst];
|
||||||
|
|
||||||
|
IMPS_LAPIC_WRITE(LAPIC_ICR+0x10, (apicid << 24));
|
||||||
IMPS_LAPIC_WRITE(LAPIC_ICR, v);
|
IMPS_LAPIC_WRITE(LAPIC_ICR, v);
|
||||||
|
|
||||||
/* Wait for send to finish */
|
/* Wait for send to finish */
|
||||||
@@ -251,9 +253,11 @@ static int
|
|||||||
boot_cpu(imps_processor *proc)
|
boot_cpu(imps_processor *proc)
|
||||||
{
|
{
|
||||||
int apicid = proc->apic_id, success = 1;
|
int apicid = proc->apic_id, success = 1;
|
||||||
|
int cpuid;
|
||||||
unsigned bootaddr;
|
unsigned bootaddr;
|
||||||
unsigned bios_reset_vector = PHYS_TO_VIRTUAL(BIOS_RESET_VECTOR);
|
unsigned bios_reset_vector = PHYS_TO_VIRTUAL(BIOS_RESET_VECTOR);
|
||||||
|
|
||||||
|
cpuid = imps_apic_cpu_map[apicid];
|
||||||
/*
|
/*
|
||||||
* Copy boot code for secondary CPUs here. Find it in between
|
* Copy boot code for secondary CPUs here. Find it in between
|
||||||
* "patch_code_start" and "patch_code_end" symbols. The other CPUs
|
* "patch_code_start" and "patch_code_end" symbols. The other CPUs
|
||||||
@@ -276,7 +280,7 @@ boot_cpu(imps_processor *proc)
|
|||||||
/* Pass start function, stack region and gdtdescr to AP
|
/* Pass start function, stack region and gdtdescr to AP
|
||||||
* see startAP.S for location */
|
* see startAP.S for location */
|
||||||
reset[1] = (uint32_t)secondary_cpu_initialize;
|
reset[1] = (uint32_t)secondary_cpu_initialize;
|
||||||
reset[2] = (uint32_t)_Per_CPU_Get_by_index(apicid)->interrupt_stack_high;
|
reset[2] = (uint32_t)_Per_CPU_Get_by_index(cpuid)->interrupt_stack_high;
|
||||||
memcpy(
|
memcpy(
|
||||||
(char*) &reset[3],
|
(char*) &reset[3],
|
||||||
&gdtdesc,
|
&gdtdesc,
|
||||||
@@ -295,13 +299,13 @@ boot_cpu(imps_processor *proc)
|
|||||||
|
|
||||||
/* assert INIT IPI */
|
/* assert INIT IPI */
|
||||||
send_ipi(
|
send_ipi(
|
||||||
apicid,
|
cpuid,
|
||||||
LAPIC_ICR_TM_LEVEL | LAPIC_ICR_LEVELASSERT | LAPIC_ICR_DM_INIT
|
LAPIC_ICR_TM_LEVEL | LAPIC_ICR_LEVELASSERT | LAPIC_ICR_DM_INIT
|
||||||
);
|
);
|
||||||
UDELAY(10000);
|
UDELAY(10000);
|
||||||
|
|
||||||
/* de-assert INIT IPI */
|
/* de-assert INIT IPI */
|
||||||
send_ipi(apicid, LAPIC_ICR_TM_LEVEL | LAPIC_ICR_DM_INIT);
|
send_ipi(cpuid, LAPIC_ICR_TM_LEVEL | LAPIC_ICR_DM_INIT);
|
||||||
|
|
||||||
UDELAY(10000);
|
UDELAY(10000);
|
||||||
|
|
||||||
@@ -312,7 +316,7 @@ boot_cpu(imps_processor *proc)
|
|||||||
if (proc->apic_ver >= APIC_VER_NEW) {
|
if (proc->apic_ver >= APIC_VER_NEW) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 1; i <= 2; i++) {
|
for (i = 1; i <= 2; i++) {
|
||||||
send_ipi(apicid, LAPIC_ICR_DM_SIPI | ((bootaddr >> 12) & 0xFF));
|
send_ipi(cpuid, LAPIC_ICR_DM_SIPI | ((bootaddr >> 12) & 0xFF));
|
||||||
UDELAY(1000);
|
UDELAY(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
* Acts as a barrier to ensure all previous I/O accesses have
|
* Acts as a barrier to ensure all previous I/O accesses have
|
||||||
* completed before any further ones are issued.
|
* completed before any further ones are issued.
|
||||||
*/
|
*/
|
||||||
static inline void eieio(void)
|
static inline void io_eieio(void)
|
||||||
{
|
{
|
||||||
__asm__ __volatile__ ("eieio");
|
__asm__ __volatile__ ("eieio");
|
||||||
}
|
}
|
||||||
@@ -59,9 +59,9 @@ static inline void eieio(void)
|
|||||||
/* Enforce in-order execution of data I/O.
|
/* Enforce in-order execution of data I/O.
|
||||||
* No distinction between read/write on PPC; use eieio for all three.
|
* No distinction between read/write on PPC; use eieio for all three.
|
||||||
*/
|
*/
|
||||||
#define iobarrier_rw() eieio()
|
#define iobarrier_rw() io_eieio()
|
||||||
#define iobarrier_r() eieio()
|
#define iobarrier_r() io_eieio()
|
||||||
#define iobarrier_w() eieio()
|
#define iobarrier_w() io_eieio()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
|
* 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
|
||||||
|
|||||||
@@ -7,13 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009, 2019 embedded brains GmbH. All rights reserved.
|
* Copyright (C) 2009, 2020 embedded brains GmbH (http://www.embedded-brains.de)
|
||||||
*
|
|
||||||
* embedded brains GmbH
|
|
||||||
* Dornierstr. 4
|
|
||||||
* 82178 Puchheim
|
|
||||||
* Germany
|
|
||||||
* <rtems@embedded-brains.de>
|
|
||||||
*
|
*
|
||||||
* The license and distribution terms for this file may be
|
* The license and distribution terms for this file may be
|
||||||
* found in the file LICENSE in this distribution or at
|
* found in the file LICENSE in this distribution or at
|
||||||
@@ -21,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
#include <rtems/chain.h>
|
#include <rtems/chain.h>
|
||||||
@@ -30,54 +25,43 @@
|
|||||||
|
|
||||||
#define BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR (BSP_INTERRUPT_VECTOR_MAX + 1)
|
#define BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR (BSP_INTERRUPT_VECTOR_MAX + 1)
|
||||||
|
|
||||||
typedef struct {
|
static rtems_interrupt_server_control bsp_interrupt_server_default;
|
||||||
RTEMS_INTERRUPT_LOCK_MEMBER(lock);
|
|
||||||
rtems_chain_control entries;
|
|
||||||
rtems_id server;
|
|
||||||
unsigned errors;
|
|
||||||
} bsp_interrupt_server_context;
|
|
||||||
|
|
||||||
#if defined(RTEMS_SMP)
|
static rtems_chain_control bsp_interrupt_server_chain =
|
||||||
static bsp_interrupt_server_context *bsp_interrupt_server_instances;
|
RTEMS_CHAIN_INITIALIZER_EMPTY(bsp_interrupt_server_chain);
|
||||||
#else
|
|
||||||
static bsp_interrupt_server_context bsp_interrupt_server_instance;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static bsp_interrupt_server_context *bsp_interrupt_server_get_context(
|
static rtems_interrupt_server_control *bsp_interrupt_server_get_context(
|
||||||
uint32_t server_index,
|
uint32_t server_index,
|
||||||
rtems_status_code *sc
|
rtems_status_code *sc
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
#if defined(RTEMS_SMP)
|
rtems_chain_node *node;
|
||||||
if (bsp_interrupt_server_instances == NULL) {
|
|
||||||
*sc = RTEMS_INCORRECT_STATE;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (bsp_interrupt_server_instance.server == RTEMS_ID_NONE) {
|
|
||||||
*sc = RTEMS_INCORRECT_STATE;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (server_index >= rtems_scheduler_get_processor_maximum()) {
|
bsp_interrupt_lock();
|
||||||
*sc = RTEMS_INVALID_ID;
|
node = rtems_chain_first(&bsp_interrupt_server_chain);
|
||||||
return NULL;
|
|
||||||
|
while (node != rtems_chain_tail(&bsp_interrupt_server_chain)) {
|
||||||
|
rtems_interrupt_server_control *s;
|
||||||
|
|
||||||
|
s = RTEMS_CONTAINER_OF(node, rtems_interrupt_server_control, node);
|
||||||
|
if (s->index == server_index) {
|
||||||
|
bsp_interrupt_unlock();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = rtems_chain_next(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
*sc = RTEMS_SUCCESSFUL;
|
bsp_interrupt_unlock();
|
||||||
#if defined(RTEMS_SMP)
|
*sc = RTEMS_INVALID_ID;
|
||||||
return &bsp_interrupt_server_instances[server_index];
|
return NULL;
|
||||||
#else
|
|
||||||
return &bsp_interrupt_server_instance;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bsp_interrupt_server_trigger(void *arg)
|
static void bsp_interrupt_server_trigger(void *arg)
|
||||||
{
|
{
|
||||||
rtems_interrupt_lock_context lock_context;
|
rtems_interrupt_lock_context lock_context;
|
||||||
rtems_interrupt_server_entry *e = arg;
|
rtems_interrupt_server_entry *e = arg;
|
||||||
bsp_interrupt_server_context *s = e->server;
|
rtems_interrupt_server_control *s = e->server;
|
||||||
|
|
||||||
if (bsp_interrupt_is_valid_vector(e->vector)) {
|
if (bsp_interrupt_is_valid_vector(e->vector)) {
|
||||||
bsp_interrupt_vector_disable(e->vector);
|
bsp_interrupt_vector_disable(e->vector);
|
||||||
@@ -137,7 +121,7 @@ static rtems_interrupt_server_entry *bsp_interrupt_server_query_entry(
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bsp_interrupt_server_context *server;
|
rtems_interrupt_server_control *server;
|
||||||
rtems_vector_number vector;
|
rtems_vector_number vector;
|
||||||
rtems_option options;
|
rtems_option options;
|
||||||
rtems_interrupt_handler handler;
|
rtems_interrupt_handler handler;
|
||||||
@@ -281,7 +265,7 @@ static void bsp_interrupt_server_remove_helper(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static rtems_status_code bsp_interrupt_server_call_helper(
|
static rtems_status_code bsp_interrupt_server_call_helper(
|
||||||
bsp_interrupt_server_context *s,
|
rtems_interrupt_server_control *s,
|
||||||
rtems_vector_number vector,
|
rtems_vector_number vector,
|
||||||
rtems_option options,
|
rtems_option options,
|
||||||
rtems_interrupt_handler handler,
|
rtems_interrupt_handler handler,
|
||||||
@@ -314,7 +298,7 @@ static rtems_status_code bsp_interrupt_server_call_helper(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static rtems_interrupt_server_entry *bsp_interrupt_server_get_entry(
|
static rtems_interrupt_server_entry *bsp_interrupt_server_get_entry(
|
||||||
bsp_interrupt_server_context *s
|
rtems_interrupt_server_control *s
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_interrupt_lock_context lock_context;
|
rtems_interrupt_lock_context lock_context;
|
||||||
@@ -337,7 +321,7 @@ static rtems_interrupt_server_entry *bsp_interrupt_server_get_entry(
|
|||||||
|
|
||||||
static void bsp_interrupt_server_task(rtems_task_argument arg)
|
static void bsp_interrupt_server_task(rtems_task_argument arg)
|
||||||
{
|
{
|
||||||
bsp_interrupt_server_context *s = (bsp_interrupt_server_context *) arg;
|
rtems_interrupt_server_control *s = (rtems_interrupt_server_control *) arg;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
rtems_event_set events;
|
rtems_event_set events;
|
||||||
@@ -377,7 +361,7 @@ rtems_status_code rtems_interrupt_server_handler_install(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
bsp_interrupt_server_context *s;
|
rtems_interrupt_server_control *s;
|
||||||
|
|
||||||
s = bsp_interrupt_server_get_context(server_index, &sc);
|
s = bsp_interrupt_server_get_context(server_index, &sc);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
@@ -402,7 +386,7 @@ rtems_status_code rtems_interrupt_server_handler_remove(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
bsp_interrupt_server_context *s;
|
rtems_interrupt_server_control *s;
|
||||||
|
|
||||||
s = bsp_interrupt_server_get_context(server_index, &sc);
|
s = bsp_interrupt_server_get_context(server_index, &sc);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
@@ -464,7 +448,7 @@ rtems_status_code rtems_interrupt_server_handler_iterate(
|
|||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
bsp_interrupt_server_handler_iterate_helper_data hihd;
|
bsp_interrupt_server_handler_iterate_helper_data hihd;
|
||||||
bsp_interrupt_server_context *s;
|
rtems_interrupt_server_control *s;
|
||||||
|
|
||||||
s = bsp_interrupt_server_get_context(server_index, &sc);
|
s = bsp_interrupt_server_get_context(server_index, &sc);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
@@ -487,6 +471,86 @@ rtems_status_code rtems_interrupt_server_handler_iterate(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The default server is statically allocated. Just clear the structure so
|
||||||
|
* that it can be re-initialized.
|
||||||
|
*/
|
||||||
|
static void bsp_interrupt_server_destroy_default(
|
||||||
|
rtems_interrupt_server_control *s
|
||||||
|
)
|
||||||
|
{
|
||||||
|
memset(s, 0, sizeof(*s));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
|
static void bsp_interrupt_server_destroy_secondary(
|
||||||
|
rtems_interrupt_server_control *s
|
||||||
|
)
|
||||||
|
{
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static rtems_status_code bsp_interrupt_server_create(
|
||||||
|
rtems_interrupt_server_control *s,
|
||||||
|
rtems_task_priority priority,
|
||||||
|
size_t stack_size,
|
||||||
|
rtems_mode modes,
|
||||||
|
rtems_attribute attributes,
|
||||||
|
uint32_t cpu_index
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_status_code sc;
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
|
rtems_id scheduler;
|
||||||
|
cpu_set_t cpu;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rtems_interrupt_lock_initialize(&s->lock, "Interrupt Server");
|
||||||
|
rtems_chain_initialize_empty(&s->entries);
|
||||||
|
|
||||||
|
sc = rtems_task_create(
|
||||||
|
rtems_build_name('I', 'R', 'Q', 'S'),
|
||||||
|
priority,
|
||||||
|
stack_size,
|
||||||
|
modes,
|
||||||
|
attributes,
|
||||||
|
&s->server
|
||||||
|
);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL) {
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
|
sc = rtems_scheduler_ident_by_processor(cpu_index, &scheduler);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL) {
|
||||||
|
/* Do not start an interrupt server on a processor without a scheduler */
|
||||||
|
return RTEMS_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc = rtems_task_set_scheduler(s->server, scheduler, priority);
|
||||||
|
_Assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
|
||||||
|
/* Set the task to processor affinity on a best-effort basis */
|
||||||
|
CPU_ZERO(&cpu);
|
||||||
|
CPU_SET(cpu_index, &cpu);
|
||||||
|
(void) rtems_task_set_affinity(s->server, sizeof(cpu), &cpu);
|
||||||
|
#else
|
||||||
|
(void) cpu_index;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rtems_chain_append_unprotected(&bsp_interrupt_server_chain, &s->node);
|
||||||
|
|
||||||
|
sc = rtems_task_start(
|
||||||
|
s->server,
|
||||||
|
bsp_interrupt_server_task,
|
||||||
|
(rtems_task_argument) s
|
||||||
|
);
|
||||||
|
_Assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
|
||||||
rtems_status_code rtems_interrupt_server_initialize(
|
rtems_status_code rtems_interrupt_server_initialize(
|
||||||
rtems_task_priority priority,
|
rtems_task_priority priority,
|
||||||
size_t stack_size,
|
size_t stack_size,
|
||||||
@@ -495,95 +559,164 @@ rtems_status_code rtems_interrupt_server_initialize(
|
|||||||
uint32_t *server_count
|
uint32_t *server_count
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
rtems_status_code sc;
|
||||||
|
rtems_interrupt_server_control *s;
|
||||||
uint32_t cpu_index;
|
uint32_t cpu_index;
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
uint32_t cpu_count;
|
uint32_t cpu_count;
|
||||||
uint32_t dummy;
|
#endif
|
||||||
bsp_interrupt_server_context *instances;
|
|
||||||
|
|
||||||
if (server_count == NULL) {
|
cpu_index = 0;
|
||||||
server_count = &dummy;
|
s = &bsp_interrupt_server_default;
|
||||||
|
|
||||||
|
bsp_interrupt_lock();
|
||||||
|
|
||||||
|
if (s->server != 0) {
|
||||||
|
sc = RTEMS_INCORRECT_STATE;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s->destroy = bsp_interrupt_server_destroy_default;
|
||||||
|
sc = bsp_interrupt_server_create(
|
||||||
|
s,
|
||||||
|
priority,
|
||||||
|
stack_size,
|
||||||
|
modes,
|
||||||
|
attributes,
|
||||||
|
cpu_index
|
||||||
|
);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu_index = 1;
|
||||||
|
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
cpu_count = rtems_scheduler_get_processor_maximum();
|
cpu_count = rtems_scheduler_get_processor_maximum();
|
||||||
|
|
||||||
#if defined(RTEMS_SMP)
|
while (cpu_index < cpu_count) {
|
||||||
instances = calloc(cpu_count, sizeof(*instances));
|
s = calloc(1, sizeof(*s));
|
||||||
if (instances == NULL) {
|
|
||||||
return RTEMS_NO_MEMORY;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
instances = &bsp_interrupt_server_instance;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
|
if (s == NULL) {
|
||||||
bsp_interrupt_server_context *s = &instances[cpu_index];
|
sc = RTEMS_NO_MEMORY;
|
||||||
rtems_status_code sc;
|
goto done;
|
||||||
#if defined(RTEMS_SMP)
|
}
|
||||||
rtems_id scheduler;
|
|
||||||
cpu_set_t cpu;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rtems_interrupt_lock_initialize(&s->lock, "Interrupt Server");
|
s->destroy = bsp_interrupt_server_destroy_secondary;
|
||||||
rtems_chain_initialize_empty(&s->entries);
|
s->index = cpu_index;
|
||||||
|
sc = bsp_interrupt_server_create(
|
||||||
sc = rtems_task_create(
|
s,
|
||||||
rtems_build_name('I', 'R', 'Q', 'S'),
|
|
||||||
priority,
|
priority,
|
||||||
stack_size,
|
stack_size,
|
||||||
modes,
|
modes,
|
||||||
attributes,
|
attributes,
|
||||||
&s->server
|
cpu_index
|
||||||
);
|
);
|
||||||
if (sc != RTEMS_SUCCESSFUL) {
|
if (sc != RTEMS_SUCCESSFUL) {
|
||||||
*server_count = cpu_index;
|
goto done;
|
||||||
|
|
||||||
#if defined(RTEMS_SMP)
|
|
||||||
if (cpu_index > 0) {
|
|
||||||
bsp_interrupt_server_instances = instances;
|
|
||||||
return RTEMS_SUCCESSFUL;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(instances);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return RTEMS_TOO_MANY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(RTEMS_SMP)
|
++cpu_index;
|
||||||
sc = rtems_scheduler_ident_by_processor(cpu_index, &scheduler);
|
}
|
||||||
if (sc != RTEMS_SUCCESSFUL) {
|
|
||||||
/* Do not start an interrupt server on a processor without a scheduler */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sc = rtems_task_set_scheduler(s->server, scheduler, priority);
|
|
||||||
_Assert(sc == RTEMS_SUCCESSFUL);
|
|
||||||
|
|
||||||
/* Set the task to processor affinity on a best-effort basis */
|
|
||||||
CPU_ZERO(&cpu);
|
|
||||||
CPU_SET(cpu_index, &cpu);
|
|
||||||
(void) rtems_task_set_affinity(s->server, sizeof(cpu), &cpu);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sc = rtems_task_start(
|
done:
|
||||||
s->server,
|
bsp_interrupt_unlock();
|
||||||
bsp_interrupt_server_task,
|
|
||||||
(rtems_task_argument) s
|
if (server_count != NULL) {
|
||||||
);
|
*server_count = cpu_index;
|
||||||
_Assert(sc == RTEMS_SUCCESSFUL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(RTEMS_SMP)
|
return sc;
|
||||||
bsp_interrupt_server_instances = instances;
|
}
|
||||||
#endif
|
|
||||||
*server_count = cpu_index;
|
|
||||||
|
|
||||||
|
rtems_status_code rtems_interrupt_server_create(
|
||||||
|
rtems_interrupt_server_control *s,
|
||||||
|
const rtems_interrupt_server_config *config,
|
||||||
|
uint32_t *server_index
|
||||||
|
)
|
||||||
|
{
|
||||||
|
rtems_status_code sc;
|
||||||
|
|
||||||
|
sc = rtems_task_create(
|
||||||
|
config->name,
|
||||||
|
config->priority,
|
||||||
|
config->storage_size,
|
||||||
|
config->modes,
|
||||||
|
config->attributes,
|
||||||
|
&s->server
|
||||||
|
);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL) {
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_interrupt_lock_initialize(&s->lock, "Interrupt Server");
|
||||||
|
rtems_chain_initialize_empty(&s->entries);
|
||||||
|
s->destroy = config->destroy;
|
||||||
|
s->index = rtems_object_id_get_index(s->server)
|
||||||
|
+ rtems_scheduler_get_processor_maximum();
|
||||||
|
*server_index = s->index;
|
||||||
|
|
||||||
|
bsp_interrupt_lock();
|
||||||
|
rtems_chain_initialize_node(&s->node);
|
||||||
|
rtems_chain_append_unprotected(&bsp_interrupt_server_chain, &s->node);
|
||||||
|
bsp_interrupt_unlock();
|
||||||
|
|
||||||
|
sc = rtems_task_start(
|
||||||
|
s->server,
|
||||||
|
bsp_interrupt_server_task,
|
||||||
|
(rtems_task_argument) s
|
||||||
|
);
|
||||||
|
_Assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bsp_interrupt_server_destroy_helper(void *arg)
|
||||||
|
{
|
||||||
|
bsp_interrupt_server_helper_data *hd = arg;
|
||||||
|
rtems_interrupt_server_control *s = hd->server;
|
||||||
|
rtems_status_code sc;
|
||||||
|
|
||||||
|
bsp_interrupt_lock();
|
||||||
|
rtems_chain_extract_unprotected(&s->node);
|
||||||
|
bsp_interrupt_unlock();
|
||||||
|
|
||||||
|
if (s->destroy != NULL) {
|
||||||
|
(*s->destroy)(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
sc = rtems_event_transient_send(hd->task);
|
||||||
|
_Assert(sc == RTEMS_SUCCESSFUL);
|
||||||
|
(void) sc;
|
||||||
|
|
||||||
|
rtems_task_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_status_code rtems_interrupt_server_delete(uint32_t server_index)
|
||||||
|
{
|
||||||
|
rtems_status_code sc;
|
||||||
|
rtems_interrupt_server_control *s;
|
||||||
|
|
||||||
|
s = bsp_interrupt_server_get_context(server_index, &sc);
|
||||||
|
if (s == NULL) {
|
||||||
|
return sc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bsp_interrupt_server_call_helper(
|
||||||
|
s,
|
||||||
|
BSP_INTERRUPT_SERVER_MANAGEMENT_VECTOR,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
bsp_interrupt_server_destroy_helper
|
||||||
|
);
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bsp_interrupt_server_entry_initialize(
|
static void bsp_interrupt_server_entry_initialize(
|
||||||
rtems_interrupt_server_entry *entry,
|
rtems_interrupt_server_entry *entry,
|
||||||
bsp_interrupt_server_context *s
|
rtems_interrupt_server_control *s
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_chain_set_off_chain(&entry->node);
|
rtems_chain_set_off_chain(&entry->node);
|
||||||
@@ -611,7 +744,7 @@ rtems_status_code rtems_interrupt_server_entry_initialize(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
bsp_interrupt_server_context *s;
|
rtems_interrupt_server_control *s;
|
||||||
|
|
||||||
s = bsp_interrupt_server_get_context(server_index, &sc);
|
s = bsp_interrupt_server_get_context(server_index, &sc);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
@@ -645,7 +778,7 @@ rtems_status_code rtems_interrupt_server_entry_move(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
bsp_interrupt_server_context *s;
|
rtems_interrupt_server_control *s;
|
||||||
|
|
||||||
s = bsp_interrupt_server_get_context(destination_server_index, &sc);
|
s = bsp_interrupt_server_get_context(destination_server_index, &sc);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
@@ -667,7 +800,7 @@ void rtems_interrupt_server_entry_destroy(
|
|||||||
rtems_interrupt_server_entry *entry
|
rtems_interrupt_server_entry *entry
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
bsp_interrupt_server_context *s;
|
rtems_interrupt_server_control *s;
|
||||||
rtems_interrupt_lock_context lock_context;
|
rtems_interrupt_lock_context lock_context;
|
||||||
|
|
||||||
s = entry->server;
|
s = entry->server;
|
||||||
@@ -698,7 +831,7 @@ rtems_status_code rtems_interrupt_server_request_initialize(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
bsp_interrupt_server_context *s;
|
rtems_interrupt_server_control *s;
|
||||||
|
|
||||||
s = bsp_interrupt_server_get_context(server_index, &sc);
|
s = bsp_interrupt_server_get_context(server_index, &sc);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
@@ -727,8 +860,8 @@ static void bsp_interrupt_server_handler_move_helper(void *arg)
|
|||||||
e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
|
e = bsp_interrupt_server_query_entry(hd->vector, &trigger_options);
|
||||||
if (e != NULL) {
|
if (e != NULL) {
|
||||||
rtems_interrupt_lock_context lock_context;
|
rtems_interrupt_lock_context lock_context;
|
||||||
bsp_interrupt_server_context *src = e->server;
|
rtems_interrupt_server_control *src = e->server;
|
||||||
bsp_interrupt_server_context *dst = hihd->arg;
|
rtems_interrupt_server_control *dst = hihd->arg;
|
||||||
bool pending;
|
bool pending;
|
||||||
|
|
||||||
/* The source server is only used in SMP configurations for the lock */
|
/* The source server is only used in SMP configurations for the lock */
|
||||||
@@ -763,8 +896,8 @@ rtems_status_code rtems_interrupt_server_move(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
bsp_interrupt_server_context *src;
|
rtems_interrupt_server_control *src;
|
||||||
bsp_interrupt_server_context *dst;
|
rtems_interrupt_server_control *dst;
|
||||||
bsp_interrupt_server_handler_iterate_helper_data hihd;
|
bsp_interrupt_server_handler_iterate_helper_data hihd;
|
||||||
|
|
||||||
src = bsp_interrupt_server_get_context(source_server_index, &sc);
|
src = bsp_interrupt_server_get_context(source_server_index, &sc);
|
||||||
@@ -810,7 +943,7 @@ static void bsp_interrupt_server_entry_suspend_helper(void *arg)
|
|||||||
rtems_status_code rtems_interrupt_server_suspend(uint32_t server_index)
|
rtems_status_code rtems_interrupt_server_suspend(uint32_t server_index)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
bsp_interrupt_server_context *s;
|
rtems_interrupt_server_control *s;
|
||||||
|
|
||||||
s = bsp_interrupt_server_get_context(server_index, &sc);
|
s = bsp_interrupt_server_get_context(server_index, &sc);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
@@ -831,7 +964,7 @@ rtems_status_code rtems_interrupt_server_suspend(uint32_t server_index)
|
|||||||
rtems_status_code rtems_interrupt_server_resume(uint32_t server_index)
|
rtems_status_code rtems_interrupt_server_resume(uint32_t server_index)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
bsp_interrupt_server_context *s;
|
rtems_interrupt_server_control *s;
|
||||||
|
|
||||||
s = bsp_interrupt_server_get_context(server_index, &sc);
|
s = bsp_interrupt_server_get_context(server_index, &sc);
|
||||||
if (s == NULL) {
|
if (s == NULL) {
|
||||||
@@ -858,7 +991,7 @@ rtems_status_code rtems_interrupt_server_set_affinity(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
bsp_interrupt_server_context *s;
|
rtems_interrupt_server_control *s;
|
||||||
rtems_id scheduler;
|
rtems_id scheduler;
|
||||||
|
|
||||||
s = bsp_interrupt_server_get_context(server_index, &sc);
|
s = bsp_interrupt_server_get_context(server_index, &sc);
|
||||||
|
|||||||
@@ -6,9 +6,6 @@
|
|||||||
* @ingroup RTEMSApplicationConfiguration
|
* @ingroup RTEMSApplicationConfiguration
|
||||||
*
|
*
|
||||||
* @brief Evaluate MPCI Configuration Options
|
* @brief Evaluate MPCI Configuration Options
|
||||||
*
|
|
||||||
* This header file defines _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT for use by
|
|
||||||
* other configuration header files.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -49,6 +46,8 @@
|
|||||||
|
|
||||||
#ifdef CONFIGURE_MP_APPLICATION
|
#ifdef CONFIGURE_MP_APPLICATION
|
||||||
|
|
||||||
|
#include <rtems/confdefs/threads.h>
|
||||||
|
|
||||||
#ifndef CONFIGURE_EXTRA_MPCI_RECEIVE_SERVER_STACK
|
#ifndef CONFIGURE_EXTRA_MPCI_RECEIVE_SERVER_STACK
|
||||||
#define CONFIGURE_EXTRA_MPCI_RECEIVE_SERVER_STACK 0
|
#define CONFIGURE_EXTRA_MPCI_RECEIVE_SERVER_STACK 0
|
||||||
#endif
|
#endif
|
||||||
@@ -83,8 +82,6 @@
|
|||||||
#error "CONFIGURE_MP_NODE_NUMBER must be less than or equal to CONFIGURE_MP_MAXIMUM_NODES"
|
#error "CONFIGURE_MP_NODE_NUMBER must be less than or equal to CONFIGURE_MP_MAXIMUM_NODES"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 1
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@@ -126,10 +123,6 @@ RTEMS_SECTION( ".rtemsstack.mpci" );
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else /* CONFIGURE_MP_APPLICATION */
|
|
||||||
|
|
||||||
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 0
|
|
||||||
|
|
||||||
#endif /* CONFIGURE_MP_APPLICATION */
|
#endif /* CONFIGURE_MP_APPLICATION */
|
||||||
|
|
||||||
#else /* RTEMS_MULTIPROCESSING */
|
#else /* RTEMS_MULTIPROCESSING */
|
||||||
@@ -138,8 +131,6 @@ RTEMS_SECTION( ".rtemsstack.mpci" );
|
|||||||
#error "CONFIGURE_MP_APPLICATION must not be defined if multiprocessing is disabled"
|
#error "CONFIGURE_MP_APPLICATION must not be defined if multiprocessing is disabled"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 0
|
|
||||||
|
|
||||||
#endif /* RTEMS_MULTIPROCESSING */
|
#endif /* RTEMS_MULTIPROCESSING */
|
||||||
|
|
||||||
#endif /* CONFIGURE_INIT */
|
#endif /* CONFIGURE_INIT */
|
||||||
|
|||||||
@@ -44,7 +44,6 @@
|
|||||||
|
|
||||||
#include <rtems/confdefs/bdbuf.h>
|
#include <rtems/confdefs/bdbuf.h>
|
||||||
#include <rtems/confdefs/extensions.h>
|
#include <rtems/confdefs/extensions.h>
|
||||||
#include <rtems/confdefs/mpci.h>
|
|
||||||
#include <rtems/confdefs/percpu.h>
|
#include <rtems/confdefs/percpu.h>
|
||||||
#include <rtems/confdefs/scheduler.h>
|
#include <rtems/confdefs/scheduler.h>
|
||||||
#include <rtems/confdefs/unlimited.h>
|
#include <rtems/confdefs/unlimited.h>
|
||||||
@@ -197,6 +196,12 @@ const size_t _Thread_Initial_thread_count =
|
|||||||
rtems_resource_maximum_per_allocation( _CONFIGURE_TASKS ) +
|
rtems_resource_maximum_per_allocation( _CONFIGURE_TASKS ) +
|
||||||
rtems_resource_maximum_per_allocation( CONFIGURE_MAXIMUM_POSIX_THREADS );
|
rtems_resource_maximum_per_allocation( CONFIGURE_MAXIMUM_POSIX_THREADS );
|
||||||
|
|
||||||
|
#if defined(RTEMS_MULTIPROCESSING) && defined(CONFIGURE_MP_APPLICATION)
|
||||||
|
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 1
|
||||||
|
#else
|
||||||
|
#define _CONFIGURE_MPCI_RECEIVE_SERVER_COUNT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
THREAD_INFORMATION_DEFINE(
|
THREAD_INFORMATION_DEFINE(
|
||||||
_Thread,
|
_Thread,
|
||||||
OBJECTS_INTERNAL_API,
|
OBJECTS_INTERNAL_API,
|
||||||
|
|||||||
@@ -214,6 +214,9 @@ typedef struct {
|
|||||||
/**
|
/**
|
||||||
* @brief Converter implementation for new file system instance.
|
* @brief Converter implementation for new file system instance.
|
||||||
*
|
*
|
||||||
|
* Note: If you pass a converter to mount, you have to destroy it yourself if
|
||||||
|
* mount failed. In a good case it is destroyed at unmount.
|
||||||
|
*
|
||||||
* Before converters have been added to the RTEMS implementation of the FAT
|
* Before converters have been added to the RTEMS implementation of the FAT
|
||||||
* file system, the implementation was:
|
* file system, the implementation was:
|
||||||
* - Short names were saved in code page format (as is still the case).
|
* - Short names were saved in code page format (as is still the case).
|
||||||
@@ -270,6 +273,10 @@ typedef struct {
|
|||||||
* RTEMS_FILESYSTEM_READ_WRITE,
|
* RTEMS_FILESYSTEM_READ_WRITE,
|
||||||
* &mount_opts
|
* &mount_opts
|
||||||
* );
|
* );
|
||||||
|
*
|
||||||
|
* if (rv != 0) {
|
||||||
|
* (*mount_opts.converter->handler->destroy)(mount_opts.converter);
|
||||||
|
* }
|
||||||
* } else {
|
* } else {
|
||||||
* rv = -1;
|
* rv = -1;
|
||||||
* errno = ENOMEM;
|
* errno = ENOMEM;
|
||||||
|
|||||||
@@ -9,13 +9,7 @@
|
|||||||
/*
|
/*
|
||||||
* Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
|
* Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008, 2019 embedded brains GmbH
|
* Copyright (C) 2008, 2020 embedded brains GmbH (http://www.embedded-brains.de)
|
||||||
*
|
|
||||||
* embedded brains GmbH
|
|
||||||
* Dornierstr. 4
|
|
||||||
* 82178 Puchheim
|
|
||||||
* Germany
|
|
||||||
* <rtems@embedded-brains.de>
|
|
||||||
*
|
*
|
||||||
* The license and distribution terms for this file may be
|
* The license and distribution terms for this file may be
|
||||||
* found in the file LICENSE in this distribution or at
|
* found in the file LICENSE in this distribution or at
|
||||||
@@ -259,6 +253,76 @@ typedef struct rtems_interrupt_server_action {
|
|||||||
*/
|
*/
|
||||||
#define RTEMS_INTERRUPT_SERVER_DEFAULT 0
|
#define RTEMS_INTERRUPT_SERVER_DEFAULT 0
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief An interrupt server control.
|
||||||
|
*
|
||||||
|
* This structure must be treated as an opaque data type. Members must not be
|
||||||
|
* accessed directly.
|
||||||
|
*
|
||||||
|
* @see rtems_interrupt_server_create()
|
||||||
|
*/
|
||||||
|
typedef struct rtems_interrupt_server_control {
|
||||||
|
RTEMS_INTERRUPT_LOCK_MEMBER( lock )
|
||||||
|
rtems_chain_control entries;
|
||||||
|
rtems_id server;
|
||||||
|
unsigned long errors;
|
||||||
|
uint32_t index;
|
||||||
|
rtems_chain_node node;
|
||||||
|
void ( *destroy )( struct rtems_interrupt_server_control * );
|
||||||
|
} rtems_interrupt_server_control;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief An interrupt server configuration.
|
||||||
|
*
|
||||||
|
* @see rtems_interrupt_server_create()
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
/**
|
||||||
|
* @brief The task name of the interrupt server.
|
||||||
|
*/
|
||||||
|
rtems_name name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The initial task priority of the interrupt server.
|
||||||
|
*/
|
||||||
|
rtems_task_priority priority;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The task storage area of the interrupt server.
|
||||||
|
*
|
||||||
|
* It shall be NULL for interrupt servers created by
|
||||||
|
* rtems_interrupt_server_create().
|
||||||
|
*/
|
||||||
|
void *storage_area;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The task storage size of the interrupt server.
|
||||||
|
*
|
||||||
|
* For interrupt servers created by rtems_interrupt_server_create() this is
|
||||||
|
* the task stack size.
|
||||||
|
*/
|
||||||
|
size_t storage_size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The initial task modes of the interrupt server.
|
||||||
|
*/
|
||||||
|
rtems_mode modes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The task attributes of the interrupt server.
|
||||||
|
*/
|
||||||
|
rtems_attribute attributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief An optional handler to destroy the interrupt server control handed
|
||||||
|
* over to rtems_interrupt_server_create().
|
||||||
|
*
|
||||||
|
* This handler is called in the context of the interrupt server to be
|
||||||
|
* deleted, see also rtems_interrupt_server_delete().
|
||||||
|
*/
|
||||||
|
void ( *destroy )( rtems_interrupt_server_control * );
|
||||||
|
} rtems_interrupt_server_config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An interrupt server entry.
|
* @brief An interrupt server entry.
|
||||||
*
|
*
|
||||||
@@ -309,16 +373,19 @@ typedef struct {
|
|||||||
*
|
*
|
||||||
* The server count pointer @a server_count may be @a NULL.
|
* The server count pointer @a server_count may be @a NULL.
|
||||||
*
|
*
|
||||||
|
* The task name of interrupt servers created by this function is
|
||||||
|
* rtems_build_name( 'I', 'R', 'Q', 'S' ).
|
||||||
|
*
|
||||||
* This function may block.
|
* This function may block.
|
||||||
*
|
*
|
||||||
* @see rtems_task_create().
|
* @retval RTEMS_SUCCESSFUL The operation was successful.
|
||||||
*
|
*
|
||||||
* @retval RTEMS_SUCCESSFUL Successful operation.
|
* @retval RTEMS_INCORRECT_STATE The interrupt servers were already initialized.
|
||||||
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
|
*
|
||||||
* @retval RTEMS_NO_MEMORY Not enough memory.
|
* @return The function uses rtems_task_create(). If this operation is not
|
||||||
* @retval RTEMS_TOO_MANY No free task available to create at least one server task.
|
* successful, then its status code is returned.
|
||||||
* @retval RTEMS_UNSATISFIED Task stack size too large.
|
*
|
||||||
* @retval RTEMS_INVALID_PRIORITY Invalid task priority.
|
* @see rtems_interrupt_server_create() and rtems_interrupt_server_delete().
|
||||||
*/
|
*/
|
||||||
rtems_status_code rtems_interrupt_server_initialize(
|
rtems_status_code rtems_interrupt_server_initialize(
|
||||||
rtems_task_priority priority,
|
rtems_task_priority priority,
|
||||||
@@ -328,6 +395,54 @@ rtems_status_code rtems_interrupt_server_initialize(
|
|||||||
uint32_t *server_count
|
uint32_t *server_count
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates an interrupt server.
|
||||||
|
*
|
||||||
|
* This function may block.
|
||||||
|
*
|
||||||
|
* @param[out] control is the interrupt server control. The ownership of this
|
||||||
|
* structure is transferred from the caller of this function to the interrupt
|
||||||
|
* server management.
|
||||||
|
*
|
||||||
|
* @param config is the interrupt server configuration.
|
||||||
|
*
|
||||||
|
* @param[out] server_index is the pointer to a server index variable. The
|
||||||
|
* index of the built interrupt server will be stored in the referenced
|
||||||
|
* variable if the operation was successful.
|
||||||
|
*
|
||||||
|
* @retval RTEMS_SUCCESSFUL The operation was successful.
|
||||||
|
*
|
||||||
|
* @return The function uses rtems_task_create(). If this operation is not
|
||||||
|
* successful, then its status code is returned.
|
||||||
|
*
|
||||||
|
* @see rtems_interrupt_server_initialize() and
|
||||||
|
* rtems_interrupt_server_delete().
|
||||||
|
*/
|
||||||
|
rtems_status_code rtems_interrupt_server_create(
|
||||||
|
rtems_interrupt_server_control *control,
|
||||||
|
const rtems_interrupt_server_config *config,
|
||||||
|
uint32_t *server_index
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destroys the interrupt server.
|
||||||
|
*
|
||||||
|
* This function may block.
|
||||||
|
*
|
||||||
|
* The interrupt server deletes itself, so after the return of the function the
|
||||||
|
* interrupt server may be still in the termination process depending on the
|
||||||
|
* task priorities of the system.
|
||||||
|
*
|
||||||
|
* @param server_index is the index of the interrupt server to destroy. Use
|
||||||
|
* ::RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server.
|
||||||
|
*
|
||||||
|
* @retval RTEMS_SUCCESSFUL The operation was successful.
|
||||||
|
* @retval RTEMS_INVALID_ID The interrupt server index was invalid.
|
||||||
|
*
|
||||||
|
* @see rtems_interrupt_server_create()
|
||||||
|
*/
|
||||||
|
rtems_status_code rtems_interrupt_server_delete( uint32_t server_index );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Installs the interrupt handler routine @a handler for the interrupt
|
* @brief Installs the interrupt handler routine @a handler for the interrupt
|
||||||
* vector with number @a vector on the server @a server.
|
* vector with number @a vector on the server @a server.
|
||||||
|
|||||||
@@ -504,6 +504,7 @@ static rtems_status_code mount_worker(
|
|||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
rmdir(mount_path);
|
rmdir(mount_path);
|
||||||
free(mount_path);
|
free(mount_path);
|
||||||
|
(*mount_options.converter->handler->destroy)(mount_options.converter);
|
||||||
|
|
||||||
return RTEMS_IO_ERROR;
|
return RTEMS_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,10 +103,12 @@ int rtems_dosfs_initialize(
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
const rtems_dosfs_mount_options *mount_options = data;
|
const rtems_dosfs_mount_options *mount_options = data;
|
||||||
rtems_dosfs_convert_control *converter;
|
rtems_dosfs_convert_control *converter;
|
||||||
|
bool converter_created = false;
|
||||||
|
|
||||||
|
|
||||||
if (mount_options == NULL || mount_options->converter == NULL) {
|
if (mount_options == NULL || mount_options->converter == NULL) {
|
||||||
converter = rtems_dosfs_create_default_converter();
|
converter = rtems_dosfs_create_default_converter();
|
||||||
|
converter_created = true;
|
||||||
} else {
|
} else {
|
||||||
converter = mount_options->converter;
|
converter = mount_options->converter;
|
||||||
}
|
}
|
||||||
@@ -117,6 +119,9 @@ int rtems_dosfs_initialize(
|
|||||||
&msdos_file_handlers,
|
&msdos_file_handlers,
|
||||||
&msdos_dir_handlers,
|
&msdos_dir_handlers,
|
||||||
converter);
|
converter);
|
||||||
|
if (rc != 0 && converter_created) {
|
||||||
|
(*converter->handler->destroy)(converter);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
rc = -1;
|
rc = -1;
|
||||||
|
|||||||
@@ -234,12 +234,16 @@ static void rtems_shell_clear_shell_env(void)
|
|||||||
eno = pthread_setspecific(rtems_shell_current_env_key, NULL);
|
eno = pthread_setspecific(rtems_shell_current_env_key, NULL);
|
||||||
if (eno != 0)
|
if (eno != 0)
|
||||||
rtems_error(0, "pthread_setspecific(shell_current_env_key): clear");
|
rtems_error(0, "pthread_setspecific(shell_current_env_key): clear");
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clear stdin and stdout file pointers of they will be closed
|
* Clear stdin, stdout and stderr file pointers so they will not be closed.
|
||||||
*/
|
*/
|
||||||
|
static void rtems_shell_clear_shell_std_handles(void)
|
||||||
|
{
|
||||||
stdin = NULL;
|
stdin = NULL;
|
||||||
stdout = NULL;
|
stdout = NULL;
|
||||||
|
stderr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -775,6 +779,7 @@ void rtems_shell_print_env(
|
|||||||
{
|
{
|
||||||
if ( !shell_env ) {
|
if ( !shell_env ) {
|
||||||
printk( "shell_env is NULL\n" );
|
printk( "shell_env is NULL\n" );
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printk( "shell_env=%p\n"
|
printk( "shell_env=%p\n"
|
||||||
@@ -797,6 +802,7 @@ static rtems_task rtems_shell_task(rtems_task_argument task_argument)
|
|||||||
rtems_shell_env_t *shell_env = (rtems_shell_env_t*) task_argument;
|
rtems_shell_env_t *shell_env = (rtems_shell_env_t*) task_argument;
|
||||||
rtems_id wake_on_end = shell_env->wake_on_end;
|
rtems_id wake_on_end = shell_env->wake_on_end;
|
||||||
rtems_shell_main_loop( shell_env );
|
rtems_shell_main_loop( shell_env );
|
||||||
|
rtems_shell_clear_shell_std_handles();
|
||||||
if (wake_on_end != RTEMS_INVALID_ID)
|
if (wake_on_end != RTEMS_INVALID_ID)
|
||||||
rtems_event_send (wake_on_end, RTEMS_EVENT_1);
|
rtems_event_send (wake_on_end, RTEMS_EVENT_1);
|
||||||
rtems_task_exit();
|
rtems_task_exit();
|
||||||
@@ -872,6 +878,11 @@ bool rtems_shell_main_loop(
|
|||||||
else
|
else
|
||||||
stdout = stderr;
|
stdout = stderr;
|
||||||
} else if (strcmp(shell_env->output, "/dev/null") == 0) {
|
} else if (strcmp(shell_env->output, "/dev/null") == 0) {
|
||||||
|
if (stdout == NULL) {
|
||||||
|
fprintf(stderr, "shell: stdout is NULLs\n");
|
||||||
|
rtems_shell_clear_shell_env();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
fclose (stdout);
|
fclose (stdout);
|
||||||
} else {
|
} else {
|
||||||
FILE *output = fopen(shell_env->output,
|
FILE *output = fopen(shell_env->output,
|
||||||
@@ -906,6 +917,13 @@ bool rtems_shell_main_loop(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!input_file) {
|
if (!input_file) {
|
||||||
|
if (stdin == NULL) {
|
||||||
|
fprintf(stderr, "shell: stdin is NULLs\n");
|
||||||
|
if (stdoutToClose != NULL)
|
||||||
|
fclose(stdoutToClose);
|
||||||
|
rtems_shell_clear_shell_env();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
/* Make a raw terminal, Linux Manuals */
|
/* Make a raw terminal, Linux Manuals */
|
||||||
if (tcgetattr(fileno(stdin), &previous_term) >= 0) {
|
if (tcgetattr(fileno(stdin), &previous_term) >= 0) {
|
||||||
term = previous_term;
|
term = previous_term;
|
||||||
@@ -967,7 +985,7 @@ bool rtems_shell_main_loop(
|
|||||||
* keep on trucking.
|
* keep on trucking.
|
||||||
*/
|
*/
|
||||||
if (shell_env->login_check != NULL) {
|
if (shell_env->login_check != NULL) {
|
||||||
result = rtems_shell_login(shell_env, stdin,stdout);
|
result = rtems_shell_login(shell_env, stdin, stdout);
|
||||||
} else {
|
} else {
|
||||||
setuid(shell_env->uid);
|
setuid(shell_env->uid);
|
||||||
setgid(shell_env->gid);
|
setgid(shell_env->gid);
|
||||||
|
|||||||
@@ -29,28 +29,29 @@ int shm_unlink( const char *name )
|
|||||||
_Objects_Allocator_lock();
|
_Objects_Allocator_lock();
|
||||||
|
|
||||||
shm = _POSIX_Shm_Get_by_name( name, 0, &obj_err );
|
shm = _POSIX_Shm_Get_by_name( name, 0, &obj_err );
|
||||||
switch ( obj_err ) {
|
if ( shm ) {
|
||||||
case OBJECTS_GET_BY_NAME_INVALID_NAME:
|
_Objects_Namespace_remove_string(
|
||||||
err = ENOENT;
|
&_POSIX_Shm_Information,
|
||||||
break;
|
&shm->Object
|
||||||
|
);
|
||||||
|
|
||||||
case OBJECTS_GET_BY_NAME_NAME_TOO_LONG:
|
if ( shm->reference_count == 0 ) {
|
||||||
err = ENAMETOOLONG;
|
/* Only remove the shm object if no references exist to it. Otherwise,
|
||||||
break;
|
* the shm object will be freed later in _POSIX_Shm_Attempt_delete */
|
||||||
|
_POSIX_Shm_Free( shm );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch ( obj_err ) {
|
||||||
|
case OBJECTS_GET_BY_NAME_NAME_TOO_LONG:
|
||||||
|
err = ENAMETOOLONG;
|
||||||
|
break;
|
||||||
|
|
||||||
case OBJECTS_GET_BY_NAME_NO_OBJECT:
|
case OBJECTS_GET_BY_NAME_INVALID_NAME:
|
||||||
default:
|
case OBJECTS_GET_BY_NAME_NO_OBJECT:
|
||||||
_Objects_Namespace_remove_string(
|
default:
|
||||||
&_POSIX_Shm_Information,
|
err = ENOENT;
|
||||||
&shm->Object
|
break;
|
||||||
);
|
}
|
||||||
|
|
||||||
if ( shm->reference_count == 0 ) {
|
|
||||||
/* Only remove the shm object if no references exist to it. Otherwise,
|
|
||||||
* the shm object will be freed later in _POSIX_Shm_Attempt_delete */
|
|
||||||
_POSIX_Shm_Free( shm );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_Objects_Allocator_unlock();
|
_Objects_Allocator_unlock();
|
||||||
|
|||||||
@@ -83,9 +83,9 @@ SYM (_CPU_Context_switch):
|
|||||||
.L_restore:
|
.L_restore:
|
||||||
movl I386_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE(eax),ecx
|
movl I386_CONTEXT_CONTROL_ISR_DISPATCH_DISABLE(eax),ecx
|
||||||
movl ecx,PER_CPU_ISR_DISPATCH_DISABLE(edx)
|
movl ecx,PER_CPU_ISR_DISPATCH_DISABLE(edx)
|
||||||
|
movl REG_ESP(eax),esp /* restore stack pointer */
|
||||||
pushl REG_EFLAGS(eax) /* push eflags */
|
pushl REG_EFLAGS(eax) /* push eflags */
|
||||||
popf /* restore eflags */
|
popf /* restore eflags */
|
||||||
movl REG_ESP(eax),esp /* restore stack pointer */
|
|
||||||
movl REG_EBP(eax),ebp /* restore base pointer */
|
movl REG_EBP(eax),ebp /* restore base pointer */
|
||||||
movl REG_EBX(eax),ebx /* restore ebx */
|
movl REG_EBX(eax),ebx /* restore ebx */
|
||||||
movl REG_ESI(eax),esi /* restore source register */
|
movl REG_ESI(eax),esi /* restore source register */
|
||||||
|
|||||||
Reference in New Issue
Block a user