git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1149 35acf78f-673a-0410-8e92-d51de3d6d3f4

master
gdisirio 2009-09-05 15:33:27 +00:00
parent 7dfa36f86d
commit e8e651a11d
110 changed files with 0 additions and 27879 deletions

View File

@ -1,136 +0,0 @@
# ARM7 common makefile scripts and rules.
# Automatic compiler options
OPT = $(USE_OPT)
CPPOPT = $(USE_CPPOPT)
ifeq ($(USE_CURRP_CACHING),yes)
OPT += -ffixed-r7 -DCH_CURRP_REGISTER_CACHE='"r7"'
endif
ifeq ($(USE_LINK_GC),yes)
OPT += -ffunction-sections -fdata-sections
endif
# Source files groups
ifeq ($(USE_THUMB),yes)
TCSRC += $(CSRC)
TCPPSRC += $(CPPSRC)
else
ACSRC += $(CSRC)
ACPPSRC += $(CPPSRC)
endif
ASRC = $(ACSRC)$(ACPPSRC)
TSRC = $(TCSRC)$(TCPPSRC)
SRC = $(ASRC)$(TSRC)
# Object files groups
ACOBJS = $(ACSRC:.c=.o)
ACPPOBJS = $(ACPPSRC:.cpp=.o)
TCOBJS = $(TCSRC:.c=.o)
TCPPOBJS = $(TCPPSRC:.cpp=.o)
ASMOBJS = $(ASMSRC:.s=.o)
OBJS = $(ASMOBJS) $(ACOBJS) $(TCOBJS) $(ACPPOBJS) $(TCPPOBJS)
# Paths
IINCDIR = $(patsubst %,-I%,$(INCDIR) $(DINCDIR) $(UINCDIR))
LLIBDIR = $(patsubst %,-L%,$(DLIBDIR) $(ULIBDIR))
# Macros
DEFS = $(DDEFS) $(UDEFS)
ADEFS = $(DADEFS) $(UADEFS)
# Libs
LIBS = $(DLIBS) $(ULIBS)
# Various settings
MCFLAGS = -mcpu=$(MCU)
ODFLAGS = -x --syms
ASFLAGS = $(MCFLAGS) -Wa,-amhls=$(<:.s=.lst) $(ADEFS)
CFLAGS = $(MCFLAGS) $(OPT) $(CWARN) -Wa,-alms=$(<:.c=.lst) $(DEFS)
CPPFLAGS = $(MCFLAGS) $(OPT) $(CPPOPT) $(CPPWARN) -Wa,-alms=$(<:.cpp=.lst) $(DEFS)
ifeq ($(LINK_GC),yes)
LDFLAGS = $(MCFLAGS) -nostartfiles -T$(LDSCRIPT) -Wl,-Map=$(PROJECT).map,--cref,--no-warn-mismatch,--gc-sections $(LLIBDIR)
else
LDFLAGS = $(MCFLAGS) -nostartfiles -T$(LDSCRIPT) -Wl,-Map=$(PROJECT).map,--cref,--no-warn-mismatch $(LLIBDIR)
endif
# Thumb interwork enabled only if needed because it kills performance.
ifneq ($(TSRC),)
CFLAGS += -DTHUMB_PRESENT
CPPFLAGS += -DTHUMB_PRESENT
ASFLAGS += -DTHUMB_PRESENT
ifneq ($(ASRC),)
# Mixed ARM and THUMB mode.
CFLAGS += -mthumb-interwork
CPPFLAGS += -mthumb-interwork
ASFLAGS += -mthumb-interwork
LDFLAGS += -mthumb-interwork
else
# Pure THUMB mode, THUMB C code cannot be called by ARM asm code directly.
CFLAGS += -mno-thumb-interwork -DTHUMB_NO_INTERWORKING
CPPFLAGS += -mno-thumb-interwork -DTHUMB_NO_INTERWORKING
ASFLAGS += -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -mthumb
LDFLAGS += -mno-thumb-interwork -mthumb
endif
else
# Pure ARM mode
CPFLAGS += -mno-thumb-interwork
CPPFLAGS += -mno-thumb-interwork
ASFLAGS += -mno-thumb-interwork
LDFLAGS += -mno-thumb-interwork
endif
# Generate dependency information
CFLAGS += -MD -MP -MF .dep/$(@F).d
CPPFLAGS += -MD -MP -MF .dep/$(@F).d
#
# Makefile rules
#
all: $(OBJS) $(PROJECT).elf $(PROJECT).hex $(PROJECT).bin $(PROJECT).dmp
$(ACPPOBJS) : %.o : %.cpp
@echo
$(CPPC) -c $(CPPFLAGS) $(AOPT) -I . $(IINCDIR) $< -o $@
$(TCPPOBJS) : %.o : %.cpp
@echo
$(CPPC) -c $(CPPFLAGS) $(TOPT) -I . $(IINCDIR) $< -o $@
$(ACOBJS) : %.o : %.c
@echo
$(CC) -c $(CFLAGS) $(AOPT) -I . $(IINCDIR) $< -o $@
$(TCOBJS) : %.o : %.c
@echo
$(CC) -c $(CFLAGS) $(TOPT) -I . $(IINCDIR) $< -o $@
$(ASMOBJS) : %.o : %.s
@echo
$(AS) -c $(ASFLAGS) -I . $(IINCDIR) $< -o $@
%elf: $(OBJS)
@echo
$(LD) $(OBJS) $(LDFLAGS) $(LIBS) -o $@
%hex: %elf
$(HEX) $< $@
%bin: %elf
$(BIN) $< $@
%dmp: %elf
$(OD) $(ODFLAGS) $< > $@
clean:
-rm -f $(OBJS)
-rm -f $(ACSRC:.c=.lst) $(TCSRC:.c=.lst) $(ACPPSRC:.cpp=.lst) $(TCPPSRC:.cpp=.lst) $(ASMSRC:.s=.lst)
-rm -f $(PROJECT).elf $(PROJECT).dmp $(PROJECT).map $(PROJECT).hex $(PROJECT).bin
-rm -fR .dep
#
# Include the dependency files, should be the last of the makefile
#
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# *** EOF ***

View File

@ -1,156 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Parts of this file are borrowed by the Linux include file linux/mii.h:
* Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com)
*/
#ifndef _MII_H_
#define _MII_H_
/* Generic MII registers. */
#define MII_BMCR 0x00 /* Basic mode control register */
#define MII_BMSR 0x01 /* Basic mode status register */
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
#define MII_LPA 0x05 /* Link partner ability reg */
#define MII_EXPANSION 0x06 /* Expansion register */
#define MII_CTRL1000 0x09 /* 1000BASE-T control */
#define MII_STAT1000 0x0a /* 1000BASE-T status */
#define MII_ESTATUS 0x0f /* Extended Status */
#define MII_DCOUNTER 0x12 /* Disconnect counter */
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
#define MII_RERRCOUNTER 0x15 /* Receive error counter */
#define MII_SREVISION 0x16 /* Silicon revision */
#define MII_RESV1 0x17 /* Reserved... */
#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
#define MII_PHYADDR 0x19 /* PHY address */
#define MII_RESV2 0x1a /* Reserved... */
#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
#define MII_NCONFIG 0x1c /* Network interface config */
/* Basic mode control register. */
#define BMCR_RESV 0x003f /* Unused... */
#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
#define BMCR_CTST 0x0080 /* Collision test */
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
/* Basic mode status register. */
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
#define BMSR_JCD 0x0002 /* Jabber detected */
#define BMSR_LSTATUS 0x0004 /* Link status */
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_RESV 0x00c0 /* Unused... */
#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */
#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
/* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
#define ADVERTISE_RESV 0x1000 /* Unused... */
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
ADVERTISE_CSMA)
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
ADVERTISE_100HALF | ADVERTISE_100FULL)
/* Link partner ability register. */
#define LPA_SLCT 0x001f /* Same as advertise selector */
#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */
#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */
#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */
#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/
#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
#define LPA_PAUSE_CAP 0x0400 /* Can pause */
#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */
#define LPA_RESV 0x1000 /* Unused... */
#define LPA_RFAULT 0x2000 /* Link partner faulted */
#define LPA_LPACK 0x4000 /* Link partner acked us */
#define LPA_NPAGE 0x8000 /* Next page bit */
#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
/* Expansion register for auto-negotiation. */
#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */
#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */
#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */
#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */
#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
#define EXPANSION_RESV 0xffe0 /* Unused... */
#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */
#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */
/* N-way test register. */
#define NWAYTEST_RESV1 0x00ff /* Unused... */
#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
#define NWAYTEST_RESV2 0xfe00 /* Unused... */
/* 1000BASE-T Control register */
#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */
#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */
/* 1000BASE-T Status register */
#define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */
#define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */
#define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */
#define LPA_1000HALF 0x0400 /* Link partner 1000BASE-T half duplex */
#define MII_DM9161_ID 0x0181b8a0
#define MII_AM79C875_ID 0x00225540
#define MII_MICREL_ID 0x00221610
#endif /* _MII_H_ */

View File

@ -1,116 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-AT91SAM7X/pal_lld.c
* @brief AT91SAM7X PIO low level driver code
* @addtogroup AT91SAM7X_PAL
* @{
*/
#include <ch.h>
#include <pal.h>
/**
* @brief AT91SAM7X I/O ports configuration.
* @details PIO registers initialization.
*
* @param[in] config the AT91SAM7X ports configuration
*/
void _pal_lld_init(const AT91SAM7XPIOConfig *config) {
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA) | (1 << AT91C_ID_PIOB);
/*
* PIOA setup.
*/
AT91C_BASE_PIOA->PIO_OER = config->P0Data.pusr; /* Pull-up as spec.*/
AT91C_BASE_PIOA->PIO_ODR = ~config->P0Data.pusr;
AT91C_BASE_PIOA->PIO_PER = 0xFFFFFFFF; /* PIO enabled.*/
AT91C_BASE_PIOA->PIO_ODSR = config->P0Data.odsr; /* Data as specified.*/
AT91C_BASE_PIOA->PIO_OER = config->P0Data.osr; /* Dir. as specified.*/
AT91C_BASE_PIOA->PIO_ODR = ~config->P0Data.osr;
AT91C_BASE_PIOA->PIO_IFDR = 0xFFFFFFFF; /* Filter disabled.*/
AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF; /* Int. disabled.*/
AT91C_BASE_PIOA->PIO_MDDR = 0xFFFFFFFF; /* Push Pull drive.*/
AT91C_BASE_PIOA->PIO_ASR = 0xFFFFFFFF; /* Peripheral A.*/
AT91C_BASE_PIOA->PIO_OWER = 0xFFFFFFFF; /* Write enabled.*/
/*
* PIOB setup.
*/
AT91C_BASE_PIOB->PIO_OER = config->P0Data.pusr; /* Pull-up as spec.*/
AT91C_BASE_PIOB->PIO_ODR = ~config->P0Data.pusr;
AT91C_BASE_PIOB->PIO_PER = 0xFFFFFFFF; /* PIO enabled.*/
AT91C_BASE_PIOB->PIO_ODSR = config->P1Data.odsr; /* Data as specified.*/
AT91C_BASE_PIOB->PIO_OER = config->P1Data.osr; /* Dir. as specified.*/
AT91C_BASE_PIOB->PIO_ODR = ~config->P1Data.osr;
AT91C_BASE_PIOB->PIO_IFDR = 0xFFFFFFFF; /* Filter disabled.*/
AT91C_BASE_PIOB->PIO_IDR = 0xFFFFFFFF; /* Int. disabled.*/
AT91C_BASE_PIOB->PIO_MDDR = 0xFFFFFFFF; /* Push Pull drive.*/
AT91C_BASE_PIOB->PIO_ASR = 0xFFFFFFFF; /* Peripheral A.*/
AT91C_BASE_PIOB->PIO_OWER = 0xFFFFFFFF; /* Write enabled.*/
}
/**
* @brief Pads mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note @p PAL_MODE_RESET is implemented as input with pull-up.
* @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with high
* state.
* @note @p PAL_MODE_OUTPUT_OPENDRAIN also enables the pull-up resistor.
*/
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode) {
switch (mode & PAL_MODE_MASK) {
case PAL_MODE_RESET:
case PAL_MODE_INPUT_PULLUP:
port->PIO_PPUER = mask;
port->PIO_ODR = mask;
break;
case PAL_MODE_INPUT:
port->PIO_PPUDR = mask;
port->PIO_ODR = mask;
break;
case PAL_MODE_UNCONNECTED:
port->PIO_SODR = mask;
/* Falls in */
case PAL_MODE_OUTPUT_PUSHPULL:
port->PIO_PPUDR = mask;
port->PIO_OER = mask;
port->PIO_MDDR = mask;
break;
case PAL_MODE_OUTPUT_OPENDRAIN:
port->PIO_PPUER = mask;
port->PIO_OER = mask;
port->PIO_MDER = mask;
}
}
/** @} */

View File

@ -1,245 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-AT91SAM7X/pal_lld.h
* @brief AT91SAM7X PIO low level driver header
* @addtogroup AT91SAM7X_PAL
* @{
*/
#ifndef _PAL_LLD_H_
#define _PAL_LLD_H_
#include "at91lib/AT91SAM7X256.h"
/*===========================================================================*/
/* Unsupported modes and specific modes */
/*===========================================================================*/
#undef PAL_MODE_INPUT_PULLDOWN
/*===========================================================================*/
/* I/O Ports Types and constants. */
/*===========================================================================*/
/**
* @brief PIO port setup info.
*/
typedef struct {
/** Initial value for ODSR register (data).*/
uint32_t odsr;
/** Initial value for OSR register (direction).*/
uint32_t osr;
/** Initial value for PUSR register (Pull-ups).*/
uint32_t pusr;
} at91sam7x_pio_setup_t;
/**
* @brief AT91SAM7X PIO static initializer.
* @details An instance of this structure must be passed to @p palInit() at
* system startup time in order to initialized the digital I/O
* subsystem. This represents only the initial setup, specific pads
* or whole ports can be reprogrammed at later time.
*/
typedef struct {
/** @brief Port 0 setup data.*/
at91sam7x_pio_setup_t P0Data;
/** @brief Port 1 setup data.*/
at91sam7x_pio_setup_t P1Data;
} AT91SAM7XPIOConfig;
/**
* @brief Width, in bits, of an I/O port.
*/
#define PAL_IOPORTS_WIDTH 32
/**
* @brief Digital I/O port sized unsigned type.
*/
typedef uint32_t ioportmask_t;
/**
* @brief Port Identifier.
* @details This type can be a scalar or some kind of pointer, do not make
* any assumption about it, use the provided macros when populating
* variables of this type.
*/
typedef AT91PS_PIO ioportid_t;
/*===========================================================================*/
/* I/O Ports Identifiers. */
/*===========================================================================*/
/**
* @brief PIO port A identifier.
*/
#define IOPORT_A AT91C_BASE_PIOA
/**
* @brief PIO port B identifier.
*/
#define IOPORT_B AT91C_BASE_PIOB
/*===========================================================================*/
/* Implementation, some of the following macros could be implemented as */
/* functions, if so please put them in a file named pal_lld.c. */
/*===========================================================================*/
/**
* @brief Low level PAL subsystem initialization.
*/
#define pal_lld_init(config) _pal_lld_init(config)
/**
* @brief Reads the physical I/O port states.
* @details This function is implemented by reading the PIO_PDSR register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @return The port bits.
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_readport(port) ((port)->PIO_PDSR)
/**
* @brief Reads the output latch.
* @details This function is implemented by reading the PIO_ODSR register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @return The latched logical states.
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_readlatch(port) ((port)->PIO_ODSR)
/**
* @brief Writes a bits mask on a I/O port.
* @details This function is implemented by writing the PIO_ODSR register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be written on the specified port
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_writeport(port, bits) { \
(port)->PIO_ODSR = (bits); \
}
/**
* @brief Sets a bits mask on a I/O port.
* @details This function is implemented by writing the PIO_SODR register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be ORed on the specified port
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_setport(port, bits) { \
(port)->PIO_SODR = (bits); \
}
/**
* @brief Clears a bits mask on a I/O port.
* @details This function is implemented by writing the PIO_CODR register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be cleared on the specified port
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_clearport(port, bits) { \
(port)->PIO_CODR = (bits); \
}
/**
* @brief Writes a group of bits.
* @details This function is implemented by writing the PIO_OWER, PIO_ODSR and
* PIO_OWDR registers, the implementation is not atomic because the
* multiple accesses.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] offset the group bit offset within the port
* @param[in] bits the bits to be written. Values exceeding the group width
* are masked.
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_writegroup(port, mask, offset, bits) { \
(port)->PIO_OWER = (mask) << (offset); \
(port)->PIO_ODSR = (bits) << (offset); \
(port)->PIO_OWDR = (mask) << (offset); \
}
/**
* @brief Pads group mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with high
* state.
*/
#define pal_lld_setgroupmode(port, mask, mode) \
_pal_lld_setgroupmode(port, mask, mode)
/**
* @brief Writes a logical state on an output pad.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
* @param[out] bit the logical value, the value must be @p 0 or @p 1
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit)
#ifdef __cplusplus
extern "C" {
#endif
void _pal_lld_init(const AT91SAM7XPIOConfig *config);
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode);
#ifdef __cplusplus
}
#endif
#endif /* _PAL_LLD_H_ */
/** @} */

View File

@ -1,73 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @defgroup AT91SAM7X AT91SAM7X Support
* @brief AT91SAM7X specific support.
* @details The AT91SAM7X support includes:
* - Buffered, interrupt driven, serial driver.
* - EMAC driver with MII support.
* - A demo supporting the kernel test suite.
* - A Web server demo using the uIP TCP/IP stack.
* .
* @ingroup ARM7
*/
/**
* @defgroup AT91SAM7X_PAL I/O Ports Support
* @brief I/O Ports peripherals support.
* @details This module supports the AT91SAM7X PIO controller. The controller
* supports the following features (see @ref PAL):
* - 32 bits wide ports.
* - Atomic set/reset functions.
* - Output latched regardless of the pad setting.
* - Direct read of input pads regardless of the pad setting.
* .
* <h2>Supported Setup Modes</h2>
* - @p PAL_MODE_RESET.
* - @p PAL_MODE_UNCONNECTED.
* - @p PAL_MODE_INPUT.
* - @p PAL_MODE_INPUT_PULLUP.
* - @p PAL_MODE_OUTPUT_PUSHPULL.
* - @p PAL_MODE_OUTPUT_OPENDRAIN.
* .
* Any attempt to setup an invalid mode is ignored.
*
* <h2>Suboptimal Behavior</h2>
* Some PIO features are less than optimal:
* - Pad/port toggling operations are not atomic.
* - Pad/group mode setup is not atomic.
* .
* @ingroup AT91SAM7X
*/
/**
* @defgroup AT91SAM7X_SERIAL USART Support
* @brief USART peripherals support.
* @details The serial driver supports the AT91SAM7X USART peripherals.
*
* @ingroup AT91SAM7X
*/
/**
* @defgroup AT91SAM7X_EMAC EMAC Support
* @brief EMAC peripheral support.
*
* @ingroup AT91SAM7X
*/

View File

@ -1,418 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-AT91SAM7X/sam7x_emac.c
* @brief AT91SAM7X EMAC driver code.
* @addtogroup AT91SAM7X_EMAC
* @{
*/
#include <string.h>
#include <ch.h>
#include "board.h"
#include "sam7x_emac.h"
#include "mii.h"
#include "at91lib/aic.h"
EventSource EMACFrameTransmitted; /* A frame was transmitted. */
EventSource EMACFrameReceived; /* A frame was received. */
#ifndef __DOXYGEN__
//static int received; /* Buffered frames counter. */
static bool_t link_up; /* Last from EMACGetLinkStatus()*/
static uint8_t default_mac[] = {0xAA, 0x55, 0x13, 0x37, 0x01, 0x10};
static BufDescriptorEntry rent[EMAC_RECEIVE_BUFFERS] __attribute__((aligned(8)));
static uint8_t rbuffers[EMAC_RECEIVE_BUFFERS * EMAC_RECEIVE_BUFFERS_SIZE] __attribute__((aligned(8)));
static BufDescriptorEntry *rxptr;
static BufDescriptorEntry tent[EMAC_TRANSMIT_BUFFERS] __attribute__((aligned(8)));
static uint8_t tbuffers[EMAC_TRANSMIT_BUFFERS * EMAC_TRANSMIT_BUFFERS_SIZE] __attribute__((aligned(8)));
static BufDescriptorEntry *txptr;
#endif
#define AT91C_PB15_ERXDV AT91C_PB15_ERXDV_ECRSDV
#define EMAC_PIN_MASK (AT91C_PB0_ETXCK_EREFCK | \
AT91C_PB1_ETXEN | AT91C_PB2_ETX0 | \
AT91C_PB3_ETX1 | AT91C_PB4_ECRS | \
AT91C_PB5_ERX0 | AT91C_PB6_ERX1 | \
AT91C_PB7_ERXER | AT91C_PB8_EMDC | \
AT91C_PB9_EMDIO | AT91C_PB10_ETX2 | \
AT91C_PB11_ETX3 | AT91C_PB12_ETXER | \
AT91C_PB13_ERX2 | AT91C_PB14_ERX3 | \
AT91C_PB15_ERXDV | AT91C_PB16_ECOL | \
AT91C_PB17_ERXCK)
#define PHY_LATCHED_PINS (AT91C_PB4_ECRS | AT91C_PB5_ERX0 | AT91C_PB6_ERX1 | \
AT91C_PB7_ERXER | AT91C_PB13_ERX2 | AT91C_PB14_ERX3 | \
AT91C_PB15_ERXDV | AT91C_PB16_ECOL | PIOB_PHY_IRQ_MASK)
/*
* PHY utilities.
*/
static uint32_t phy_get(uint8_t regno) {
AT91C_BASE_EMAC->EMAC_MAN = (1 << 30) | // SOF = 01
(2 << 28) | // RW = 10
(PHY_ADDRESS << 23) |
(regno << 18) |
(2 << 16); // CODE = 10
while (!( AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE))
;
return AT91C_BASE_EMAC->EMAC_MAN & 0xFFFF;
}
/*static void phy_put(uint8_t regno, uint32_t val) {
AT91C_BASE_EMAC->EMAC_MAN = (1 << 30) | // SOF = 01
(1 << 28) | // RW = 01
(PHY_ADDRESS << 23) |
(regno << 18) |
(2 << 16) | // CODE = 10
val;
while (!( AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE))
;
}*/
#define RSR_BITS (AT91C_EMAC_BNA | AT91C_EMAC_REC | AT91C_EMAC_OVR)
#define TSR_BITS (AT91C_EMAC_UBR | AT91C_EMAC_COL | AT91C_EMAC_RLES | \
AT91C_EMAC_BEX | AT91C_EMAC_COMP | AT91C_EMAC_UND)
__attribute__((noinline))
static void ServeInterrupt(void) {
uint32_t isr, rsr, tsr;
/* Fix for the EMAC errata */
isr = AT91C_BASE_EMAC->EMAC_ISR;
rsr = AT91C_BASE_EMAC->EMAC_RSR;
tsr = AT91C_BASE_EMAC->EMAC_TSR;
if ((isr & AT91C_EMAC_RCOMP) || (rsr & RSR_BITS)) {
if (rsr & AT91C_EMAC_REC) {
// received++;
chSysLockFromIsr();
chEvtBroadcastI(&EMACFrameReceived);
chSysUnlockFromIsr();
}
AT91C_BASE_EMAC->EMAC_RSR = RSR_BITS;
}
if ((isr & AT91C_EMAC_TCOMP) || (tsr & TSR_BITS)) {
if (tsr & AT91C_EMAC_COMP) {
chSysLockFromIsr();
chEvtBroadcastI(&EMACFrameTransmitted);
chSysUnlockFromIsr();
}
AT91C_BASE_EMAC->EMAC_TSR = TSR_BITS;
}
AT91C_BASE_AIC->AIC_EOICR = 0;
}
CH_IRQ_HANDLER(EMACIrqHandler) {
CH_IRQ_PROLOGUE();
ServeInterrupt();
CH_IRQ_EPILOGUE();
}
/*
* EMAC subsystem initialization.
*/
void emac_init(int prio) {
int i;
/*
* Buffers initialization.
*/
// received = 0;
for (i = 0; i < EMAC_RECEIVE_BUFFERS; i++) {
rent[i].w1 = (uint32_t)&rbuffers[i * EMAC_RECEIVE_BUFFERS_SIZE];
rent[i].w2 = 0;
}
rent[EMAC_RECEIVE_BUFFERS - 1].w1 |= W1_R_WRAP;
rxptr = rent;
for (i = 0; i < EMAC_TRANSMIT_BUFFERS; i++) {
tent[i].w1 = (uint32_t)&tbuffers[i * EMAC_TRANSMIT_BUFFERS_SIZE];
tent[i].w2 = EMAC_TRANSMIT_BUFFERS_SIZE | W2_T_USED;
}
tent[EMAC_TRANSMIT_BUFFERS - 1].w2 |= W2_T_WRAP;
txptr = tent;
/*
* Disables the pullups on all the pins that are latched on reset by the PHY.
* The status latched into the PHY is:
* PHYADDR = 00001
* PCS_LPBK = 0 (disabled)
* ISOLATE = 0 (disabled)
* RMIISEL = 0 (MII mode)
* RMIIBTB = 0 (BTB mode disabled)
* SPEED = 1 (100mbps)
* DUPLEX = 1 (full duplex)
* ANEG_EN = 1 (auto negotiation enabled)
*/
AT91C_BASE_PIOB->PIO_PPUDR = PHY_LATCHED_PINS;
/*
* PHY power control.
*/
AT91C_BASE_PIOB->PIO_OER = PIOB_PHY_PD_MASK; // Becomes an output.
AT91C_BASE_PIOB->PIO_PPUDR = PIOB_PHY_PD_MASK; // Default pullup disabled.
AT91C_BASE_PIOB->PIO_SODR = PIOB_PHY_PD_MASK; // Output to high level.
/*
* PHY reset by pulsing the NRST pin.
*/
AT91C_BASE_RSTC->RSTC_RMR = 0xA5000100;
AT91C_BASE_RSTC->RSTC_RCR = 0xA5000000 | AT91C_RSTC_EXTRST;
while (!(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL))
;
/*
* EMAC pins setup and clock enable. Note, PB18 is not included because it is
* used as #PD control and not as EF100.
*/
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_EMAC;
AT91C_BASE_PIOB->PIO_ASR = EMAC_PIN_MASK;
AT91C_BASE_PIOB->PIO_PDR = EMAC_PIN_MASK;
AT91C_BASE_PIOB->PIO_PPUDR = EMAC_PIN_MASK;
/*
* EMAC setup.
*/
AT91C_BASE_EMAC->EMAC_NCR = 0; // Initial setting.
AT91C_BASE_EMAC->EMAC_NCFGR = 2 << 10; // MDC-CLK = MCK / 32
AT91C_BASE_EMAC->EMAC_USRIO = AT91C_EMAC_CLKEN; // Enable EMAC in MII mode
AT91C_BASE_EMAC->EMAC_RBQP = (AT91_REG)rent; // RX buffers list
AT91C_BASE_EMAC->EMAC_TBQP = (AT91_REG)tent; // TX buffers list
AT91C_BASE_EMAC->EMAC_RSR = AT91C_EMAC_OVR |
AT91C_EMAC_REC |
AT91C_EMAC_BNA; // Clears RSR
AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_DRFCS; // Initial NCFGR settings
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TE |
AT91C_EMAC_RE |
AT91C_EMAC_CLRSTAT; // Initial NCR settings
EMACSetAddress(default_mac);
/*
* PHY detection and settings.
*/
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE;
if ((phy_get(MII_PHYSID1) != (MII_MICREL_ID >> 16)) ||
((phy_get(MII_PHYSID2) & 0xFFF0) != (MII_MICREL_ID & 0xFFF0)))
chSysHalt();
/*
* Waits for auto-negotiation to end and then detects the link status.
*/
AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
/*
* Interrupt setup.
*/
AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP | AT91C_EMAC_TCOMP;
AIC_ConfigureIT(AT91C_ID_EMAC,
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | prio,
EMACIrqHandler);
AIC_EnableIT(AT91C_ID_EMAC);
/*
* Event sources setup.
*/
chEvtInit(&EMACFrameTransmitted);
chEvtInit(&EMACFrameReceived);
}
/*
* Set the MAC address.
*/
void EMACSetAddress(const uint8_t *eaddr) {
AT91C_BASE_EMAC->EMAC_SA1L = (AT91_REG)((eaddr[3] << 24) | (eaddr[2] << 16) |
(eaddr[1] << 8) | eaddr[0]);
AT91C_BASE_EMAC->EMAC_SA1H = (AT91_REG)((eaddr[5] << 8) | eaddr[4]);
}
/*
* Returns TRUE if the link is active. To be invoked at regular intervals in
* order to monitor the link.
* @note It is not thread-safe.
*/
bool_t EMACGetLinkStatus(void) {
uint32_t ncfgr, bmsr, bmcr, lpa;
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE;
(void)phy_get(MII_BMSR);
bmsr = phy_get(MII_BMSR);
if (!(bmsr & BMSR_LSTATUS)) {
AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
return link_up = FALSE;
}
ncfgr = AT91C_BASE_EMAC->EMAC_NCFGR & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
bmcr = phy_get(MII_BMCR);
if (bmcr & BMCR_ANENABLE) {
lpa = phy_get(MII_LPA);
if (lpa & (LPA_100HALF | LPA_100FULL | LPA_100BASE4))
ncfgr |= AT91C_EMAC_SPD;
if (lpa & (LPA_10FULL | LPA_100FULL))
ncfgr |= AT91C_EMAC_FD;
}
else {
if (bmcr & BMCR_SPEED100)
ncfgr |= AT91C_EMAC_SPD;
if (bmcr & BMCR_FULLDPLX)
ncfgr |= AT91C_EMAC_FD;
}
AT91C_BASE_EMAC->EMAC_NCFGR = ncfgr;
AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
return link_up = TRUE;
}
/*
* Allocates and locks a buffer for a transmission operation.
*/
BufDescriptorEntry *EMACGetTransmitBuffer(void) {
BufDescriptorEntry *cptr;
if (!link_up)
return NULL;
chSysLock();
cptr = txptr;
if (!(cptr->w2 & W2_T_USED) ||
(cptr->w2 & W2_T_LOCKED)) {
chSysUnlock();
return FALSE;
}
cptr->w2 |= W2_T_LOCKED; /* Locks the buffer while copying.*/
if (++txptr >= &tent[EMAC_TRANSMIT_BUFFERS])
txptr = tent;
chSysUnlock();
return cptr;
}
/*
* Transmits a previously allocated buffer and then releases it.
*/
void EMACTransmit(BufDescriptorEntry *cptr, size_t size) {
chDbgAssert(size <= EMAC_TRANSMIT_BUFFERS_SIZE,
"EMACTransmit(), #1",
"unexpected size");
chSysLock();
if (cptr < &tent[EMAC_TRANSMIT_BUFFERS - 1])
cptr->w2 = size | W2_T_LAST_BUFFER;
else
cptr->w2 = size | W2_T_LAST_BUFFER | W2_T_WRAP;
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TSTART;
chSysUnlock();
}
/*
* Reads a buffered frame.
* Returns TRUE if a frame was present and read else FALSE.
* @note It is not thread-safe.
*/
bool_t EMACReceive(uint8_t *buf, size_t *sizep) {
unsigned n;
size_t size;
uint8_t *p;
bool_t overflow, found;
// chSysLock();
// if (received <= 0) {
// chSysUnlock();
// return FALSE;
// }
// received--;
// chSysUnlock();
n = EMAC_RECEIVE_BUFFERS;
/*
* Skips unused buffers, if any.
*/
skip:
while (n && !(rxptr->w1 & W1_R_OWNERSHIP)) {
if (++rxptr >= &rent[EMAC_RECEIVE_BUFFERS])
rxptr = rent;
n--;
}
/*
* Skips fragments, if any.
*/
while (n && (rxptr->w1 & W1_R_OWNERSHIP) && !(rxptr->w2 & W2_R_FRAME_START)) {
rxptr->w1 &= ~W1_R_OWNERSHIP;
if (++rxptr >= &rent[EMAC_RECEIVE_BUFFERS])
rxptr = rent;
n--;
}
restart:
p = buf;
size = 0;
found = overflow = FALSE;
while (n && !found) {
size_t segsize;
if (!(rxptr->w1 & W1_R_OWNERSHIP))
goto skip; /* Empty buffer for some reason... */
if (size && (rxptr->w2 & W2_R_FRAME_START))
goto restart; /* Another start buffer for some reason... */
if (rxptr->w2 & W2_R_FRAME_END) {
segsize = (rxptr->w2 & W2_T_LENGTH_MASK) - size;
if (((rxptr->w2 & W2_T_LENGTH_MASK) > *sizep) ||
(segsize > EMAC_RECEIVE_BUFFERS_SIZE))
overflow = TRUE;
found = TRUE;
}
else {
segsize = EMAC_RECEIVE_BUFFERS_SIZE;
if (size + segsize > *sizep)
overflow = TRUE;
}
if (!overflow) {
chDbgAssert(segsize <= 128, "EMACReceive(), #1", "");
memcpy(p, (void *)(rxptr->w1 & W1_R_ADDRESS_MASK), segsize);
p += segsize;
size += segsize;
}
rxptr->w1 &= ~W1_R_OWNERSHIP;
if (++rxptr >= &rent[EMAC_RECEIVE_BUFFERS])
rxptr = rent;
n--;
}
*sizep = size;
return found && !overflow;
}
/** @} */

View File

@ -1,93 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-AT91SAM7X/sam7x_emac.h
* @brief AT91SAM7X EMAC driver macros and structures.
* @addtogroup AT91SAM7X_EMAC
* @{
*/
#ifndef _SAM7X_EMAC_H_
#define _SAM7X_EMAC_H_
#define PHY_ADDRESS 1
#define EMAC_RECEIVE_BUFFERS 24
#define EMAC_RECEIVE_BUFFERS_SIZE 128
#define EMAC_TRANSMIT_BUFFERS 2
#define EMAC_TRANSMIT_BUFFERS_SIZE 1518
typedef struct {
uint32_t w1;
uint32_t w2;
} BufDescriptorEntry;
#define W1_R_OWNERSHIP 0x00000001
#define W1_R_WRAP 0x00000002
#define W1_R_ADDRESS_MASK 0xFFFFFFFC
#define W2_R_LENGTH_MASK 0x00000FFF
#define W2_R_FRAME_START 0x00004000
#define W2_R_FRAME_END 0x00008000
#define W2_R_CFI 0x00010000
#define W2_R_VLAN_PRIO_MASK 0x000E0000
#define W2_R_PRIO_TAG_DETECTED 0x00100000
#define W2_R_VLAN_TAG_DETECTED 0x00200000
#define W2_R_TYPE_ID_MATCH 0x00400000
#define W2_R_ADDR4_MATCH 0x00800000
#define W2_R_ADDR3_MATCH 0x01000000
#define W2_R_ADDR2_MATCH 0x02000000
#define W2_R_ADDR1_MATCH 0x04000000
#define W2_R_RFU1 0x08000000
#define W2_R_ADDR_EXT_MATCH 0x10000000
#define W2_R_UNICAST_MATCH 0x20000000
#define W2_R_MULTICAST_MATCH 0x40000000
#define W2_R_BROADCAST_DETECTED 0x80000000
#define W2_T_LENGTH_MASK 0x000007FF
#define W2_T_LOCKED 0x00000800 /* Not an EMAC flag, used by the driver */
#define W2_T_RFU1 0x00003000
#define W2_T_LAST_BUFFER 0x00008000
#define W2_T_NO_CRC 0x00010000
#define W2_T_RFU2 0x07FE0000
#define W2_T_BUFFERS_EXHAUSTED 0x08000000
#define W2_T_TRANSMIT_UNDERRUN 0x10000000
#define W2_T_RETRY_LIMIT_EXC 0x20000000
#define W2_T_WRAP 0x40000000
#define W2_T_USED 0x80000000
#ifdef __cplusplus
extern "C" {
#endif
void emac_init(int prio);
void EMACSetAddress(const uint8_t *eaddr);
bool_t EMACGetLinkStatus(void);
BufDescriptorEntry *EMACGetTransmitBuffer(void);
void EMACTransmit(BufDescriptorEntry *cptr, size_t size);
bool_t EMACReceive(uint8_t *buf, size_t *sizep);
#ifdef __cplusplus
}
#endif
extern EventSource EMACFrameTransmitted, EMACFrameReceived;
#endif /* _SAM7X_EMAC_H_ */
/** @} */

View File

@ -1,224 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-AT91SAM7X/sam7x_serial.c
* @brief AT91SAM7X Serial driver code.
* @addtogroup AT91SAM7X_SERIAL
* @{
*/
#include <ch.h>
#include "board.h"
#include "sam7x_serial.h"
#include "at91lib/aic.h"
#if USE_SAM7X_USART0 || defined(__DOXYGEN__)
/** @brief USART0 serial driver identifier.*/
FullDuplexDriver COM1;
static uint8_t ib1[SERIAL_BUFFERS_SIZE];
static uint8_t ob1[SERIAL_BUFFERS_SIZE];
#endif
#if USE_SAM7X_USART1 || defined(__DOXYGEN__)
/** @brief USART1 serial driver identifier.*/
FullDuplexDriver COM2;
static uint8_t ib2[SERIAL_BUFFERS_SIZE];
static uint8_t ob2[SERIAL_BUFFERS_SIZE];
#endif
static void SetError(AT91_REG csr, FullDuplexDriver *com) {
dflags_t sts = 0;
if (csr & AT91C_US_OVRE)
sts |= SD_OVERRUN_ERROR;
if (csr & AT91C_US_PARE)
sts |= SD_PARITY_ERROR;
if (csr & AT91C_US_FRAME)
sts |= SD_FRAMING_ERROR;
if (csr & AT91C_US_RXBRK)
sts |= SD_BREAK_DETECTED;
chSysLockFromIsr();
chFDDAddFlagsI(com, sts);
chSysUnlockFromIsr();
}
/** @cond never*/
__attribute__((noinline))
/** @endcond*/
/**
* @brief Common IRQ handler.
* @param[in] u pointer to an USART I/O block
* @param[in] com communication channel associated to the USART
*/
static void ServeInterrupt(AT91PS_USART u, FullDuplexDriver *com) {
if (u->US_CSR & AT91C_US_RXRDY) {
chSysLockFromIsr();
chFDDIncomingDataI(com, u->US_RHR);
chSysUnlockFromIsr();
}
if (u->US_CSR & AT91C_US_TXRDY) {
chSysLockFromIsr();
msg_t b = chFDDRequestDataI(com);
chSysUnlockFromIsr();
if (b < Q_OK)
u->US_IDR = AT91C_US_TXRDY;
else
u->US_THR = b;
}
if (u->US_CSR & (AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE | AT91C_US_RXBRK)) {
SetError(u->US_CSR, com);
u->US_CR = AT91C_US_RSTSTA;
}
AT91C_BASE_AIC->AIC_EOICR = 0;
}
#if USE_SAM7X_USART0 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(USART0IrqHandler) {
CH_IRQ_PROLOGUE();
ServeInterrupt(AT91C_BASE_US0, &COM1);
CH_IRQ_EPILOGUE();
}
static void OutNotify1(void) {
AT91C_BASE_US0->US_IER = AT91C_US_TXRDY;
}
#endif
#if USE_SAM7X_USART1 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(USART1IrqHandler) {
CH_IRQ_PROLOGUE();
ServeInterrupt(AT91C_BASE_US1, &COM2);
CH_IRQ_EPILOGUE();
}
static void OutNotify2(void) {
AT91C_BASE_US1->US_IER = AT91C_US_TXRDY;
}
#endif
/**
* @brief USART setup.
* @param[in] u pointer to an UART I/O block
* @param[in] speed serial port speed in bits per second
* @param[in] mr the value for the @p MR register
* @note Must be invoked with interrupts disabled.
* @note Does not reset the I/O queues.
*/
void usart_setup(AT91PS_USART u, int speed, int mr) {
/* Disables IRQ sources and stop operations.*/
u->US_IDR = 0xFFFFFFFF;
u->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RSTSTA;
/* New parameters setup.*/
if (mr & AT91C_US_OVER)
u->US_BRGR = MCK / (speed * 8);
else
u->US_BRGR = MCK / (speed * 16);
u->US_MR = mr;
u->US_RTOR = 0;
u->US_TTGR = 0;
/* Enables operations and IRQ sources.*/
u->US_CR = AT91C_US_RXEN | AT91C_US_TXEN | AT91C_US_DTREN | AT91C_US_RTSEN;
u->US_IER = AT91C_US_RXRDY | AT91C_US_OVRE | AT91C_US_FRAME | AT91C_US_PARE |
AT91C_US_RXBRK;
}
/**
* @brief Serial driver initialization.
* @param[in] prio0 priority to be assigned to the USART1 IRQ
* @param[in] prio1 priority to be assigned to the USART2 IRQ
* @note Handshake pads are not enabled inside this function because they
* may have another use, enable them externally if needed.
* RX and TX pads are handled inside.
*/
void serial_init(int prio0, int prio1) {
#if USE_SAM7X_USART0 || defined(__DOXYGEN__)
/* I/O queue setup.*/
chFDDInit(&COM1, ib1, sizeof ib1, NULL, ob1, sizeof ob1, OutNotify1);
/* Switches the I/O pins to the peripheral function A, disables pullups.*/
AT91C_BASE_PIOA->PIO_PDR = AT91C_PA0_RXD0 | AT91C_PA1_TXD0;
AT91C_BASE_PIOA->PIO_ASR = AT91C_PIO_PA0 | AT91C_PIO_PA1;
AT91C_BASE_PIOA->PIO_PPUDR = AT91C_PIO_PA0 | AT91C_PIO_PA1;
/* Starts the clock and clears possible sources of immediate interrupts.*/
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US0);
AT91C_BASE_US0->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RSTSTA;
/* Interrupts setup.*/
AIC_ConfigureIT(AT91C_ID_US0,
AT91C_AIC_SRCTYPE_HIGH_LEVEL | prio0,
USART0IrqHandler);
AIC_EnableIT(AT91C_ID_US0);
/* Default parameters.*/
usart_setup(AT91C_BASE_US0, DEFAULT_USART_BITRATE,
AT91C_US_USMODE_NORMAL |
AT91C_US_CLKS_CLOCK |
AT91C_US_CHRL_8_BITS |
AT91C_US_PAR_NONE |
AT91C_US_NBSTOP_1_BIT);
#endif
#if USE_SAM7X_USART1 || defined(__DOXYGEN__)
/* I/O queues setup.*/
chFDDInit(&COM2, ib2, sizeof ib2, NULL, ob2, sizeof ob2, OutNotify2);
/* Switches the I/O pins to the peripheral function A, disables pullups.*/
AT91C_BASE_PIOA->PIO_PDR = AT91C_PA5_RXD1 | AT91C_PA6_TXD1;
AT91C_BASE_PIOA->PIO_ASR = AT91C_PIO_PA5 | AT91C_PIO_PA6;
AT91C_BASE_PIOA->PIO_PPUDR = AT91C_PIO_PA5 | AT91C_PIO_PA6;
/* Starts the clock and clears possible sources of immediate interrupts.*/
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US1);
AT91C_BASE_US1->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RSTSTA;
/* Interrupts setup.*/
AIC_ConfigureIT(AT91C_ID_US1,
AT91C_AIC_SRCTYPE_HIGH_LEVEL | prio1,
USART1IrqHandler);
AIC_EnableIT(AT91C_ID_US1);
/* Default parameters.*/
usart_setup(AT91C_BASE_US1, DEFAULT_USART_BITRATE,
AT91C_US_USMODE_NORMAL |
AT91C_US_CLKS_CLOCK |
AT91C_US_CHRL_8_BITS |
AT91C_US_PAR_NONE |
AT91C_US_NBSTOP_1_BIT);
#endif
}
/** @} */

View File

@ -1,86 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-AT91SAM7X/sam7x_serial.h
* @brief AT91SAM7X Serial driver macros and structures.
* @addtogroup AT91SAM7X_SERIAL
* @{
*/
#ifndef _SAM7X_SERIAL_H_
#define _SAM7X_SERIAL_H_
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
* @note The default is 128 bytes for both the transmission and receive buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 128
#endif
/**
* @brief Default bit rate.
* @details Configuration parameter, at startup the UARTs are configured at
* this speed.
* @note It is possible to use @p SetUART() in order to change the working
* parameters at runtime.
*/
#if !defined(DEFAULT_USART_BITRATE) || defined(__DOXYGEN__)
#define DEFAULT_USART_BITRATE 38400
#endif
/**
* @brief UART0 driver enable switch.
* @details If set to @p TRUE the support for USART1 is included.
* @note The default is @p TRUE.
*/
#if !defined(USE_SAM7X_USART0) || defined(__DOXYGEN__)
#define USE_SAM7X_USART0 TRUE
#endif
/**
* @brief UART1 driver enable switch.
* @details If set to @p TRUE the support for USART2 is included.
* @note The default is @p TRUE.
*/
#if !defined(USE_SAM7X_USART1) || defined(__DOXYGEN__)
#define USE_SAM7X_USART1 TRUE
#endif
#ifdef __cplusplus
extern "C" {
#endif
void serial_init(int prio0, int prio1);
void usart_setup(AT91PS_USART u, int speed, int mr);
CH_IRQ_HANDLER(UART0IrqHandler);
CH_IRQ_HANDLER(UART1IrqHandler);
#ifdef __cplusplus
}
#endif
/** @cond never*/
extern FullDuplexDriver COM1, COM2;
/** @endcond*/
#endif /* _SAM7X_SERIAL_H_ */
/** @} */

View File

@ -1,74 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
.section vectors
.code 32
.balign 4
/*
* System entry points.
*/
_start:
ldr pc, _reset
ldr pc, _undefined
ldr pc, _swi
ldr pc, _prefetch
ldr pc, _abort
nop
ldr pc, [pc,#-0xF20] /* AIC - AIC_IVR */
ldr pc, [pc,#-0xF20] /* AIC - AIC_FVR */
_reset:
.word ResetHandler /* In crt0.s */
_undefined:
.word UndHandler
_swi:
.word SwiHandler
_prefetch:
.word PrefetchHandler
_abort:
.word AbortHandler
.word 0
.word 0
.word 0
.text
.code 32
.balign 4
/*
* Default exceptions handlers. The handlers are declared weak in order to be
* replaced by the real handling code. Everything is defaulted to an infinite
* loop.
*/
.weak UndHandler
UndHandler:
.weak SwiHandler
SwiHandler:
.weak PrefetchHandler
PrefetchHandler:
.weak AbortHandler
AbortHandler:
.weak FiqHandler
FiqHandler:
.loop: b .loop

View File

@ -1,35 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WFI_H_
#define _WFI_H_
#include "at91lib/AT91SAM7X256.h"
#ifndef port_wait_for_interrupt
#if ENABLE_WFI_IDLE != 0
#define port_wait_for_interrupt() { \
AT91C_BASE_SYS->PMC_SCDR = AT91C_PMC_PCK; \
}
#else
#define port_wait_for_interrupt()
#endif
#endif
#endif /* _WFI_H_ */

View File

@ -1,523 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file lpc214x.h
* @brief LPC214x register definitions
*/
#ifndef _LPC214X_H_
#define _LPC214X_H_
typedef volatile unsigned char IOREG8;
typedef volatile unsigned int IOREG32;
/*
* System.
*/
#define MEMMAP (*((IOREG32 *)0xE01FC040))
#define PCON (*((IOREG32 *)0xE01FC0C0))
#define PCONP (*((IOREG32 *)0xE01FC0C4))
#define VPBDIV (*((IOREG32 *)0xE01FC100))
#define EXTINT (*((IOREG32 *)0xE01FC140))
#define INTWAKE (*((IOREG32 *)0xE01FC144))
#define EXTMODE (*((IOREG32 *)0xE01FC148))
#define EXTPOLAR (*((IOREG32 *)0xE01FC14C))
#define RSID (*((IOREG32 *)0xE01FC180))
#define CSPR (*((IOREG32 *)0xE01FC184))
#define SCS (*((IOREG32 *)0xE01FC1A0))
#define VPD_D4 0
#define VPD_D1 1
#define VPD_D2 2
#define VPD_RESERVED 3
#define PCTIM0 (1 << 1)
#define PCTIM1 (1 << 2)
#define PCUART0 (1 << 3)
#define PCUART1 (1 << 4)
#define PCPWM0 (1 << 5)
#define PCI2C0 (1 << 7)
#define PCSPI0 (1 << 8)
#define PCRTC (1 << 9)
#define PCSPI1 (1 << 10)
#define PCAD0 (1 << 12)
#define PCI2C1 (1 << 19)
#define PCAD1 (1 << 20)
#define PCUSB (1 << 31)
#define PCALL (PCTIM0 | PCTIM1 | PCUART0 | PCUART1 | \
PCPWM0 | PCI2C0 | PCSPI0 | PCRTC | PCSPI1 | \
PCAD0 | PCI2C1 | PCAD1 | PCUSB)
#define EINT0 1
#define EINT1 2
#define EINT2 4
#define EINT3 8
#define EXTWAKE0 1
#define EXTWAKE1 2
#define EXTWAKE2 4
#define EXTWAKE3 8
#define USBWAKE 0x20
#define BODWAKE 0x4000
#define RTCWAKE 0x8000
#define EXTMODE0 1
#define EXTMODE1 2
#define EXTMODE2 4
#define EXTMODE3 8
#define EXTPOLAR0 1
#define EXTPOLAR1 2
#define EXTPOLAR2 4
#define EXTPOLAR3 8
typedef struct {
IOREG32 PLL_CON;
IOREG32 PLL_CFG;
IOREG32 PLL_STAT;
IOREG32 PLL_FEED;
} PLL;
#define PLL0Base ((PLL *)0xE01FC080)
#define PLL1Base ((PLL *)0xE01FC0A0)
#define PLL0CON (PLL0Base->PLL_CON)
#define PLL0CFG (PLL0Base->PLL_CFG)
#define PLL0STAT (PLL0Base->PLL_STAT)
#define PLL0FEED (PLL0Base->PLL_FEED)
#define PLL1CON (PLL1Base->PLL_CON)
#define PLL1CFG (PLL1Base->PLL_CFG)
#define PLL1STAT (PLL1Base->PLL_STAT)
#define PLL1FEED (PLL1Base->PLL_FEED)
/*
* Pins.
*/
typedef struct {
IOREG32 PS_SEL0;
IOREG32 PS_SEL1;
IOREG32 PS_SEL2;
} PS;
#define PSBase ((PS *)0xE002C000)
#define PINSEL0 (PSBase->PS_SEL0)
#define PINSEL1 (PSBase->PS_SEL1)
#define PINSEL2 (PSBase->PS_SEL2)
/*
* VIC
*/
#define SOURCE_WDT 0
#define SOURCE_ARMCore0 2
#define SOURCE_ARMCore1 3
#define SOURCE_Timer0 4
#define SOURCE_Timer1 5
#define SOURCE_UART0 6
#define SOURCE_UART1 7
#define SOURCE_PWM0 8
#define SOURCE_I2C0 9
#define SOURCE_SPI0 10
#define SOURCE_SPI1 11
#define SOURCE_PLL 12
#define SOURCE_RTC 13
#define SOURCE_EINT0 14
#define SOURCE_EINT1 15
#define SOURCE_EINT2 16
#define SOURCE_EINT3 17
#define SOURCE_ADC0 18
#define SOURCE_I2C1 19
#define SOURCE_BOD 20
#define SOURCE_ADC1 21
#define SOURCE_USB 22
#define INTMASK(n) (1 << (n))
#define ALLINTMASK (INTMASK(SOURCE_WDT) | INTMASK(SOURCE_ARMCore0) | \
INTMASK(SOURCE_ARMCore1) | INTMASK(SOURCE_Timer0) | \
INTMASK(SOURCE_Timer1) | INTMASK(SOURCE_UART0) | \
INTMASK(SOURCE_UART1) | INTMASK(SOURCE_PWM0) | \
INTMASK(SOURCE_I2C0) | INTMASK(SOURCE_SPI0) | \
INTMASK(SOURCE_SPI1) | INTMASK(SOURCE_PLL) | \
INTMASK(SOURCE_RTC) | INTMASK(SOURCE_EINT0) | \
INTMASK(SOURCE_EINT1) | INTMASK(SOURCE_EINT2) | \
INTMASK(SOURCE_EINT3) | INTMASK(SOURCE_ADC0) | \
INTMASK(SOURCE_I2C1) | INTMASK(SOURCE_BOD) | \
INTMASK(SOURCE_ADC1) | INTMASK(SOURCE_USB))
typedef struct {
IOREG32 VIC_IRQStatus;
IOREG32 VIC_FIQStatus;
IOREG32 VIC_RawIntr;
IOREG32 VIC_IntSelect;
IOREG32 VIC_IntEnable;
IOREG32 VIC_IntEnClear;
IOREG32 VIC_SoftInt;
IOREG32 VIC_SoftIntClear;
IOREG32 VIC_Protection;
IOREG32 unused1[3];
IOREG32 VIC_VectAddr;
IOREG32 VIC_DefVectAddr;
IOREG32 unused2[50];
IOREG32 VIC_VectAddrs[16];
IOREG32 unused3[48];
IOREG32 VIC_VectCntls[16];
} VIC;
#define VICBase ((VIC *)0xFFFFF000)
#define VICVectorsBase ((IOREG32 *)0xFFFFF100)
#define VICControlsBase ((IOREG32 *)0xFFFFF200)
#define VICIRQStatus (VICBase->VIC_IRQStatus)
#define VICFIQStatus (VICBase->VIC_FIQStatus)
#define VICRawIntr (VICBase->VIC_RawIntr)
#define VICIntSelect (VICBase->VIC_IntSelect)
#define VICIntEnable (VICBase->VIC_IntEnable)
#define VICIntEnClear (VICBase->VIC_IntEnClear)
#define VICSoftInt (VICBase->VIC_SoftInt)
#define VICSoftIntClear (VICBase->VIC_SoftIntClear)
#define VICProtection (VICBase->VIC_Protection)
#define VICVectAddr (VICBase->VIC_VectAddr)
#define VICDefVectAddr (VICBase->VIC_DefVectAddr)
#define VICVectAddrs(n) (VICBase->VIC_VectAddrs[n])
#define VICVectCntls(n) (VICBase->VIC_VectCntls[n])
/*
* MAM.
*/
typedef struct {
IOREG32 MAM_Control;
IOREG32 MAM_Timing;
} MAM;
#define MAMBase ((MAM *)0xE01FC000)
#define MAMCR (MAMBase->MAM_Control)
#define MAMTIM (MAMBase->MAM_Timing)
/*
* GPIO - FIO.
*/
typedef struct {
IOREG32 IO_PIN;
IOREG32 IO_SET;
IOREG32 IO_DIR;
IOREG32 IO_CLR;
} GPIO;
#define GPIO0Base ((GPIO *)0xE0028000)
#define IO0PIN (GPIO0Base->IO_PIN)
#define IO0SET (GPIO0Base->IO_SET)
#define IO0DIR (GPIO0Base->IO_DIR)
#define IO0CLR (GPIO0Base->IO_CLR)
#define GPIO1Base ((GPIO *)0xE0028010)
#define IO1PIN (GPIO1Base->IO_PIN)
#define IO1SET (GPIO1Base->IO_SET)
#define IO1DIR (GPIO1Base->IO_DIR)
#define IO1CLR (GPIO1Base->IO_CLR)
typedef struct {
IOREG32 FIO_DIR;
IOREG32 unused1;
IOREG32 unused2;
IOREG32 unused3;
IOREG32 FIO_MASK;
IOREG32 FIO_PIN;
IOREG32 FIO_SET;
IOREG32 FIO_CLR;
} FIO;
#define FIO0Base ((FIO *)0x3FFFC000)
#define FIO0DIR (FIO0Base->FIO_DIR)
#define FIO0MASK (FIO0Base->FIO_MASK)
#define FIO0PIN (FIO0Base->FIO_PIN)
#define FIO0SET (FIO0Base->FIO_SET)
#define FIO0CLR (FIO0Base->FIO_CLR)
#define FIO1Base ((FIO *)0x3FFFC020)
#define FIO1DIR (FIO1Base->FIO_DIR)
#define FIO1MASK (FIO1Base->FIO_MASK)
#define FIO1PIN (FIO1Base->FIO_PIN)
#define FIO1SET (FIO1Base->FIO_SET)
#define FIO1CLR (FIO1Base->FIO_CLR)
/*
* UART.
*/
typedef struct {
union {
IOREG32 UART_RBR;
IOREG32 UART_THR;
IOREG32 UART_DLL;
};
union {
IOREG32 UART_IER;
IOREG32 UART_DLM;
};
union {
IOREG32 UART_IIR;
IOREG32 UART_FCR;
};
IOREG32 UART_LCR;
IOREG32 UART_MCR; // UART1 only
IOREG32 UART_LSR;
IOREG32 unused18;
IOREG32 UART_SCR;
IOREG32 UART_ACR;
IOREG32 unused24;
IOREG32 UART_FDR;
IOREG32 unused2C;
IOREG32 UART_TER;
} UART;
#define U0Base ((UART *)0xE000C000)
#define U0RBR (U0Base->UART_RBR)
#define U0THR (U0Base->UART_THR)
#define U0DLL (U0Base->UART_DLL)
#define U0IER (U0Base->UART_IER)
#define U0DLM (U0Base->UART_DLM)
#define U0IIR (U0Base->UART_IIR)
#define U0FCR (U0Base->UART_FCR)
#define U0LCR (U0Base->UART_LCR)
#define U0LSR (U0Base->UART_LSR)
#define U0SCR (U0Base->UART_SCR)
#define U0ACR (U0Base->UART_ACR)
#define U0FDR (U0Base->UART_FDR)
#define U0TER (U0Base->UART_TER)
#define U1Base ((UART *)0xE0010000)
#define U1RBR (U1Base->UART_RBR)
#define U1THR (U1Base->UART_THR)
#define U1DLL (U1Base->UART_DLL)
#define U1IER (U1Base->UART_IER)
#define U1DLM (U1Base->UART_DLM)
#define U1IIR (U1Base->UART_IIR)
#define U1FCR (U1Base->UART_FCR)
#define U1MCR (U1Base->UART_MCR)
#define U1LCR (U1Base->UART_LCR)
#define U1LSR (U1Base->UART_LSR)
#define U1SCR (U1Base->UART_SCR)
#define U1ACR (U1Base->UART_ACR)
#define U1FDR (U1Base->UART_FDR)
#define U1TER (U1Base->UART_TER)
#define IIR_SRC_MASK 0x0F
#define IIR_SRC_NONE 0x01
#define IIR_SRC_TX 0x02
#define IIR_SRC_RX 0x04
#define IIR_SRC_ERROR 0x06
#define IIR_SRC_TIMEOUT 0x0C
#define IER_RBR 1
#define IER_THRE 2
#define IER_STATUS 4
#define IIR_INT_PENDING 1
#define LCR_WL5 0
#define LCR_WL6 1
#define LCR_WL7 2
#define LCR_WL8 3
#define LCR_STOP1 0
#define LCR_STOP2 4
#define LCR_NOPARITY 0
#define LCR_PARITYODD 0x08
#define LCR_PARITYEVEN 0x18
#define LCR_PARITYONE 0x28
#define LCR_PARITYZERO 0x38
#define LCR_BREAK_ON 0x40
#define LCR_DLAB 0x80
#define FCR_ENABLE 1
#define FCR_RXRESET 2
#define FCR_TXRESET 4
#define FCR_TRIGGER0 0
#define FCR_TRIGGER1 0x40
#define FCR_TRIGGER2 0x80
#define FCR_TRIGGER3 0xC0
#define LSR_RBR_FULL 1
#define LSR_OVERRUN 2
#define LSR_PARITY 4
#define LSR_FRAMING 8
#define LSR_BREAK 0x10
#define LSR_THRE 0x20
#define LSR_TEMT 0x40
#define LSR_RXFE 0x80
#define TER_ENABLE 0x80
/*
* SSP.
*/
typedef struct {
IOREG32 SSP_CR0;
IOREG32 SSP_CR1;
IOREG32 SSP_DR;
IOREG32 SSP_SR;
IOREG32 SSP_CPSR;
IOREG32 SSP_IMSC;
IOREG32 SSP_RIS;
IOREG32 SSP_MIS;
IOREG32 SSP_ICR;
} SSP;
#define SSPBase ((SSP *)0xE0068000)
#define SSPCR0 (SSPBase->SSP_CR0)
#define SSPCR1 (SSPBase->SSP_CR1)
#define SSPDR (SSPBase->SSP_DR)
#define SSPSR (SSPBase->SSP_SR)
#define SSPCPSR (SSPBase->SSP_CPSR)
#define SSPIMSC (SSPBase->SSP_IMSC)
#define SSPRIS (SSPBase->SSP_RIS)
#define SSPMIS (SSPBase->SSP_MIS)
#define SSPICR (SSPBase->SSP_ICR)
#define CR0_DSS4BIT 3
#define CR0_DSS5BIT 4
#define CR0_DSS6BIT 5
#define CR0_DSS7BIT 6
#define CR0_DSS8BIT 7
#define CR0_DSS9BIT 8
#define CR0_DSS10BIT 9
#define CR0_DSS11BIT 0xA
#define CR0_DSS12BIT 0xB
#define CR0_DSS13BIT 0xC
#define CR0_DSS14BIT 0xD
#define CR0_DSS15BIT 0xE
#define CR0_DSS16BIT 0xF
#define CR0_FRFSPI 0
#define CR0_FRFSSI 0x10
#define CR0_FRFMW 0x20
#define CR0_CPOL 0x40
#define CR0_CPHA 0x80
#define CR0_CLOCKRATE(n) ((n) << 8)
#define CR1_LBM 1
#define CR1_SSE 2
#define CR1_MS 4
#define CR1_SOD 8
#define SR_TFE 1
#define SR_TNF 2
#define SR_RNE 4
#define SR_RFF 8
#define SR_BSY 0x10
#define IMSC_ROR 1
#define IMSC_RT 2
#define IMSC_RX 4
#define IMSC_TX 8
#define RIS_ROR 1
#define RIS_RT 2
#define RIS_RX 4
#define RIS_TX 8
#define MIS_ROR 1
#define MIS_RT 2
#define MIS_RX 4
#define MIS_TX 8
#define ICR_ROR 1
#define ICR_RT 2
/*
* Timers/Counters.
*/
typedef struct {
IOREG32 TC_IR;
IOREG32 TC_TCR;
IOREG32 TC_TC;
IOREG32 TC_PR;
IOREG32 TC_PC;
IOREG32 TC_MCR;
IOREG32 TC_MR0;
IOREG32 TC_MR1;
IOREG32 TC_MR2;
IOREG32 TC_MR3;
IOREG32 TC_CCR;
IOREG32 TC_CR0;
IOREG32 TC_CR1;
IOREG32 TC_CR2;
IOREG32 TC_CR3;
IOREG32 TC_EMR;
IOREG32 TC_CTCR;
} TC;
#define T0Base ((TC *)0xE0004000)
#define T0IR (T0Base->TC_IR)
#define T0TCR (T0Base->TC_TCR)
#define T0TC (T0Base->TC_TC)
#define T0PR (T0Base->TC_PR)
#define T0PC (T0Base->TC_PC)
#define T0MCR (T0Base->TC_MCR)
#define T0MR0 (T0Base->TC_MR0)
#define T0MR1 (T0Base->TC_MR1)
#define T0MR2 (T0Base->TC_MR2)
#define T0MR3 (T0Base->TC_MR3)
#define T0CCR (T0Base->TC_CCR)
#define T0CR0 (T0Base->TC_CR0)
#define T0CR1 (T0Base->TC_CR1)
#define T0CR2 (T0Base->TC_CR2)
#define T0CR3 (T0Base->TC_CR3)
#define T0EMR (T0Base->TC_EMR)
#define T0CTCR (T0Base->TC_CTCR)
#define T1Base ((TC *)0xE0008000)
#define T1IR (T1Base->TC_IR)
#define T1TCR (T1Base->TC_TCR)
#define T1TC (T1Base->TC_TC)
#define T1PR (T1Base->TC_PR)
#define T1PC (T1Base->TC_PC)
#define T1MCR (T1Base->TC_MCR)
#define T1MR0 (T1Base->TC_MR0)
#define T1MR1 (T1Base->TC_MR1)
#define T1MR2 (T1Base->TC_MR2)
#define T1MR3 (T1Base->TC_MR3)
#define T1CCR (T1Base->TC_CCR)
#define T1CR0 (T1Base->TC_CR0)
#define T1CR1 (T1Base->TC_CR1)
#define T1CR2 (T1Base->TC_CR2)
#define T1CR3 (T1Base->TC_CR3)
#define T1EMR (T1Base->TC_EMR)
#define T1CTCR (T1Base->TC_CTCR)
/*
* Watchdog.
*/
typedef struct {
IOREG32 WD_MOD;
IOREG32 WD_TC;
IOREG32 WD_FEED;
IOREG32 WD_TV;
} WD;
#define WDBase ((WD *)0xE0000000)
#define WDMOD (WDBase->WD_MOD)
#define WDTC (WDBase->WD_TC)
#define WDFEED (WDBase->WD_FEED)
#define WDTV (WDBase->WD_TV)
/*
* DAC.
*/
#define DACR (*((IOREG32 *)0xE006C000))
#endif /* _LPC214X_H_ */

View File

@ -1,268 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-LPC214x/lpc214x_serial.c
* @brief LPC214x Serial driver code.
* @addtogroup LPC214x_SERIAL
* @{
*/
#include <ch.h>
#include "lpc214x.h"
#include "vic.h"
#include "lpc214x_serial.h"
#include "board.h"
#if USE_LPC214x_UART0 || defined(__DOXYGEN__)
/** @brief UART0 serial driver identifier.*/
FullDuplexDriver COM1;
static uint8_t ib1[SERIAL_BUFFERS_SIZE];
static uint8_t ob1[SERIAL_BUFFERS_SIZE];
#endif
#if USE_LPC214x_UART1 || defined(__DOXYGEN__)
/** @brief UART1 serial driver identifier.*/
FullDuplexDriver COM2;
static uint8_t ib2[SERIAL_BUFFERS_SIZE];
static uint8_t ob2[SERIAL_BUFFERS_SIZE];
#endif
/**
* @brief Error handling routine.
* @param[in] err UART LSR register value
* @param[in] com communication channel associated to the USART
*/
static void SetError(IOREG32 err, FullDuplexDriver *com) {
dflags_t sts = 0;
if (err & LSR_OVERRUN)
sts |= SD_OVERRUN_ERROR;
if (err & LSR_PARITY)
sts |= SD_PARITY_ERROR;
if (err & LSR_FRAMING)
sts |= SD_FRAMING_ERROR;
if (err & LSR_BREAK)
sts |= SD_BREAK_DETECTED;
chSysLockFromIsr();
chFDDAddFlagsI(com, sts);
chSysUnlockFromIsr();
}
/** @cond never*/
__attribute__((noinline))
/** @endcond*/
/**
* @brief Common IRQ handler.
* @param[in] u pointer to an UART I/O block
* @param[in] com communication channel associated to the UART
* @note Tries hard to clear all the pending interrupt sources, we dont want to
* go through the whole ISR and have another interrupt soon after.
*/
static void ServeInterrupt(UART *u, FullDuplexDriver *com) {
while (TRUE) {
switch (u->UART_IIR & IIR_SRC_MASK) {
case IIR_SRC_NONE:
return;
case IIR_SRC_ERROR:
SetError(u->UART_LSR, com);
break;
case IIR_SRC_TIMEOUT:
case IIR_SRC_RX:
while (u->UART_LSR & LSR_RBR_FULL) {
chSysLockFromIsr();
if (chIQPutI(&com->d2.iqueue, u->UART_RBR) < Q_OK)
chFDDAddFlagsI(com, SD_OVERRUN_ERROR);
chSysUnlockFromIsr();
}
chSysLockFromIsr();
chEvtBroadcastI(&com->d1.ievent);
chSysUnlockFromIsr();
break;
case IIR_SRC_TX:
{
#if UART_FIFO_PRELOAD > 0
int i = UART_FIFO_PRELOAD;
do {
chSysLockFromIsr();
msg_t b = chOQGetI(&com->d2.oqueue);
chSysUnlockFromIsr();
if (b < Q_OK) {
u->UART_IER &= ~IER_THRE;
chSysLockFromIsr();
chEvtBroadcastI(&com->d1.oevent);
chSysUnlockFromIsr();
break;
}
u->UART_THR = b;
} while (--i);
#else
chSysLockFromIsr();
msg_t b = chFDDRequestDataI(com);
chSysUnlockFromIsr();
if (b < Q_OK)
u->UART_IER &= ~IER_THRE;
else
u->UART_THR = b;
#endif
}
default:
u->UART_THR;
u->UART_RBR;
}
}
}
#if UART_FIFO_PRELOAD > 0
static void preload(UART *u, FullDuplexDriver *com) {
if (u->UART_LSR & LSR_THRE) {
int i = UART_FIFO_PRELOAD;
do {
chSysLockFromIsr();
msg_t b = chOQGetI(&com->d2.oqueue);
chSysUnlockFromIsr();
if (b < Q_OK) {
chSysLockFromIsr();
chEvtBroadcastI(&com->d1.oevent);
chSysUnlockFromIsr();
return;
}
u->UART_THR = b;
} while (--i);
}
u->UART_IER |= IER_THRE;
}
#endif
#if USE_LPC214x_UART0 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(UART0IrqHandler) {
CH_IRQ_PROLOGUE();
ServeInterrupt(U0Base, &COM1);
VICVectAddr = 0;
CH_IRQ_EPILOGUE();
}
static void OutNotify1(void) {
#if UART_FIFO_PRELOAD > 0
preload(U0Base, &COM1);
#else
UART *u = U0Base;
if (u->UART_LSR & LSR_THRE) {
chSysLockFromIsr();
u->UART_THR = chOQGetI(&COM1.sd_oqueue);
chSysUnlockFromIsr();
}
u->UART_IER |= IER_THRE;
#endif
}
#endif
#if USE_LPC214x_UART1 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(UART1IrqHandler) {
CH_IRQ_PROLOGUE();
ServeInterrupt(U1Base, &COM2);
VICVectAddr = 0;
CH_IRQ_EPILOGUE();
}
static void OutNotify2(void) {
#if UART_FIFO_PRELOAD > 0
preload(U1Base, &COM2);
#else
UART *u = U1Base;
if (u->UART_LSR & LSR_THRE)
u->UART_THR = chOQGetI(&COM2.sd_oqueue);
u->UART_IER |= IER_THRE;
#endif
}
#endif
/**
* @brief UART setup.
* @param[in] u pointer to an UART I/O block
* @param[in] speed serial port speed in bits per second
* @param[in] lcr the value for the @p LCR register
* @param[in] fcr the value for the @p FCR register
* @note Must be invoked with interrupts disabled.
* @note Does not reset the I/O queues.
*/
void uart_setup(UART *u, int speed, int lcr, int fcr) {
int div = PCLK / (speed << 4);
u->UART_LCR = lcr | LCR_DLAB;
u->UART_DLL = div;
u->UART_DLM = div >> 8;
u->UART_LCR = lcr;
u->UART_FCR = FCR_ENABLE | FCR_RXRESET | FCR_TXRESET | fcr;
u->UART_ACR = 0;
u->UART_FDR = 0x10;
u->UART_TER = TER_ENABLE;
u->UART_IER = IER_RBR | IER_STATUS;
}
/**
* @brief Serial driver initialization.
* @param[in] vector1 IRC vector to be used for UART0
* @param[in] vector2 IRC vector to be used for UART1
* @note Handshake pads are not enabled inside this function because they
* may have another use, enable them externally if needed.
* RX and TX pads are handled inside.
*/
void serial_init(int vector1, int vector2) {
#if USE_LPC214x_UART0
SetVICVector(UART0IrqHandler, vector1, SOURCE_UART0);
PCONP = (PCONP & PCALL) | PCUART0;
chFDDInit(&COM1, ib1, sizeof ib1, NULL, ob1, sizeof ob1, OutNotify1);
uart_setup(U0Base,
DEFAULT_UART_BITRATE,
LCR_WL8 | LCR_STOP1 | LCR_NOPARITY,
FCR_TRIGGER0);
VICIntEnable = INTMASK(SOURCE_UART0);
#endif
#if USE_LPC214x_UART1
SetVICVector(UART1IrqHandler, vector2, SOURCE_UART1);
PCONP = (PCONP & PCALL) | PCUART1;
chFDDInit(&COM2, ib2, sizeof ib2, NULL, ob2, sizeof ob2, OutNotify2);
uart_setup(U1Base,
DEFAULT_UART_BITRATE,
LCR_WL8 | LCR_STOP1 | LCR_NOPARITY,
FCR_TRIGGER0);
VICIntEnable = INTMASK(SOURCE_UART0) | INTMASK(SOURCE_UART1);
#endif
}
/** @} */

View File

@ -1,102 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-LPC214x/lpc214x_serial.h
* @brief LPC214x Serial driver macros and structures.
* @addtogroup LPC214x_SERIAL
* @{
*/
#ifndef _LPC214x_SERIAL_H_
#define _LPC214x_SERIAL_H_
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
* @note The default is 128 bytes for both the transmission and receive buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 128
#endif
/**
* @brief Default bit rate.
* @details Configuration parameter, at startup the UARTs are configured at
* this speed.
* @note It is possible to use @p SetUART() in order to change the working
* parameters at runtime.
*/
#if !defined(DEFAULT_UART_BITRATE) || defined(__DOXYGEN__)
#define DEFAULT_UART_BITRATE 38400
#endif
/**
* @brief FIFO preload parameter.
* @details Configuration parameter, this values defines how many bytes are
* preloaded in the HW transmit FIFO for each interrupt, the maximum value is
* 16 the minimum is 2, the value 0 disables the feature.
* @note An high value reduces the number of interrupts generated but can
* also increase the worst case interrupt response time because the
* preload loops.
* @note The value zero disables the feature and reverts to a simpler code
* that will generate an interrupt for each output byte but is much
* smaller and simpler.
*/
#if !defined(UART_FIFO_PRELOAD) || defined(__DOXYGEN__)
#define UART_FIFO_PRELOAD 16
#endif
/**
* @brief UART0 driver enable switch.
* @details If set to @p TRUE the support for USART1 is included.
* @note The default is @p TRUE .
*/
#if !defined(USE_LPC214x_UART0) || defined(__DOXYGEN__)
#define USE_LPC214x_UART0 TRUE
#endif
/**
* @brief UART1 driver enable switch.
* @details If set to @p TRUE the support for USART2 is included.
* @note The default is @p TRUE.
*/
#if !defined(USE_LPC214x_UART1) || defined(__DOXYGEN__)
#define USE_LPC214x_UART1 TRUE
#endif
#ifdef __cplusplus
extern "C" {
#endif
void serial_init(int vector1, int vector2);
void uart_setup(UART *u, int speed, int lcr, int fcr);
CH_IRQ_HANDLER(UART0IrqHandler);
CH_IRQ_HANDLER(UART1IrqHandler);
#ifdef __cplusplus
}
#endif
/** @cond never*/
extern FullDuplexDriver COM1, COM2;
/** @endcond*/
#endif /* _LPC214x_SERIAL_H_*/
/** @} */

View File

@ -1,133 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-LPC214x/lpc214x_ssp.c
* @brief LPC214x SSP driver code.
* @addtogroup LPC214x_SSP
* @{
*/
#include <ch.h>
#include <pal.h>
#include "lpc214x.h"
#include "lpc214x_ssp.h"
#if LPC214x_SSP_USE_MUTEX
static Semaphore me;
#endif
/**
* @brief Aquires access to the SSP bus.
* @note This function also handles the mutual exclusion on the SSP bus if
* the @p LPC214x_SSP_USE_MUTEX option is enabled.
*/
void sspAcquireBus(void) {
#if LPC214x_SSP_USE_MUTEX
chSemWait(&me);
#endif
palClearPad(IOPORT_A, 20);
}
/**
* @brief Releases the SSP bus.
* @note This function also handles the mutual exclusion on the SSP bus if
* the @p LPC214x_SSP_USE_MUTEX option is enabled.
*/
void sspReleaseBus(void) {
palClearPad(IOPORT_A, 20);
#if LPC214x_SSP_USE_MUTEX
chSemSignal(&me);
#endif
}
/**
* @brief Synchronous SSP transfer.
* @param[in] in pointer to the incoming data buffer, if this parameter is set
* to @p NULL then the incoming data is discarded
* @param[out] out pointer to the outgoing data buffer, if this parameter is
* set to @p NULL then 0xFF bytes will be output
* @param[in] n the number of bytes to be transferred
* @note The transfer is performed in a software loop and is not interrupt
* driven for performance reasons, this function should be invoked
* by a low priority thread in order to "play nice" with the
* rest of the system. This kind of peripheral would really need a
* dedicated DMA channel.
*/
void sspRW(uint8_t *in, uint8_t *out, size_t n) {
int icnt, ocnt;
SSP *ssp = SSPBase;
icnt = ocnt = n;
while (icnt) {
if (ssp->SSP_SR & SR_RNE) {
if (in)
*in++ = ssp->SSP_DR;
else
ssp->SSP_DR;
icnt--;
continue; /* Priority over transmission. */
}
if (ocnt && (ssp->SSP_SR & SR_TNF)) {
if (out)
ssp->SSP_DR = *out++;
else
ssp->SSP_DR = 0xFF;
ocnt--;
}
}
}
/**
* @brief SSP setup.
* @param[in] cpsr the value for the @p CPSR register
* @param[in] cr0 the value for the @p CR0 register
* @param[in] cr1 the value for the @p CR1 register
*/
void ssp_setup(int cpsr, int cr0, int cr1) {
SSP *ssp = SSPBase;
ssp->SSP_CR1 = 0;
ssp->SSP_CR0 = cr0;
ssp->SSP_CPSR = cpsr;
ssp->SSP_CR1 = cr1 | CR1_SSE;
}
/**
* @brief SSP subsystem initialization.
*/
void ssp_init(void) {
/* Enables the SPI1 clock */
PCONP = (PCONP & PCALL) | PCSPI1;
/* Clock = PCLK / 2 (fastest). */
ssp_setup(2, CR0_DSS8BIT | CR0_FRFSPI | CR0_CLOCKRATE(0), 0);
#if LPC214x_SSP_USE_MUTEX
chSemInit(&me, 1);
#endif
}
/** @} */

View File

@ -1,54 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-LPC214x/lpc214x_ssp.h
* @brief LPC214x SSP driver macros and structures.
* @addtogroup LPC214x_SSP
* @{
*/
#ifndef _LPC214x_SSP_H_
#define _LPC214x_SSP_H_
/**
* @brief SSP bus mutual exclusion control.
* @details Configuration parameter, if set to @p TRUE enforces mutual
* exclusion when invoking @p sspAcquireBus() and @p sspReleaseBus().
* @note The internally used synchronization mechanism is a @p Semaphore.
*/
#if !defined(LPC214x_SSP_USE_MUTEX) || defined(__DOXYGEN__)
#define LPC214x_SSP_USE_MUTEX TRUE
#endif
#ifdef __cplusplus
}
#endif
void ssp_init(void);
void ssp_setup(int cpsr, int cr0, int cr1);
void sspAcquireBus(void);
void sspReleaseBus(void);
void sspRW(uint8_t *in, uint8_t *out, size_t n);
#ifdef __cplusplus
}
#endif
#endif /* _LPC214x_SSP_H_*/
/** @} */

View File

@ -1,89 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-LPC214x/pal_lld.c
* @brief LPC214x FIO low level driver code
* @addtogroup LPC214x_PAL
* @{
*/
#include <ch.h>
#include <pal.h>
/**
* @brief LPC214x I/O ports configuration.
* @details FIO units and PINSEL registers initialization.
*
* @param[in] config the LPC214x ports configuration
*/
void _pal_lld_init(const LPC214xFIOConfig *config) {
/* Enables the access through the fast registers.*/
SCS = 3;
/* I/O pads initial assignment, device drivers may change this setup at a
* later time.*/
PINSEL0 = config->pinsel0;
PINSEL1 = config->pinsel1;
PINSEL2 = config->pinsel2;
/* I/O pads direction initial setting.*/
FIO0Base->FIO_MASK = 0;
FIO0Base->FIO_PIN = config->P0Data.pin;
FIO0Base->FIO_DIR = config->P0Data.dir;
FIO1Base->FIO_MASK = 0;
FIO1Base->FIO_PIN = config->P1Data.pin;
FIO1Base->FIO_DIR = config->P1Data.dir;
}
/**
* @brief Pads mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with high
* state.
* @note This function does not alter the @p PINSELx registers. Alternate
* functions setup must be handled by device-specific code.
*/
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode) {
switch (mode) {
case PAL_MODE_RESET:
case PAL_MODE_INPUT:
port->FIO_DIR &= ~mask;
break;
case PAL_MODE_UNCONNECTED:
port->FIO_PIN |= mask;
case PAL_MODE_OUTPUT_PUSHPULL:
port->FIO_DIR |= mask;
break;
}
}
/** @} */

View File

@ -1,252 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-LPC214x/pal_lld.h
* @brief LPC214x FIO low level driver header
* @addtogroup LPC214x_PAL
* @{
*/
#ifndef _PAL_LLD_H_
#define _PAL_LLD_H_
#include "lpc214x.h"
/*===========================================================================*/
/* Unsupported modes and specific modes */
/*===========================================================================*/
#undef PAL_MODE_INPUT_PULLUP
#undef PAL_MODE_INPUT_PULLDOWN
#undef PAL_MODE_OUTPUT_OPENDRAIN
/*===========================================================================*/
/* I/O Ports Types and constants. */
/*===========================================================================*/
/**
* @brief FIO port setup info.
*/
typedef struct {
/** Initial value for FIO_PIN register.*/
uint32_t pin;
/** Initial value for FIO_DIR register.*/
uint32_t dir;
} lpc214x_fio_setup_t;
/**
* @brief LPC214x FIO static initializer.
* @details An instance of this structure must be passed to @p palInit() at
* system startup time in order to initialized the digital I/O
* subsystem. This represents only the initial setup, specific pads
* or whole ports can be reprogrammed at later time.
*/
typedef struct {
/** @brief PINSEL0 initial value.*/
uint32_t pinsel0;
/** @brief PINSEL1 initial value.*/
uint32_t pinsel1;
/** @brief PINSEL2 initial value.*/
uint32_t pinsel2;
/** @brief Port 0 setup data.*/
lpc214x_fio_setup_t P0Data;
/** @brief Port 1 setup data.*/
lpc214x_fio_setup_t P1Data;
} LPC214xFIOConfig;
/**
* @brief Width, in bits, of an I/O port.
*/
#define PAL_IOPORTS_WIDTH 32
/**
* @brief Digital I/O port sized unsigned type.
*/
typedef uint32_t ioportmask_t;
/**
* @brief Port Identifier.
*/
typedef FIO * ioportid_t;
/*===========================================================================*/
/* I/O Ports Identifiers. */
/*===========================================================================*/
/**
* @brief FIO port 0 identifier.
*/
#define IOPORT_A FIO0Base
/**
* @brief FIO port 1 identifier.
*/
#define IOPORT_B FIO1Base
/*===========================================================================*/
/* Implementation, some of the following macros could be implemented as */
/* functions, please put them in a file named ioports_lld.c if so. */
/*===========================================================================*/
/**
* @brief FIO subsystem initialization.
* @details Enables the access through the fast registers.
*/
#define pal_lld_init(config) _pal_lld_init(config)
/**
* @brief Reads an I/O port.
* @details This function is implemented by reading the FIO PIN register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @return the port bits
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_readport(port) ((port)->FIO_PIN)
/**
* @brief Reads the output latch.
* @details This function is implemented by reading the FIO SET register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @return The latched logical states.
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_readlatch(port) ((port)->FIO_SET)
/**
* @brief Writes a bits mask on a I/O port.
* @details This function is implemented by writing the FIO PIN register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be written on the specified port
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_writeport(port, bits) ((port)->FIO_PIN = (bits))
/**
* @brief Sets a bits mask on a I/O port.
* @details This function is implemented by writing the FIO SET register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be ORed on the specified port
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_setport(port, bits) ((port)->FIO_SET = (bits))
/**
* @brief Clears a bits mask on a I/O port.
* @details This function is implemented by writing the FIO CLR register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be cleared on the specified port
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_clearport(port, bits) ((port)->FIO_CLR = (bits))
/**
* @brief Writes a value on an I/O bus.
* @details This function is implemented by writing the FIO PIN and MASK
* registers, the implementation is not atomic because the multiple
* accesses.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] offset the group bit offset within the port
* @param[in] bits the bits to be written. Values exceeding the group width
* are masked.
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_writegroup(port, mask, offset, bits) { \
(port)->FIO_MASK = (mask) << (offset); \
(port)->FIO_PIN = (bits) << (offset); \
(port)->FIO_MASK = 0; \
}
/**
* @brief Pads group mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with high
* state.
* @note This function does not alter the @p PINSELx registers. Alternate
* functions setup must be handled by device-specific code.
*/
#define pal_lld_setgroupmode(port, mask, mode) \
_pal_lld_setgroupmode(port, mask, mode)
/**
* @brief Writes a logical state on an output pad.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
* @param[out] bit the logical value, the value must be @p 0 or @p 1
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit)
/**
* @brief FIO port setup.
* @details This function programs the pins direction within a port.
*/
#define pal_lld_lpc214x_set_direction(port, dir) { \
(port)->FIO_DIR = (dir); \
}
#ifdef __cplusplus
extern "C" {
#endif
void _pal_lld_init(const LPC214xFIOConfig *config);
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode);
#ifdef __cplusplus
}
#endif
#endif /* _PAL_LLD_H_ */
/** @} */

View File

@ -1,83 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @defgroup LPC214x LPC214x Support
* @brief LPC214x specific support.
* @details The LPC214x support includes:
* - VIC support code.
* - I/O ports driver.
* - Buffered, interrupt driven, serial driver.
* - SSP driver.
* - A MMC/SD demo driver.
* - A timer driven buzzer demo driver.
* - A minimal demo, useful as project template.
* - A demo supporting the kernel test suite.
* - A C++ demo supporting the kernel test suite.
* .
* @ingroup ARM7
*/
/**
* @defgroup LPC214x_VIC VIC Support
* @brief VIC peripheral support.
*
* @ingroup LPC214x
*/
/**
* @defgroup LPC214x_PAL I/O Ports Support
* @brief I/O Ports peripherals support.
* @details This module supports the LPC214x FIO controller. The controller
* supports the following features (see @ref PAL):
* - 32 bits wide ports.
* - Atomic set/reset functions.
* - Output latched regardless of the pad setting.
* - Direct read of input pads regardless of the pad setting.
* .
* <h2>Supported Setup Modes</h2>
* - @p PAL_MODE_RESET.
* - @p PAL_MODE_UNCONNECTED.
* - @p PAL_MODE_INPUT.
* - @p PAL_MODE_OUTPUT_PUSHPULL.
* .
* Any attempt to setup an invalid mode is ignored.
*
* <h2>Suboptimal Behavior</h2>
* - Pad/port toggling operations are not atomic.
* - Pad/group mode setup is not atomic.
* .
* @ingroup LPC214x
*/
/**
* @defgroup LPC214x_SERIAL UART Support
* @brief UART peripherals support.
* @details The serial driver supports the LPC214x UART peripherals.
*
* @ingroup LPC214x
*/
/**
* @defgroup LPC214x_SSP SSP Support
* @brief SSP peripheral support.
* @details This SPI driver supports the LPC214x SSP peripheral.
*
* @ingroup LPC214x
*/

View File

@ -1,71 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
.section vectors
.code 32
.balign 4
/*
* System entry points.
*/
_start:
ldr pc, _reset
ldr pc, _undefined
ldr pc, _swi
ldr pc, _prefetch
ldr pc, _abort
nop
ldr pc, [pc,#-0xFF0] /* VIC - IRQ Vector Register */
ldr pc, _fiq
_reset:
.word ResetHandler /* In crt0.s */
_undefined:
.word UndHandler
_swi:
.word SwiHandler
_prefetch:
.word PrefetchHandler
_abort:
.word AbortHandler
_fiq:
.word FiqHandler
.word 0
.word 0
/*
* Default exceptions handlers. The handlers are declared weak in order to be
* replaced by the real handling code. Everything is defaulted to an infinite
* loop.
*/
.weak UndHandler
UndHandler:
.weak SwiHandler
SwiHandler:
.weak PrefetchHandler
PrefetchHandler:
.weak AbortHandler
AbortHandler:
.weak FiqHandler
FiqHandler:
.loop: b .loop

View File

@ -1,63 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-LPC214x/vic.c
* @brief LPC214x VIC peripheral support code.
* @addtogroup LPC214x_VIC
* @{
*/
#include <ch.h>
#include "lpc214x.h"
/**
* @brief VIC Initialization.
* @note Better reset everything in the VIC, it is a HUGE source of trouble.
*/
void vic_init(void) {
int i;
VIC *vic = VICBase;
vic->VIC_IntSelect = 0; /* All sources assigned to IRQ. */
vic->VIC_SoftIntClear = ALLINTMASK; /* No interrupts enforced */
vic->VIC_IntEnClear = ALLINTMASK; /* All sources disabled. */
for (i = 0; i < 16; i++) {
vic->VIC_VectCntls[i] = 0;
vic->VIC_VectAddrs[i] = 0;
vic->VIC_VectAddr = 0;
}
}
/**
* @brief Initializes a VIC vector.
* @details Set a vector for an interrupt source and enables it.
* @param[in] handler the pointer to the IRQ service routine
* @param[in] vector the vector number
* @param[in] source the IRQ source to be associated to the vector
*/
void SetVICVector(void *handler, int vector, int source) {
VIC *vicp = VICBase;
vicp->VIC_VectAddrs[vector] = (IOREG32)handler;
vicp->VIC_VectCntls[vector] = (IOREG32)(source | 0x20);
}
/** @} */

View File

@ -1,41 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7-LPC214x/vic.h
* @brief LPC214x VIC peripheral support code.
* @addtogroup LPC214x_VIC
* @{
*/
#ifndef _VIC_H_
#define _VIC_H_
#ifdef __cplusplus
extern "C" {
#endif
void vic_init(void);
void SetVICVector(void *handler, int vector, int source);
#ifdef __cplusplus
}
#endif
#endif /* _VIC_H_ */
/** @} */

View File

@ -1,35 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WFI_H_
#define _WFI_H_
#include "lpc214x.h"
#ifndef port_wait_for_interrupt
#if ENABLE_WFI_IDLE != 0
#define port_wait_for_interrupt() { \
PCON = 1; \
}
#else
#define port_wait_for_interrupt()
#endif
#endif
#endif /* _WFI_H_ */

View File

@ -1,42 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7/chcore.c
* @brief ARM7 architecture port code.
* @addtogroup ARM7_CORE
* @{
*/
#include <ch.h>
/**
* Halts the system.
*/
/** @cond never */
__attribute__((weak))
/** @endcond */
void port_halt(void) {
port_disable();
while (TRUE) {
}
}
/** @} */

View File

@ -1,331 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7/chcore.h
* @brief ARM7 architecture port macros and structures.
* @addtogroup ARM7_CORE
* @{
*/
#ifndef _CHCORE_H_
#define _CHCORE_H_
/**
* If enabled allows the idle thread to enter a low power mode.
*/
#ifndef ENABLE_WFI_IDLE
#define ENABLE_WFI_IDLE 0
#endif
#include <wfi.h>
/**
* Macro defining the ARM7 architecture.
*/
#define CH_ARCHITECTURE_ARM7
/**
* Name of the implemented architecture.
*/
#define CH_ARCHITECTURE_NAME "ARM7TDMI"
/**
* 32 bit stack alignment.
*/
typedef uint32_t stkalign_t;
/**
* Generic ARM register.
*/
typedef void *regarm_t;
/** @cond never */
/**
* This structure represents the stack frame saved during a preemption-capable
* interrupt handler.
*/
struct extctx {
regarm_t spsr_irq;
regarm_t lr_irq;
regarm_t r0;
regarm_t r1;
regarm_t r2;
regarm_t r3;
regarm_t r12;
regarm_t lr_usr;
};
/** @endcond */
/** @cond never */
/**
* This structure represents the inner stack frame during a context switching.
*/
struct intctx {
regarm_t r4;
regarm_t r5;
regarm_t r6;
#ifndef CH_CURRP_REGISTER_CACHE
regarm_t r7;
#endif
regarm_t r8;
regarm_t r9;
regarm_t r10;
regarm_t r11;
regarm_t lr;
};
/** @endcond */
/** @cond never */
/**
* In the ARM7 port this structure contains just the copy of the user mode
* stack pointer.
*/
struct context {
struct intctx *r13;
};
/** @endcond */
/**
* Platform dependent part of the @p chThdInit() API.
*/
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \
wsize - \
sizeof(struct intctx)); \
tp->p_ctx.r13->r4 = pf; \
tp->p_ctx.r13->r5 = arg; \
tp->p_ctx.r13->lr = _port_thread_start; \
}
/**
* Stack size for the system idle thread.
*/
#ifndef IDLE_THREAD_STACK_SIZE
#define IDLE_THREAD_STACK_SIZE 0
#endif
/**
* Per-thread stack overhead for interrupts servicing, it is used in the
* calculation of the correct working area size.
* In this port 0x10 is a safe value, it can be reduced after careful generated
* code analysis.
*/
#ifndef INT_REQUIRED_STACK
#define INT_REQUIRED_STACK 0x10
#endif
/**
* Enforces a correct alignment for a stack area size value.
*/
#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1)
/**
* Computes the thread working area global size.
*/
#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
sizeof(struct intctx) + \
sizeof(struct extctx) + \
(n) + (INT_REQUIRED_STACK))
/**
* Macro used to allocate a thread working area aligned as both position and
* size.
*/
#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)];
/**
* IRQ prologue code, inserted at the start of all IRQ handlers enabled to
* invoke system APIs.
* @note This macro has a different implementation depending if compiled in
* ARM or THUMB mode.
* @note The THUMB implementation starts with ARM code because interrupt
* vectors are always invoked in ARM mode regardless the bit 0
* value. The switch in THUMB mode is done in the function prologue so
* it is transparent to the user code.
*/
#ifdef THUMB
#define PORT_IRQ_PROLOGUE() { \
asm volatile (".code 32 \n\t" \
"stmfd sp!, {r0-r3, r12, lr} \n\t" \
"add r0, pc, #1 \n\t" \
"bx r0 \n\t" \
".code 16"); \
}
#else /* !THUMB */
#define PORT_IRQ_PROLOGUE() { \
asm volatile ("stmfd sp!, {r0-r3, r12, lr}"); \
}
#endif /* !THUMB */
/**
* IRQ epilogue code, inserted at the end of all IRQ handlers enabled to
* invoke system APIs.
* @note This macro has a different implementation depending if compiled in
* ARM or THUMB mode.
*/
#ifdef THUMB
#define PORT_IRQ_EPILOGUE() { \
asm volatile ("ldr r0, =_port_irq_common \n\t" \
"bx r0"); \
}
#else /* !THUMB */
#define PORT_IRQ_EPILOGUE() { \
asm volatile ("b _port_irq_common"); \
}
#endif /* !THUMB */
/**
* IRQ handler function declaration.
*/
#define PORT_IRQ_HANDLER(id) __attribute__((naked)) void id(void)
/**
* This function is empty in this port.
*/
#define port_init()
/**
* Disables the IRQ sources and keeps the FIQ sources enabled.
*/
#ifdef THUMB
//#define port_lock() _port_lock_thumb()
#define port_lock() { \
asm volatile ("bl _port_lock_thumb" : : : "r3", "lr"); \
}
#else /* !THUMB */
#define port_lock() asm volatile ("msr CPSR_c, #0x9F")
#endif /* !THUMB */
/**
* Enables both the IRQ and FIQ sources.
*/
#ifdef THUMB
//#define port_unlock() _port_unlock_thumb()
#define port_unlock() { \
asm volatile ("bl _port_unlock_thumb" : : : "r3", "lr"); \
}
#else /* !THUMB */
#define port_unlock() asm volatile ("msr CPSR_c, #0x1F")
#endif /* !THUMB */
/**
* This function is empty in this port.
*/
#define port_lock_from_isr()
/**
* This function is empty in this port.
*/
#define port_unlock_from_isr()
/**
* Disables both the IRQ and FIQ sources.
* @note Implements a workaround for spurious interrupts taken from the NXP
* LPC214x datasheet.
*/
#ifdef THUMB
//#define port_disable() _port_disable_thumb()
#define port_disable() { \
asm volatile ("bl _port_disable_thumb" : : : "r3", "lr"); \
}
#else /* !THUMB */
#define port_disable() { \
asm volatile ("mrs r3, CPSR \n\t" \
"orr r3, #0x80 \n\t" \
"msr CPSR_c, r3 \n\t" \
"orr r3, #0x40 \n\t" \
"msr CPSR_c, r3" : : : "r3"); \
}
#endif /* !THUMB */
/**
* Disables the IRQ sources and enables the FIQ sources.
*/
#ifdef THUMB
#define port_suspend() { \
asm volatile ("bl _port_suspend_thumb" : : : "r3", "lr"); \
}
#else /* !THUMB */
#define port_suspend() asm volatile ("msr CPSR_c, #0x9F")
#endif /* !THUMB */
/**
* Enables both the IRQ and FIQ sources.
*/
#ifdef THUMB
#define port_enable() { \
asm volatile ("bl _port_enable_thumb" : : : "r3", "lr"); \
}
#else /* !THUMB */
#define port_enable() asm volatile ("msr CPSR_c, #0x1F")
#endif /* !THUMB */
/**
* Performs a context switch between two threads.
* @param otp the thread to be switched out
* @param ntp the thread to be switched in
*/
#ifdef THUMB
#if CH_DBG_ENABLE_STACK_CHECK
#define port_switch(otp, ntp) { \
register Thread *_otp asm ("r0") = (otp); \
register Thread *_ntp asm ("r1") = (ntp); \
register char *sp asm ("sp"); \
if (sp - sizeof(struct intctx) - sizeof(Thread) < (char *)_otp) \
asm volatile ("mov r0, #0 \n\t" \
"ldr r1, =chDbgPanic \n\t" \
"bx r1"); \
_port_switch_thumb(_otp, _ntp); \
}
#else /* !CH_DBG_ENABLE_STACK_CHECK */
#define port_switch(otp, ntp) _port_switch_thumb(otp, ntp)
#endif /* !CH_DBG_ENABLE_STACK_CHECK */
#else /* !THUMB */
#if CH_DBG_ENABLE_STACK_CHECK
#define port_switch(otp, ntp) { \
register Thread *_otp asm ("r0") = (otp); \
register Thread *_ntp asm ("r1") = (ntp); \
register char *sp asm ("sp"); \
if (sp - sizeof(struct intctx) - sizeof(Thread) < (char *)_otp) \
asm volatile ("mov r0, #0 \n\t" \
"b chDbgPanic"); \
_port_switch_arm(_otp, _ntp); \
}
#else /* !CH_DBG_ENABLE_STACK_CHECK */
#define port_switch(otp, ntp) _port_switch_arm(otp, ntp)
#endif /* !CH_DBG_ENABLE_STACK_CHECK */
#endif /* !THUMB */
#ifdef __cplusplus
extern "C" {
#endif
void port_halt(void);
#ifdef THUMB
void _port_switch_thumb(Thread *otp, Thread *ntp);
#else /* !THUMB */
void _port_switch_arm(Thread *otp, Thread *ntp);
#endif /* !THUMB */
void _port_thread_start(void);
#ifdef __cplusplus
}
#endif
#endif /* _CHCORE_H_ */
/** @} */

View File

@ -1,234 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7/chcoreasm.s
* @brief ARM7 architecture port low level code.
* @addtogroup ARM7_CORE
* @{
*/
/** @cond never */
#include <chconf.h>
.set MODE_USR, 0x10
.set MODE_FIQ, 0x11
.set MODE_IRQ, 0x12
.set MODE_SVC, 0x13
.set MODE_ABT, 0x17
.set MODE_UND, 0x1B
.set MODE_SYS, 0x1F
.equ I_BIT, 0x80
.equ F_BIT, 0x40
.text
/*
* Interrupt enable/disable functions, only present if there is THUMB code in
* the system because those are inlined in ARM code.
*/
#ifdef THUMB_PRESENT
.balign 16
.code 16
.thumb_func
.global _port_disable_thumb
_port_disable_thumb:
mov r3, pc
bx r3
.code 32
mrs r3, CPSR
orr r3, #I_BIT
msr CPSR_c, r3
orr r3, #F_BIT
msr CPSR_c, r3
bx lr
.balign 16
.code 16
.thumb_func
.global _port_suspend_thumb
_port_suspend_thumb:
.thumb_func
.global _port_lock_thumb
_port_lock_thumb:
mov r3, pc
bx r3
.code 32
msr CPSR_c, #MODE_SYS | I_BIT
bx lr
.balign 16
.code 16
.thumb_func
.global _port_enable_thumb
_port_enable_thumb:
.thumb_func
.global _port_unlock_thumb
_port_unlock_thumb:
mov r3, pc
bx r3
.code 32
msr CPSR_c, #MODE_SYS
bx lr
#endif
.balign 16
#ifdef THUMB_PRESENT
.code 16
.thumb_func
.global _port_switch_thumb
_port_switch_thumb:
mov r2, pc
bx r2
// Jumps into _port_switch_arm in ARM mode
#endif
.code 32
.global _port_switch_arm
_port_switch_arm:
#ifdef CH_CURRP_REGISTER_CACHE
stmfd sp!, {r4, r5, r6, r8, r9, r10, r11, lr}
str sp, [r0, #16]
ldr sp, [r1, #16]
#ifdef THUMB_PRESENT
ldmfd sp!, {r4, r5, r6, r8, r9, r10, r11, lr}
bx lr
#else /* !THUMB_PRESENT */
ldmfd sp!, {r4, r5, r6, r8, r9, r10, r11, pc}
#endif /* !THUMB_PRESENT */
#else /* !CH_CURRP_REGISTER_CACHE */
stmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}
str sp, [r0, #16]
ldr sp, [r1, #16]
#ifdef THUMB_PRESENT
ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr}
bx lr
#else /* !THUMB_PRESENT */
ldmfd sp!, {r4, r5, r6, r7, r8, r9, r10, r11, pc}
#endif /* !THUMB_PRESENT */
#endif /* !CH_CURRP_REGISTER_CACHE */
/*
* Common exit point for all IRQ routines, it performs the rescheduling if
* required.
* System stack frame structure after a context switch in the
* interrupt handler:
*
* High +------------+
* | LR_USR | -+
* | R12 | |
* | R3 | |
* | R2 | | External context: IRQ handler frame
* | R1 | |
* | R0 | |
* | PC | | (user code return address)
* | PSR_USR | -+ (user code status)
* | .... | <- mk_DoRescheduleI() stack frame, optimize it for space
* | LR | -+ (system code return address)
* | R11 | |
* | R10 | |
* | R9 | |
* | R8 | | Internal context: mk_SwitchI() frame
* | (R7) | | (optional, see CH_CURRP_REGISTER_CACHE)
* | R6 | |
* | R5 | |
* SP-> | R4 | -+
* Low +------------+
*/
.balign 16
#ifdef THUMB_NO_INTERWORKING
.code 16
.thumb_func
.globl _port_irq_common
_port_irq_common:
bl chSchRescRequiredI
mov lr, pc
bx lr
.code 32
#else /* !THUMB_NO_INTERWORKING */
.code 32
.globl _port_irq_common
_port_irq_common:
bl chSchRescRequiredI
#endif /* !THUMB_NO_INTERWORKING */
cmp r0, #0 // Simply returns if a
ldmeqfd sp!, {r0-r3, r12, lr} // reschedule is not
subeqs pc, lr, #4 // required.
// Saves the IRQ mode registers in the system stack.
ldmfd sp!, {r0-r3, r12, lr} // IRQ stack now empty.
msr CPSR_c, #MODE_SYS | I_BIT
stmfd sp!, {r0-r3, r12, lr} // Registers on System Stack.
msr CPSR_c, #MODE_IRQ | I_BIT
mrs r0, SPSR
mov r1, lr
msr CPSR_c, #MODE_SYS | I_BIT
stmfd sp!, {r0, r1} // Push R0=SPSR, R1=LR_IRQ.
// Context switch.
#ifdef THUMB_NO_INTERWORKING
add r0, pc, #1
bx r0
.code 16
bl chSchDoRescheduleI
mov lr, pc
bx lr
.code 32
#else /* !THUMB_NO_INTERWORKING */
bl chSchDoRescheduleI
#endif /* !THUMB_NO_INTERWORKING */
// Re-establish the IRQ conditions again.
ldmfd sp!, {r0, r1} // Pop R0=SPSR, R1=LR_IRQ.
msr CPSR_c, #MODE_IRQ | I_BIT
msr SPSR_fsxc, r0
mov lr, r1
msr CPSR_c, #MODE_SYS | I_BIT
ldmfd sp!, {r0-r3, r12, lr}
msr CPSR_c, #MODE_IRQ | I_BIT
subs pc, lr, #4
/*
* Threads trampoline code.
* NOTE: The threads always start in ARM mode then switch to the thread-function mode.
*/
.balign 16
.code 32
.globl _port_thread_start
_port_thread_start:
msr CPSR_c, #MODE_SYS
#ifndef THUMB_NO_INTERWORKING
mov r0, r5
mov lr, pc
bx r4
bl chThdExit
#else /* !THUMB_NO_INTERWORKING */
add r0, pc, #1
bx r0
.code 16
mov r0, r5
bl jmpr4
bl chThdExit
jmpr4:
bx r4
#endif /* !THUMB_NO_INTERWORKING */
/** @endcond */
/** @} */

View File

@ -1,56 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7/chtypes.h
* @brief ARM7 architecture port system types.
* @addtogroup ARM7_CORE
* @{
*/
#ifndef _CHTYPES_H_
#define _CHTYPES_H_
#define __need_NULL
#define __need_size_t
#define __need_ptrdiff_t
#include <stddef.h>
#if !defined(_STDINT_H) && !defined(__STDINT_H_)
#include <stdint.h>
#endif
typedef int32_t bool_t; /**< Fast boolean type. */
typedef uint8_t tmode_t; /**< Thread flags. */
typedef uint8_t tstate_t; /**< Thread state. */
typedef uint32_t tprio_t; /**< Thread priority. */
typedef int32_t msg_t; /**< Inter-thread message. */
typedef int32_t eventid_t; /**< Event Id. */
typedef uint32_t eventmask_t; /**< Events mask. */
typedef uint32_t systime_t; /**< System time. */
typedef int32_t cnt_t; /**< Resources counter. */
#define INLINE inline
#define PACK_STRUCT_STRUCT __attribute__((packed))
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_END
#endif /* _CHTYPES_H_ */
/** @} */

View File

@ -1,181 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARM7/crt0.s
* @brief Generic ARM7 startup file for ChibiOS/RT.
* @addtogroup ARM7_CORE
* @{
*/
/** @cond never */
.set MODE_USR, 0x10
.set MODE_FIQ, 0x11
.set MODE_IRQ, 0x12
.set MODE_SVC, 0x13
.set MODE_ABT, 0x17
.set MODE_UND, 0x1B
.set MODE_SYS, 0x1F
.equ I_BIT, 0x80
.equ F_BIT, 0x40
.text
.code 32
.balign 4
/*
* Reset handler.
*/
.global ResetHandler
ResetHandler:
/*
* Stack pointers initialization.
*/
ldr r0, =__ram_end__
/* Undefined */
msr CPSR_c, #MODE_UND | I_BIT | F_BIT
mov sp, r0
ldr r1, =__und_stack_size__
sub r0, r0, r1
/* Abort */
msr CPSR_c, #MODE_ABT | I_BIT | F_BIT
mov sp, r0
ldr r1, =__abt_stack_size__
sub r0, r0, r1
/* FIQ */
msr CPSR_c, #MODE_FIQ | I_BIT | F_BIT
mov sp, r0
ldr r1, =__fiq_stack_size__
sub r0, r0, r1
/* IRQ */
msr CPSR_c, #MODE_IRQ | I_BIT | F_BIT
mov sp, r0
ldr r1, =__irq_stack_size__
sub r0, r0, r1
/* Supervisor */
msr CPSR_c, #MODE_SVC | I_BIT | F_BIT
mov sp, r0
ldr r1, =__svc_stack_size__
sub r0, r0, r1
/* System */
msr CPSR_c, #MODE_SYS | I_BIT | F_BIT
mov sp, r0
// ldr r1, =__sys_stack_size__
// sub r0, r0, r1
/*
* Early initialization.
*/
#ifndef THUMB_NO_INTERWORKING
bl hwinit0
#else
add r0, pc, #1
bx r0
.code 16
bl hwinit0
mov r0, pc
bx r0
.code 32
#endif
/*
* Data initialization.
* NOTE: It assumes that the DATA size is a multiple of 4.
*/
ldr r1, =_textdata
ldr r2, =_data
ldr r3, =_edata
dataloop:
cmp r2, r3
ldrlo r0, [r1], #4
strlo r0, [r2], #4
blo dataloop
/*
* BSS initialization.
* NOTE: It assumes that the BSS size is a multiple of 4.
*/
mov r0, #0
ldr r1, =_bss_start
ldr r2, =_bss_end
bssloop:
cmp r1, r2
strlo r0, [r1], #4
blo bssloop
/*
* Late initialization.
*/
#ifdef THUMB_NO_INTERWORKING
add r0, pc, #1
bx r0
.code 16
bl hwinit1
mov r0, #0
mov r1, r0
bl main
ldr r1, =MainExitHandler
bx r1
.code 32
#else
bl hwinit1
mov r0, #0
mov r1, r0
bl main
b MainExitHandler
#endif
/*
* Default main function exit handler.
*/
.weak MainExitHandler
.globl MainExitHandler
MainExitHandler:
.loop: b .loop
/*
* Default early initialization code. It is declared weak in order to be
* replaced by the real initialization code.
* Early initialization is performed just after reset before BSS and DATA
* segments initialization.
*/
#ifdef THUMB_NO_INTERWORKING
.thumb_func
.code 16
#endif
.weak hwinit0
hwinit0:
bx lr
.code 32
/*
* Default late initialization code. It is declared weak in order to be
* replaced by the real initialization code.
* Late initialization is performed after BSS and DATA segments initialization
* and before invoking the main() function.
*/
#ifdef THUMB_NO_INTERWORKING
.thumb_func
.code 16
#endif
.weak hwinit1
hwinit1:
bx lr
.code 32
/** @endcond */
/** @} */

View File

@ -1,200 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @defgroup ARM7 ARM7TDMI
* @details The ARM7 architecture is quite complex for a microcontroller and
* some explanations are required about the port choices.
*
* @section ARM7_NOTES The ARM7 modes
* The ARM7 port supports three modes:
* - Pure ARM mode, this is the preferred mode for code speed. The code size
* is larger however. This mode is enabled when all the modules are compiled
* in ARM mode, see the Makefiles.
* - Pure THUMB mode, this is the preferred mode for code size. In this mode
* the execution speed is slower than the ARM mode. This mode is enabled
* when all the modules are compiled in THUMB mode, see the Makefiles.
* - Interworking mode, when in the system there are ARM modules mixed with
* THUMB modules then the interworking compiler option is enabled. This is
* usually the slowest mode and the code size is not as good as in pure
* THUMB mode.
* .
* @section ARM7_STATES Mapping of the System States in the ARM7 port
* The ChibiOS/RT logical @ref system_states are mapped as follow in the ARM7
* port:
* - <b>Init</b>. This state is represented by the startup code and the
* initialization code before @p chSysInit() is executed. It has not a
* special hardware state associated, usually the CPU goes through several
* hardware states during the startup phase.
* - <b>Normal</b>. This is the state the system has after executing
* @p chSysInit(). In this state the ARM7TDMI has both the interrupt sources
* (IRQ and FIQ) enabled and is running in ARM System Mode.
* - <b>Suspended</b>. In this state the IRQ sources are disabled but the FIQ
* sources are served, the core is running in ARM System Mode.
* - <b>Disabled</b>. Both the IRQ and FIQ sources are disabled, the core is
* running in ARM System Mode.
* - <b>Sleep</b>. The ARM7 code does not have any built-in low power mode but
* there are clock stop modes implemented in custom ways by the various
* silicon vendors. This state is implemented in each microcontroller support
* code in a different way, the core is running (or freezed...) in ARM
* System Mode.
* - <b>S-Locked</b>. IRQ sources disabled, core running in ARM System Mode.
* - <b>I-Locked</b>. IRQ sources disabled, core running in ARM IRQ Mode. Note
* that this state is not different from the SRI state in this port, the
* @p chSysLockI() and @p chSysUnlockI() APIs do nothing (still use them in
* order to formally change state because this may change).
* - <b>Serving Regular Interrupt</b>. IRQ sources disabled, core running in
* ARM IRQ Mode. See also the I-Locked state.
* - <b>Serving Fast Interrupt</b>. IRQ and FIQ sources disabled, core running
* in ARM FIQ Mode.
* - <b>Serving Non-Maskable Interrupt</b>. There are no asynchronous NMI
* sources in ARM7 architecture but synchronous SVC, ABT and UND exception
* handlers can be seen as belonging to this category.
* - <b>Halted</b>. Implemented as an infinite loop after disabling both IRQ
* and FIQ sources. The ARM state is whatever the processor was running when
* @p chSysHalt() was invoked.
* .
* @section ARM7_NOTES The ARM7 port notes
* The ARM7 port makes some assumptions on the application code organization:
* - The @p main() function is invoked in system mode.
* - Each thread has a private user/system stack, the system has a single
* interrupt stack where all the interrupts are processed.
* - The threads are started in system mode.
* - The threads code can run in system mode or user mode, however the
* code running in user mode cannot invoke the ChibiOS/RT APIs directly
* because privileged instructions are used inside.<br>
* The kernel APIs can be eventually invoked by using a SWI entry point
* that handles the switch in system mode and the return in user mode.
* - Other modes are not preempt-able because the system code assumes the
* threads running in system mode. When running in supervisor or other
* modes make sure that the interrupts are globally disabled.
* - Interrupts nesting is not supported in the ARM7 code because their
* implementation, even if possible, is not really efficient in this
* architecture.
* - FIQ sources can preempt the kernel (by design) so it is not possible to
* invoke the kernel APIs from inside a FIQ handler. FIQ handlers are not
* affected by the kernel activity so there is not added jitter.
* .
* @section ARM7_IH ARM7 Interrupt Handlers
* ARM7 Interrupt handlers do not save function-saved registers so you need to
* make sure your code saves them or does not use them (this happens
* because in the ARM7 port all the OS interrupt handler functions are declared
* naked).<br>
* Function-trashed registers (R0-R3, R12, LR, SR) are saved/restored by the
* system macros @p CH_IRQ_PROLOGUE() and @p CH_IRQ_EPILOGUE().<br>
* The easiest way to ensure this is to just invoke a normal function from
* within the interrupt handler, the function code will save all the required
* registers.<br>
* Example:
* @code
* CH_IRQ_HANDLER(irq_handler) {
* CH_IRQ_PROLOGUE();
*
* serve_interrupt();
*
* VICVectAddr = 0; // This is LPC214x-specific.
* CH_IRQ_EPILOGUE();
* }
* @endcode
* This is not a bug but an implementation choice, this solution allows to
* have interrupt handlers compiled in thumb mode without have to use an
* interworking mode (the mode switch is hidden in the macros), this
* greatly improves code efficiency and size. You can look at the serial
* driver for real examples of interrupt handlers.
*
* @ingroup Ports
*/
/**
* @defgroup ARM7_CONF Configuration Options
* @brief ARM7 specific configuration options.
* @details The ARM7 port allows some architecture-specific configurations
* settings that can be specified externally, as example on the compiler
* command line:
* - @p INT_REQUIRED_STACK, this value represent the amount of stack space used
* by an interrupt handler between the @p extctx and @p intctx
* structures.<br>
* In practice this value is the stack space used by the chSchDoReschedule()
* stack frame.<br>
* This value can be affected by a variety of external things like compiler
* version, compiler options, kernel settings (speed/size) and so on.<br>
* The default for this value is @p 0x10 which should be a safe value, you
* can trim this down by defining the macro externally. This would save
* some valuable RAM space for each thread present in the system.<br>
* The default value is set into <b>./ports/ARM7/chcore.h</b>.
* .
* @ingroup ARM7
*/
/**
* @defgroup ARM7_CORE Core Port Implementation
* @brief ARM7 specific port code, structures and macros.
*
* @ingroup ARM7
* @file ports/ARM7/chtypes.h Port types.
* @file ports/ARM7/chcore.h Port related structures and macros.
* @file ports/ARM7/chcore.c Port related code.
*/
/**
* @defgroup ARM7_STARTUP Startup Support
* @brief ARM7 startup code support.
* @details ChibiOS/RT provides its own generic startup file for the ARM7 port.
* Of course it is not mandatory to use it but care should be taken about the
* startup phase details.
*
* <h2>Startup Process</h2>
* The startup process, as implemented, is the following:
* -# The stacks are initialized by assigning them the sizes defined in the
* linker script (usually named @p ch.ld). Stack areas are allocated from
* the highest RAM location downward.
* -# The ARM state is switched to System with both IRQ and FIQ sources
* disabled.
* -# An early initialization routine @p hwinit0 is invoked, if the symbol is
* not defined then an empty default routine is executed (weak symbol).
* -# DATA and BSS segments are initialized.
* -# A late initialization routine @p hwinit1 is invoked, if the symbol not
* defined then an empty default routine is executed (weak symbol).<br>
* This late initialization function is also the proper place for a
* @a bootloader, if your application requires one.
* -# The @p main() function is invoked with the parameters @p argc and @p argv
* set to zero.
* -# Should the @p main() function return a branch is performed to the weak
* symbol MainExitHandler. The default code is an endless empty loop.
* .
* <h2>Expected linker symbols</h2>
* The startup code starts at the symbol @p ResetHandler and expects the
* following symbols to be defined in the linker script:
* - @p __ram_end__ RAM end location +1.
* - @p __und_stack_size__ Undefined Instruction stack size.
* - @p __abt_stack_size__ Memory Abort stack size.
* - @p __fiq_stack_size__ FIQ service stack size.
* - @p __irq_stack_size__ IRQ service stack size.
* - @p __svc_stack_size__ SVC service stack size.
* - @p __sys_stack_size__ System/User stack size. This is the stack area used
* by the @p main() function.
* - @p _textdata address of the data segment source read only data.
* - @p _data data segment start location.
* - @p _edata data segment end location +1.
* - @p _bss_start BSS start location.
* - @p _bss_end BSS end location +1.
* .
* @ingroup ARM7
* @file ports/ARM7/crt0.s Startup code.
*/

View File

@ -1,158 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARMCM3-STM32F103/pal_lld.c
* @brief STM32 GPIO low level driver code
* @addtogroup STM32F103_PAL
* @{
*/
#include <ch.h>
#include <pal.h>
#if defined(STM32F10X_LD)
#define APB2_RST_MASK (RCC_APB2RSTR_IOPARST | RCC_APB2RSTR_IOPBRST | \
RCC_APB2RSTR_IOPCRST | RCC_APB2RSTR_IOPDRST | \
RCC_APB2RSTR_AFIORST)
#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \
RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \
RCC_APB2ENR_AFIOEN)
#elif defined(STM32F10X_HD)
#define APB2_RST_MASK (RCC_APB2RSTR_IOPARST | RCC_APB2RSTR_IOPBRST | \
RCC_APB2RSTR_IOPCRST | RCC_APB2RSTR_IOPDRST | \
RCC_APB2RSTR_IOPERST | RCC_APB2RSTR_IOPFRST | \
RCC_APB2RSTR_IOPGRST | RCC_APB2RSTR_AFIORST);
#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \
RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \
RCC_APB2ENR_IOPEEN | RCC_APB2ENR_IOPFEN | \
RCC_APB2ENR_IOPGEN | RCC_APB2ENR_AFIOEN)
#else
/* Defaults on Medium Density devices.*/
#define APB2_RST_MASK (RCC_APB2RSTR_IOPARST | RCC_APB2RSTR_IOPBRST | \
RCC_APB2RSTR_IOPCRST | RCC_APB2RSTR_IOPDRST | \
RCC_APB2RSTR_IOPERST | RCC_APB2RSTR_AFIORST);
#define APB2_EN_MASK (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | \
RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | \
RCC_APB2ENR_IOPEEN | RCC_APB2ENR_AFIOEN)
#endif
/**
* @brief STM32 I/O ports configuration.
* @details Ports A-D(E, F, G) clocks enabled, AFIO clock enabled.
*
* @param[in] config the STM32 ports configuration
*/
void _pal_lld_init(const STM32GPIOConfig *config) {
/*
* Enables the GPIO related clocks.
*/
RCC->APB2ENR |= APB2_EN_MASK;
/*
* Resets the GPIO ports and AFIO.
*/
RCC->APB2RSTR = APB2_RST_MASK;
RCC->APB2RSTR = 0;
IOPORT_A->ODR = config->PAData.odr;
IOPORT_A->CRH = config->PAData.crh;
IOPORT_A->CRL = config->PAData.crl;
IOPORT_B->ODR = config->PBData.odr;
IOPORT_B->CRH = config->PBData.crh;
IOPORT_B->CRL = config->PBData.crl;
IOPORT_C->ODR = config->PCData.odr;
IOPORT_C->CRH = config->PCData.crh;
IOPORT_C->CRL = config->PCData.crl;
IOPORT_D->ODR = config->PDData.odr;
IOPORT_D->CRH = config->PDData.crh;
IOPORT_D->CRL = config->PDData.crl;
#if !defined(STM32F10X_LD) || defined(__DOXYGEN__)
IOPORT_E->ODR = config->PEData.odr;
IOPORT_E->CRH = config->PEData.crh;
IOPORT_E->CRL = config->PEData.crl;
#endif
#if defined(STM32F10X_HD) || defined(__DOXYGEN__)
IOPORT_F->ODR = config->PFData.odr;
IOPORT_F->CRH = config->PFData.crh;
IOPORT_F->CRL = config->PFData.crl;
IOPORT_G->ODR = config->PGData.odr;
IOPORT_G->CRH = config->PGData.crh;
IOPORT_G->CRL = config->PGData.crl;
#endif
}
/**
* @brief Pads mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note @p PAL_MODE_UNCONNECTED is implemented as push pull output at 2MHz.
* @note Writing on pads programmed as pull-up or pull-down has the side
* effect to modify the resistor setting because the output latched data
* is used for the resistor selection.
*/
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode) {
static const uint8_t cfgtab[] = {
4, /* PAL_MODE_RESET, implemented as input.*/
2, /* PAL_MODE_UNCONNECTED, implemented as push pull output 2MHz.*/
4, /* PAL_MODE_INPUT */
8, /* PAL_MODE_INPUT_PULLUP */
8, /* PAL_MODE_INPUT_PULLDOWN */
3, /* PAL_MODE_OUTPUT_PUSHPULL, 50MHz.*/
7, /* PAL_MODE_OUTPUT_OPENDRAIN, 50MHz.*/
};
uint32_t mh, ml, crh, crl, cfg;
unsigned i;
if (mode == PAL_MODE_INPUT_PULLUP)
port->BSRR = mask;
else if (mode == PAL_MODE_INPUT_PULLDOWN)
port->BRR = mask;
cfg = cfgtab[mode];
mh = ml = crh = crl = 0;
for (i = 0; i < 8; i++) {
ml <<= 4;
mh <<= 4;
crl <<= 4;
crh <<= 4;
if ((mask & 1) == 0)
ml |= 0xf;
else
crl |= cfg;
if ((mask & 0x10000) == 0)
mh |= 0xf;
else
crh |= cfg;
mask >>= 1;
}
port->CRH = (port->CRH & mh) | crh;
port->CRL = (port->CRL & ml) | crl;
}
/** @} */

View File

@ -1,307 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARMCM3-STM32F103/pal_lld.h
* @brief STM32 GPIO low level driver header
* @addtogroup STM32F103_PAL
* @{
*/
#ifndef _PAL_LLD_H_
#define _PAL_LLD_H_
/*
* Tricks required to make the TRUE/FALSE declaration inside the library
* compatible.
*/
#ifndef __STM32F10x_H
#undef FALSE
#undef TRUE
#include <stm32f10x.h>
#define FALSE 0
#define TRUE (!FALSE)
#endif
/*===========================================================================*/
/* I/O Ports Types and constants. */
/*===========================================================================*/
/**
* @brief GPIO port setup info.
*/
typedef struct {
/** Initial value for ODR register.*/
uint32_t odr;
/** Initial value for CRL register.*/
uint32_t crl;
/** Initial value for CRH register.*/
uint32_t crh;
} stm32_gpio_setup_t;
/**
* @brief STM32 GPIO static initializer.
* @details An instance of this structure must be passed to @p palInit() at
* system startup time in order to initialized the digital I/O
* subsystem. This represents only the initial setup, specific pads
* or whole ports can be reprogrammed at later time.
*/
typedef struct {
/** @brief Port A setup data.*/
stm32_gpio_setup_t PAData;
/** @brief Port B setup data.*/
stm32_gpio_setup_t PBData;
/** @brief Port C setup data.*/
stm32_gpio_setup_t PCData;
/** @brief Port D setup data.*/
stm32_gpio_setup_t PDData;
#if !defined(STM32F10X_LD) || defined(__DOXYGEN__)
/** @brief Port E setup data.*/
stm32_gpio_setup_t PEData;
#endif
#if defined(STM32F10X_HD) || defined(__DOXYGEN__)
/** @brief Port F setup data.*/
stm32_gpio_setup_t PFData;
/** @brief Port G setup data.*/
stm32_gpio_setup_t PGData;
#endif
} STM32GPIOConfig;
/**
* @brief Width, in bits, of an I/O port.
*/
#define PAL_IOPORTS_WIDTH 16
/**
* @brief Whole port mask.
* @brief This macro specifies all the valid bits into a port.
*/
#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFF)
/**
* @brief Digital I/O port sized unsigned type.
*/
typedef uint32_t ioportmask_t;
/**
* @brief Port Identifier.
* @details This type can be a scalar or some kind of pointer, do not make
* any assumption about it, use the provided macros when populating
* variables of this type.
*/
typedef GPIO_TypeDef * ioportid_t;
/*===========================================================================*/
/* I/O Ports Identifiers. */
/* The low level driver wraps the definitions already present in the STM32 */
/* firmware library. */
/*===========================================================================*/
/**
* @brief GPIO port A identifier.
*/
#define IOPORT_A GPIOA
/**
* @brief GPIO port B identifier.
*/
#define IOPORT_B GPIOB
/**
* @brief GPIO port C identifier.
*/
#define IOPORT_C GPIOC
/**
* @brief GPIO port D identifier.
*/
#define IOPORT_D GPIOD
/**
* @brief GPIO port E identifier.
*/
#if !defined(STM32F10X_LD) || defined(__DOXYGEN__)
#define IOPORT_E GPIOE
#endif
/**
* @brief GPIO port F identifier.
*/
#if defined(STM32F10X_HD) || defined(__DOXYGEN__)
#define IOPORT_F GPIOF
/**
* @brief GPIO port G identifier.
*/
#define IOPORT_G GPIOG
#endif
/*===========================================================================*/
/* Implementation, some of the following macros could be implemented as */
/* functions, please put them in a file named ioports_lld.c if so. */
/*===========================================================================*/
/**
* @brief GPIO ports subsystem initialization.
*/
#define pal_lld_init(config) _pal_lld_init(config)
/**
* @brief Reads an I/O port.
* @details This function is implemented by reading the GPIO IDR register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @return the port bits
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_readport(port) ((port)->IDR)
/**
* @brief Reads the output latch.
* @details This function is implemented by reading the GPIO ODR register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @return The latched logical states.
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_readlatch(port) ((port)->ODR)
/**
* @brief Writes on a I/O port.
* @details This function is implemented by writing the GPIO ODR register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be written on the specified port
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note Writing on pads programmed as pull-up or pull-down has the side
* effect to modify the resistor setting because the output latched data
* is used for the resistor selection.
*/
#define pal_lld_writeport(port, bits) ((port)->ODR = (bits))
/**
* @brief Sets a bits mask on a I/O port.
* @details This function is implemented by writing the GPIO BSRR register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be ORed on the specified port
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note Writing on pads programmed as pull-up or pull-down has the side
* effect to modify the resistor setting because the output latched data
* is used for the resistor selection.
*/
#define pal_lld_setport(port, bits) ((port)->BSRR = (bits))
/**
* @brief Clears a bits mask on a I/O port.
* @details This function is implemented by writing the GPIO BRR register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be cleared on the specified port
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note Writing on pads programmed as pull-up or pull-down has the side
* effect to modify the resistor setting because the output latched data
* is used for the resistor selection.
*/
#define pal_lld_clearport(port, bits) ((port)->BRR = (bits))
/**
* @brief Writes a group of bits.
* @details This function is implemented by writing the GPIO BSRR register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] offset the group bit offset within the port
* @param[in] bits the bits to be written. Values exceeding the group width
* are masked.
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note Writing on pads programmed as pull-up or pull-down has the side
* effect to modify the resistor setting because the output latched data
* is used for the resistor selection.
*/
#define pal_lld_writegroup(port, mask, offset, bits) { \
(port)->BSRR = ((~(bits) & (mask)) << (16 + (offset))) | \
(((bits) & (mask)) << (offset)); \
}
/**
* @brief Pads group mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note Writing on pads programmed as pull-up or pull-down has the side
* effect to modify the resistor setting because the output latched data
* is used for the resistor selection.
*/
#define pal_lld_setgroupmode(port, mask, mode) \
_pal_lld_setgroupmode(port, mask, mode)
/**
* @brief Writes a logical state on an output pad.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
* @param[out] bit the logical value, the value must be @p 0 or @p 1
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note Writing on pads programmed as pull-up or pull-down has the side
* effect to modify the resistor setting because the output latched data
* is used for the resistor selection.
*/
#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit)
#ifdef __cplusplus
extern "C" {
#endif
void _pal_lld_init(const STM32GPIOConfig *config);
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode);
#ifdef __cplusplus
}
#endif
#endif /* _PAL_LLD_H_ */
/** @} */

View File

@ -1,72 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @defgroup STM32F103 STM32F103 Support
* @brief STM32F103 specific support.
* @details The STM32F103 support includes:
* - I/O ports driver.
* - Buffered, interrupt driven, serial driver.
* - A demo supporting the kernel test suite.
* .
* @ingroup ARMCM3
*/
/**
* @defgroup STM32F103_PAL I/O Ports Support
* @brief I/O Ports peripherals support.
* @details This module supports the STM32F103 GPIO controller. The controller
* supports the following features (see @ref PAL):
* - 16 bits wide ports.
* - Atomic set/reset functions.
* - Atomic set+reset function (atomic bus operations).
* - Output latched regardless of the pad setting.
* - Direct read of input pads regardless of the pad setting.
* .
* <h2>Supported Setup Modes</h2>
* - @p PAL_MODE_RESET.
* - @p PAL_MODE_UNCONNECTED.
* - @p PAL_MODE_INPUT.
* - @p PAL_MODE_INPUT_PULLUP.
* - @p PAL_MODE_INPUT_PULLDOWN.
* - @p PAL_MODE_OUTPUT_PUSHPULL.
* - @p PAL_MODE_OUTPUT_OPENDRAIN.
* .
* Any attempt to setup an invalid mode is ignored.
*
* <h2>Suboptimal Behavior</h2>
* Some GPIO features are less than optimal:
* - Pad/port toggling operations are not atomic.
* - Pad/group mode setup is not atomic.
* - Writing on pads/groups/ports programmed as input with pull-up/down
* resistor can change the resistor setting because the output latch is
* used for resistor selection.
* .
* @ingroup STM32F103
*/
/**
* @defgroup STM32F103_SERIAL USART Support
* @brief USART peripherals support.
* @details The serial driver supports the STM32F103 USARTs in asynchronous
* mode.
*
* @ingroup STM32F103
*/

View File

@ -1,27 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARMCM3-STM32F103/stm32_can.c
* @brief STM32 CAN driver code
* @addtogroup STM32F103_CAN
* @{
*/
/** @} */

View File

@ -1,48 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARMCM3-STM32F103/stm32_can.h
* @brief STM32 CAN driver header file
* @addtogroup STM32F103_CAN
* @{
*/
#ifndef _STM32_CAN_H_
#define _STM32_CAN_H_
typedef struct {
} CANConfig;
typedef struct {
} CANMessage;
#ifdef __cplusplus
extern "C" {
#endif
void canInit(CANConfig *config);
bool_t canReceive(CANMessage *canmsg);
bool_t canTransmit(CANMessage *canmsg);
#ifdef __cplusplus
}
#endif
#endif /* _STM32_CAN_H_ */
/** @} */

View File

@ -1,222 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARMCM3-STM32F103/stm32_serial.c
* @brief STM32F103 Serial driver code.
* @addtogroup STM32F103_SERIAL
* @{
*/
#include <ch.h>
#include "board.h"
#include "nvic.h"
#include "stm32_serial.h"
#if USE_STM32_USART1 || defined(__DOXYGEN__)
/** @brief USART1 serial driver identifier.*/
FullDuplexDriver COM1;
static uint8_t ib1[SERIAL_BUFFERS_SIZE];
static uint8_t ob1[SERIAL_BUFFERS_SIZE];
#endif
#if USE_STM32_USART2 || defined(__DOXYGEN__)
/** @brief USART2 serial driver identifier.*/
FullDuplexDriver COM2;
static uint8_t ib2[SERIAL_BUFFERS_SIZE];
static uint8_t ob2[SERIAL_BUFFERS_SIZE];
#endif
#if USE_STM32_USART3 || defined(__DOXYGEN__)
/** @brief USART3 serial driver identifier.*/
FullDuplexDriver COM3;
static uint8_t ib3[SERIAL_BUFFERS_SIZE];
static uint8_t ob3[SERIAL_BUFFERS_SIZE];
#endif
/**
* @brief Error handling routine.
* @param[in] sr USART SR register value
* @param[in] com communication channel associated to the USART
*/
static void SetError(uint16_t sr, FullDuplexDriver *com) {
dflags_t sts = 0;
if (sr & USART_SR_ORE)
sts |= SD_OVERRUN_ERROR;
if (sr & USART_SR_PE)
sts |= SD_PARITY_ERROR;
if (sr & USART_SR_FE)
sts |= SD_FRAMING_ERROR;
if (sr & USART_SR_LBD)
sts |= SD_BREAK_DETECTED;
chSysLockFromIsr();
chFDDAddFlagsI(com, sts);
chSysUnlockFromIsr();
}
/**
* @brief Common IRQ handler.
* @param[in] u pointer to an USART I/O block
* @param[in] com communication channel associated to the USART
*/
static void ServeInterrupt(USART_TypeDef *u, FullDuplexDriver *com) {
uint16_t sr = u->SR;
if (sr & (USART_SR_ORE | USART_SR_FE | USART_SR_PE | USART_SR_LBD))
SetError(sr, com);
if (sr & USART_SR_RXNE) {
chSysLockFromIsr();
chFDDIncomingDataI(com, u->DR);
chSysUnlockFromIsr();
}
if (sr & USART_SR_TXE) {
chSysLockFromIsr();
msg_t b = chFDDRequestDataI(com);
chSysUnlockFromIsr();
if (b < Q_OK)
u->CR1 &= ~USART_CR1_TXEIE;
else
u->DR = b;
}
}
#if USE_STM32_USART1 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(VectorD4) {
CH_IRQ_PROLOGUE();
ServeInterrupt(USART1, &COM1);
CH_IRQ_EPILOGUE();
}
static void OutNotify1(void) {
USART1->CR1 |= USART_CR1_TXEIE;
}
#endif
#if USE_STM32_USART2 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(VectorD8) {
CH_IRQ_PROLOGUE();
ServeInterrupt(USART2, &COM2);
CH_IRQ_EPILOGUE();
}
static void OutNotify2(void) {
USART2->CR1 |= USART_CR1_TXEIE;
}
#endif
#if USE_STM32_USART3 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(VectorDC) {
CH_IRQ_PROLOGUE();
ServeInterrupt(USART3, &COM3);
CH_IRQ_EPILOGUE();
}
static void OutNotify3(void) {
USART3->CR1 |= USART_CR1_TXEIE;
}
#endif
/**
* @brief USART1 setup.
* @details This function must be invoked with interrupts disabled.
* @param[in] u pointer to an USART I/O block
* @param[in] speed serial port speed in bits per second
* @param[in] cr1 the value for the @p CR1 register
* @param[in] cr2 the value for the @p CR2 register
* @param[in] cr3 the value for the @p CR3 register
* @note Must be invoked with interrupts disabled.
* @note Does not reset the I/O queues.
*/
void usart_setup(USART_TypeDef *u, uint32_t speed, uint16_t cr1,
uint16_t cr2, uint16_t cr3) {
/*
* Baud rate setting.
*/
if (u == USART1)
u->BRR = APB2CLK / speed;
else
u->BRR = APB1CLK / speed;
/*
* Note that some bits are enforced.
*/
u->CR1 = cr1 | USART_CR1_UE | USART_CR1_PEIE | USART_CR1_RXNEIE |
USART_CR1_TE | USART_CR1_RE;
u->CR2 = cr2;
u->CR3 = cr3 | USART_CR3_EIE;
}
/**
* @brief Serial driver initialization.
* @param[in] prio1 priority to be assigned to the USART1 IRQ
* @param[in] prio2 priority to be assigned to the USART2 IRQ
* @param[in] prio3 priority to be assigned to the USART3 IRQ
* @note Handshake pads are not enabled inside this function because they
* may have another use, enable them externally if needed.
* RX and TX pads are handled inside.
*/
void serial_init(uint32_t prio1, uint32_t prio2, uint32_t prio3) {
#if USE_STM32_USART1
chFDDInit(&COM1, ib1, sizeof ib1, NULL, ob1, sizeof ob1, OutNotify1);
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
usart_setup(USART1, DEFAULT_USART_BITRATE, 0,
USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0);
GPIOA->CRH = (GPIOA->CRH & 0xFFFFF00F) | 0x000004B0;
NVICEnableVector(USART1_IRQn, prio1);
#endif
#if USE_STM32_USART2
chFDDInit(&COM2, ib2, sizeof ib2, NULL, ob2, sizeof ob2, OutNotify2);
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
usart_setup(USART2, DEFAULT_USART_BITRATE, 0,
USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0);
GPIOA->CRL = (GPIOA->CRL & 0xFFFF00FF) | 0x00004B00;
NVICEnableVector(USART2_IRQn, prio2);
#endif
#if USE_STM32_USART3
chFDDInit(&COM3, ib3, sizeof ib3, NULL, ob3, sizeof ob3, OutNotify3);
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
usart_setup(USART3, DEFAULT_USART_BITRATE, 0,
USART_CR2_STOP1_BITS | USART_CR2_LINEN, 0);
GPIOB->CRH = (GPIOB->CRH & 0xFFFF00FF) | 0x00004B00;
NVICEnableVector(USART3_IRQn, prio3);
#endif
}
/** @} */

View File

@ -1,122 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARMCM3-STM32F103/stm32_serial.h
* @brief STM32F103 Serial driver macros and structures.
* @addtogroup STM32F103_SERIAL
* @{
*/
#ifndef _STM32_SERIAL_H_
#define _STM32_SERIAL_H_
/*
* Tricks required to make the TRUE/FALSE declaration inside the library
* compatible.
*/
#ifndef __STM32F10x_H
#undef FALSE
#undef TRUE
#include <stm32f10x.h>
#define FALSE 0
#define TRUE (!FALSE)
#endif
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
* @note The default is 128 bytes for both the transmission and receive buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 128
#endif
/**
* @brief Default bit rate.
* @details Configuration parameter, at startup the USARTs are configured at
* this speed.
* @note It is possible to use @p SetUSART() in order to change the working
* parameters at runtime.
*/
#if !defined(DEFAULT_USART_BITRATE) || defined(__DOXYGEN__)
#define DEFAULT_USART_BITRATE 38400
#endif
/**
* @brief USART1 driver enable switch.
* @details If set to @p TRUE the support for USART1 is included.
* @note The default is @p FALSE.
*/
#if !defined(USE_STM32_USART1) || defined(__DOXYGEN__)
#define USE_STM32_USART1 FALSE
#endif
/**
* @brief USART2 driver enable switch.
* @details If set to @p TRUE the support for USART2 is included.
* @note The default is @p TRUE.
*/
#if !defined(USE_STM32_USART2) || defined(__DOXYGEN__)
#define USE_STM32_USART2 TRUE
#endif
/**
* @brief USART3 driver enable switch.
* @details If set to @p TRUE the support for USART3 is included.
* @note The default is @p FALSE.
*/
#if !defined(USE_STM32_USART3) || defined(__DOXYGEN__)
#define USE_STM32_USART3 FALSE
#endif
/*
* Extra USARTs definitions here (missing from the ST header file).
*/
#define USART_CR2_STOP1_BITS (0 << 12) /**< @brief CR2 1 stop bit value.*/
#define USART_CR2_STOP0P5_BITS (1 << 12) /**< @brief CR2 0.5 stop bit value.*/
#define USART_CR2_STOP2_BITS (2 << 12) /**< @brief CR2 2 stop bit value.*/
#define USART_CR2_STOP1P5_BITS (3 << 12) /**< @brief CR2 1.5 stop bit value.*/
/** @cond never*/
#if USE_STM32_USART1
extern FullDuplexDriver COM1;
#endif
#if USE_STM32_USART2
extern FullDuplexDriver COM2;
#endif
#if USE_STM32_USART3
extern FullDuplexDriver COM3;
#endif
/** @endcond*/
#ifdef __cplusplus
extern "C" {
#endif
void serial_init(uint32_t prio1, uint32_t prio2, uint32_t prio3);
void usart_setup(USART_TypeDef *u, uint32_t speed, uint16_t cr1,
uint16_t cr2, uint16_t cr3);
#ifdef __cplusplus
}
#endif
#endif /* _STM32_SERIAL_H_ */
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -1,256 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
.syntax unified
.thumb
.section vectors
_vectors:
.word __ram_end__
.word ResetHandler
.word NMIVector
.word HardFaultVector
.word MemManageVector
.word BusFaultVector
.word UsageFaultVector
.word Vector1C
.word Vector20
.word Vector24
.word Vector28
.word SVCallVector
.word DebugMonitorVector
.word Vector34
.word PendSVVector
.word SysTickVector
.word Vector40
.word Vector44
.word Vector48
.word Vector4C
.word Vector50
.word Vector54
.word Vector58
.word Vector5C
.word Vector60
.word Vector64
.word Vector68
.word Vector6C
.word Vector70
.word Vector74
.word Vector78
.word Vector7C
.word Vector80
.word Vector84
.word Vector88
.word Vector8C
.word Vector90
.word Vector94
.word Vector98
.word Vector9C
.word VectorA0
.word VectorA4
.word VectorA8
.word VectorAC
.word VectorB0
.word VectorB4
.word VectorB8
.word VectorBC
.word VectorC0
.word VectorC4
.word VectorC8
.word VectorCC
.word VectorD0
.word VectorD4
.word VectorD8
.word VectorDC
.word VectorE0
.word VectorE4
.word VectorE8
.weak NMIVector
NMIVector:
.weak HardFaultVector
HardFaultVector:
.weak MemManageVector
MemManageVector:
.weak BusFaultVector
BusFaultVector:
.weak UsageFaultVector
UsageFaultVector:
.weak Vector1C
Vector1C:
.weak Vector20
Vector20:
.weak Vector24
Vector24:
.weak Vector28
Vector28:
.weak SVCallVector
SVCallVector:
.weak DebugMonitorVector
DebugMonitorVector:
.weak Vector34
Vector34:
.weak PendSVVector
PendSVVector:
.weak SysTickVector
SysTickVector:
.weak Vector40
Vector40:
.weak Vector44
Vector44:
.weak Vector48
Vector48:
.weak Vector4C
Vector4C:
.weak Vector50
Vector50:
.weak Vector54
Vector54:
.weak Vector58
Vector58:
.weak Vector5C
Vector5C:
.weak Vector60
Vector60:
.weak Vector64
Vector64:
.weak Vector68
Vector68:
.weak Vector6C
Vector6C:
.weak Vector70
Vector70:
.weak Vector74
Vector74:
.weak Vector78
Vector78:
.weak Vector7C
Vector7C:
.weak Vector80
Vector80:
.weak Vector84
Vector84:
.weak Vector88
Vector88:
.weak Vector8C
Vector8C:
.weak Vector90
Vector90:
.weak Vector94
Vector94:
.weak Vector98
Vector98:
.weak Vector9C
Vector9C:
.weak VectorA0
VectorA0:
.weak VectorA4
VectorA4:
.weak VectorA8
VectorA8:
.weak VectorAC
VectorAC:
.weak VectorB0
VectorB0:
.weak VectorB4
VectorB4:
.weak VectorB8
VectorB8:
.weak VectorBC
VectorBC:
.weak VectorC0
VectorC0:
.weak VectorC4
VectorC4:
.weak VectorC8
VectorC8:
.weak VectorCC
VectorCC:
.weak VectorD0
VectorD0:
.weak VectorD4
VectorD4:
.weak VectorD8
VectorD8:
.weak VectorDC
VectorDC:
.weak VectorE0
VectorE0:
.weak VectorE4
VectorE4:
.weak VectorE8
VectorE8:
here: b here

View File

@ -1,177 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARMCM3/chcore.c
* @brief ARM Cortex-M3 architecture port code.
* @addtogroup ARMCM3_CORE
* @{
*/
#include <ch.h>
#include <nvic.h>
/**
* Halts the system.
* @note The function is declared as a weak symbol, it is possible to redefine
* it in your application code.
*/
/** @cond never */
__attribute__((weak))
/** @endcond */
void port_halt(void) {
port_disable();
while (TRUE) {
}
}
#if !CH_OPTIMIZE_SPEED
void _port_lock(void) {
register uint32_t tmp asm ("r3") = BASEPRI_KERNEL;
asm volatile ("msr BASEPRI, %0" : : "r" (tmp));
}
void _port_unlock(void) {
register uint32_t tmp asm ("r3") = BASEPRI_USER;
asm volatile ("msr BASEPRI, %0" : : "r" (tmp));
}
#endif
/**
* System Timer vector.
* This interrupt is used as system tick.
* @note The timer is initialized in the board setup code.
*/
CH_IRQ_HANDLER(SysTickVector) {
CH_IRQ_PROLOGUE();
chSysLockFromIsr();
chSysTimerHandlerI();
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE();
}
/**
* The SVC vector is used for commanded context switch.
* @param otp the thread to be switched out
* @param ntp the thread to be switched it
*/
/** @cond never */
__attribute__((naked))
/** @endcond */
void SVCallVector(Thread *otp, Thread *ntp) {
/* { r0 = otp, r1 = ntp } */
/* get the BASEPRI in r3 */
/* get the PSP in r12 */
/* push the registers on the PSP stack */
/* stores the modified PSP into the thread context */
/* fetches the PSP position from the new thread context */
/* pop the registers from the PSP stack */
/* set the PSP from r12 */
/* set the BASEPRI from R3 */
#ifdef CH_CURRP_REGISTER_CACHE
asm volatile ("mrs r3, BASEPRI \n\t" \
"mrs r12, PSP \n\t" \
"stmdb r12!, {r3-r6,r8-r11, lr} \n\t" \
"str r12, [r0, #16] \n\t" \
"ldr r12, [r1, #16] \n\t" \
"ldmia r12!, {r3-r6,r8-r11, lr} \n\t" \
"msr PSP, r12 \n\t" \
"msr BASEPRI, r3 \n\t" \
"bx lr ");
#else
asm volatile ("mrs r3, BASEPRI \n\t" \
"mrs r12, PSP \n\t" \
"stmdb r12!, {r3-r11, lr} \n\t" \
"str r12, [r0, #16] \n\t" \
"ldr r12, [r1, #16] \n\t" \
"ldmia r12!, {r3-r11, lr} \n\t" \
"msr PSP, r12 \n\t" \
"msr BASEPRI, r3 \n\t" \
"bx lr ");
#endif
}
#ifdef CH_CURRP_REGISTER_CACHE
#define PUSH_CONTEXT(sp) { \
register uint32_t tmp asm ("r3") = BASEPRI_USER; \
asm volatile ("mrs %0, PSP \n\t" \
"stmdb %0!, {r3-r6,r8-r11, lr}" : \
"=r" (sp) : "r" (sp), "r" (tmp)); \
}
#define POP_CONTEXT(sp) { \
asm volatile ("ldmia %0!, {r3-r6,r8-r11, lr} \n\t" \
"msr PSP, %0 \n\t" \
"msr BASEPRI, r3 \n\t" \
"bx lr" : "=r" (sp) : "r" (sp)); \
}
#else
#define PUSH_CONTEXT(sp) { \
register uint32_t tmp asm ("r3") = BASEPRI_USER; \
asm volatile ("mrs %0, PSP \n\t" \
"stmdb %0!, {r3-r11,lr}" : \
"=r" (sp) : "r" (sp), "r" (tmp)); \
}
#define POP_CONTEXT(sp) { \
asm volatile ("ldmia %0!, {r3-r11, lr} \n\t" \
"msr PSP, %0 \n\t" \
"msr BASEPRI, r3 \n\t" \
"bx lr" : "=r" (sp) : "r" (sp)); \
}
#endif
/**
* Preemption invoked context switch.
*/
/** @cond never */
__attribute__((naked))
/** @endcond */
void PendSVVector(void) {
Thread *otp;
register struct intctx *sp_thd asm("r12");
chSysLockFromIsr();
asm volatile ("push {lr}");
if (!chSchRescRequiredI()) {
chSysUnlockFromIsr();
asm volatile ("pop {pc}");
}
asm volatile ("pop {lr}");
PUSH_CONTEXT(sp_thd);
(otp = currp)->p_ctx.r13 = sp_thd;
(currp = fifo_remove((void *)&rlist))->p_state = PRCURR;
chSchReadyI(otp);
#if CH_USE_ROUNDROBIN
/* set the round-robin time quantum */
rlist.r_preempt = CH_TIME_QUANTUM;
#endif
chDbgTrace(otp, currp);
sp_thd = currp->p_ctx.r13;
POP_CONTEXT(sp_thd);
}
/** @} */

View File

@ -1,333 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARMCM3/chcore.h
* @brief ARM Cortex-M3 architecture port macros and structures.
* @addtogroup ARMCM3_CORE
* @{
*/
#ifndef _CHCORE_H_
#define _CHCORE_H_
/*
* Port-related configuration parameters.
*/
/**
* Enables the use of the WFI ins.
*/
#ifndef ENABLE_WFI_IDLE
#define ENABLE_WFI_IDLE 0
#endif
/**
* BASEPRI user level, 0 = disabled.
*/
#ifndef BASEPRI_USER
#define BASEPRI_USER 0
#endif
/**
* BASEPRI level within kernel lock.
* Priority levels higher than this one (lower values) are unaffected by
* the OS activity and can be classified as fast interrupt sources, see
* @ref interrupt_classes.
*/
#ifndef BASEPRI_KERNEL
#define BASEPRI_KERNEL 0x40
#endif
/**
* SVCALL handler priority.
* @note This priority must always be one level above the @p BASEPRI_KERNEL
* value.
* @note It is recommended to leave this priority level for this handler alone.
*/
#ifndef PRIORITY_SVCALL
#define PRIORITY_SVCALL (BASEPRI_KERNEL - 0x10)
#endif
/**
* SYSTICK handler priority.
*/
#ifndef PRIORITY_SYSTICK
#define PRIORITY_SYSTICK 0x80
#endif
/**
* PENDSV handler priority.
* @note It is recommended to leave this priority level for this handler alone.
* @note This is a reserved handler and its priority must always be the
* lowest priority in the system in order to be always executed last
* in the interrupt servicing chain.
*/
#ifndef PRIORITY_PENDSV
#define PRIORITY_PENDSV 0xF0
#endif
/**
* Macro defining the ARM Cortex-M3 architecture.
*/
#define CH_ARCHITECTURE_ARMCM3
/**
* Name of the implemented architecture.
*/
#define CH_ARCHITECTURE_NAME "ARM Cortex-M3"
/**
* 32 bit stack alignment.
*/
typedef uint32_t stkalign_t;
/**
* Generic ARM register.
*/
typedef void *regarm_t;
/** @cond never */
/**
* Interrupt saved context, empty in this architecture.
*/
struct extctx {
};
/** @endcond */
/** @cond never */
/**
* This structure represents the inner stack frame during a context switching.
*/
struct intctx {
regarm_t basepri;
regarm_t r4;
regarm_t r5;
regarm_t r6;
#ifndef CH_CURRP_REGISTER_CACHE
regarm_t r7;
#endif
regarm_t r8;
regarm_t r9;
regarm_t r10;
regarm_t r11;
regarm_t lr_exc;
regarm_t r0;
regarm_t r1;
regarm_t r2;
regarm_t r3;
regarm_t r12;
regarm_t lr_thd;
regarm_t pc;
regarm_t xpsr;
};
/** @endcond */
/** @cond never */
/**
* Cortex-M3 context structure.
*/
struct context {
struct intctx *r13;
};
/** @endcond */
/**
* Platform dependent part of the @p chThdInit() API.
* This code usually setup the context switching frame represented by a
* @p intctx structure.
*/
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
tp->p_ctx.r13 = (struct intctx *)((uint8_t *)workspace + \
wsize - \
sizeof(struct intctx)); \
tp->p_ctx.r13->basepri = BASEPRI_USER; \
tp->p_ctx.r13->lr_exc = (regarm_t)0xFFFFFFFD; \
tp->p_ctx.r13->r0 = arg; \
tp->p_ctx.r13->lr_thd = chThdExit; \
tp->p_ctx.r13->pc = pf; \
tp->p_ctx.r13->xpsr = (regarm_t)0x01000000; \
}
/**
* The default idle thread implementation requires no extra stack space in
* this port.
*/
#ifndef IDLE_THREAD_STACK_SIZE
#define IDLE_THREAD_STACK_SIZE 0
#endif
/**
* This port requires no extra stack space for interrupt handling.
*/
#ifndef INT_REQUIRED_STACK
#define INT_REQUIRED_STACK 0
#endif
/**
* Enforces a correct alignment for a stack area size value.
*/
#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1)
/**
* Computes the thread working area global size.
*/
#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
sizeof(struct intctx) + \
sizeof(struct extctx) + \
(n) + (INT_REQUIRED_STACK))
/**
* Macro used to allocate a thread working area aligned as both position and
* size.
*/
#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)];
/**
* IRQ prologue code, inserted at the start of all IRQ handlers enabled to
* invoke system APIs.
*/
#define PORT_IRQ_PROLOGUE()
/**
* IRQ epilogue code, inserted at the end of all IRQ handlers enabled to
* invoke system APIs.
*/
#define PORT_IRQ_EPILOGUE() { \
SCB_ICSR = ICSR_PENDSVSET; \
}
/**
* IRQ handler function declaration.
*/
#define PORT_IRQ_HANDLER(id) void id(void)
/**
* This function is empty in this port.
*/
#define port_init()
/**
* Raises the base priority to kernel level.
*/
#if CH_OPTIMIZE_SPEED
#define port_lock() { \
register uint32_t tmp asm ("r3") = BASEPRI_KERNEL; \
asm volatile ("msr BASEPRI, %0" : : "r" (tmp)); \
}
#else
#define port_lock() { \
asm volatile ("bl _port_lock" : : : "r3", "lr"); \
}
#endif
/**
* Lowers the base priority to user level.
*/
#if CH_OPTIMIZE_SPEED
#define port_unlock() { \
register uint32_t tmp asm ("r3") = BASEPRI_USER; \
asm volatile ("msr BASEPRI, %0" : : "r" (tmp)); \
}
#else
#define port_unlock() { \
asm volatile ("bl _port_unlock" : : : "r3", "lr"); \
}
#endif
/**
* Same as @p port_lock() in this port.
*/
#define port_lock_from_isr() port_lock()
/**
* Same as @p port_unlock() in this port.
*/
#define port_unlock_from_isr() port_unlock()
/**
* Disables all the interrupt sources by raising the priority mask to level 0.
*/
#define port_disable() asm volatile ("cpsid i")
/**
* Raises/lowers the base priority to kernel level.
*/
#define port_suspend() { \
register uint32_t tmp asm ("r3") = BASEPRI_KERNEL; \
asm volatile ("msr BASEPRI, %0 \n\t" \
"cpsie i" : : "r" (tmp)); \
}
/**
* Lowers the base priority to user level.
*/
#define port_enable() { \
register uint32_t tmp asm ("r3") = BASEPRI_USER; \
asm volatile ("msr BASEPRI, %0 \n\t" \
"cpsie i" : : "r" (tmp)); \
}
/**
* This port function is implemented as inlined code for performance reasons.
*/
#if ENABLE_WFI_IDLE || defined(__DOXYGEN__)
#define port_wait_for_interrupt() { \
asm volatile ("wfi"); \
}
#else
#define port_wait_for_interrupt()
#endif
/**
* This port function is implemented as inlined code for performance reasons.
*/
#if CH_DBG_ENABLE_STACK_CHECK
#define port_switch(otp, ntp) { \
register Thread *_otp asm ("r0") = (otp); \
register Thread *_ntp asm ("r1") = (ntp); \
register char *sp asm ("sp"); \
if (sp - sizeof(struct intctx) - sizeof(Thread) < (char *)_otp) \
asm volatile ("movs r0, #0 \n\t" \
"b chDbgPanic"); \
asm volatile ("svc #0" : : "r" (_otp), "r" (_ntp)); \
}
#else /* !CH_DBG_ENABLE_STACK_CHECK */
#define port_switch(otp, ntp) { \
register Thread *_otp asm ("r0") = (otp); \
register Thread *_ntp asm ("r1") = (ntp); \
asm volatile ("svc #0" : : "r" (_otp), "r" (_ntp)); \
}
#endif /* !CH_DBG_ENABLE_STACK_CHECK */
#ifdef __cplusplus
extern "C" {
#endif
void port_halt(void);
#if !CH_OPTIMIZE_SPEED
void _port_lock(void);
void _port_unlock(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* _CHCORE_H_ */
/** @} */

View File

@ -1,56 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARMCM3/chtypes.h
* @brief ARM Cortex-M3 architecture port system types.
* @addtogroup ARMCM3_CORE
* @{
*/
#ifndef _CHTYPES_H_
#define _CHTYPES_H_
#define __need_NULL
#define __need_size_t
#define __need_ptrdiff_t
#include <stddef.h>
#if !defined(_STDINT_H) && !defined(__STDINT_H_)
#include <stdint.h>
#endif
typedef int32_t bool_t; /**< Fast boolean type. */
typedef uint8_t tmode_t; /**< Thread flags. */
typedef uint8_t tstate_t; /**< Thread state. */
typedef uint32_t tprio_t; /**< Thread priority. */
typedef int32_t msg_t; /**< Inter-thread message. */
typedef int32_t eventid_t; /**< Event Id. */
typedef uint32_t eventmask_t; /**< Events mask. */
typedef uint32_t systime_t; /**< System time. */
typedef int32_t cnt_t; /**< Resources counter. */
#define INLINE inline
#define PACK_STRUCT_STRUCT __attribute__((packed))
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_END
#endif /* _CHTYPES_H_ */
/** @} */

View File

@ -1,829 +0,0 @@
/******************************************************************************
* @file: core_cm3.c
* @purpose: CMSIS Cortex-M3 Core Peripheral Access Layer Source File
* @version: V1.20
* @date: 22. May 2009
*----------------------------------------------------------------------------
*
* Copyright (C) 2009 ARM Limited. All rights reserved.
*
* ARM Limited (ARM) is supplying this software for use with Cortex-Mx
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#include <stdint.h>
/* define compiler specific symbols */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for armcc */
#define __INLINE __inline /*!< inline keyword for armcc */
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for iarcc */
#define __INLINE inline /*!< inline keyword for iarcc. Only avaiable in High optimization mode! */
#elif defined ( __GNUC__ )
#define __ASM __asm /*!< asm keyword for gcc */
#define __INLINE inline /*!< inline keyword for gcc */
#elif defined ( __TASKING__ )
#define __ASM __asm /*!< asm keyword for TASKING Compiler */
#define __INLINE inline /*!< inline keyword for TASKING Compiler */
#endif
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/**
* @brief Return the Process Stack Pointer
*
* @param none
* @return uint32_t ProcessStackPointer
*
* Return the actual process stack pointer
*/
__ASM uint32_t __get_PSP(void)
{
mrs r0, psp
bx lr
}
/**
* @brief Set the Process Stack Pointer
*
* @param uint32_t Process Stack Pointer
* @return none
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
__ASM void __set_PSP(uint32_t topOfProcStack)
{
msr psp, r0
bx lr
}
/**
* @brief Return the Main Stack Pointer
*
* @param none
* @return uint32_t Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
__ASM uint32_t __get_MSP(void)
{
mrs r0, msp
bx lr
}
/**
* @brief Set the Main Stack Pointer
*
* @param uint32_t Main Stack Pointer
* @return none
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
__ASM void __set_MSP(uint32_t mainStackPointer)
{
msr msp, r0
bx lr
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param uint16_t value to reverse
* @return uint32_t reversed value
*
* Reverse byte order in unsigned short value
*/
__ASM uint32_t __REV16(uint16_t value)
{
rev16 r0, r0
bx lr
}
/**
* @brief Reverse byte order in signed short value with sign extension to integer
*
* @param int16_t value to reverse
* @return int32_t reversed value
*
* Reverse byte order in signed short value with sign extension to integer
*/
__ASM int32_t __REVSH(int16_t value)
{
revsh r0, r0
bx lr
}
#if (__ARMCC_VERSION < 400000)
/**
* @brief Remove the exclusive lock created by ldrex
*
* @param none
* @return none
*
* Removes the exclusive lock which is created by ldrex.
*/
__ASM void __CLREX(void)
{
clrex
}
/**
* @brief Return the Base Priority value
*
* @param none
* @return uint32_t BasePriority
*
* Return the content of the base priority register
*/
__ASM uint32_t __get_BASEPRI(void)
{
mrs r0, basepri
bx lr
}
/**
* @brief Set the Base Priority value
*
* @param uint32_t BasePriority
* @return none
*
* Set the base priority register
*/
__ASM void __set_BASEPRI(uint32_t basePri)
{
msr basepri, r0
bx lr
}
/**
* @brief Return the Priority Mask value
*
* @param none
* @return uint32_t PriMask
*
* Return the state of the priority mask bit from the priority mask
* register
*/
__ASM uint32_t __get_PRIMASK(void)
{
mrs r0, primask
bx lr
}
/**
* @brief Set the Priority Mask value
*
* @param uint32_t PriMask
* @return none
*
* Set the priority mask bit in the priority mask register
*/
__ASM void __set_PRIMASK(uint32_t priMask)
{
msr primask, r0
bx lr
}
/**
* @brief Return the Fault Mask value
*
* @param none
* @return uint32_t FaultMask
*
* Return the content of the fault mask register
*/
__ASM uint32_t __get_FAULTMASK(void)
{
mrs r0, faultmask
bx lr
}
/**
* @brief Set the Fault Mask value
*
* @param uint32_t faultMask value
* @return none
*
* Set the fault mask register
*/
__ASM void __set_FAULTMASK(uint32_t faultMask)
{
msr faultmask, r0
bx lr
}
/**
* @brief Return the Control Register value
*
* @param none
* @return uint32_t Control value
*
* Return the content of the control register
*/
__ASM uint32_t __get_CONTROL(void)
{
mrs r0, control
bx lr
}
/**
* @brief Set the Control Register value
*
* @param uint32_t Control value
* @return none
*
* Set the control register
*/
__ASM void __set_CONTROL(uint32_t control)
{
msr control, r0
bx lr
}
#endif /* __ARMCC_VERSION */
#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/
#pragma diag_suppress=Pe940
/**
* @brief Return the Process Stack Pointer
*
* @param none
* @return uint32_t ProcessStackPointer
*
* Return the actual process stack pointer
*/
uint32_t __get_PSP(void)
{
__ASM("mrs r0, psp");
__ASM("bx lr");
}
/**
* @brief Set the Process Stack Pointer
*
* @param uint32_t Process Stack Pointer
* @return none
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
void __set_PSP(uint32_t topOfProcStack)
{
__ASM("msr psp, r0");
__ASM("bx lr");
}
/**
* @brief Return the Main Stack Pointer
*
* @param none
* @return uint32_t Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
uint32_t __get_MSP(void)
{
__ASM("mrs r0, msp");
__ASM("bx lr");
}
/**
* @brief Set the Main Stack Pointer
*
* @param uint32_t Main Stack Pointer
* @return none
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
void __set_MSP(uint32_t topOfMainStack)
{
__ASM("msr msp, r0");
__ASM("bx lr");
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param uint16_t value to reverse
* @return uint32_t reversed value
*
* Reverse byte order in unsigned short value
*/
uint32_t __REV16(uint16_t value)
{
__ASM("rev16 r0, r0");
__ASM("bx lr");
}
/**
* @brief Reverse bit order of value
*
* @param uint32_t value to reverse
* @return uint32_t reversed value
*
* Reverse bit order of value
*/
uint32_t __RBIT(uint32_t value)
{
__ASM("rbit r0, r0");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive
*
* @param uint8_t* address
* @return uint8_t value of (*address)
*
* Exclusive LDR command
*/
uint8_t __LDREXB(uint8_t *addr)
{
__ASM("ldrexb r0, [r0]");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive
*
* @param uint16_t* address
* @return uint16_t value of (*address)
*
* Exclusive LDR command
*/
uint16_t __LDREXH(uint16_t *addr)
{
__ASM("ldrexh r0, [r0]");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive
*
* @param uint32_t* address
* @return uint32_t value of (*address)
*
* Exclusive LDR command
*/
uint32_t __LDREXW(uint32_t *addr)
{
__ASM("ldrex r0, [r0]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive
*
* @param uint8_t *address
* @param uint8_t value to store
* @return uint32_t successful / failed
*
* Exclusive STR command
*/
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
__ASM("strexb r0, r0, [r1]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive
*
* @param uint16_t *address
* @param uint16_t value to store
* @return uint32_t successful / failed
*
* Exclusive STR command
*/
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
__ASM("strexh r0, r0, [r1]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive
*
* @param uint32_t *address
* @param uint32_t value to store
* @return uint32_t successful / failed
*
* Exclusive STR command
*/
uint32_t __STREXW(uint32_t value, uint32_t *addr)
{
__ASM("strex r0, r0, [r1]");
__ASM("bx lr");
}
#pragma diag_default=Pe940
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/**
* @brief Return the Process Stack Pointer
*
* @param none
* @return uint32_t ProcessStackPointer
*
* Return the actual process stack pointer
*/
uint32_t __get_PSP(void) __attribute__( ( naked ) );
uint32_t __get_PSP(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, psp\n\t"
"MOV r0, %0 \n\t"
"BX lr \n\t" : "=r" (result) );
return(result);
}
/**
* @brief Set the Process Stack Pointer
*
* @param uint32_t Process Stack Pointer
* @return none
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
void __set_PSP(uint32_t topOfProcStack) __attribute__( ( naked ) );
void __set_PSP(uint32_t topOfProcStack)
{
__ASM volatile ("MSR psp, %0\n\t"
"BX lr \n\t" : : "r" (topOfProcStack) );
}
/**
* @brief Return the Main Stack Pointer
*
* @param none
* @return uint32_t Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
uint32_t __get_MSP(void) __attribute__( ( naked ) );
uint32_t __get_MSP(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, msp\n\t"
"MOV r0, %0 \n\t"
"BX lr \n\t" : "=r" (result) );
return(result);
}
/**
* @brief Set the Main Stack Pointer
*
* @param uint32_t Main Stack Pointer
* @return none
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
void __set_MSP(uint32_t topOfMainStack) __attribute__( ( naked ) );
void __set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0\n\t"
"BX lr \n\t" : : "r" (topOfMainStack) );
}
/**
* @brief Return the Base Priority value
*
* @param none
* @return uint32_t BasePriority
*
* Return the content of the base priority register
*/
uint32_t __get_BASEPRI(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
return(result);
}
/**
* @brief Set the Base Priority value
*
* @param uint32_t BasePriority
* @return none
*
* Set the base priority register
*/
void __set_BASEPRI(uint32_t value)
{
__ASM volatile ("MSR basepri, %0" : : "r" (value) );
}
/**
* @brief Return the Priority Mask value
*
* @param none
* @return uint32_t PriMask
*
* Return the state of the priority mask bit from the priority mask
* register
*/
uint32_t __get_PRIMASK(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/**
* @brief Set the Priority Mask value
*
* @param uint32_t PriMask
* @return none
*
* Set the priority mask bit in the priority mask register
*/
void __set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) );
}
/**
* @brief Return the Fault Mask value
*
* @param none
* @return uint32_t FaultMask
*
* Return the content of the fault mask register
*/
uint32_t __get_FAULTMASK(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
return(result);
}
/**
* @brief Set the Fault Mask value
*
* @param uint32_t faultMask value
* @return none
*
* Set the fault mask register
*/
void __set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) );
}
/**
* @brief Reverse byte order in integer value
*
* @param uint32_t value to reverse
* @return uint32_t reversed value
*
* Reverse byte order in integer value
*/
uint32_t __REV(uint32_t value)
{
uint32_t result=0;
__ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param uint16_t value to reverse
* @return uint32_t reversed value
*
* Reverse byte order in unsigned short value
*/
uint32_t __REV16(uint16_t value)
{
uint32_t result=0;
__ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse byte order in signed short value with sign extension to integer
*
* @param int32_t value to reverse
* @return int32_t reversed value
*
* Reverse byte order in signed short value with sign extension to integer
*/
int32_t __REVSH(int16_t value)
{
uint32_t result=0;
__ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse bit order of value
*
* @param uint32_t value to reverse
* @return uint32_t reversed value
*
* Reverse bit order of value
*/
uint32_t __RBIT(uint32_t value)
{
uint32_t result=0;
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief LDR Exclusive
*
* @param uint8_t* address
* @return uint8_t value of (*address)
*
* Exclusive LDR command
*/
uint8_t __LDREXB(uint8_t *addr)
{
uint8_t result=0;
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief LDR Exclusive
*
* @param uint16_t* address
* @return uint16_t value of (*address)
*
* Exclusive LDR command
*/
uint16_t __LDREXH(uint16_t *addr)
{
uint16_t result=0;
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief LDR Exclusive
*
* @param uint32_t* address
* @return uint32_t value of (*address)
*
* Exclusive LDR command
*/
uint32_t __LDREXW(uint32_t *addr)
{
uint32_t result=0;
__ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief STR Exclusive
*
* @param uint8_t *address
* @param uint8_t value to store
* @return uint32_t successful / failed
*
* Exclusive STR command
*/
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
/**
* @brief STR Exclusive
*
* @param uint16_t *address
* @param uint16_t value to store
* @return uint32_t successful / failed
*
* Exclusive STR command
*/
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
/**
* @brief STR Exclusive
*
* @param uint32_t *address
* @param uint32_t value to store
* @return uint32_t successful / failed
*
* Exclusive STR command
*/
uint32_t __STREXW(uint32_t value, uint32_t *addr)
{
uint32_t result=0;
__ASM volatile ("strex %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
/**
* @brief Return the Control Register value
*
* @param none
* @return uint32_t Control value
*
* Return the content of the control register
*/
uint32_t __get_CONTROL(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, control" : "=r" (result) );
return(result);
}
/**
* @brief Set the Control Register value
*
* @param uint32_t Control value
* @return none
*
* Set the control register
*/
void __set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) );
}
#elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/
/* TASKING carm specific functions */
/*
* The CMSIS functions have been implemented as intrinsics in the compiler.
* Please use "carm -?i" to get an up to date list of all instrinsics,
* Including the CMSIS ones.
*/
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,128 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARMCM3/crt0.s
* @brief Generic ARM Cortex-M3 startup file for ChibiOS/RT.
* @addtogroup ARMCM3_CORE
* @{
*/
/** @cond never */
.set CONTROL_MODE_PRIVILEGED, 0
.set CONTROL_MODE_UNPRIVILEGED, 1
.set CONTROL_USE_MSP, 0
.set CONTROL_USE_PSP, 2
.text
.balign 2
.syntax unified
.thumb
/*
* Reset handler.
*/
.thumb_func
.global ResetHandler
.weak ResetHandler
ResetHandler:
/* Interrupts globally masked. */
cpsid i
/*
* Stack pointers initialization.
*/
ldr r0, =__ram_end__
ldr r1, =__main_stack_size__
sub r0, r0, r1
/* { r0 = main stack low address } */
msr PSP, r0
/* Early initialization. */
bl hwinit0
/*
* Data initialization.
* NOTE: It assumes that the DATA size is a multiple of 4.
*/
ldr r1, =_textdata
ldr r2, =_data
ldr r3, =_edata
dloop:
cmp r2, r3
ittt lo
ldrlo r0, [r1], #4
strlo r0, [r2], #4
blo dloop
/*
* BSS initialization.
* NOTE: It assumes that the BSS size is a multiple of 4.
*/
movs r0, #0
ldr r1, =_bss_start
ldr r2, =_bss_end
bloop:
cmp r1, r2
itt lo
strlo r0, [r1], #4
blo bloop
/* Switches to the Process Stack. */
movs r0, #CONTROL_MODE_PRIVILEGED | CONTROL_USE_PSP
msr CONTROL, r0
isb
/* Late initialization. */
bl hwinit1
movs r0, #0
mov r1, r0
bl main
b MainExitHandler
/*
* Default main exit code, just a loop.
* It is a weak symbol, the application code can redefine the behavior.
*/
.thumb_func
.global MainExitHandler
.weak MainExitHandler
MainExitHandler:
.loop: b .loop
/*
* Default early initialization code. It is declared weak in order to be
* replaced by the real initialization code.
* Early initialization is performed just after reset before BSS and DATA
* segments initialization.
*/
.thumb_func
.global hwinit0
.weak hwinit0
hwinit0:
bx lr
/*
* Default late initialization code. It is declared weak in order to be
* replaced by the real initialization code.
* Late initialization is performed after BSS and DATA segments initialization
* and before invoking the main() function.
*/
.thumb_func
.global hwinit1
.weak hwinit1
hwinit1:
bx lr
/** @endcond */
/** @} */

View File

@ -1,57 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARMCM3/nvic.c
* @brief Cortex-M3 NVIC support code.
* @addtogroup ARMCM3_NVIC
* @{
*/
#include <ch.h>
#include <nvic.h>
/**
* @brief Sets the priority of an interrupt handler and enables it.
*
* @param n the interrupt number
* @param prio the interrupt priority
* @note The parameters are not tested for correctness.
*/
void NVICEnableVector(uint32_t n, uint32_t prio) {
unsigned sh = (n & 3) << 3;
NVIC_IPR(n >> 2) = (NVIC_IPR(n >> 2) & ~(0xFF << sh)) | (prio << sh);
NVIC_ISER(n >> 5) = 1 << (n & 0x1F);
}
/**
* @brief Changes the priority of a system handler.
*
* @param handler the system handler number
* @param prio the system handler priority
* @note The parameters are not tested for correctness.
*/
void NVICSetSystemHandlerPriority(uint32_t handler, uint32_t prio) {
unsigned sh = (handler & 3) * 8;
SCB_SHPR(handler >> 2) = (SCB_SHPR(handler >> 2) & ~(0xFF << sh)) | (prio << sh);
}
/** @} */

View File

@ -1,190 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/ARMCM3/nvic.h
* @brief Cortex-M3 NVIC support macros and structures.
* @addtogroup ARMCM3_NVIC
* @{
*/
#ifndef _NVIC_H_
#define _NVIC_H_
/*
* System vector constants for @p NVICSetSystemHandlerPriority().
*/
#define HANDLER_MEM_MANAGE 0 /**< MEM MANAGE vector id.*/
#define HANDLER_BUS_FAULT 1 /**< BUS FAULT vector id.*/
#define HANDLER_USAGE_FAULT 2 /**< USAGE FAULT vector id.*/
#define HANDLER_RESERVED_3 3
#define HANDLER_RESERVED_4 4
#define HANDLER_RESERVED_5 5
#define HANDLER_RESERVED_6 6
#define HANDLER_SVCALL 7 /**< SVCALL vector id.*/
#define HANDLER_DEBUG_MONITOR 8 /**< DEBUG MONITOR vector id.*/
#define HANDLER_RESERVED_9 9
#define HANDLER_PENDSV 10 /**< PENDSV vector id.*/
#define HANDLER_SYSTICK 11 /**< SYS TCK vector id.*/
typedef volatile unsigned char IOREG8; /**< 8 bits I/O register type.*/
typedef volatile unsigned int IOREG32; /**< 32 bits I/O register type.*/
/**
* @brief NVIC ITCR register.
*/
#define NVIC_ITCR (*((IOREG32 *)0xE000E004))
/**
* @brief NVIC STIR register.
*/
#define NVIC_STIR (*((IOREG32 *)0xE000EF00))
/**
* @brief Structure representing the SYSTICK I/O space.
*/
typedef struct {
IOREG32 CSR;
IOREG32 RVR;
IOREG32 CVR;
IOREG32 CBVR;
} CM3_ST;
/**
* @brief SYSTICK peripheral base address.
*/
#define STBase ((CM3_ST *)0xE000E010)
#define ST_CSR (STBase->CSR)
#define ST_RVR (STBase->RVR)
#define ST_CVR (STBase->CVR)
#define ST_CBVR (STBase->CBVR)
#define CSR_ENABLE_MASK (0x1 << 0)
#define ENABLE_OFF_BITS (0 << 0)
#define ENABLE_ON_BITS (1 << 0)
#define CSR_TICKINT_MASK (0x1 << 1)
#define TICKINT_DISABLED_BITS (0 << 1)
#define TICKINT_ENABLED_BITS (1 << 1)
#define CSR_CLKSOURCE_MASK (0x1 << 2)
#define CLKSOURCE_EXT_BITS (0 << 2)
#define CLKSOURCE_CORE_BITS (1 << 2)
#define CSR_COUNTFLAG_MASK (0x1 << 16)
#define RVR_RELOAD_MASK (0xFFFFFF << 0)
#define CVR_CURRENT_MASK (0xFFFFFF << 0)
#define CBVR_TENMS_MASK (0xFFFFFF << 0)
#define CBVR_SKEW_MASK (0x1 << 30)
#define CBVR_NOREF_MASK (0x1 << 31)
/**
* @brief Structure representing the NVIC I/O space.
*/
typedef struct {
IOREG32 ISER[8];
IOREG32 unused1[24];
IOREG32 ICER[8];
IOREG32 unused2[24];
IOREG32 ISPR[8];
IOREG32 unused3[24];
IOREG32 ICPR[8];
IOREG32 unused4[24];
IOREG32 IABR[8];
IOREG32 unused5[56];
IOREG32 IPR[60];
} CM3_NVIC;
/**
* @brief NVIC peripheral base address.
*/
#define NVICBase ((CM3_NVIC *)0xE000E100)
#define NVIC_ISER(n) (NVICBase->ISER[n])
#define NVIC_ICER(n) (NVICBase->ICER[n])
#define NVIC_ISPR(n) (NVICBase->ISPR[n])
#define NVIC_ICPR(n) (NVICBase->ICPR[n])
#define NVIC_IABR(n) (NVICBase->IABR[n])
#define NVIC_IPR(n) (NVICBase->IPR[n])
/**
* @brief Structure representing the System Control Block I/O space.
*/
typedef struct {
IOREG32 CPUID;
IOREG32 ICSR;
IOREG32 VTOR;
IOREG32 AIRCR;
IOREG32 SCR;
IOREG32 CCR;
IOREG32 SHPR[3];
IOREG32 SHCSR;
IOREG32 CFSR;
IOREG32 HFSR;
IOREG32 DFSR;
IOREG32 MMFAR;
IOREG32 BFAR;
IOREG32 AFSR;
} CM3_SCB;
/**
* @brief SCB peripheral base address.
*/
#define SCBBase ((CM3_SCB *)0xE000ED00)
#define SCB_CPUID (SCBBase->CPUID)
#define SCB_ICSR (SCBBase->ICSR)
#define SCB_VTOR (SCBBase->VTOR)
#define SCB_AIRCR (SCBBase->AIRCR)
#define SCB_SCR (SCBBase->SCR)
#define SCB_CCR (SCBBase->CCR)
#define SCB_SHPR(n) (SCBBase->SHPR[n])
#define SCB_SHCSR (SCBBase->SHCSR)
#define SCB_CFSR (SCBBase->CFSR)
#define SCB_HFSR (SCBBase->HFSR)
#define SCB_DFSR (SCBBase->DFSR)
#define SCB_MMFAR (SCBBase->MMFAR)
#define SCB_BFAR (SCBBase->BFAR)
#define SCB_AFSR (SCBBase->AFSR)
#define ICSR_VECTACTIVE_MASK (0x1FF << 0)
#define ICSR_RETTOBASE (0x1 << 11)
#define ICSR_VECTPENDING_MASK (0x1FF << 12)
#define ICSR_ISRPENDING (0x1 << 22)
#define ICSR_ISRPREEMPT (0x1 << 23)
#define ICSR_PENDSTCLR (0x1 << 25)
#define ICSR_PENDSTSET (0x1 << 26)
#define ICSR_PENDSVCLR (0x1 << 27)
#define ICSR_PENDSVSET (0x1 << 28)
#define ICSR_NMIPENDSET (0x1 << 31)
#define AIRCR_VECTKEY 0x05FA0000
#define AIRCR_PRIGROUP_MASK (0x7 << 8)
#define AIRCR_PRIGROUP(n) ((n) << 8)
#ifdef __cplusplus
extern "C" {
#endif
void NVICEnableVector(uint32_t n, uint32_t prio);
void NVICSetSystemHandlerPriority(uint32_t handler, uint32_t prio);
#ifdef __cplusplus
}
#endif
#endif /* _NVIC_H_ */
/** @} */

View File

@ -1,170 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @defgroup ARMCM3 ARM Cortex-M3
* @details The ARM Cortex-M3 architecture is quite complex for a
* microcontroller and some explanations are required about the port choices.
*
* @section ARMCM3_STATES Mapping of the System States in the ARM Cortex-M3 port
* The ChibiOS/RT logical @ref system_states are mapped as follow in the ARM
* Cortex-M3 port:
* - <b>Init</b>. This state is represented by the startup code and the
* initialization code before @p chSysInit() is executed. It has not a
* special hardware state associated.
* - <b>Normal</b>. This is the state the system has after executing
* @p chSysInit(). In this state the ARM Cortex-M3 has the BASEPRI register
* set at @p BASEPRI_USER level, interrupts are not masked. The processor
* is running in thread-privileged mode.
* - <b>Suspended</b>. In this state the interrupt sources are not globally
* masked but the BASEPRI register is set to @p BASEPRI_KERNEL thus masking
* any interrupt source with lower or equal priority. The processor
* is running in thread-privileged mode.
* - <b>Disabled</b>. Interrupt sources are globally masked. The processor
* is running in thread-privileged mode.
* - <b>Sleep</b>. This state is entered with the execution of the specific
* instruction @p <b>wfi</b>.
* - <b>S-Locked</b>. In this state the interrupt sources are not globally
* masked but the BASEPRI register is set to @p BASEPRI_KERNEL thus masking
* any interrupt source with lower or equal priority. The processor
* is running in thread-privileged mode.
* - <b>I-Locked</b>. In this state the interrupt sources are not globally
* masked but the BASEPRI register is set to @p BASEPRI_KERNEL thus masking
* any interrupt source with lower or equal priority. The processor
* is running in exception-privileged mode.
* - <b>Serving Regular Interrupt</b>. In this state the interrupt sources are
* not globally masked but only interrupts with higher priority can preempt
* the current handler. The processor is running in exception-privileged mode.
* - <b>Serving Fast Interrupt</b>. It is basically the same of the SRI state
* but it is not possible to switch to the I-Locked state because fast
* interrupts can preempt the kernel critical zone.
* - <b>Serving Non-Maskable Interrupt</b>. The Cortex-M3 has a specific
* asynchronous NMI vector and several synchronous fault vectors that can
* be considered to be in this category.
* - <b>Halted</b>. Implemented as an infinite loop after globally masking all
* the maskable interrupt sources. The ARM state is whatever the processor
* was running when @p chSysHalt() was invoked.
* .
* @section ARMCM3_NOTES The ARM Cortex-M3 port notes
* The ARM Cortex-M3 port is organized as follow:
* - The @p main() function is invoked in thread-privileged mode.
* - Each thread has a private process stack, the system has a single main
* stack where all the interrupts and exceptions are processed.
* - Only the 4 MSb of the priority level are used, the 4 LSb are assumed
* to be zero.
* - The threads are started in thread-privileged mode with BASEPRI level
* 0x00 (disabled).
* - The kernel raises its BASEPRI level to @p BASEPRI_KERNEL in order to
* protect the kernel data structures.
* - Interrupt nesting and the other advanced NVIC features are supported.
* - The SVC instruction and vector, with parameter #0, is internally used
* for commanded context switching.<br>
* It is possible to share the SVC handler at the cost of slower context
* switching.
* - The PendSV vector is internally used for preemption context switching.
* .
* @ingroup Ports
*/
/**
* @defgroup ARMCM3_CONF Configuration Options
* @brief ARM Cortex-M3 Configuration Options.
* @details The ARMCM3 port allows some architecture-specific configurations
* settings that can be specified externally, as example on the compiler
* command line:
* - @p INT_REQUIRED_STACK, this value represent the amount of stack space used
* by an interrupt handler between the @p extctx and @p intctx
* structures.<br>
* In the current implementation this value is guaranteed to be zero so
* there is no need to modify this value unless changes are done at the
* interrupts handling code.
* - @p BASEPRI_USER, this is the @p BASEPRI value for the user threads. The
* default value is @p 0 (disabled).<br>
* Usually there is no need to change this value, please refer to the
* Cortex-M3 technical reference manual for a detailed description.
* - @p BASEPRI_KERNEL, this is the @p BASEPRI value for the kernel lock code.
* The default value is 0x40.<br>
* Code running at higher priority levels must not invoke any OS API.<br>
* Usually there is no need to change this value, please refer to the
* Cortex-M3 technical reference manual for a detailed description.
* - @p ENABLE_WFI_IDLE, if set to @p 1 enables the use of the @p <b>wfi</b>
* instruction from within the idle loop. This is defaulted to 0 because
* it can create problems with some debuggers. Setting this option to 1
* reduces the system power requirements.
* .
* @ingroup ARMCM3
*/
/**
* @defgroup ARMCM3_CORE Core Port Implementation
* @brief ARM Cortex-M3 specific port code, structures and macros.
*
* @ingroup ARMCM3
*/
/**
* @defgroup ARMCM3_STARTUP Startup Support
* @brief ARM Cortex-M3 startup code support.
* @details ChibiOS/RT provides its own generic startup file for the ARM
* Cortex-M3 port.
* Of course it is not mandatory to use it but care should be taken about the
* startup phase details.
*
* <h2>Startup Process</h2>
* The startup process, as implemented, is the following:
* -# Interrupts are masked globally.
* -# The two stacks are initialized by assigning them the sizes defined in the
* linker script (usually named @p ch.ld). Stack areas are allocated from
* the highest RAM location downward.
* -# An early initialization routine @p hwinit0 is invoked, if the symbol is
* not defined then an empty default routine is executed (weak symbol).
* -# DATA and BSS segments are initialized.
* -# The CPU state is switched to Privileged and the PSP stack is used.
* -# A late initialization routine @p hwinit1 is invoked, if the symbol not
* defined then an empty default routine is executed (weak symbol).<br>
* This late initialization function is also the proper place for a
* @a bootloader, if your application requires one.
* -# The @p main() function is invoked with the parameters @p argc and @p argv
* set to zero.
* -# Should the @p main() function return a branch is performed to the weak
* symbol MainExitHandler. The default code is an endless empty loop.
* .
* <h2>Expected linker symbols</h2>
* The startup code starts at the symbol @p ResetHandler and expects the
* following symbols to be defined in the linker script:
* - @p __ram_end__ RAM end location +1.
* - @p __main_stack_size__ Exception stack size.
* - @p __process_stack_size__ Process stack size. This is the stack area used
* by the @p main() function.
* - @p _textdata address of the data segment source read only data.
* - @p _data data segment start location.
* - @p _edata data segment end location +1.
* - @p _bss_start BSS start location.
* - @p _bss_end BSS end location +1.
* .
* @ingroup ARMCM3
* @file ports/ARMCM3/crt0.s Startup code.
*/
/**
* @defgroup ARMCM3_NVIC NVIC Support
* @brief ARM Cortex-M3 NVIC support.
*
* @ingroup ARMCM3
*/

View File

@ -1,185 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/AVR/avr_serial.c
* @brief AVR Serial driver code.
* @addtogroup AVR_SERIAL
* @{
*/
#include <ch.h>
#include "avr_serial.h"
static void SetError(uint8_t sra, FullDuplexDriver *com) {
dflags_t sts = 0;
if (sra & (1 << DOR))
sts |= SD_OVERRUN_ERROR;
if (sra & (1 << UPE))
sts |= SD_PARITY_ERROR;
if (sra & (1 << FE))
sts |= SD_FRAMING_ERROR;
chSysLockFromIsr();
chFDDAddFlagsI(com, sts);
chSysUnlockFromIsr();
}
#if USE_AVR_USART0 || defined(__DOXYGEN__)
/** @brief USART0 serial driver identifier.*/
FullDuplexDriver SER1;
static uint8_t ib1[SERIAL_BUFFERS_SIZE];
static uint8_t ob1[SERIAL_BUFFERS_SIZE];
CH_IRQ_HANDLER(USART0_RX_vect) {
uint8_t sra;
CH_IRQ_PROLOGUE();
sra = UCSR0A;
if (sra & ((1 << DOR) | (1 << UPE) | (1 << FE)))
SetError(sra, &SER1);
chSysLockFromIsr();
chFDDIncomingDataI(&SER1, UDR0);
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE();
}
CH_IRQ_HANDLER(USART0_UDRE_vect) {
msg_t b;
CH_IRQ_PROLOGUE();
chSysLockFromIsr();
b = chFDDRequestDataI(&SER1);
chSysUnlockFromIsr();
if (b < Q_OK)
UCSR0B &= ~(1 << UDRIE);
else
UDR0 = b;
CH_IRQ_EPILOGUE();
}
static void OutNotify1(void) {
UCSR0B |= (1 << UDRIE);
}
/**
* @brief USART0 setup.
* @details This function must be invoked with interrupts disabled.
* @param[in] brr the divider value as calculated by the @p UBRR() macro
* @param[in] csrc the value for the @p UCSR0C register
* @note Must be invoked with interrupts disabled.
* @note Does not reset the I/O queues.
*/
void usart0_setup(uint16_t brr, uint8_t csrc) {
UBRR0L = brr;
UBRR0H = brr >> 8;
UCSR0A = 0;
UCSR0B = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
UCSR0C = csrc;
}
#endif /* USE_AVR_USART0 */
#if USE_AVR_USART1 || defined(__DOXYGEN__)
/** @brief USART1 serial driver identifier.*/
FullDuplexDriver SER2;
static uint8_t ib2[SERIAL_BUFFERS_SIZE];
static uint8_t ob2[SERIAL_BUFFERS_SIZE];
CH_IRQ_HANDLER(USART1_RX_vect) {
uint8_t sra;
CH_IRQ_PROLOGUE();
sra = UCSR1A;
if (sra & ((1 << DOR) | (1 << UPE) | (1 << FE)))
SetError(sra, &SER2);
chSysLockFromIsr();
chFDDIncomingDataI(&SER2, UDR1);
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE();
}
CH_IRQ_HANDLER(USART1_UDRE_vect) {
msg_t b;
CH_IRQ_PROLOGUE();
chSysLockFromIsr();
b = chFDDRequestDataI(&SER2);
chSysUnlockFromIsr();
if (b < Q_OK)
UCSR1B &= ~(1 << UDRIE);
else
UDR1 = b;
CH_IRQ_EPILOGUE();
}
static void OutNotify2(void) {
UCSR1B |= (1 << UDRIE);
}
/**
* @brief USART1 setup.
* @details This function must be invoked with interrupts disabled.
* @param[in] brr the divider value as calculated by the @p UBRR() macro
* @param[in] csrc the value for the @p UCSR1C register
* @note Must be invoked with interrupts disabled.
* @note Does not reset the I/O queues.
*/
void usart1_setup(uint16_t brr, uint8_t csrc) {
UBRR1L = brr;
UBRR1H = brr >> 8;
UCSR1A = 0;
UCSR1B = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
UCSR1C = csrc;
}
#endif /* USE_AVR_USART1 */
/**
* @brief Serial driver initialization.
* @note The serial ports are initialized at @p 38400-8-N-1 by default.
*/
void serial_init(void) {
#if USE_AVR_USART0
/* I/O queues setup.*/
chFDDInit(&SER1, ib1, sizeof ib1, NULL, ob1, sizeof ob1, OutNotify1);
usart0_setup(UBRR(DEFAULT_USART_BITRATE), (1 << UCSZ1) | (1 << UCSZ0));
#endif
#if USE_AVR_USART1
chFDDInit(&SER2, ib2, sizeof ib2, NULL, ob2, sizeof ob2, OutNotify2);
usart1_setup(UBRR(DEFAULT_USART_BITRATE), (1 << UCSZ1) | (1 << UCSZ0));
#endif
}
/** @} */

View File

@ -1,92 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/AVR/avr_serial.h
* @brief AVR Serial driver macros and structures.
* @addtogroup AVR_SERIAL
* @{
*/
#ifndef _AVR_SERIAL_H_
#define _AVR_SERIAL_H_
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
* @note The default is 32 bytes for both the transmission and receive buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 32
#endif
/**
* @brief Default bit rate.
* @details Configuration parameter, at startup the UARTs are configured at
* this speed.
* @note It is possible to use @p SetUART() in order to change the working
* parameters at runtime.
*/
#if !defined(DEFAULT_USART_BITRATE) || defined(__DOXYGEN__)
#define DEFAULT_USART_BITRATE 38400
#endif
/**
* @brief USART0 driver enable switch.
* @details If set to @p TRUE the support for USART0 is included.
* @note The default is @p FALSE.
*/
#if !defined(USE_AVR_USART0) || defined(__DOXYGEN__)
#define USE_AVR_USART0 FALSE
#endif
/**
* @brief USART1 driver enable switch.
* @details If set to @p TRUE the support for USART1 is included.
* @note The default is @p TRUE.
*/
#if !defined(USE_AVR_USART1) || defined(__DOXYGEN__)
#define USE_AVR_USART1 TRUE
#endif
/**
* @brief Macro for baud rate computation.
* @note Make sure the final baud rate is within tolerance.
*/
#define UBRR(b) ((F_CPU / (b << 4)) - 1)
#ifdef __cplusplus
extern "C" {
#endif
void serial_init(void);
void usart0_setup(uint16_t brr, uint8_t csrc);
void usart1_setup(uint16_t brr, uint8_t csrc);
#ifdef __cplusplus
}
#endif
/** @cond never*/
extern FullDuplexDriver SER1, SER2;
/** @endcond*/
#endif /* _AVR_SERIAL_H_ */
/** @} */

View File

@ -1,125 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/AVR/chcore.c
* @brief AVR architecture port code.
* @addtogroup AVR_CORE
* @{
*/
#include <ch.h>
/**
* Performs a context switch between two threads.
* @param otp the thread to be switched out
* @param ntp the thread to be switched in
* @note The function is declared as a weak symbol, it is possible to redefine
* it in your application code.
*/
/** @cond never */
__attribute__((naked, weak))
/** @endcond */
void port_switch(Thread *otp, Thread *ntp) {
asm volatile ("push r2");
asm volatile ("push r3");
asm volatile ("push r4");
asm volatile ("push r5");
asm volatile ("push r6");
asm volatile ("push r7");
#ifndef CH_CURRP_REGISTER_CACHE
asm volatile ("push r8");
asm volatile ("push r9");
#endif
asm volatile ("push r10");
asm volatile ("push r11");
asm volatile ("push r12");
asm volatile ("push r13");
asm volatile ("push r14");
asm volatile ("push r15");
asm volatile ("push r16");
asm volatile ("push r17");
asm volatile ("push r28");
asm volatile ("push r29");
asm volatile ("movw r30, r24");
asm volatile ("in r0, 0x3d");
asm volatile ("std Z+7, r0");
asm volatile ("in r0, 0x3e");
asm volatile ("std Z+8, r0");
asm volatile ("movw r30, r22");
asm volatile ("ldd r0, Z+7");
asm volatile ("out 0x3d, r0");
asm volatile ("ldd r0, Z+8");
asm volatile ("out 0x3e, r0");
asm volatile ("pop r29");
asm volatile ("pop r28");
asm volatile ("pop r17");
asm volatile ("pop r16");
asm volatile ("pop r15");
asm volatile ("pop r14");
asm volatile ("pop r13");
asm volatile ("pop r12");
asm volatile ("pop r11");
asm volatile ("pop r10");
#ifndef CH_CURRP_REGISTER_CACHE
asm volatile ("pop r9");
asm volatile ("pop r8");
#endif
asm volatile ("pop r7");
asm volatile ("pop r6");
asm volatile ("pop r5");
asm volatile ("pop r4");
asm volatile ("pop r3");
asm volatile ("pop r2");
asm volatile ("ret");
}
/**
* Disables the interrupts and halts the system.
* @note The function is declared as a weak symbol, it is possible to redefine
* it in your application code.
*/
/** @cond never */
__attribute__((weak))
/** @endcond */
void port_halt(void) {
port_disable();
while (TRUE) {
}
}
/**
* Start a thread by invoking its work function.
* If the work function returns @p chThdExit() is automatically invoked.
*/
void threadstart(void) {
asm volatile ("sei");
asm volatile ("movw r24, r4");
asm volatile ("movw r30, r2");
asm volatile ("icall");
asm volatile ("call chThdExit");
}
/** @} */

View File

@ -1,267 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/AVR/chcore.h
* @brief AVR architecture port macros and structures.
* @addtogroup AVR_CORE
* @{
*/
#ifndef _CHCORE_H_
#define _CHCORE_H_
#include <avr/io.h>
#include <avr/interrupt.h>
/**
* If enabled allows the idle thread to enter a low power mode.
*/
#ifndef ENABLE_WFI_IDLE
#define ENABLE_WFI_IDLE 0
#endif
/**
* Macro defining the AVR architecture.
*/
#define CH_ARCHITECTURE_AVR
/**
* Name of the implemented architecture.
*/
#define CH_ARCHITECTURE_NAME "AVR"
/**
* 8 bit stack alignment.
*/
typedef uint8_t stkalign_t;
/** @cond never */
/**
* Interrupt saved context.
* @note The field @p _next is not part of the context, it represents the
* offset of the structure relative to the stack pointer.
*/
struct extctx {
uint8_t _next;
uint8_t r31;
uint8_t r30;
uint8_t r27;
uint8_t r26;
uint8_t r25;
uint8_t r24;
uint8_t r23;
uint8_t r22;
uint8_t r21;
uint8_t r20;
uint8_t r19;
uint8_t r18;
uint8_t sr;
uint8_t r1;
uint8_t r0;
uint16_t pc;
};
/** @endcond */
/** @cond never */
/**
* System saved context.
* @note The field @p _next is not part of the context, it represents the
* offset of the structure relative to the stack pointer.
*/
struct intctx {
uint8_t _next;
uint8_t r29;
uint8_t r28;
uint8_t r17;
uint8_t r16;
uint8_t r15;
uint8_t r14;
uint8_t r13;
uint8_t r12;
uint8_t r11;
uint8_t r10;
#ifndef CH_CURRP_REGISTER_CACHE
uint8_t r9;
uint8_t r8;
#endif
uint8_t r7;
uint8_t r6;
uint8_t r5;
uint8_t r4;
uint8_t r3;
uint8_t r2;
uint8_t pcl;
uint8_t pch;
};
/** @endcond */
/** @cond never */
/**
* In the AVR port this structure just holds a pointer to the @p intctx
* structure representing the stack pointer at the time of the context switch.
*/
struct context {
struct intctx *sp;
};
/** @endcond */
/**
* Platform dependent part of the @p chThdInit() API.
* This code usually setup the context switching frame represented by a
* @p intctx structure.
*/
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
tp->p_ctx.sp = (struct intctx*)((uint8_t *)workspace + wsize - \
sizeof(struct intctx)); \
tp->p_ctx.sp->r2 = (int)pf; \
tp->p_ctx.sp->r3 = (int)pf >> 8; \
tp->p_ctx.sp->r4 = (int)arg; \
tp->p_ctx.sp->r5 = (int)arg >> 8; \
tp->p_ctx.sp->pcl = (int)threadstart >> 8; \
tp->p_ctx.sp->pch = (int)threadstart; \
}
/**
* The default idle thread implementation requires no extra stack space in
* this port.
*/
#ifndef IDLE_THREAD_STACK_SIZE
#define IDLE_THREAD_STACK_SIZE 8
#endif
/**
* Per-thread stack overhead for interrupts servicing, it is used in the
* calculation of the correct working area size. In this port the default is
* 32 bytes per thread.
*/
#ifndef INT_REQUIRED_STACK
#define INT_REQUIRED_STACK 32
#endif
/**
* Enforces a correct alignment for a stack area size value.
*/
#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1)
/**
* Computes the thread working area global size.
*/
#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
(sizeof(struct intctx) - 1) + \
(sizeof(struct extctx) - 1) + \
(n) + (INT_REQUIRED_STACK))
/**
* Macro used to allocate a thread working area aligned as both position and
* size.
*/
#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)];
/**
* IRQ prologue code, inserted at the start of all IRQ handlers enabled to
* invoke system APIs.
* This code tricks the compiler to save all the specified registers by
* "touching" them.
*/
#define PORT_IRQ_PROLOGUE() { \
asm ("" : : : "r18", "r19", "r20", "r21", "r22", "r23", "r24", \
"r25", "r26", "r27", "r30", "r31"); \
}
/**
* IRQ epilogue code, inserted at the end of all IRQ handlers enabled to
* invoke system APIs.
*/
#define PORT_IRQ_EPILOGUE() { \
if (chSchRescRequiredI()) \
chSchDoRescheduleI(); \
}
/**
* IRQ handler function declaration. Note, it just aliases the WinAVR "ISR"
* macro.
*/
#define PORT_IRQ_HANDLER(id) ISR(id)
/**
* This function is empty in this port.
*/
#define port_init()
/**
* Implemented as global interrupt disable.
*/
#define port_lock() asm volatile ("cli")
/**
* Implemented as global interrupt enable.
*/
#define port_unlock() asm volatile ("sei")
/**
* This function is empty in this port.
*/
#define port_lock_from_isr()
/**
* This function is empty in this port.
*/
#define port_unlock_from_isr()
/**
* Implemented as global interrupt disable.
*/
#define port_disable() asm volatile ("cli")
/**
* Same as @p port_disable() in this port, there is no difference between the
* two states.
*/
#define port_suspend() asm volatile ("cli")
/**
* Implemented as global interrupt enable.
*/
#define port_enable() asm volatile ("sei")
/**
* This port function is implemented as inlined code for performance reasons.
*/
#if ENABLE_WFI_IDLE != 0
#define port_wait_for_interrupt() { \
asm volatile ("sleep"); \
}
#else
#define port_wait_for_interrupt()
#endif
#ifdef __cplusplus
extern "C" {
#endif
void port_switch(Thread *otp, Thread *ntp);
void port_halt(void);
void threadstart(void);
#ifdef __cplusplus
}
#endif
#endif /* _CHCORE_H_ */
/** @} */

View File

@ -1,56 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/AVR/chtypes.h
* @brief AVR architecture port system types.
* @addtogroup AVR_CORE
* @{
*/
#ifndef _CHTYPES_H_
#define _CHTYPES_H_
#define __need_NULL
#define __need_size_t
#define __need_ptrdiff_t
#include <stddef.h>
#if !defined(_STDINT_H) && !defined(__STDINT_H_)
#include <stdint.h>
#endif
typedef int8_t bool_t; /**< Fast boolean type. */
typedef uint8_t tmode_t; /**< Thread flags. */
typedef uint8_t tstate_t; /**< Thread state. */
typedef uint8_t tprio_t; /**< Thread priority. */
typedef int16_t msg_t; /**< Inter-thread message. */
typedef uint8_t eventid_t; /**< Event Id. */
typedef uint8_t eventmask_t; /**< Events mask. */
typedef uint16_t systime_t; /**< System time. */
typedef int8_t cnt_t; /**< Resources counter. */
#define INLINE inline
#define PACK_STRUCT_STRUCT __attribute__((packed))
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_END
#endif /* _CHTYPES_H_ */
/** @} */

View File

@ -1,95 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @defgroup AVR MegaAVR
* @details AVR port details. This section how the ChibiOS/RT features are
* implemented on this architecture.
*
* @section AVR_STATES Mapping of the System States in the AVR port
* The ChibiOS/RT logical @ref system_states are mapped as follow in the AVR
* port:
* - <b>Init</b>. This state is represented by the startup code and the
* initialization code before @p chSysInit() is executed. It has not a
* special hardware state associated.
* - <b>Normal</b>. This is the state the system has after executing
* @p chSysInit(). Interrupts are enabled.
* - <b>Suspended</b>. Interrupts are disabled.
* - <b>Disabled</b>. Interrupts are enabled. This state is equivalent to the
* Suspended state because there are no fast interrupts in this architecture.
* - <b>Sleep</b>. This state is entered with the execution of the specific
* instruction @p <b>sleep</b>.
* - <b>S-Locked</b>. Interrupts are disabled.
* - <b>I-Locked</b>. This state is equivalent to the SRI state, the
* @p chSysLockI() and @p chSysUnlockI() APIs do nothing (still use them in
* order to formally change state because this may change).
* - <b>Serving Regular Interrupt</b>. Normal interrupt service code.
* - <b>Serving Fast Interrupt</b>. Not present in this architecture.
* - <b>Serving Non-Maskable Interrupt</b>. Not present in this architecture.
* - <b>Halted</b>. Implemented as an infinite loop with interrupts disabled.
* .
* @section AVR_NOTES The AVR port notes
* - The AVR does not have a dedicated interrupt stack, make sure to reserve
* enough stack space for interrupts in each thread stack. This can be done
* by modifying the @p INT_REQUIRED_STACK macro into
* <b>./ports/AVR/chcore.h</b>.
* .
* @ingroup Ports
*/
/**
* @defgroup AVR_CONF Configuration Options
* @brief AVR Configuration Options.
* @details The AVR port allows some architecture-specific configurations
* settingsthat can be specified externally, as example on the compiler
* command line:
* - @p INT_REQUIRED_STACK, this value represent the amount of stack space
* used by the interrupt handlers.<br>
* The default for this value is @p 32, this space is allocated for each
* thread so be careful in order to not waste precious RAM space.<br>
* The default value is set into <b>./ports/AVR/chcore.h</b>.
* .
* @ingroup AVR
*/
/**
* @defgroup AVR_CORE AVR Core Implementation
* @brief AVR specific port code, structures and macros.
*
* @ingroup AVR
* @file ports/AVR/chtypes.h Port types.
* @file ports/AVR/chcore.h Port related structures and macros.
* @file ports/AVR/chcore.c Port related code.
*/
/**
* @defgroup AVR_DRIVERS AVR Drivers
* @brief Device drivers included in the AVR support.
*
* @ingroup AVR
*/
/**
* @defgroup AVR_SERIAL USART Support
* @brief USART support.
* @details The serial driver supports both the AVR USARTs in asynchronous
* mode.
*
* @ingroup AVR_DRIVERS
*/

View File

@ -1,90 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/MSP430/chcore.c
* @brief MSP430 architecture port code.
* @addtogroup MSP430_CORE
* @{
*/
#include <ch.h>
/**
* Performs a context switch between two threads.
* @param otp the thread to be switched out
* @param ntp the thread to be switched in
* @note The function is declared as a weak symbol, it is possible to redefine
* it in your application code.
*/
/** @cond never */
__attribute__((naked, weak))
/** @endcond */
void port_switch(Thread *otp, Thread *ntp) {
register struct intctx *sp asm("r1");
asm volatile ("push r11 \n\t" \
"push r10 \n\t" \
"push r9 \n\t" \
"push r8 \n\t" \
"push r7 \n\t" \
"push r6 \n\t" \
"push r6 \n\t" \
"push r4");
otp->p_ctx.sp = sp;
sp = ntp->p_ctx.sp;
asm volatile ("pop r4 \n\t" \
"pop r5 \n\t" \
"pop r6 \n\t" \
"pop r7 \n\t" \
"pop r8 \n\t" \
"pop r9 \n\t" \
"pop r10 \n\t" \
"pop r11 \n\t" \
"ret" : : "r" (sp));
}
/**
* Disables the interrupts and halts the system.
* @note The function is declared as a weak symbol, it is possible to redefine
* it in your application code.
*/
/** @cond never */
__attribute__((weak))
/** @endcond */
void port_halt(void) {
port_disable();
while (TRUE) {
}
}
/**
* Start a thread by invoking its work function.
* If the work function returns @p chThdExit() is automatically invoked.
*/
void threadstart(void) {
asm volatile ("eint \n\t" \
"mov r11, r15 \n\t" \
"call r10 \n\t" \
"call #chThdExit");
}
/** @} */

View File

@ -1,238 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/MSP430/chcore.h
* @brief MSP430 architecture port macros and structures.
* @addtogroup MSP430_CORE
* @{
*/
#ifndef _CHCORE_H_
#define _CHCORE_H_
#include <iomacros.h>
#include <msp430/common.h>
/**
* If enabled allows the idle thread to enter a low power mode.
*/
#ifndef ENABLE_WFI_IDLE
#define ENABLE_WFI_IDLE 0
#endif
/**
* Macro defining the MSP430 architecture.
*/
#define CH_ARCHITECTURE_MSP430
/**
* Name of the implemented architecture.
*/
#define CH_ARCHITECTURE_NAME "MSP430"
/**
* 16 bit stack alignment.
*/
typedef uint16_t stkalign_t;
/**
* Generic MSP430 register.
*/
typedef void *regmsp_t;
/** @cond never */
/**
* Interrupt saved context.
*/
struct extctx {
regmsp_t r12;
regmsp_t r13;
regmsp_t r14;
regmsp_t r15;
regmsp_t sr;
regmsp_t pc;
};
/** @endcond */
/** @cond never */
/**
* This structure represents the inner stack frame during a context switching.
*/
struct intctx {
regmsp_t r4;
regmsp_t r5;
regmsp_t r6;
regmsp_t r7;
regmsp_t r8;
regmsp_t r9;
regmsp_t r10;
regmsp_t r11;
regmsp_t pc;
};
/** @endcond */
/** @cond never */
/**
* In the MSP430 port this structure just holds a pointer to the @p intctx
* structure representing the stack pointer at the time of the context switch.
*/
struct context {
struct intctx *sp;
};
/** @endcond */
/**
* Platform dependent part of the @p chThdInit() API.
*/
#define SETUP_CONTEXT(workspace, wsize, pf, arg) { \
tp->p_ctx.sp = (struct intctx *)((uint8_t *)workspace + \
wsize - \
sizeof(struct intctx)); \
tp->p_ctx.sp->r10 = pf; \
tp->p_ctx.sp->r11 = arg; \
tp->p_ctx.sp->pc = threadstart; \
}
/**
* The default idle thread implementation requires no extra stack space in
* this port.
*/
#ifndef IDLE_THREAD_STACK_SIZE
#define IDLE_THREAD_STACK_SIZE 0
#endif
/**
* Per-thread stack overhead for interrupts servicing, it is used in the
* calculation of the correct working area size. In this port the default is
* 32 bytes per thread.
*/
#ifndef INT_REQUIRED_STACK
#define INT_REQUIRED_STACK 32
#endif
/**
* Enforces a correct alignment for a stack area size value.
*/
#define STACK_ALIGN(n) ((((n) - 1) | (sizeof(stkalign_t) - 1)) + 1)
/**
* Computes the thread working area global size.
*/
#define THD_WA_SIZE(n) STACK_ALIGN(sizeof(Thread) + \
sizeof(struct intctx) + \
sizeof(struct extctx) + \
(n) + (INT_REQUIRED_STACK))
/**
* Macro used to allocate a thread working area aligned as both position and
* size.
*/
#define WORKING_AREA(s, n) stkalign_t s[THD_WA_SIZE(n) / sizeof(stkalign_t)];
/**
* IRQ prologue code, inserted at the start of all IRQ handlers enabled to
* invoke system APIs.
*/
#define PORT_IRQ_PROLOGUE()
/**
* IRQ epilogue code, inserted at the end of all IRQ handlers enabled to
* invoke system APIs.
*/
#define PORT_IRQ_EPILOGUE() { \
if (chSchRescRequiredI()) \
chSchDoRescheduleI(); \
}
/**
* IRQ handler function modifier.
*/
#define PORT_IRQ_HANDLER(id) interrupt(id) _vect_##id(void)
/**
* This function is empty in this port.
*/
#define port_init()
/**
* Implemented as global interrupt disable.
*/
#define port_lock() asm volatile ("dint")
/**
* Implemented as global interrupt enable.
*/
#define port_unlock() asm volatile ("eint")
/**
* This function is empty in this port.
*/
#define port_lock_from_isr()
/**
* This function is empty in this port.
*/
#define port_unlock_from_isr()
/**
* Implemented as global interrupt disable.
*/
#define port_disable() asm volatile ("dint")
/**
* Same as @p port_disable() in this port, there is no difference between the
* two states.
*/
#define port_suspend() asm volatile ("dint")
/**
* Implemented as global interrupt enable.
*/
#define port_enable() asm volatile ("eint")
/**
* This port function is implemented as inlined code for performance reasons.
* @note The port code does not define a low power mode, this macro has to be
* defined externally. The default implementation is a "nop", not a
* real low power mode.
*/
#if ENABLE_WFI_IDLE != 0
#ifndef port_wait_for_interrupt
#define port_wait_for_interrupt() { \
asm volatile ("nop"); \
}
#endif
#else
#define port_wait_for_interrupt()
#endif
#ifdef __cplusplus
extern "C" {
#endif
void port_switch(Thread *otp, Thread *ntp);
void port_halt(void);
void threadstart(void);
#ifdef __cplusplus
}
#endif
#endif /* _CHCORE_H_ */
/** @} */

View File

@ -1,56 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/MSP430/chtypes.h
* @brief MSP430 architecture port system types.
* @addtogroup MSP430_CORE
* @{
*/
#ifndef _CHTYPES_H_
#define _CHTYPES_H_
#define __need_NULL
#define __need_size_t
#define __need_ptrdiff_t
#include <stddef.h>
#if !defined(_STDINT_H) && !defined(__STDINT_H_)
#include <stdint.h>
#endif
typedef int16_t bool_t; /**< Fast boolean type. */
typedef uint8_t tmode_t; /**< Thread flags. */
typedef uint8_t tstate_t; /**< Thread state. */
typedef uint16_t tprio_t; /**< Thread priority. */
typedef int16_t msg_t; /**< Inter-thread message. */
typedef int16_t eventid_t; /**< Event Id. */
typedef uint16_t eventmask_t; /**< Events mask. */
typedef uint16_t systime_t; /**< System time. */
typedef int16_t cnt_t; /**< Resources counter. */
#define INLINE inline
#define PACK_STRUCT_STRUCT __attribute__((packed))
#define PACK_STRUCT_BEGIN
#define PACK_STRUCT_END
#endif /* _CHTYPES_H_ */
/** @} */

View File

@ -1,216 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/MSP430/msp430_serial.c
* @brief MSP430 Serial driver code.
* @addtogroup MSP430_SERIAL
* @{
*/
#include <ch.h>
#include <signal.h>
#include "board.h"
#include "msp430_serial.h"
static void SetError(uint8_t urctl, FullDuplexDriver *com) {
dflags_t sts = 0;
if (urctl & OE)
sts |= SD_OVERRUN_ERROR;
if (urctl & PE)
sts |= SD_PARITY_ERROR;
if (urctl & FE)
sts |= SD_FRAMING_ERROR;
if (urctl & BRK)
sts |= SD_BREAK_DETECTED;
chSysLockFromIsr();
chFDDAddFlagsI(com, sts);
chSysUnlockFromIsr();
}
#if USE_MSP430_USART0 || defined(__DOXYGEN__)
/** @brief USART0 serial driver identifier.*/
FullDuplexDriver COM1;
static uint8_t ib1[SERIAL_BUFFERS_SIZE];
static uint8_t ob1[SERIAL_BUFFERS_SIZE];
CH_IRQ_HANDLER(USART0TX_VECTOR) {
msg_t b;
CH_IRQ_PROLOGUE();
chSysLockFromIsr();
b = chFDDRequestDataI(&COM1);
chSysUnlockFromIsr();
if (b < Q_OK)
U0IE &= ~UTXIE0;
else
U0TXBUF = b;
CH_IRQ_EPILOGUE();
}
CH_IRQ_HANDLER(USART0RX_VECTOR) {
uint8_t urctl;
CH_IRQ_PROLOGUE();
if ((urctl = U0RCTL) & RXERR)
SetError(urctl, &COM1);
chSysLockFromIsr();
chFDDIncomingDataI(&COM1, U0RXBUF);
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE();
}
static void OutNotify1(void) {
if (!(U0IE & UTXIE0)) {
chSysLockFromIsr();
U0TXBUF = (uint8_t)chFDDRequestDataI(&COM1);
chSysUnlockFromIsr();
U0IE |= UTXIE0;
}
}
/**
* @brief USART0 setup.
* @details This function must be invoked with interrupts disabled.
* @param div The divider value as calculated by the @p UBR() macro.
* @param mod The value for the @p U0MCTL register.
* @param ctl The value for the @p U0CTL register.
* @note Does not reset the I/O queues.
*/
void usart0_setup(uint16_t div, uint8_t mod, uint8_t ctl) {
U0CTL = SWRST; /* Resets the USART, it should already be */
/* USART init */
U0TCTL = SSEL0 | SSEL1; /* SMCLK as clock source */
U0MCTL = mod; /* Modulator */
U0BR1 = (uint8_t)(div >> 8); /* Divider high */
U0BR0 = (uint8_t)(div >> 0); /* Divider low */
/* Clear USART status */
(void)U0RXBUF;
U0RCTL = 0;
/* USART enable */
P3SEL |= BV(4) + BV(5); /* I/O pins for USART 0 */
U0ME |= UTXE0 + URXE0; /* Enables the USART */
U0CTL = ctl & ~SWRST; /* Various settings, clears reset state */
U0IE |= URXIE0; /* Enables RX interrupt */
}
#endif /* USE_MSP430_USART0 */
#if USE_MSP430_USART1 || defined(__DOXYGEN__)
/** @brief USART1 serial driver identifier.*/
FullDuplexDriver COM2;
static uint8_t ib2[SERIAL_BUFFERS_SIZE];
static uint8_t ob2[SERIAL_BUFFERS_SIZE];
CH_IRQ_HANDLER(USART1TX_VECTOR) {
msg_t b;
CH_IRQ_PROLOGUE();
chSysLockFromIsr();
b = chFDDRequestDataI(&COM2);
chSysUnlockFromIsr();
if (b < Q_OK)
U1IE &= ~UTXIE1;
else
U1TXBUF = b;
CH_IRQ_EPILOGUE();
}
CH_IRQ_HANDLER(USART1RX_VECTOR) {
uint8_t urctl;
CH_IRQ_PROLOGUE();
if ((urctl = U1RCTL) & RXERR)
SetError(urctl, &COM2);
chSysLockFromIsr();
chFDDIncomingDataI(&COM2, U1RXBUF);
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE();
}
static void OutNotify2(void) {
if (!(U1IE & UTXIE1)) {
U1TXBUF = (uint8_t)chFDDRequestDataI(&COM2);
U1IE |= UTXIE1;
}
}
/**
* @brief USART1 setup.
* @details This function must be invoked with interrupts disabled.
* @param[in] div the divider value as calculated by the @p UBR() macro
* @param[in] mod the value for the @p U1MCTL register
* @param[in] ctl the value for the @p U1CTL register.
* @note Must be invoked with interrupts disabled.
* @note Does not reset the I/O queues.
*/
void usart1_setup(uint16_t div, uint8_t mod, uint8_t ctl) {
U1CTL = SWRST; /* Resets the USART, it should already be */
/* USART init */
U1TCTL = SSEL0 | SSEL1; /* SMCLK as clock source */
U1MCTL = mod; /* Modulator */
U1BR1 = (uint8_t)(div >> 8); /* Divider high */
U1BR0 = (uint8_t)(div >> 0); /* Divider low */
/* Clear USART status */
(void)U0RXBUF;
U1RCTL = 0;
/* USART enable */
P3SEL |= BV(6) + BV(7); /* I/O pins for USART 1 */
U1ME |= UTXE0 + URXE0; /* Enables the USART */
U1CTL = ctl & ~SWRST; /* Various settings, clears reset state */
U1IE |= URXIE0; /* Enables RX interrupt */
}
#endif
/**
* @brief Serial driver initialization.
* @note The serial ports are initialized at @p 38400-8-N-1 by default.
*/
void serial_init(void) {
/* I/O queues setup.*/
#if USE_MSP430_USART0
chFDDInit(&COM1, ib1, sizeof ib1, NULL, ob1, sizeof ob1, OutNotify1);
usart0_setup(UBR(DEFAULT_USART_BITRATE), 0, CHAR);
#endif
#if USE_MSP430_USART1
chFDDInit(&COM2, ib2, sizeof ib2, NULL, ob2, sizeof ob2, OutNotify2);
usart1_setup(UBR(DEFAULT_USART_BITRATE), 0, CHAR);
#endif
}
/** @} */

View File

@ -1,91 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/MSP430/msp430_serial.h
* @brief MSP430 Serial driver macros and structures.
* @addtogroup MSP430_SERIAL
* @{
*/
#ifndef _MSP430_SERIAL_H_
#define _MSP430_SERIAL_H_
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
* @note The default is 32 bytes for both the transmission and receive buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 32
#endif
/**
* @brief Default bit rate.
* @details Configuration parameter, at startup the UARTs are configured at
* this speed.
* @note It is possible to use @p SetUART() in order to change the working
* parameters at runtime.
*/
#if !defined(DEFAULT_USART_BITRATE) || defined(__DOXYGEN__)
#define DEFAULT_USART_BITRATE 38400
#endif
/**
* @brief USART0 driver enable switch.
* @details If set to @p TRUE the support for USART0 is included.
* @note The default is @p TRUE.
*/
#if !defined(USE_MSP430_USART0) || defined(__DOXYGEN__)
#define USE_MSP430_USART0 TRUE
#endif
/**
* @brief USART1 driver enable switch.
* @details If set to @p TRUE the support for USART1 is included.
* @note The default is @p FALSE.
*/
#if !defined(USE_MSP430_USART1) || defined(__DOXYGEN__)
#define USE_MSP430_USART1 FALSE
#endif
/**
* @brief Macro for baud rate computation.
* @note Make sure the final baud rate is within tolerance.
*/
#define UBR(b) (SMCLK / (b))
#ifdef __cplusplus
extern "C" {
#endif
void serial_init(void);
void usart0_setup(uint16_t div, uint8_t mod, uint8_t ctl);
void usart1_setup(uint16_t div, uint8_t mod, uint8_t ctl);
#ifdef __cplusplus
}
#endif
/** @cond never*/
extern FullDuplexDriver COM1, COM2;
/** @endcond*/
#endif /* _MSP430_SERIAL_H_ */
/** @} */

View File

@ -1,115 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/MSP430/pal_lld.c
* @brief MSP430 Digital I/O low level driver code
* @addtogroup MSP430_PAL
* @{
*/
#include <ch.h>
#include <pal.h>
/**
* @brief MSP430 I/O ports configuration.
*
* @param[in] config the MSP430 ports configuration
*
* @note The @p PxIFG, @p PxIE and @p PxSEL registers are cleared. @p PxOUT
* and @p PxDIR are configured as specified.
*/
void _pal_lld_init(const MSP430DIOConfig *config) {
#if defined(__MSP430_HAS_PORT1__) || defined(__MSP430_HAS_PORT1_R__)
IOPORT_A->iop_full.ie.reg_p = 0;
IOPORT_A->iop_full.ifg.reg_p = 0;
IOPORT_A->iop_full.sel.reg_p = 0;
IOPORT_A->iop_common.out = config->P1Data.out;
IOPORT_A->iop_common.dir = config->P1Data.dir;
#endif
#if defined(__MSP430_HAS_PORT2__) || defined(__MSP430_HAS_PORT2_R__)
IOPORT_B->iop_full.ie.reg_p = 0;
IOPORT_B->iop_full.ifg.reg_p = 0;
IOPORT_B->iop_full.sel.reg_p = 0;
IOPORT_B->iop_common.out = config->P2Data.out;
IOPORT_B->iop_common.dir = config->P2Data.dir;
#endif
#if defined(__MSP430_HAS_PORT3__) || defined(__MSP430_HAS_PORT3_R__)
IOPORT_C->iop_simple.sel.reg_p = 0;
IOPORT_C->iop_common.out = config->P3Data.out;
IOPORT_C->iop_common.dir = config->P3Data.dir;
#endif
#if defined(__MSP430_HAS_PORT4__) || defined(__MSP430_HAS_PORT4_R__)
IOPORT_D->iop_simple.sel.reg_p = 0;
IOPORT_D->iop_common.out = config->P4Data.out;
IOPORT_D->iop_common.dir = config->P4Data.dir;
#endif
#if defined(__MSP430_HAS_PORT5__) || defined(__MSP430_HAS_PORT5_R__)
IOPORT_E->iop_simple.sel.reg_p = 0;
IOPORT_E->iop_common.out = config->P5Data.out;
IOPORT_E->iop_common.dir = config->P5Data.dir;
#endif
#if defined(__MSP430_HAS_PORT6__) || defined(__MSP430_HAS_PORT6_R__)
IOPORT_F->iop_simple.sel.reg_p = 0;
IOPORT_F->iop_common.out = config->P6Data.out;
IOPORT_F->iop_common.dir = config->P6Data.dir;
#endif
}
/**
* @brief Pads mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note @p PAL_MODE_UNCONNECTED is implemented as output as recommended by
* the MSP430x1xx Family User's Guide. Unconnected pads are set to
* high logic state by default.
* @note This function does not alter the @p PxSEL registers. Alternate
* functions setup must be handled by device-specific code.
*/
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode) {
switch (mode) {
case PAL_MODE_RESET:
case PAL_MODE_INPUT:
port->iop_common.dir.reg_p &= ~mask;
break;
case PAL_MODE_UNCONNECTED:
port->iop_common.out.reg_p |= mask;
case PAL_MODE_OUTPUT_PUSHPULL:
port->iop_common.dir.reg_p |= mask;
break;
}
}
/** @} */

View File

@ -1,292 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ports/MSP430/pal_lld.h
* @brief MSP430 Digital I/O low level driver header
* @addtogroup MSP430_PAL
* @{
*/
#ifndef _PAL_LLD_H_
#define _PAL_LLD_H_
#include <msp430x16x.h>
/*===========================================================================*/
/* Unsupported modes and specific modes */
/*===========================================================================*/
#undef PAL_MODE_INPUT_PULLUP
#undef PAL_MODE_INPUT_PULLDOWN
#undef PAL_MODE_OUTPUT_OPENDRAIN
/*===========================================================================*/
/* I/O Ports Types and constants. */
/*===========================================================================*/
/**
* @brief Simplified MSP430 I/O port representation.
* @details This structure represents the common part of all the MSP430 I/O
* ports.
*/
struct port_common_t {
ioregister_t in;
ioregister_t out;
ioregister_t dir;
};
/**
* @brief Generic MSP430 I/O port.
*/
union __ioport {
struct port_common_t iop_common;
struct port_simple_t iop_simple;
struct port_full_t iop_full;
};
/**
* @brief Setup registers common to all the MSP430 ports.
*/
typedef struct {
ioregister_t out;
ioregister_t dir;
} msp430_dio_setup_t;
/**
* @brief MSP430 I/O ports static initializer.
* @details An instance of this structure must be passed to @p palInit() at
* system startup time in order to initialized the digital I/O
* subsystem. This represents only the initial setup, specific pads
* or whole ports can be reprogrammed at later time.
*/
typedef struct {
#if defined(__MSP430_HAS_PORT1__) || \
defined(__MSP430_HAS_PORT1_R__) || \
defined(__DOXYGEN__)
/** @brief Port 1 setup data.*/
msp430_dio_setup_t P1Data;
#endif
#if defined(__MSP430_HAS_PORT2__) || \
defined(__MSP430_HAS_PORT2_R__) || \
defined(__DOXYGEN__)
/** @brief Port 2 setup data.*/
msp430_dio_setup_t P2Data;
#endif
#if defined(__MSP430_HAS_PORT3__) || \
defined(__MSP430_HAS_PORT3_R__) || \
defined(__DOXYGEN__)
/** @brief Port 3 setup data.*/
msp430_dio_setup_t P3Data;
#endif
#if defined(__MSP430_HAS_PORT4__) || \
defined(__MSP430_HAS_PORT4_R__) || \
defined(__DOXYGEN__)
/** @brief Port 4 setup data.*/
msp430_dio_setup_t P4Data;
#endif
#if defined(__MSP430_HAS_PORT5__) || \
defined(__MSP430_HAS_PORT5_R__) || \
defined(__DOXYGEN__)
/** @brief Port 5 setup data.*/
msp430_dio_setup_t P5Data;
#endif
#if defined(__MSP430_HAS_PORT6__) || \
defined(__MSP430_HAS_PORT6_R__) || \
defined(__DOXYGEN__)
/** @brief Port 6 setup data.*/
msp430_dio_setup_t P6Data;
#endif
} MSP430DIOConfig;
/**
* @brief Width, in bits, of an I/O port.
*/
#define PAL_IOPORTS_WIDTH 8
/**
* @brief Whole port mask.
* @brief This macro specifies all the valid bits into a port.
*/
#define PAL_WHOLE_PORT ((ioportmask_t)0xFF)
/**
* @brief Digital I/O port sized unsigned type.
*/
typedef uint8_t ioportmask_t;
/**
* @brief Port Identifier.
* @details This type can be a scalar or some kind of pointer, do not make
* any assumption about it, use the provided macros when populating
* variables of this type.
*/
typedef union __ioport * ioportid_t;
/*===========================================================================*/
/* I/O Ports Identifiers. */
/*===========================================================================*/
/**
* @brief I/O port A identifier.
* @details This port identifier is mapped on the MSP430 port 1 (P1).
*/
#if defined(__MSP430_HAS_PORT1__) || \
defined(__MSP430_HAS_PORT1_R__) || \
defined(__DOXYGEN__)
#define IOPORT_A ((ioportid_t)0x0020)
#endif
/**
* @brief I/O port B identifier.
* @details This port identifier is mapped on the MSP430 port 2 (P2).
*/
#if defined(__MSP430_HAS_PORT2__) || \
defined(__MSP430_HAS_PORT2_R__) || \
defined(__DOXYGEN__)
#define IOPORT_B ((ioportid_t)0x0028)
#endif
/**
* @brief I/O port C identifier.
* @details This port identifier is mapped on the MSP430 port 3 (P3).
*/
#if defined(__MSP430_HAS_PORT3__) || \
defined(__MSP430_HAS_PORT3_R__) || \
defined(__DOXYGEN__)
#define IOPORT_C ((ioportid_t)0x0018)
#endif
/**
* @brief I/O port D identifier.
* @details This port identifier is mapped on the MSP430 port 4 (P4).
*/
#if defined(__MSP430_HAS_PORT4__) || \
defined(__MSP430_HAS_PORT4_R__) || \
defined(__DOXYGEN__)
#define IOPORT_D ((ioportid_t)0x001c)
#endif
/**
* @brief I/O port E identifier.
* @details This port identifier is mapped on the MSP430 port 5 (P5).
*/
#if defined(__MSP430_HAS_PORT5__) || \
defined(__MSP430_HAS_PORT5_R__) || \
defined(__DOXYGEN__)
#define IOPORT_E ((ioportid_t)0x0030)
#endif
/**
* @brief I/O port F identifier.
* @details This port identifier is mapped on the MSP430 port 6 (P6).
*/
#if defined(__MSP430_HAS_PORT6__) || \
defined(__MSP430_HAS_PORT6_R__) || \
defined(__DOXYGEN__)
#define IOPORT_F ((ioportid_t)0x0034)
#endif
/*===========================================================================*/
/* Implementation, some of the following macros could be implemented as */
/* functions, if so please put them in a file named pal_lld.c. */
/*===========================================================================*/
/**
* @brief Low level PAL subsystem initialization.
* @details In MSP430 programs all the ports as input.
*
* @param[in] config the MSP430 ports configuration
*/
#define pal_lld_init(config) _pal_lld_init(config)
/**
* @brief Reads the physical I/O port states.
* @details This function is implemented by reading the PxIN register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @return The port bits.
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_readport(port) ((port)->iop_common.in.reg_p)
/**
* @brief Reads the output latch.
* @details This function is implemented by reading the PxOUT register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @return The latched logical states.
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_readlatch(port) ((port)->iop_common.out.reg_p)
/**
* @brief Writes a bits mask on a I/O port.
* @details This function is implemented by writing the PxOUT register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be written on the specified port
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_writeport(port, bits) { \
(port)->iop_common.out.reg_p = (bits); \
}
/**
* @brief Pads group mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note @p PAL_MODE_UNCONNECTED is implemented as output as recommended by
* the MSP430x1xx Family User's Guide.
* @note This function does not alter the @p PxSEL registers. Alternate
* functions setup must be handled by device-specific code.
*/
#define pal_lld_setgroupmode(port, mask, mode) \
_pal_lld_setgroupmode(port, mask, mode)
#ifdef __cplusplus
extern "C" {
#endif
void _pal_lld_init(const MSP430DIOConfig *config);
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode);
#ifdef __cplusplus
}
#endif
#endif /* _PAL_LLD_H_ */
/** @} */

View File

@ -1,124 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @defgroup MSP430 MSP430
* @details MSP430 port details. This section how the ChibiOS/RT features are
* implemented on this architecture.
*
* @section MSP430_STATES Mapping of the System States in the MSP430 port
* The ChibiOS/RT logical @ref system_states are mapped as follow in the MSP430
* port:
* - <b>Init</b>. This state is represented by the startup code and the
* initialization code before @p chSysInit() is executed. It has not a
* special hardware state associated.
* - <b>Normal</b>. This is the state the system has after executing
* @p chSysInit(). Interrupts are enabled.
* - <b>Suspended</b>. Interrupts are disabled.
* - <b>Disabled</b>. Interrupts are enabled. This state is equivalent to the
* Suspended state because there are no fast interrupts in this architecture.
* - <b>Sleep</b>. Not yet implemented.
* - <b>S-Locked</b>. Interrupts are disabled.
* - <b>I-Locked</b>. This state is equivalent to the SRI state, the
* @p chSysLockI() and @p chSysUnlockI() APIs do nothing (still use them in
* order to formally change state because this may change).
* - <b>Serving Regular Interrupt</b>. Normal interrupt service code.
* - <b>Serving Fast Interrupt</b>. Not present in this architecture.
* - <b>Serving Non-Maskable Interrupt</b>. The MSP430 has several non
* maskable interrupt sources that can be associated to this state.
* - <b>Halted</b>. Implemented as an infinite loop with interrupts disabled.
* .
* @section MSP430_NOTES The MSP430 port notes
* - The MSP430 does not have a dedicated interrupt stack, make sure to reserve
* enough stack space for interrupts in each thread stack. This can be done
* by modifying the @p INT_REQUIRED_STACK macro into
* <b>./ports/MSP430/chcore.h</b>.
* - The state of the hardware multiplier is not saved in the thread context,
* make sure to use it in <b>Suspended</b> state (interrupts masked).
* - The port code does not define the switch to a low power mode for the
* idle thread because the MSP430 has several low power modes. You can
* select the proper low power mode for you application by defining the
* macro @p port_wait_for_interrupt().
* .
* @ingroup Ports
*/
/**
* @defgroup MSP430_CONF Configuration Options
* @brief MSP430 Configuration Options.
* @details The MSP430 port allows some architecture-specific configurations
* settings that can be specified externally, as example on the compiler
* command line:
* - @p INT_REQUIRED_STACK, this value represent the amount of stack space
* used by the interrupt handlers.<br>
* The default for this value is @p 32, this space is allocated for each
* thread so be careful in order to not waste precious RAM space.<br>
* The default value is set into <b>./ports/MSP430/chcore.h</b>.
* .
* @ingroup MSP430
*/
/**
* @defgroup MSP430_CORE Core Port Implementation
* @brief MSP430 specific port code, structures and macros.
*
* @ingroup MSP430
*/
/**
* @defgroup MSP430_DRIVERS MSP430 Drivers
* @brief Device drivers included in the MSP430 support.
*
* @ingroup MSP430
*/
/**
* @defgroup MSP430_PAL I/O Ports Support
* @brief I/O Ports peripherals support.
* @details This module supports the MSP430 Digital I/O controller. The
* controller supports the following features (see @ref PAL):
* - 8 bits wide ports.
* - Atomic set/reset/toggle functions because special MSP430 instruction set.
* - Output latched regardless of the pad setting.
* - Direct read of input pads regardless of the pad setting.
* .
* <h2>Supported Setup Modes</h2>
* - @p PAL_MODE_RESET.
* - @p PAL_MODE_UNCONNECTED.
* - @p PAL_MODE_INPUT.
* - @p PAL_MODE_OUTPUT_PUSHPULL.
* .
* Any attempt to setup an invalid mode is ignored.
*
* <h2>Suboptimal Behavior</h2>
* Some MSP430 I/O ports features are less than optimal:
* - Bus/group writing is not atomic.
* - Pad/group mode setup is not atomic.
* .
* @ingroup MSP430_DRIVERS
*/
/**
* @defgroup MSP430_SERIAL USART Support
* @brief USART support.
* @details The serial driver supports both the MSP430 USARTs in asynchronous
* mode.
*
* @ingroup MSP430_DRIVERS
*/

View File

@ -1,87 +0,0 @@
# MSP430 makefile scripts and rules.
# Automatic compiler options
OPT = $(USE_OPT)
CPPOPT = $(USE_CPPOPT)
ifeq ($(USE_CURRP_CACHING),yes)
OPT += -ffixed-r7 -DCH_CURRP_REGISTER_CACHE='"r7"'
endif
ifeq ($(USE_LINK_GC),yes)
OPT += -ffunction-sections -fdata-sections
endif
# Source files groups
SRC = $(CSRC)$(CPPSRC)
# Object files groups
COBJS = $(CSRC:.c=.o)
CPPOBJS = $(CPPSRC:.cpp=.o)
ASMOBJS = $(ASMSRC:.s=.o)
OBJS = $(ASMOBJS) $(COBJS) $(CPPOBJS)
# Paths
IINCDIR = $(patsubst %,-I%,$(INCDIR) $(DINCDIR) $(UINCDIR))
LLIBDIR = $(patsubst %,-L%,$(DLIBDIR) $(ULIBDIR))
# Macros
DEFS = $(DDEFS) $(UDEFS)
ADEFS = $(DADEFS) $(UADEFS)
# Libs
LIBS = $(DLIBS) $(ULIBS)
MCFLAGS = -mmcu=$(MCU)
ODFLAGS = -x --syms
ASFLAGS = $(MCFLAGS) -Wa,-amhls=$(<:.s=.lst) $(ADEFS)
CPFLAGS = $(MCFLAGS) $(OPT) $(WARN) -Wa,-alms=$(<:.c=.lst) $(DEFS)
ifeq ($(LINK_GC),yes)
LDFLAGS = $(MCFLAGS) -T$(LDSCRIPT) -Wl,-Map=$(PROJECT).map,--cref,--no-warn-mismatch,--gc-sections $(LLIBDIR)
else
LDFLAGS = $(MCFLAGS) -T$(LDSCRIPT) -Wl,-Map=$(PROJECT).map,--cref,--no-warn-mismatch $(LLIBDIR)
endif
# Generate dependency information
CPFLAGS += -MD -MP -MF .dep/$(@F).d
#
# Makefile rules
#
all: $(OBJS) $(PROJECT).elf $(PROJECT).hex $(PROJECT).bin $(PROJECT).dmp
$(CPPOBJS) : %.o : %.cpp
@echo
$(CPPC) -c $(CPPFLAGS) -I . $(IINCDIR) $< -o $@
$(COBJS) : %.o : %.c
@echo
$(CC) -c $(CPFLAGS) -I . $(IINCDIR) $< -o $@
$(ASMOBJS) : %.o : %.s
@echo
$(AS) -c $(ASFLAGS) -I . $(IINCDIR) $< -o $@
%elf: $(OBJS)
@echo
$(LD) $(OBJS) $(LDFLAGS) $(LIBS) -o $@
%hex: %elf
$(HEX) $< $@
%bin: %elf
$(BIN) $< $@
%dmp: %elf
$(OD) $(ODFLAGS) $< > $@
clean:
-rm -f $(OBJS)
-rm -f $(CSRC:.c=.lst) $(CPPSRC:.cpp=.lst) $(ASMSRC:.s=.lst)
-rm -f $(PROJECT).elf $(PROJECT).dmp $(PROJECT).map $(PROJECT).hex $(PROJECT).bin
-rm -fR .dep
#
# Include the dependency files, should be the last of the makefile
#
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
# *** EOF ***

View File

@ -1,227 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Win32 COM port simulator (on socket).
*/
#include <chconf.h>
#include <windows.h>
#include <stdio.h>
#undef CDECL
#include <ch.h>
#define COM1PORT 29001
#define COM2PORT 29002
struct simcom {
uint8_t com_ib[1024];
uint8_t com_ob[1024];
SOCKET com_listen;
SOCKET com_data;
};
FullDuplexDriver COM1;
static struct simcom sc1;
FullDuplexDriver COM2;
static struct simcom sc2;
static u_long nb = 1;
static void init(char *name, FullDuplexDriver *sd,
struct simcom *sc, unsigned short port) {
struct sockaddr_in sad;
struct protoent *prtp;
chFDDInit(sd,
sc->com_ib, sizeof(sc->com_ib), NULL,
sc->com_ob, sizeof(sc->com_ob), NULL);
sc->com_listen = INVALID_SOCKET;
sc->com_data = INVALID_SOCKET;
if ((prtp = getprotobyname("tcp")) == NULL) {
printf("%s: Error mapping protocol name to protocol number\n", name);
goto abort;
}
sc->com_listen = socket(PF_INET, SOCK_STREAM, prtp->p_proto);
if (sc->com_listen == INVALID_SOCKET) {
printf("%s: Error creating simulator socket\n", name);
goto abort;
}
if (ioctlsocket(sc->com_listen, FIONBIO, &nb) != 0) {
printf("%s: Unable to setup non blocking mode on socket\n", name);
goto abort;
}
memset(&sad, 0, sizeof(sad));
sad.sin_family = AF_INET;
sad.sin_addr.s_addr = INADDR_ANY;
sad.sin_port = htons(port);
if (bind(sc->com_listen, (struct sockaddr *)&sad, sizeof(sad))) {
printf("%s: Error binding socket\n", name);
goto abort;
}
if (listen(sc->com_listen, 1) != 0) {
printf("%s: Error binding socket\n", name);
goto abort;
}
printf("Full Duplex Channel %s listening on port %d\n", name, port);
return;
abort:
if (sc->com_listen != INVALID_SOCKET)
closesocket(sc->com_listen);
WSACleanup();
exit(1);
}
void InitSimCom1(void) {
init("COM1", &COM1, &sc1, COM1PORT);
}
void InitSimCom2(void) {
init("COM2", &COM2, &sc2, COM2PORT);
}
static bool_t connint(char *name, FullDuplexDriver *sd, struct simcom *sc) {
if (sc->com_data == INVALID_SOCKET) {
struct sockaddr addr;
int addrlen = sizeof(addr);
if ((sc->com_data = accept(sc->com_listen, &addr, &addrlen)) == INVALID_SOCKET)
return FALSE;
if (ioctlsocket(sc->com_data, FIONBIO, &nb) != 0) {
printf("%s: Unable to setup non blocking mode on data socket\n", name);
goto abort;
}
chFDDAddFlagsI(sd, SD_CONNECTED);
return TRUE;
}
return FALSE;
abort:
if (sc->com_listen != INVALID_SOCKET)
closesocket(sc->com_listen);
if (sc->com_data != INVALID_SOCKET)
closesocket(sc->com_data);
WSACleanup();
exit(1);
}
bool_t Com1ConnInterruptSimCom(void) {
return connint("COM1", &COM1, &sc1);
}
bool_t Com2ConnInterruptSimCom(void) {
return connint("COM2", &COM2, &sc2);
}
static bool_t inint(char *name, FullDuplexDriver *sd, struct simcom *sc) {
if (sc->com_data != INVALID_SOCKET) {
int i;
uint8_t data[32];
/*
* Input.
*/
int n = recv(sc->com_data, data, sizeof(data), 0);
switch (n) {
case 0:
closesocket(sc->com_data);
sc->com_data = INVALID_SOCKET;
chFDDAddFlagsI(sd, SD_DISCONNECTED);
return FALSE;
case SOCKET_ERROR:
if (WSAGetLastError() == WSAEWOULDBLOCK)
return FALSE;
closesocket(sc->com_data);
sc->com_data = INVALID_SOCKET;
return FALSE;
}
for (i = 0; i < n; i++)
chFDDIncomingDataI(sd, data[i]);
return TRUE;
}
return FALSE;
}
bool_t Com1InInterruptSimCom(void) {
return inint("COM1", &COM1, &sc1);
}
bool_t Com2InInterruptSimCom(void) {
return inint("COM2", &COM2, &sc2);
}
static bool_t outint(char *name, FullDuplexDriver *sd, struct simcom *sc) {
if (sc->com_data != INVALID_SOCKET) {
int n;
uint8_t data[1];
/*
* Input.
*/
n = chFDDRequestDataI(sd);
if (n < 0)
return FALSE;
data[0] = (uint8_t)n;
n = send(sc->com_data, data, sizeof(data), 0);
switch (n) {
case 0:
closesocket(sc->com_data);
sc->com_data = INVALID_SOCKET;
chFDDAddFlagsI(sd, SD_DISCONNECTED);
return FALSE;
case SOCKET_ERROR:
if (WSAGetLastError() == WSAEWOULDBLOCK)
return FALSE;
closesocket(sc->com_data);
sc->com_data = INVALID_SOCKET;
return FALSE;
}
return TRUE;
}
return FALSE;
}
bool_t Com1OutInterruptSimCom(void) {
return outint("COM1", &COM1, &sc1);
}
bool_t Com2OutInterruptSimCom(void) {
return outint("COM2", &COM2, &sc2);
}

View File

@ -1,227 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Concepts and parts of this file are contributed by and Copyright (C) 2008
of Leon Woestenberg.
*/
/**
* @file chcond.c
* @brief Condition Variables code.
* @addtogroup CondVars
* @{
*/
#include <ch.h>
#if CH_USE_CONDVARS && CH_USE_MUTEXES
/**
* @brief Initializes s @p CondVar structure.
*
* @param[out] cp pointer to a @p CondVar structure
* @note This function can be invoked from within an interrupt handler even if
* it is not an I-Class API because it does not touch any critical kernel
* data structure.
*/
void chCondInit(CondVar *cp) {
chDbgCheck(cp != NULL, "chCondInit");
queue_init(&cp->c_queue);
}
/**
* @brief Signals one thread that is waiting on the condition variable.
*
* @param[in] cp pointer to the @p CondVar structure
*/
void chCondSignal(CondVar *cp) {
chDbgCheck(cp != NULL, "chCondSignal");
chSysLock();
if (notempty(&cp->c_queue)) /* any thread ? */
chSchWakeupS(fifo_remove(&cp->c_queue), RDY_OK);
chSysUnlock();
}
/**
* @brief Signals one thread that is waiting on the condition variable.
*
* @param[in] cp pointer to the @p CondVar structure
*/
void chCondSignalI(CondVar *cp) {
chDbgCheck(cp != NULL, "chCondSignalI");
if (notempty(&cp->c_queue)) /* any thread ? */
chSchReadyI(fifo_remove(&cp->c_queue))->p_rdymsg = RDY_OK;
}
/**
* @brief Signals all threads that are waiting on the condition variable.
*
* @param[in] cp pointer to the @p CondVar structure
*/
void chCondBroadcast(CondVar *cp) {
chSysLock();
chCondBroadcastI(cp);
chSchRescheduleS();
chSysUnlock();
}
/**
* @brief Signals all threads that are waiting on the condition variable.
*
* @param[in] cp pointer to the @p CondVar structure
*/
void chCondBroadcastI(CondVar *cp) {
chDbgCheck(cp != NULL, "chCondBroadcastI");
/* empties the condition variable queue and inserts all the Threads into the
* ready list in FIFO order. The wakeup message is set to @p RDY_RESET in
* order to make a chCondBroadcast() detectable from a chCondSignal(). */
while (cp->c_queue.p_next != (void *)&cp->c_queue)
chSchReadyI(fifo_remove(&cp->c_queue))->p_rdymsg = RDY_RESET;
}
/**
* @brief Waits on the condition variable releasing the mutex lock.
* @details Releases the mutex, waits on the condition variable, and finally
* acquires the mutex again. This is done atomically.
*
* @param[in] cp pointer to the @p CondVar structure
* @return The wakep mode.
* @retval RDY_OK if the condvar was signaled using chCondSignal().
* @retval RDY_RESET if the condvar was signaled using chCondBroadcast().
* @note The thread MUST already have locked the mutex when calling
* @p chCondWait().
*/
msg_t chCondWait(CondVar *cp) {
msg_t msg;
chSysLock();
msg = chCondWaitS(cp);
chSysUnlock();
return msg;
}
/**
* @brief Waits on the condition variable releasing the mutex lock.
* @details Releases the mutex, waits on the condition variable, and finally
* acquires the mutex again. This is done atomically.
*
* @param[in] cp pointer to the @p CondVar structure
* @return The wakep mode.
* @retval RDY_OK if the condvar was signaled using chCondSignal().
* @retval RDY_RESET if the condvar was signaled using chCondBroadcast().
* @note The thread MUST already have locked the mutex when calling
* @p chCondWaitS().
*/
msg_t chCondWaitS(CondVar *cp) {
Mutex *mp;
msg_t msg;
chDbgCheck(cp != NULL, "chCondWaitS");
chDbgAssert(currp->p_mtxlist != NULL,
"chCondWaitS(), #1",
"not owning a mutex");
mp = chMtxUnlockS(); /* unlocks the condvar mutex */
prio_insert(currp, &cp->c_queue); /* enters the condvar queue */
currp->p_wtcondp = cp; /* needed by the tracer */
chSchGoSleepS(PRWTCOND); /* waits on the condvar */
msg = currp->p_rdymsg; /* fetches the wakeup message */
chMtxLockS(mp); /* atomically relocks the mutex */
return msg; /* returns the wakeup message */
}
#if CH_USE_CONDVARS_TIMEOUT
/**
* @brief Waits on the condition variable releasing the mutex lock.
* @details Releases the mutex, waits on the condition variable, and finally
* acquires the mutex again. This is done atomically.
*
* @param[in] cp pointer to the @p CondVar structure
* @param[in] time the number of ticks before the operation timeouts,
* the special value @p TIME_INFINITE is allowed.
* It is not possible to specify zero @p TIME_IMMEDIATE
* as timeout specification because it would make no sense
* in this function.
* @return The wakep mode.
* @retval RDY_OK if the condvar was signaled using chCondSignal().
* @retval RDY_RESET if the condvar was signaled using chCondBroadcast().
* @retval RDY_TIMEOUT if the condvar was not signaled within the specified
* timeout.
* @note The thread MUST already have locked the mutex when calling
* @p chCondWaitTimeout().
*/
msg_t chCondWaitTimeout(CondVar *cp, systime_t time) {
msg_t msg;
chSysLock();
msg = chCondWaitTimeoutS(cp, time);
chSysUnlock();
return msg;
}
/**
* @brief Waits on the condition variable releasing the mutex lock.
* @details Releases the mutex, waits on the condition variable, and finally
* acquires the mutex again. This is done atomically.
*
* @param[in] cp pointer to the @p CondVar structure
* @param[in] time the number of ticks before the operation timeouts,
* the special value @p TIME_INFINITE is allowed.
* It is not possible to specify zero @p TIME_IMMEDIATE
* as timeout specification because it would make no sense
* in this function.
* @return The wakep mode.
* @retval RDY_OK if the condvar was signaled using chCondSignal().
* @retval RDY_RESET if the condvar was signaled using chCondBroadcast().
* @retval RDY_TIMEOUT if the condvar was not signaled within the specified
* timeout.
* @note The thread MUST already have locked the mutex when calling
* @p chCondWaitTimeoutS().
*/
msg_t chCondWaitTimeoutS(CondVar *cp, systime_t time) {
Mutex *mp;
msg_t msg;
chDbgCheck(cp != NULL, "chCondWaitTimeoutS");
chDbgAssert(currp->p_mtxlist != NULL,
"chCondWaitTimeoutS(), #1",
"not owning a mutex");
mp = chMtxUnlockS(); /* unlocks the condvar mutex */
prio_insert(currp, &cp->c_queue); /* enters the condvar queue */
currp->p_wtcondp = cp; /* needed by the tracer */
chSchGoSleepTimeoutS(PRWTCOND, time); /* waits on the condvar */
msg = currp->p_rdymsg; /* fetches the wakeup message */
chMtxLockS(mp); /* atomically relocks the mutex */
return msg; /* returns the wakeup message */
}
#endif /* CH_USE_CONDVARS_TIMEOUT */
#endif /* CH_USE_CONDVARS && CH_USE_MUTEXES */
/** @} */

View File

@ -1,81 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chdebug.c
* @brief ChibiOS/RT Debug code.
* @addtogroup Debug
* @{
*/
#include <ch.h>
#if CH_DBG_ENABLE_TRACE
/**
* @brief Public trace buffer.
*/
TraceBuffer trace_buffer;
/**
* @brief Trace circular buffer subsystem initialization.
*/
void trace_init(void) {
trace_buffer.tb_size = TRACE_BUFFER_SIZE;
trace_buffer.tb_ptr = &trace_buffer.tb_buffer[0];
}
/**
* @brief Inserts in the circular debug trace buffer a context switch record.
*
* @param[in] otp the thread being switched out
* @param[in] ntp the thread to be switched in
*/
void chDbgTrace(Thread *otp, Thread *ntp) {
trace_buffer.tb_ptr->cse_wtobjp = otp->p_wtobjp;
trace_buffer.tb_ptr->cse_time = chTimeNow();
trace_buffer.tb_ptr->cse_state = otp->p_state;
trace_buffer.tb_ptr->cse_tid = (unsigned)ntp >> 4;
if (++trace_buffer.tb_ptr >= &trace_buffer.tb_buffer[TRACE_BUFFER_SIZE])
trace_buffer.tb_ptr = &trace_buffer.tb_buffer[0];
}
#endif /* CH_DBG_ENABLE_TRACE */
#if CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK
/**
* @brief Pointer to the panic message.
* @details This pointer is meant to be accessed through the debugger, it is
* written once and then the system is halted.
*/
char *panic_msg;
/**
* @brief Prints a panic message on the console and then halts the system.
*
* @param[in] msg the pointer to the panic message string
*/
void chDbgPanic(char *msg) {
panic_msg = msg;
chSysHalt();
}
#endif /* CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK */
/** @} */

View File

@ -1,392 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chevents.c
* @brief Events code.
* @addtogroup Events
* @{
*/
#include <ch.h>
#if CH_USE_EVENTS
/**
* @brief Registers an Event Listener on an Event Source.
*
* @param[in] esp pointer to the @p EventSource structure
* @param[in] elp pointer to the @p EventListener structure
* @param[in] emask the mask of event flags to be pended to the thread when the
* event source is broadcasted
* @note Multiple Event Listeners can specify the same bits to be pended.
*/
void chEvtRegisterMask(EventSource *esp, EventListener *elp, eventmask_t emask) {
chDbgCheck((esp != NULL) && (elp != NULL), "chEvtRegisterMask");
chSysLock();
elp->el_next = esp->es_next;
esp->es_next = elp;
elp->el_listener = currp;
elp->el_mask = emask;
chSysUnlock();
}
/**
* @brief Unregisters an Event Listener from its Event Source.
*
* @param[in] esp pointer to the @p EventSource structure
* @param[in] elp pointer to the @p EventListener structure
* @note If the event listener is not registered on the specified event source
* then the function does nothing.
* @note For optimal performance it is better to perform the unregister
* operations in inverse order of the register operations (elements are
* found on top of the list).
*/
void chEvtUnregister(EventSource *esp, EventListener *elp) {
EventListener *p;
chDbgCheck((esp != NULL) && (elp != NULL), "chEvtUnregister");
p = (EventListener *)esp;
chSysLock();
while (p->el_next != (EventListener *)esp) {
if (p->el_next == elp) {
p->el_next = elp->el_next;
break;
}
p = p->el_next;
}
chSysUnlock();
}
/**
* @brief Clears the pending events specified in the mask.
*
* @param[in] mask the events to be cleared
* @return The pending events that were cleared.
*/
eventmask_t chEvtClear(eventmask_t mask) {
eventmask_t m;
chSysLock();
m = currp->p_epending & mask;
currp->p_epending &= ~mask;
chSysUnlock();
return m;
}
/**
* @brief Pends a set of event flags on the current thread, this is @b much
* faster than using @p chEvtBroadcast() or @p chEvtSignal().
*
* @param[in] mask the events to be pended
* @return The current pending events mask.
*/
eventmask_t chEvtPend(eventmask_t mask) {
chSysLock();
mask = (currp->p_epending |= mask);
chSysUnlock();
return mask;
}
/**
* @brief Pends a set of event flags on the specified @p Thread.
*
* @param[in] tp the thread to be signaled
* @param[in] mask the event flags set to be pended
*/
void chEvtSignal(Thread *tp, eventmask_t mask) {
chDbgCheck(tp != NULL, "chEvtSignal");
chSysLock();
chEvtSignalI(tp, mask);
chSysUnlock();
}
/**
* @brief Pends a set of event flags on the specified @p Thread.
*
* @param[in] tp the thread to be signaled
* @param[in] mask the event flags set to be pended
*/
void chEvtSignalI(Thread *tp, eventmask_t mask) {
chDbgCheck(tp != NULL, "chEvtSignalI");
tp->p_epending |= mask;
/* Test on the AND/OR conditions wait states.*/
if (((tp->p_state == PRWTOREVT) && ((tp->p_epending & tp->p_ewmask) != 0)) ||
((tp->p_state == PRWTANDEVT) && ((tp->p_epending & tp->p_ewmask) == tp->p_ewmask)))
chSchReadyI(tp)->p_rdymsg = RDY_OK;
}
/**
* @brief Signals all the Event Listeners registered on the specified Event
* Source.
*
* @param[in] esp pointer to the @p EventSource structure
*/
void chEvtBroadcast(EventSource *esp) {
chSysLock();
chEvtBroadcastI(esp);
chSchRescheduleS();
chSysUnlock();
}
/**
* @brief Signals all the Event Listeners registered on the specified Event
* Source.
*
* @param[in] esp pointer to the @p EventSource structure
*/
void chEvtBroadcastI(EventSource *esp) {
EventListener *elp;
chDbgCheck(esp != NULL, "chEvtBroadcastI");
elp = esp->es_next;
while (elp != (EventListener *)esp) {
chEvtSignalI(elp->el_listener, elp->el_mask);
elp = elp->el_next;
}
}
/**
* @brief Invokes the event handlers associated with a mask.
*
* @param[in] mask mask of the events to be dispatched
* @param[in] handlers an array of @p evhandler_t. The array must have size
* equal to the number of bits in eventmask_t.
*/
void chEvtDispatch(const evhandler_t handlers[], eventmask_t mask) {
eventid_t eid;
chDbgCheck(handlers != NULL, "chEvtDispatch");
eid = 0;
while (mask) {
if (mask & EVENT_MASK(eid)) {
chDbgAssert(handlers[eid] != NULL,
"chEvtDispatch(), #1",
"null handler");
mask &= ~EVENT_MASK(eid);
handlers[eid](eid);
}
eid++;
}
}
#if CH_OPTIMIZE_SPEED || !CH_USE_EVENTS_TIMEOUT || defined(__DOXYGEN__)
/**
* @brief Waits for exactly one of the specified events.
* @details The function waits for one event among those specified in
* @p ewmask to become pending then the event is cleared and returned.
*
* @param[in] ewmask mask of the events that the function should wait for,
* @p ALL_EVENTS enables all the events
* @return The mask of the lowest id served and cleared event.
* @note One and only one event is served in the function, the one with the
* lowest event id. The function is meant to be invoked into a loop in
* order to serve all the pending events.<br>
* This means that Event Listeners with a lower event identifier have
* an higher priority.
*/
eventmask_t chEvtWaitOne(eventmask_t ewmask) {
eventmask_t m;
chSysLock();
if ((m = (currp->p_epending & ewmask)) == 0) {
currp->p_ewmask = ewmask;
chSchGoSleepS(PRWTOREVT);
m = currp->p_epending & ewmask;
}
m &= -m;
currp->p_epending &= ~m;
chSysUnlock();
return m;
}
/**
* @brief Waits for any of the specified events.
* @details The function waits for any event among those specified in
* @p ewmask to become pending then the events are cleared and returned.
*
* @param[in] ewmask mask of the events that the function should wait for,
* @p ALL_EVENTS enables all the events
* @return The mask of the served and cleared events.
*/
eventmask_t chEvtWaitAny(eventmask_t ewmask) {
eventmask_t m;
chSysLock();
if ((m = (currp->p_epending & ewmask)) == 0) {
currp->p_ewmask = ewmask;
chSchGoSleepS(PRWTOREVT);
m = currp->p_epending & ewmask;
}
currp->p_epending &= ~m;
chSysUnlock();
return m;
}
/**
* @brief Waits for all the specified events.
* @details The function waits for all the events specified in @p ewmask to
* become pending then the events are cleared and returned.
*
* @param[in] ewmask mask of the event ids that the function should wait for
* @return The mask of the served and cleared events.
*/
eventmask_t chEvtWaitAll(eventmask_t ewmask) {
chSysLock();
if ((currp->p_epending & ewmask) != ewmask) {
currp->p_ewmask = ewmask;
chSchGoSleepS(PRWTANDEVT);
}
currp->p_epending &= ~ewmask;
chSysUnlock();
return ewmask;
}
#endif /* CH_OPTIMIZE_SPEED || !CH_USE_EVENTS_TIMEOUT */
#if CH_USE_EVENTS_TIMEOUT
/**
* @brief Waits for exactly one of the specified events.
* @details The function waits for one event among those specified in
* @p ewmask to become pending then the event is cleared and returned.
*
* @param[in] ewmask mask of the events that the function should wait for,
* @p ALL_EVENTS enables all the events
* @param[in] time the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The mask of the lowest id served and cleared event.
* @retval 0 if the specified timeout expired.
* @note One and only one event is served in the function, the one with the
* lowest event id. The function is meant to be invoked into a loop in
* order to serve all the pending events.<br>
* This means that Event Listeners with a lower event identifier have
* an higher priority.
*/
eventmask_t chEvtWaitOneTimeout(eventmask_t ewmask, systime_t time) {
eventmask_t m;
chSysLock();
if ((m = (currp->p_epending & ewmask)) == 0) {
if (TIME_IMMEDIATE == time)
return (eventmask_t)0;
currp->p_ewmask = ewmask;
if (chSchGoSleepTimeoutS(PRWTOREVT, time) < RDY_OK)
return (eventmask_t)0;
m = currp->p_epending & ewmask;
}
m &= -m;
currp->p_epending &= ~m;
chSysUnlock();
return m;
}
/**
* @brief Waits for any of the specified events.
* @details The function waits for any event among those specified in
* @p ewmask to become pending then the events are cleared and
* returned.
*
* @param[in] ewmask mask of the events that the function should wait for,
* @p ALL_EVENTS enables all the events
* @param[in] time the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The mask of the served and cleared events.
* @retval 0 if the specified timeout expired.
*/
eventmask_t chEvtWaitAnyTimeout(eventmask_t ewmask, systime_t time) {
eventmask_t m;
chSysLock();
if ((m = (currp->p_epending & ewmask)) == 0) {
if (TIME_IMMEDIATE == time)
return (eventmask_t)0;
currp->p_ewmask = ewmask;
if (chSchGoSleepTimeoutS(PRWTOREVT, time) < RDY_OK)
return (eventmask_t)0;
m = currp->p_epending & ewmask;
}
currp->p_epending &= ~m;
chSysUnlock();
return m;
}
/**
* @brief Waits for all the specified events.
* @details The function waits for all the events specified in @p ewmask to
* become pending then the events are cleared and returned.
*
* @param[in] ewmask mask of the event ids that the function should wait for
* @param[in] time the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The mask of the served and cleared events.
* @retval 0 if the specified timeout expired.
*/
eventmask_t chEvtWaitAllTimeout(eventmask_t ewmask, systime_t time) {
chSysLock();
if ((currp->p_epending & ewmask) != ewmask) {
if (TIME_IMMEDIATE == time)
return (eventmask_t)0;
currp->p_ewmask = ewmask;
if (chSchGoSleepTimeoutS(PRWTANDEVT, time) < RDY_OK)
return (eventmask_t)0;
}
currp->p_epending &= ~ewmask;
chSysUnlock();
return ewmask;
}
#endif /* CH_USE_EVENTS_TIMEOUT */
#endif /* CH_USE_EVENTS */
/** @} */

View File

@ -1,276 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chheap.c
* @brief Heap code.
* @addtogroup Heap
* @{
*/
#include <ch.h>
#if CH_USE_HEAP
#if !CH_USE_MALLOC_HEAP
#define MAGIC 0xF5A0
#define ALIGN_TYPE void *
#define ALIGN_MASK (sizeof(ALIGN_TYPE) - 1)
#define ALIGN_SIZE(p) (((size_t)(p) + ALIGN_MASK) & ~ALIGN_MASK)
struct header {
union {
struct header *h_next;
size_t h_magic;
};
size_t h_size;
};
static struct {
struct header free; /* Guaranteed to be not adjacent to the heap */
#if CH_USE_MUTEXES
#define H_LOCK() chMtxLock(&heap.hmtx)
#define H_UNLOCK() chMtxUnlock()
Mutex hmtx;
#elif CH_USE_SEMAPHORES
#define H_LOCK() chSemWait(&heap.hsem)
#define H_UNLOCK() chSemSignal(&heap.hsem)
Semaphore hsem;
#else
#error "The heap allocator requires mutexes or semaphores to be enabled"
#endif
#if CH_HEAP_SIZE > 0
union {
ALIGN_TYPE alignment;
char buffer[ALIGN_SIZE(CH_HEAP_SIZE)];
};
#endif
} heap;
/**
* @brief Initializes the allocator subsystem.
*
* @note Internal use only.
*/
void heap_init(void) {
struct header *hp;
#if CH_HEAP_SIZE == 0
extern char __heap_base__;
extern char __heap_end__;
hp = (void *)&__heap_base__;
hp->h_size = &__heap_end__ - &__heap_base__ - sizeof(struct header);
#else
hp = (void *)&heap.buffer[0];
hp->h_size = (&heap.buffer[ALIGN_SIZE(CH_HEAP_SIZE)] - &heap.buffer[0]) -
sizeof(struct header);
#endif
hp->h_next = NULL;
heap.free.h_next = hp;
heap.free.h_size = 0;
#if CH_USE_MUTEXES
chMtxInit(&heap.hmtx);
#else
chSemInit(&heap.hsem, 1);
#endif
}
/**
* @brief Allocates a block of memory from the heap by using the first-fit
* algorithm.
* @details The allocated block is guaranteed to be properly aligned for a
* pointer data type.
*
* @param[in] size the size of the block to be allocated. Note that the
* allocated block may be a bit bigger than the requested
* size for alignment and fragmentation reasons.
* @return A pointer to the allocated block.
* @retval NULL if the block cannot be allocated.
*/
void *chHeapAlloc(size_t size) {
struct header *qp, *hp, *fp;
size = ALIGN_SIZE(size);
qp = &heap.free;
H_LOCK();
while (qp->h_next != NULL) {
hp = qp->h_next;
if (hp->h_size >= size) {
if (hp->h_size < size + sizeof(struct header)) {
/* Gets the whole block even if it is slightly bigger than the
requested size because the fragment would be too small to be
useful */
qp->h_next = hp->h_next;
}
else {
/* Block bigger enough, must split it */
fp = (void *)((char *)(hp) + sizeof(struct header) + size);
fp->h_next = hp->h_next;
fp->h_size = hp->h_size - sizeof(struct header) - size;
qp->h_next = fp;
hp->h_size = size;
}
hp->h_magic = MAGIC;
H_UNLOCK();
return (void *)(hp + 1);
}
qp = hp;
}
H_UNLOCK();
return NULL;
}
#define LIMIT(p) (struct header *)((char *)(p) + \
sizeof(struct header) + \
(p)->h_size)
/**
* @brief Frees a previously allocated memory block.
*
* @param[in] p the memory block pointer
*/
void chHeapFree(void *p) {
struct header *qp, *hp;
chDbgCheck(p != NULL, "chHeapFree");
hp = (struct header *)p - 1;
chDbgAssert(hp->h_magic == MAGIC,
"chHeapFree(), #1",
"it is not magic");
qp = &heap.free;
H_LOCK();
while (TRUE) {
chDbgAssert((hp < qp) || (hp >= LIMIT(qp)),
"chHeapFree(), #2",
"within free block");
if (((qp == &heap.free) || (hp > qp)) &&
((qp->h_next == NULL) || (hp < qp->h_next))) {
/* Insertion after qp */
hp->h_next = qp->h_next;
qp->h_next = hp;
/* Verifies if the newly inserted block should be merged */
if (LIMIT(hp) == hp->h_next) {
/* Merge with the next block */
hp->h_size += hp->h_next->h_size + sizeof(struct header);
hp->h_next = hp->h_next->h_next;
}
if ((LIMIT(qp) == hp)) { /* Cannot happen when qp == &heap.free */
/* Merge with the previous block */
qp->h_size += hp->h_size + sizeof(struct header);
qp->h_next = hp->h_next;
}
H_UNLOCK();
return;
}
qp = qp->h_next;
}
}
/**
* @brief Reports the heap status.
*
* @param[in] sizep pointer to a variable that will receive the total
* fragmented free space
* @return The number of fragments in the heap.
* @note This function is meant to be used in the test suite, it should not be
* really useful for the application code.
* @note This function is not implemented when the @p CH_USE_MALLOC_HEAP
* configuration option is used (it always returns zero).
*/
size_t chHeapStatus(size_t *sizep) {
struct header *qp;
size_t n, sz;
H_LOCK();
sz = 0;
for (n = 0, qp = &heap.free; qp->h_next; n++, qp = qp->h_next)
sz += qp->h_next->h_size;
if (sizep)
*sizep = sz;
H_UNLOCK();
return n;
}
#else /* CH_USE_MALLOC_HEAP */
#include <stdlib.h>
#if CH_USE_MUTEXES
#define H_LOCK() chMtxLock(&hmtx)
#define H_UNLOCK() chMtxLock(&hmtx)
static Mutex hmtx;
#elif CH_USE_SEMAPHORES
#define H_LOCK() chSemWait(&hsem)
#define H_UNLOCK() chSemSignal(&hsem)
static Semaphore hsem;
#else
#error "The heap allocator requires mutexes or semaphores to be enabled"
#endif
void heap_init(void) {
#if CH_USE_MUTEXES
chMtxInit(&hmtx);
#else
chSemInit(&hsem, 1);
#endif
}
void *chHeapAlloc(size_t size) {
void *p;
H_LOCK();
p = malloc(size);
H_UNLOCK();
return p;
}
void chHeapFree(void *p) {
chDbgCheck(p != NULL, "chHeapFree");
H_LOCK();
free(p);
H_UNLOCK();
}
size_t chHeapStatus(size_t *sizep) {
if (sizep)
*sizep = 0;
return 0;
}
#endif /* CH_USE_MALLOC_HEAP */
#endif /* CH_USE_HEAP */
/** @} */

View File

@ -1,111 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chlists.c
* @brief Thread queues/lists code.
* @addtogroup ThreadLists
* @{
*/
#include <ch.h>
#if !CH_OPTIMIZE_SPEED || defined(__DOXYGEN__)
/**
* @brief Inserts a thread into a priority ordered queue.
*
* @param[in] tp the pointer to the thread to be inserted in the list
* @param[in] tqp the pointer to the threads list header
* @note The insertion is done by scanning the list from the highest priority
* toward the lowest.
* @note This function is @b not an API.
*/
void prio_insert(Thread *tp, ThreadsQueue *tqp) {
/* cp iterates over the queue */
Thread *cp = (Thread *)tqp;
do {
/* iterate to next thread in queue */
cp = cp->p_next;
/* not end of queue? and cp has equal or higher priority than tp? */
} while ((cp != (Thread *)tqp) && (cp->p_prio >= tp->p_prio));
/* insert before cp, point tp to next and prev in queue */
tp->p_prev = (tp->p_next = cp)->p_prev;
/* make prev point to tp, and cp point back to tp */
tp->p_prev->p_next = cp->p_prev = tp;
}
/**
* @brief Inserts a Thread into a queue.
*
* @param[in] tp the pointer to the thread to be inserted in the list
* @param[in] tqp the pointer to the threads list header
* @note This function is @b not an API.
*/
void queue_insert(Thread *tp, ThreadsQueue *tqp) {
tp->p_prev = (tp->p_next = (Thread *)tqp)->p_prev;
tp->p_prev->p_next = tqp->p_prev = tp;
}
/**
* @brief Removes the first-out Thread from a queue and returns it.
*
* @param[in] tqp the pointer to the threads list header
* @return The removed thread pointer.
* @note This function is @b not an API.
*/
Thread *fifo_remove(ThreadsQueue *tqp) {
Thread *tp = tqp->p_next;
(tqp->p_next = tp->p_next)->p_prev = (Thread *)tqp;
return tp;
}
/**
* @brief Removes the last-out Thread from a queue and returns it.
*
* @param[in] tqp the pointer to the threads list header
* @return The removed thread pointer.
* @note This function is @b not an API.
*/
Thread *lifo_remove(ThreadsQueue *tqp) {
Thread *tp = tqp->p_next;
(tqp->p_next = tp->p_next)->p_prev = (Thread *)tqp;
return tp;
}
/**
* @brief Removes a Thread from a queue and returns it.
* @details The thread is removed from the queue regardless of its relative
* position and regardless the used insertion method.
*
* @param[in] tp the pointer to the thread to be removed from the queue
* @return The removed thread pointer.
* @note This function is @b not an API.
*/
Thread *dequeue(Thread *tp) {
tp->p_prev->p_next = tp->p_next;
tp->p_next->p_prev = tp->p_prev;
return tp;
}
#endif /* CH_OPTIMIZE_SPEED */
/** @} */

View File

@ -1,244 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chmboxes.c
* @brief Mailboxes code.
* @addtogroup Mailboxes
* @{
*/
#include <ch.h>
#if CH_USE_MAILBOXES
/**
* @brief Initializes a Mailbox object.
*
* @param[out] mbp the pointer to the Mailbox structure to be initialized
* @param[in] buf the circular messages buffer
* @param[in] n the buffer size as number of @p msg_t
*/
void chMBInit(Mailbox *mbp, msg_t *buf, cnt_t n) {
chDbgCheck((mbp != NULL) && (buf != NULL) && (n > 0), "chMBInit");
mbp->mb_buffer = mbp->mb_wrptr = mbp->mb_rdptr = buf;
mbp->mb_top = &buf[n];
chSemInit(&mbp->mb_emptysem, n);
chSemInit(&mbp->mb_fullsem, 0);
}
/**
* @brief Resets a Mailbox object.
* @details All the waiting threads are resumed with status @p RDY_RESET and
* the queued messages are lost.
*
* @param[in] mbp the pointer to an initialized Mailbox object
*/
void chMBReset(Mailbox *mbp) {
chDbgCheck(mbp != NULL, "chMBReset");
chSysLock();
mbp->mb_wrptr = mbp->mb_rdptr = mbp->mb_buffer;
chSemResetI(&mbp->mb_emptysem, mbp->mb_top - mbp->mb_buffer);
chSemResetI(&mbp->mb_fullsem, 0);
chSchRescheduleS();
chSysUnlock();
}
/**
* @brief Posts a message into a mailbox.
* @details The invoking thread waits until a empty slot in the mailbox becomes
* available or the specified time runs out.
*
* @param[in] mbp the pointer to an initialized Mailbox object
* @param[in] msg the message to be posted on the mailbox
* @param[in] time the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval RDY_OK if the message was correctly posted.
* @retval RDY_RESET if the mailbox was reset while waiting.
* @retval RDY_TIMEOUT if the operation timed out.
*/
msg_t chMBPost(Mailbox *mbp, msg_t msg, systime_t time) {
msg_t rdymsg;
chSysLock();
rdymsg = chMBPostS(mbp, msg, time);
chSysUnlock();
return rdymsg;
}
/**
* @brief Posts a message into a mailbox.
* @details The invoking thread waits until a empty slot in the mailbox becomes
* available or the specified time runs out.
*
* @param[in] mbp the pointer to an initialized Mailbox object
* @param[in] msg the message to be posted on the mailbox
* @param[in] time the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval RDY_OK if the message was correctly posted.
* @retval RDY_RESET if the mailbox was reset while waiting.
* @retval RDY_TIMEOUT if the operation timed out.
*/
msg_t chMBPostS(Mailbox *mbp, msg_t msg, systime_t time) {
msg_t rdymsg;
chDbgCheck(mbp != NULL, "chMBPostS");
rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time);
if (rdymsg == RDY_OK) {
*mbp->mb_wrptr++ = msg;
if (mbp->mb_wrptr >= mbp->mb_top)
mbp->mb_wrptr = mbp->mb_buffer;
chSemSignalI(&mbp->mb_fullsem);
chSchRescheduleS();
}
return rdymsg;
}
/**
* @brief Posts an high priority message into a mailbox.
* @details The invoking thread waits until a empty slot in the mailbox becomes
* available or the specified time runs out.
*
* @param[in] mbp the pointer to an initialized Mailbox object
* @param[in] msg the message to be posted on the mailbox
* @param[in] time the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval RDY_OK if the message was correctly posted.
* @retval RDY_RESET if the mailbox was reset while waiting.
* @retval RDY_TIMEOUT if the operation timed out.
*/
msg_t chMBPostAhead(Mailbox *mbp, msg_t msg, systime_t time) {
msg_t rdymsg;
chSysLock();
rdymsg = chMBPostAheadS(mbp, msg, time);
chSysUnlock();
return rdymsg;
}
/**
* @brief Posts an high priority message into a mailbox.
* @details The invoking thread waits until a empty slot in the mailbox becomes
* available or the specified time runs out.
*
* @param[in] mbp the pointer to an initialized Mailbox object
* @param[in] msg the message to be posted on the mailbox
* @param[in] time the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval RDY_OK if the message was correctly posted.
* @retval RDY_RESET if the mailbox was reset while waiting.
* @retval RDY_TIMEOUT if the operation timed out.
*/
msg_t chMBPostAheadS(Mailbox *mbp, msg_t msg, systime_t time) {
msg_t rdymsg;
chDbgCheck(mbp != NULL, "chMBPostAheadS");
rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time);
if (rdymsg == RDY_OK) {
if (--mbp->mb_rdptr < mbp->mb_buffer)
mbp->mb_rdptr = mbp->mb_top - 1;
*mbp->mb_rdptr = msg;
chSemSignalI(&mbp->mb_fullsem);
chSchRescheduleS();
}
return rdymsg;
}
/**
* @brief Retrieves a message from a mailbox.
* @details The invoking thread waits until a message is posted in the mailbox
* or the specified time runs out.
*
* @param[in] mbp the pointer to an initialized Mailbox object
* @param[out] msgp pointer to a message variable for the received message
* @param[in] time the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval RDY_OK if a message was correctly fetched.
* @retval RDY_RESET if the mailbox was reset while waiting.
* @retval RDY_TIMEOUT if the operation timed out.
*/
msg_t chMBFetch(Mailbox *mbp, msg_t *msgp, systime_t time) {
msg_t rdymsg;
chSysLock();
rdymsg = chMBFetchS(mbp, msgp, time);
chSysUnlock();
return rdymsg;
}
/**
* @brief Retrieves a message from a mailbox.
* @details The invoking thread waits until a message is posted in the mailbox
* or the specified time runs out.
*
* @param[in] mbp the pointer to an initialized Mailbox object
* @param[out] msgp pointer to a message variable for the received message
* @param[in] time the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval RDY_OK if a message was correctly fetched.
* @retval RDY_RESET if the mailbox was reset while waiting.
* @retval RDY_TIMEOUT if the operation timed out.
*/
msg_t chMBFetchS(Mailbox *mbp, msg_t *msgp, systime_t time) {
msg_t rdymsg;
chDbgCheck((mbp != NULL) && (msgp != NULL), "chMBFetchS");
rdymsg = chSemWaitTimeoutS(&mbp->mb_fullsem, time);
if (rdymsg == RDY_OK) {
*msgp = *mbp->mb_rdptr++;
if (mbp->mb_rdptr >= mbp->mb_top)
mbp->mb_rdptr = mbp->mb_buffer;
chSemSignalI(&mbp->mb_emptysem);
chSchRescheduleS();
}
return rdymsg;
}
#endif /* CH_USE_MAILBOXES */
/** @} */

View File

@ -1,112 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chmempools.c
* @brief Memory Pools code.
* @addtogroup MemoryPools
* @{
*/
#include <ch.h>
#if CH_USE_MEMPOOLS
/**
* @brief Initializes an empty memory pool.
*
* @param[out] mp pointer to a @p MemoryPool structure
* @param[in] size the size of the objects contained in this memory pool,
* the minimum accepted size is the size of a pointer to void
*/
void chPoolInit(MemoryPool *mp, size_t size) {
chDbgCheck((mp != NULL) && (size >= sizeof(void *)), "chPoolInit");
mp->mp_next = NULL;
mp->mp_object_size = size;
}
/**
* @brief Allocates an object from a memory pool.
*
* @param[in] mp pointer to a @p MemoryPool structure
* @return The pointer to the allocated object.
* @retval NULL if pool is empty.
*/
void *chPoolAllocI(MemoryPool *mp) {
void *objp;
chDbgCheck(mp != NULL, "chPoolAllocI");
if ((objp = mp->mp_next) != NULL)
mp->mp_next = mp->mp_next->ph_next;
return objp;
}
/**
* @brief Allocates an object from a memory pool.
*
* @param[in] mp pointer to a @p MemoryPool structure
* @return The pointer to the allocated object.
* @retval NULL if pool is empty.
*/
void *chPoolAlloc(MemoryPool *mp) {
void *objp;
chSysLock();
objp = chPoolAllocI(mp);
chSysUnlock();
return objp;
}
/**
* @brief Releases (or adds) an object into (to) a memory pool.
*
* @param[in] mp pointer to a @p MemoryPool structure
* @param[in] objp the pointer to the object to be released or added
* @note the object is assumed to be of the right size for the specified
* memory pool.
*/
void chPoolFreeI(MemoryPool *mp, void *objp) {
struct pool_header *php = objp;
chDbgCheck((mp != NULL) && (objp != NULL), "chPoolFreeI");
php->ph_next = mp->mp_next;
mp->mp_next = php;
}
/**
* @brief Releases (or adds) an object into (to) a memory pool.
*
* @param[in] mp pointer to a @p MemoryPool structure
* @param[in] objp the pointer to the object to be released or added
* @note the object is assumed to be of the right size for the specified
* memory pool.
*/
void chPoolFree(MemoryPool *mp, void *objp) {
chSysLock();
chPoolFreeI(mp, objp);
chSysUnlock();
}
#endif /* CH_USE_MEMPOOLS */
/** @} */

View File

@ -1,125 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chmsg.c
* @brief Messages code.
* @addtogroup Messages
* @{
*/
#include <ch.h>
#if CH_USE_MESSAGES
#if CH_USE_MESSAGES_PRIORITY
#define msg_insert(tp, qp) prio_insert(tp, qp)
#else
#define msg_insert(tp, qp) queue_insert(tp, qp)
#endif
/**
* @brief Sends a message to the specified thread.
* @details The sender is stopped until the receiver executes a
* @p chMsgRelease()after receiving the message.
*
* @param[in] tp the pointer to the thread
* @param[in] msg the message
* @return The return message from @p chMsgRelease().
*/
msg_t chMsgSend(Thread *tp, msg_t msg) {
chDbgCheck(tp != NULL, "chMsgSend");
chSysLock();
msg_insert(currp, &tp->p_msgqueue);
currp->p_msg = msg;
currp->p_wtthdp = tp;
if (tp->p_state == PRWTMSG)
chSchReadyI(tp);
chSchGoSleepS(PRSNDMSG);
msg = currp->p_rdymsg;
chSysUnlock();
return msg;
}
/**
* @brief Suspends the thread and waits for an incoming message.
*
* @return The pointer to the message structure. Note, it is always the
* message associated to the thread on the top of the messages queue.
* @note You can assume that the data contained in the message is stable until
* you invoke @p chMsgRelease() because the sending thread is
* suspended until then.
*/
msg_t chMsgWait(void) {
msg_t msg;
chSysLock();
if (!chMsgIsPendingI(currp))
chSchGoSleepS(PRWTMSG);
msg = chMsgGetI(currp);
chSysUnlock();
return msg;
}
/**
* @brief Returns the next message in the queue.
*
* @return The pointer to the message structure. Note, it is always the
* message associated to the thread on the top of the messages queue.
* If the queue is empty then @p NULL is returned.
* @note You can assume that the data pointed by the message is stable until
* you invoke @p chMsgRelease() because the sending thread is
* suspended until then. Always remember that the message data is not
* copied between the sender and the receiver, just a pointer is passed.
*/
msg_t chMsgGet(void) {
msg_t msg;
chSysLock();
msg = chMsgIsPendingI(currp) ? chMsgGetI(currp) : (msg_t)NULL;
chSysUnlock();
return msg;
}
/**
* @brief Releases the thread waiting on top of the messages queue.
*
* @param[in] msg the message returned to the message sender
* @note You can call this function only if there is a message already in the
* queue else the result will be unpredictable (a crash most likely).
* Exiting from the @p chMsgWait() ensures you have at least one
* message in the queue so it is not a big deal.<br>
* The condition is only tested in debug mode in order to make this code
* as fast as possible.
*/
void chMsgRelease(msg_t msg) {
chSysLock();
chDbgAssert(chMsgIsPendingI(currp),
"chMsgRelease(), #1",
"no message pending");
chSchWakeupS(fifo_remove(&currp->p_msgqueue), msg);
chSysUnlock();
}
#endif /* CH_USE_MESSAGES */
/** @} */

View File

@ -1,299 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chmtx.c
* @brief Mutexes code.
* @addtogroup Mutexes
* @{
*/
#include <ch.h>
#if CH_USE_MUTEXES
/**
* @brief Initializes s @p Mutex structure.
*
* @param[out] mp pointer to a @p Mutex structure
* @note This function can be invoked from within an interrupt handler even if
* it is not an I-Class API because it does not touch any critical kernel
* data structure.
*/
void chMtxInit(Mutex *mp) {
chDbgCheck(mp != NULL, "chMtxInit");
queue_init(&mp->m_queue);
mp->m_owner = NULL;
}
/**
* @brief Locks the specified mutex.
*
* @param[in] mp pointer to the @p Mutex structure
*/
void chMtxLock(Mutex *mp) {
chSysLock();
chMtxLockS(mp);
chSysUnlock();
}
/**
* @brief Locks the specified mutex.
*
* @param[in] mp pointer to the @p Mutex structure
* @note This function must be called within a @p chSysLock() / @p chSysUnlock()
* block.
*/
void chMtxLockS(Mutex *mp) {
chDbgCheck(mp != NULL, "chMtxLockS");
/* the mutex is already locked? */
if (mp->m_owner != NULL) {
/*
* Priority inheritance protocol; explores the thread-mutex dependencies
* boosting the priority of all the affected threads to equal the priority
* of the running thread requesting the mutex.
*/
Thread *tp = mp->m_owner;
/* { tp is the thread currently owning the mutex } */
/* the running thread has higher priority than tp? */
while (tp->p_prio < currp->p_prio) {
/* make priority of thread tp match the running thread's priority */
tp->p_prio = currp->p_prio;
/*
* The following states need priority queues reordering.
*/
switch (tp->p_state) {
/* thread tp is waiting on a mutex? */
case PRWTMTX:
/* Requeues tp with its new priority on the mutex wait queue. */
prio_insert(dequeue(tp), &tp->p_wtmtxp->m_queue);
/* boost the owner of this mutex if needed */
tp = tp->p_wtmtxp->m_owner;
continue;
#if CH_USE_CONDVARS
case PRWTCOND:
/* Requeues tp with its new priority on the condvar queue. */
prio_insert(dequeue(tp), &tp->p_wtcondp->c_queue);
break;
#endif
#if CH_USE_SEMAPHORES_PRIORITY
case PRWTSEM:
/* Requeues tp with its new priority on the semaphore queue. */
prio_insert(dequeue(tp), &tp->p_wtsemp->s_queue);
break;
#endif
#if CH_USE_MESSAGES_PRIORITY
case PRSNDMSG:
/* Requeues tp with its new priority on the server thread queue. */
prio_insert(dequeue(tp), &tp->p_wtthdp->p_msgqueue);
break;
#endif
/* thread tp is ready? */
case PRREADY:
/* Requeue tp with its new priority on the ready list. */
chSchReadyI(dequeue(tp));
}
break;
}
/* sleep on the mutex */
prio_insert(currp, &mp->m_queue);
/* thread remembers the mutex where it is waiting on */
currp->p_wtmtxp = mp;
chSchGoSleepS(PRWTMTX);
chDbgAssert(mp->m_owner == NULL, "chMtxLockS(), #1", "still owned");
}
/*
* The mutex is now inserted in the owned mutexes list.
*/
mp->m_owner = currp;
mp->m_next = currp->p_mtxlist;
currp->p_mtxlist = mp;
}
/**
* @brief Tries to lock a mutex.
* @details This function does not have any overhead related to
* the priority inheritance mechanism because it does not try to
* enter a sleep state on the mutex.
*
* @param[in] mp pointer to the @p Mutex structure
* @retval TRUE if the mutex was successfully acquired
* @retval FALSE if the lock attempt failed.
*/
bool_t chMtxTryLock(Mutex *mp) {
bool_t b;
chSysLock();
b = chMtxTryLockS(mp);
chSysUnlock();
return b;
}
/**
* @brief Tries to lock a mutex.
* @details This function does not have any overhead related to
* the priority inheritance mechanism because it does not try to
* enter a sleep state on the mutex.
* @param[in] mp pointer to the @p Mutex structure
* @retval TRUE if the mutex was successfully acquired
* @retval FALSE if the lock attempt failed.
* @note This function must be called within a @p chSysLock() / @p chSysUnlock()
* block.
*/
bool_t chMtxTryLockS(Mutex *mp) {
chDbgCheck(mp != NULL, "chMtxTryLockS");
if (mp->m_owner != NULL)
return FALSE;
mp->m_owner = currp;
mp->m_next = currp->p_mtxlist;
currp->p_mtxlist = mp;
return TRUE;
}
/**
* @brief Unlocks the next owned mutex in reverse lock order.
*
* @return The pointer to the unlocked mutex.
*/
Mutex *chMtxUnlock(void) {
Mutex *ump, *mp;
chSysLock();
chDbgAssert(currp->p_mtxlist != NULL,
"chMtxUnlock(), #1",
"owned mutexes list empty");
chDbgAssert(currp->p_mtxlist->m_owner == currp,
"chMtxUnlock(), #2",
"ownership failure");
/* remove the top Mutex from the Threads's owned mutexes list */
ump = currp->p_mtxlist;
currp->p_mtxlist = ump->m_next;
/* mark the Mutex as not owned */
ump->m_owner = NULL;
/*
* If a thread is waiting on the mutex then the hard part begins.
*/
if (chMtxQueueNotEmptyS(ump)) {
/* get the highest priority thread waiting for the unlocked mutex */
Thread *tp = fifo_remove(&ump->m_queue);
/*
* Recalculates the optimal thread priority by scanning the owned mutexes list.
*/
tprio_t newprio = currp->p_realprio;
/* iterate mp over all the (other) mutexes the current thread still owns */
mp = currp->p_mtxlist;
while (mp != NULL) {
/* mutex mp has a higher priority thread pending? */
if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
/* boost current thread's priority to waiting thread */
newprio = mp->m_queue.p_next->p_prio;
mp = mp->m_next;
}
/* (possibly) boost the priority of the current thread */
currp->p_prio = newprio;
/* awaken the highest priority thread waiting for the unlocked mutex */
chSchWakeupS(tp, RDY_OK);
}
chSysUnlock();
return ump;
}
/**
* @brief Unlocks the next owned mutex in reverse lock order.
*
* @return The pointer to the unlocked mutex.
* @note This function must be called within a @p chSysLock() / @p chSysUnlock()
* block.
* @note This function does not reschedule internally.
*/
Mutex *chMtxUnlockS(void) {
Mutex *ump, *mp;
chDbgAssert(currp->p_mtxlist != NULL,
"chMtxUnlockS(), #1",
"owned mutexes list empty");
chDbgAssert(currp->p_mtxlist->m_owner == currp,
"chMtxUnlockS(), #2",
"ownership failure");
/*
* Removes the top Mutex from the owned mutexes list and marks it as not owned.
*/
ump = currp->p_mtxlist;
currp->p_mtxlist = ump->m_next;
ump->m_owner = NULL;
/*
* If a thread is waiting on the mutex then the hard part begins.
*/
if (chMtxQueueNotEmptyS(ump)) {
Thread *tp = fifo_remove(&ump->m_queue);
/*
* Recalculates the optimal thread priority by scanning the owned mutexes list.
*/
tprio_t newprio = currp->p_realprio;
mp = currp->p_mtxlist;
while (mp != NULL) {
if (chMtxQueueNotEmptyS(mp) && (mp->m_queue.p_next->p_prio > newprio))
newprio = mp->m_queue.p_next->p_prio;
mp = mp->m_next;
}
currp->p_prio = newprio;
chSchReadyI(tp);
}
return ump;
}
/**
* @brief Unlocks all the mutexes owned by the invoking thread.
* @details This function is <b>MUCH MORE</b> efficient than releasing the
* mutexes one by one and not just because the call overhead,
* this function does not have any overhead related to the priority
* inheritance mechanism.
*/
void chMtxUnlockAll(void) {
chSysLock();
if (currp->p_mtxlist != NULL) {
do {
Mutex *mp = currp->p_mtxlist;
currp->p_mtxlist = mp->m_next;
mp->m_owner = NULL;
if (chMtxQueueNotEmptyS(mp))
chSchReadyI(fifo_remove(&mp->m_queue));
} while (currp->p_mtxlist != NULL);
currp->p_prio = currp->p_realprio;
chSchRescheduleS();
}
chSysUnlock();
}
#endif /* CH_USE_MUTEXES */
/** @} */

View File

@ -1,304 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chqueues.c
* @brief I/O Queues code.
* @addtogroup IOQueues
* @{
*/
#include <ch.h>
#if CH_USE_QUEUES
/**
* @brief Initializes an input queue.
* @details A Semaphore is internally initialized and works as a counter of
* the bytes contained in the queue.
*
* @param[out] iqp pointer to an @p InputQueue structure
* @param[in] buffer pointer to a memory area allocated as queue buffer
* @param[in] size size of the queue buffer
* @param[in] inotify pointer to a callback function that is invoked when
* some data is read from the queue. The value can be
* @p NULL.
*
* @note The callback is invoked from within the S-Locked system state,
* see @ref system_states.
*/
void chIQInit(InputQueue *iqp, uint8_t *buffer,
size_t size, qnotify_t inotify) {
iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = buffer;
iqp->q_top = buffer + size;
chSemInit(&iqp->q_sem, 0);
iqp->q_notify = inotify;
}
/**
* @brief Resets an input queue.
* @details All the data in the input queue is erased and lost, any waiting
* thread is resumed with status @p Q_RESET.
*
* @param[in] iqp pointer to an @p InputQueue structure
*
* @note A reset operation can be used by a low level driver in order to obtain
* immediate attention from the high level layers.
*/
void chIQResetI(InputQueue *iqp) {
iqp->q_rdptr = iqp->q_wrptr = iqp->q_buffer;
chSemResetI(&iqp->q_sem, 0);
}
/**
* @brief Input queue write.
* @details A byte value is written into the low end of an input queue.
*
* @param[in] iqp pointer to an @p InputQueue structure
* @param[in] b the byte value to be written in the queue
* @return The operation status, it can be one of:
* @retval Q_OK if the operation has been completed with success.
* @retval Q_FULL if the queue is full and the operation cannot be completed.
*/
msg_t chIQPutI(InputQueue *iqp, uint8_t b) {
if (chIQIsFull(iqp))
return Q_FULL;
*iqp->q_wrptr++ = b;
if (iqp->q_wrptr >= iqp->q_top)
iqp->q_wrptr = iqp->q_buffer;
chSemSignalI(&iqp->q_sem);
return Q_OK;
}
/**
* @brief Input queue read with timeout.
* @details This function reads a byte value from an input queue. If the queue
* is empty then the calling thread is suspended until a byte arrives
* in the queue or a timeout occurs.
*
* @param[in] iqp pointer to an @p InputQueue structure
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return A byte value from the queue or:
* @retval Q_TIMEOUT if the specified time expired.
* @retval Q_RESET if the queue was reset.
*/
msg_t chIQGetTimeout(InputQueue *iqp, systime_t timeout) {
uint8_t b;
msg_t msg;
chSysLock();
if ((msg = chSemWaitTimeoutS(&iqp->q_sem, timeout)) < RDY_OK) {
chSysUnlock();
return msg;
}
b = *iqp->q_rdptr++;
if (iqp->q_rdptr >= iqp->q_top)
iqp->q_rdptr = iqp->q_buffer;
if (iqp->q_notify)
iqp->q_notify();
chSysUnlock();
return b;
}
/**
* @brief Non-blocking read.
* @details The function reads data from an input queue into a buffer. The
* transfer is non-blocking and can return zero if the queue is
* empty.
*
* @param[in] iqp pointer to an @p InputQueue structure
* @param[out] buffer pointer to the buffer where the input data is copied
* @param[in] n the maximum amount of data to be transferred
* @return The number of bytes transferred.
*
* @note The function is not atomic, if you need atomicity it is suggested
* to use a semaphore or a mutex for mutual exclusion.
*/
size_t chIQRead(InputQueue *iqp, uint8_t *buffer, size_t n) {
size_t r = 0;
while (n--) {
chSysLock();
if (chIQIsEmpty(iqp)) {
chSysUnlock();
break;
}
chSemFastWaitI(&iqp->q_sem);
*buffer++ = *iqp->q_rdptr++;
if (iqp->q_rdptr >= iqp->q_top)
iqp->q_rdptr = iqp->q_buffer;
chSysUnlock();
r++;
}
if (r && iqp->q_notify) {
chSysLock();
iqp->q_notify();
chSysUnlock();
}
return r;
}
/**
* @brief Initializes an output queue.
* @details A Semaphore is internally initialized and works as a counter of
* the free bytes in the queue.
*
* @param[out] oqp pointer to an @p OutputQueue structure
* @param[in] buffer pointer to a memory area allocated as queue buffer
* @param[in] size size of the queue buffer
* @param[in] onotify pointer to a callback function that is invoked when
* some data is written to the queue. The value can be
* @p NULL.
*
* @note The callback is invoked from within the S-Locked system state,
* see @ref system_states.
*/
void chOQInit(OutputQueue *oqp, uint8_t *buffer,
size_t size, qnotify_t onotify) {
oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = buffer;
oqp->q_top = buffer + size;
chSemInit(&oqp->q_sem, size);
oqp->q_notify = onotify;
}
/**
* @brief Resets an output queue.
* @details All the data in the output queue is erased and lost, any waiting
* thread is resumed with status @p Q_RESET.
*
* @param[in] oqp pointer to an @p OutputQueue structure
*
* @note A reset operation can be used by a low level driver in order to obtain
* immediate attention from the high level layers.
*/
void chOQResetI(OutputQueue *oqp) {
oqp->q_rdptr = oqp->q_wrptr = oqp->q_buffer;
chSemResetI(&oqp->q_sem, (cnt_t)(oqp->q_top - oqp->q_buffer));
}
/**
* @brief Output queue write with timeout.
* @details This function writes a byte value to an output queue. If the queue
* is full then the calling thread is suspended until there is space
* in the queue or a timeout occurs.
*
* @param[in] oqp pointer to an @p OutputQueue structure
* @param[in] b the byte value to be written in the queue
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status:
* @retval Q_OK if the operation succeeded.
* @retval Q_TIMEOUT if the specified time expired.
* @retval Q_RESET if the queue was reset.
*/
msg_t chOQPutTimeout(OutputQueue *oqp, uint8_t b, systime_t timeout) {
msg_t msg;
chSysLock();
if ((msg = chSemWaitTimeoutS(&oqp->q_sem, timeout)) < RDY_OK) {
chSysUnlock();
return msg;
}
*oqp->q_wrptr++ = b;
if (oqp->q_wrptr >= oqp->q_top)
oqp->q_wrptr = oqp->q_buffer;
if (oqp->q_notify)
oqp->q_notify();
chSysUnlock();
return Q_OK;
}
/**
* @brief Output queue read.
* @details A byte value is read from the low end of an output queue.
*
* @param[in] oqp pointer to an @p OutputQueue structure
* @return The byte value from the queue or:
* @retval Q_EMPTY if the queue is empty.
*/
msg_t chOQGetI(OutputQueue *oqp) {
uint8_t b;
if (chOQIsEmpty(oqp))
return Q_EMPTY;
b = *oqp->q_rdptr++;
if (oqp->q_rdptr >= oqp->q_top)
oqp->q_rdptr = oqp->q_buffer;
chSemSignalI(&oqp->q_sem);
return b;
}
/**
* @brief Non-blocking write.
* @details The function writes data from a buffer to an output queue. The
* transfer is non-blocking and can return zero if the queue is
* already full.
*
* @param[in] oqp pointer to an @p OutputQueue structure
* @param[out] buffer pointer to the buffer where the output data is stored
* @param[in] n the maximum amount of data to be transferred
* @return The number of bytes transferred.
*
* @note The function is not atomic, if you need atomicity it is suggested
* to use a semaphore or a mutex for mutual exclusion.
*/
size_t chOQWrite(OutputQueue *oqp, uint8_t *buffer, size_t n) {
size_t w = 0;
while (n--) {
chSysLock();
if (chOQIsFull(oqp)) {
chSysUnlock();
break;
}
chSemFastWaitI(&oqp->q_sem);
*oqp->q_wrptr++ = *buffer++;
if (oqp->q_wrptr >= oqp->q_top)
oqp->q_wrptr = oqp->q_buffer;
chSysUnlock();
w++;
}
if (w && oqp->q_notify) {
chSysLock();
oqp->q_notify();
chSysUnlock();
}
return w;
}
#endif /* CH_USE_QUEUES */
/** @} */

View File

@ -1,242 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chschd.c
* @brief Scheduler code.
* @addtogroup Scheduler
* @{
*/
#include <ch.h>
/** @cond never */
ReadyList rlist;
/** @endcond */
/**
* @brief Scheduler initialization.
*
* @note Internally invoked by the @p chSysInit().
*/
void scheduler_init(void) {
queue_init(&rlist);
rlist.r_prio = NOPRIO;
#if CH_USE_ROUNDROBIN
rlist.r_preempt = CH_TIME_QUANTUM;
#endif
}
/**
* @brief Inserts a thread in the Ready List.
*
* @param[in] tp the Thread to be made ready
* @return The Thread pointer.
* @note The function does not reschedule, the @p chSchRescheduleS() should
* be called soon after.
*/
#if CH_OPTIMIZE_SPEED
/* NOTE: it is inlined in this module only.*/
INLINE Thread *chSchReadyI(Thread *tp) {
#else
Thread *chSchReadyI(Thread *tp) {
#endif
Thread *cp;
tp->p_state = PRREADY;
cp = (Thread *)&rlist;
do {
cp = cp->p_next;
} while (cp->p_prio >= tp->p_prio);
/* Insertion on p_prev.*/
tp->p_prev = (tp->p_next = cp)->p_prev;
tp->p_prev->p_next = cp->p_prev = tp;
return tp;
}
/**
* @brief Puts the current thread to sleep into the specified state.
* @details The thread goes into a sleeping state. The @ref thread_states are
* described into @p threads.h.
*
* @param[in] newstate the new thread state
*/
void chSchGoSleepS(tstate_t newstate) {
Thread *otp;
(otp = currp)->p_state = newstate;
(currp = fifo_remove((void *)&rlist))->p_state = PRCURR;
#if CH_USE_ROUNDROBIN
rlist.r_preempt = CH_TIME_QUANTUM;
#endif
chDbgTrace(otp, currp);
chSysSwitchI(otp, currp);
}
/*
* Timeout wakeup callback.
*/
static void wakeup(void *p) {
Thread *tp = (Thread *)p;
#if CH_USE_SEMAPHORES || CH_USE_MUTEXES || CH_USE_CONDVARS
switch (tp->p_state) {
#if CH_USE_SEMAPHORES
case PRWTSEM:
chSemFastSignalI(tp->p_wtsemp);
/* Falls into, intentional. */
#endif
#if CH_USE_MUTEXES
case PRWTMTX:
#endif
#if CH_USE_CONDVARS
case PRWTCOND:
#endif
/* States requiring dequeuing. */
dequeue(tp);
}
#endif
chSchReadyI(tp)->p_rdymsg = RDY_TIMEOUT;
}
/**
* @brief Puts the current thread to sleep into the specified state with
* timeout specification.
* @details The thread goes into a sleeping state, if it is not awakened
* explicitly within the specified timeout then it is forcibly
* awakened with a @p RDY_TIMEOUT low level message. The @ref
* thread_states are described into @p threads.h.
*
* @param[in] newstate the new thread state
* @param[in] time the number of ticks before the operation timeouts, the
* special values are handled as follow:
* - @a TIME_INFINITE the thread enters an infinite sleep
* state, this is equivalent to invoking @p chSchGoSleepS()
* but, of course, less efficient.
* - @a TIME_IMMEDIATE this value is accepted but interpreted
* as a normal time specification not as an immediate timeout
* specification.
* .
* @return The wakeup message.
* @retval RDY_TIMEOUT if a timeout occurs.
*/
msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time) {
if (TIME_INFINITE != time) {
VirtualTimer vt;
chVTSetI(&vt, time, wakeup, currp);
chSchGoSleepS(newstate);
if (chVTIsArmedI(&vt))
chVTResetI(&vt);
}
else
chSchGoSleepS(newstate);
return currp->p_rdymsg;
}
/**
* @brief Wakes up a thread.
* @details The thread is inserted into the ready list or immediately made
* running depending on its relative priority compared to the current
* thread.
*
* @param[in] ntp the Thread to be made ready
* @param[in] msg message to the awakened thread
* @note It is equivalent to a @p chSchReadyI() followed by a
* @p chSchRescheduleS() but much more efficient.
*/
void chSchWakeupS(Thread *ntp, msg_t msg) {
ntp->p_rdymsg = msg;
/* If the waken thread has a not-greater priority than the current
* one then it is just inserted in the ready list else it made
* running immediately and the invoking thread goes in the ready
* list instead.*/
if (ntp->p_prio <= currp->p_prio)
chSchReadyI(ntp);
else {
Thread *otp = currp;
chSchReadyI(otp);
(currp = ntp)->p_state = PRCURR;
#if CH_USE_ROUNDROBIN
rlist.r_preempt = CH_TIME_QUANTUM;
#endif
chDbgTrace(otp, ntp);
chSysSwitchI(otp, ntp);
}
}
/**
* @brief Switches to the first thread on the runnable queue.
*
* @note It is intended to be called if @p chSchRescRequiredI() evaluates to
* @p TRUE.
*/
void chSchDoRescheduleI(void) {
Thread *otp = currp;
/* pick the first thread from the ready queue and makes it current */
(currp = fifo_remove((void *)&rlist))->p_state = PRCURR;
chSchReadyI(otp);
#if CH_USE_ROUNDROBIN
rlist.r_preempt = CH_TIME_QUANTUM;
#endif
chDbgTrace(otp, currp);
chSysSwitchI(otp, currp);
}
/**
* @brief Performs a reschedulation if a higher priority thread is runnable.
* @details If a thread with a higher priority than the current thread is in
* the ready list then make the higher priority thread running.
*/
void chSchRescheduleS(void) {
/* first thread in the runnable queue has higher priority than the running
* thread? */
if (firstprio(&rlist) > currp->p_prio)
chSchDoRescheduleI();
}
/**
* @brief Evaluates if a reschedulation is required.
* @details The decision is taken by comparing the relative priorities and
* depending on the state of the round robin timeout counter.
*
* @retval TRUE if there is a thread that should go in running state.
* @retval FALSE if a reschedulation is not required.
*/
bool_t chSchRescRequiredI(void) {
tprio_t p1 = firstprio(&rlist);
tprio_t p2 = currp->p_prio;
#if CH_USE_ROUNDROBIN
/* If the running thread has not reached its time quantum, reschedule only
* if the first thread on the ready queue has a higher priority.
* Otherwise, if the running thread has used up its time quantum, reschedule
* if the first thread on the ready queue has equal or higher priority.*/
return rlist.r_preempt ? p1 > p2 : p1 >= p2;
#else
/* If the round robin feature is not enabled then performs a simpler
* comparison.*/
return p1 > p2;
#endif
}
/** @} */

View File

@ -1,257 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chsem.c
* @brief Semaphores code.
* @addtogroup Semaphores
* @{
*/
#include <ch.h>
#if CH_USE_SEMAPHORES
#if CH_USE_SEMAPHORES_PRIORITY
#define sem_insert(tp, qp) prio_insert(tp, qp)
#else
#define sem_insert(tp, qp) queue_insert(tp, qp)
#endif
/**
* @brief Initializes a semaphore with the specified counter value.
*
* @param[out] sp pointer to a @p Semaphore structure
* @param[in] n initial value of the semaphore counter. Must be non-negative.
* @note This function can be invoked from within an interrupt handler even if
* it is not an I-Class API because it does not touch any critical kernel
* data structure.
*/
void chSemInit(Semaphore *sp, cnt_t n) {
chDbgCheck((sp != NULL) && (n >= 0), "chSemInit");
queue_init(&sp->s_queue);
sp->s_cnt = n;
}
/**
* @brief Performs a reset operation on the semaphore.
*
* @param[in] sp pointer to a @p Semaphore structure
* @param[in] n the new value of the semaphore counter. The value must be non-negative.
* @note The released threads can recognize they were waked up by a reset
* instead than a signal because the @p chSemWait() will return
* @p RDY_RESET instead of @p RDY_OK.
*/
void chSemReset(Semaphore *sp, cnt_t n) {
chSysLock();
chSemResetI(sp, n);
chSchRescheduleS();
chSysUnlock();
}
/**
* @brief Performs a reset operation on the semaphore.
*
* @param[in] sp pointer to a @p Semaphore structure
* @param[in] n the new value of the semaphore counter. The value must be non-negative.
* @note The released threads can recognize they were waked up by a reset
* instead than a signal because the @p chSemWait() will return
* @p RDY_RESET instead of @p RDY_OK.
* @note This function does not reschedule.
*/
void chSemResetI(Semaphore *sp, cnt_t n) {
cnt_t cnt;
chDbgCheck((sp != NULL) && (n >= 0), "chSemResetI");
cnt = sp->s_cnt;
sp->s_cnt = n;
while (cnt++ < 0)
chSchReadyI(lifo_remove(&sp->s_queue))->p_rdymsg = RDY_RESET;
}
/**
* @brief Performs a wait operation on a semaphore.
*
* @param[in] sp pointer to a @p Semaphore structure
* @retval RDY_OK if the semaphore was signaled or not taken.
* @retval RDY_RESET if the semaphore was reset using @p chSemReset().
*/
msg_t chSemWait(Semaphore *sp) {
msg_t msg;
chSysLock();
msg = chSemWaitS(sp);
chSysUnlock();
return msg;
}
/**
* @brief Performs a wait operation on a semaphore.
*
* @param[in] sp pointer to a @p Semaphore structure
* @retval RDY_OK if the semaphore was signaled or not taken.
* @retval RDY_RESET if the semaphore was reset using @p chSemReset().
* @note This function must be called with interrupts disabled.
* @note This function cannot be called by an interrupt handler.
*/
msg_t chSemWaitS(Semaphore *sp) {
chDbgCheck(sp != NULL, "chSemWaitS");
if (--sp->s_cnt < 0) {
sem_insert(currp, &sp->s_queue);
currp->p_wtsemp = sp;
chSchGoSleepS(PRWTSEM);
return currp->p_rdymsg;
}
return RDY_OK;
}
/**
* @brief Performs a wait operation on a semaphore with timeout specification.
*
* @param[in] sp pointer to a @p Semaphore structure
* @param[in] time the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @retval RDY_OK if the semaphore was signaled or not taken.
* @retval RDY_RESET if the semaphore was reset using @p chSemReset().
* @retval RDY_TIMEOUT if the semaphore was not signaled or reset within the
* specified timeout.
*/
msg_t chSemWaitTimeout(Semaphore *sp, systime_t time) {
msg_t msg;
chSysLock();
msg = chSemWaitTimeoutS(sp, time);
chSysUnlock();
return msg;
}
/**
* @brief Performs a wait operation on a semaphore with timeout specification.
*
* @param[in] sp pointer to a @p Semaphore structure
* @param[in] time the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @retval RDY_OK if the semaphore was signaled or not taken.
* @retval RDY_RESET if the semaphore was reset using @p chSemReset().
* @retval RDY_TIMEOUT if the semaphore was not signaled or reset within the specified
* timeout.
*/
msg_t chSemWaitTimeoutS(Semaphore *sp, systime_t time) {
chDbgCheck(sp != NULL, "chSemWaitTimeoutS");
if (--sp->s_cnt < 0) {
if (TIME_IMMEDIATE == time) {
sp->s_cnt++;
return RDY_TIMEOUT;
}
sem_insert(currp, &sp->s_queue);
currp->p_wtsemp = sp;
return chSchGoSleepTimeoutS(PRWTSEM, time);
}
return RDY_OK;
}
/**
* @brief Performs a signal operation on a semaphore.
*
* @param[in] sp pointer to a @p Semaphore structure
* @note The function is available only if the @p CH_USE_SEMAPHORES
* option is enabled in @p chconf.h.
*/
void chSemSignal(Semaphore *sp) {
chDbgCheck(sp != NULL, "chSemSignal");
chSysLock();
if (sp->s_cnt++ < 0)
chSchWakeupS(fifo_remove(&sp->s_queue), RDY_OK);
chSysUnlock();
}
/**
* @brief Performs a signal operation on a semaphore.
*
* @param[in] sp pointer to a @p Semaphore structure
* @note The function is available only if the @p CH_USE_SEMAPHORES
* option is enabled in @p chconf.h.
* @note This function does not reschedule.
*/
void chSemSignalI(Semaphore *sp) {
chDbgCheck(sp != NULL, "chSemSignalI");
if (sp->s_cnt++ < 0) {
/* NOTE: It is done this way in order to allow a tail call on
chSchReadyI().*/
Thread *tp = fifo_remove(&sp->s_queue);
tp->p_rdymsg = RDY_OK;
chSchReadyI(tp);
}
}
#if CH_USE_SEMSW
/**
* @brief Performs atomic signal and wait operations on two semaphores.
*
* @param[in] sps pointer to a @p Semaphore structure to be signaled
* @param[in] spw pointer to a @p Semaphore structure to be wait on
* @retval RDY_OK if the semaphore was signaled or not taken.
* @retval RDY_RESET if the semaphore was reset using @p chSemReset().
* @note The function is available only if the @p CH_USE_SEMSW
* option is enabled in @p chconf.h.
*/
msg_t chSemSignalWait(Semaphore *sps, Semaphore *spw) {
msg_t msg;
chDbgCheck((sps != NULL) && (spw != NULL), "chSemSignalWait");
chSysLock();
if (sps->s_cnt++ < 0)
chSchReadyI(fifo_remove(&sps->s_queue))->p_rdymsg = RDY_OK;
if (--spw->s_cnt < 0) {
sem_insert(currp, &spw->s_queue);
currp->p_wtsemp = spw;
chSchGoSleepS(PRWTSEM);
msg = currp->p_rdymsg;
}
else {
chSchRescheduleS();
msg = RDY_OK;
}
chSysUnlock();
return msg;
}
#endif /* CH_USE_SEMSW */
#endif /* CH_USE_SEMAPHORES */
/** @} */

View File

@ -1,168 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chserial.c
* @brief Serial Drivers code.
* @addtogroup Serial
* @{
*/
#include <ch.h>
#if CH_USE_SERIAL_FULLDUPLEX
/*
* Interface implementation, the following functions just invoke the equivalent
* queue-level function or macro.
*/
static bool_t putwouldblock(void *instance) {
return chOQIsFull(&((FullDuplexDriver *)instance)->d2.oqueue);
}
static bool_t getwouldblock(void *instance) {
return chIQIsEmpty(&((FullDuplexDriver *)instance)->d2.iqueue);
}
static msg_t put(void *instance, uint8_t b, systime_t timeout) {
return chOQPutTimeout(&((FullDuplexDriver *)instance)->d2.oqueue, b, timeout);
}
static msg_t get(void *instance, systime_t timeout) {
return chIQGetTimeout(&((FullDuplexDriver *)instance)->d2.iqueue, timeout);
}
static size_t write(void *instance, uint8_t *buffer, size_t n) {
return chOQWrite(&((FullDuplexDriver *)instance)->d2.oqueue, buffer, n);
}
static size_t read(void *instance, uint8_t *buffer, size_t n) {
return chIQRead(&((FullDuplexDriver *)instance)->d2.iqueue, buffer, n);
}
static const struct FullDuplexDriverVMT vmt = {
{putwouldblock, getwouldblock, put, get},
{write, read},
{}
};
/**
* @brief Initializes a generic full duplex driver.
* @details The HW dependent part of the initialization has to be performed
* outside, usually in the hardware initialization code.
*
* @param[out] sd pointer to a @p FullDuplexDriver structure
* @param[in] ib pointer to a memory area allocated for the Input Queue buffer
* @param[in] isize size of the Input Queue buffer
* @param[in] inotify pointer to a callback function that is invoked when
* some data is read from the Queue. The value can be
* @p NULL.
* @param[in] ob pointer to a memory area allocated for the Output Queue buffer
* @param[in] osize size of the Output Queue buffer
* @param[in] onotify pointer to a callback function that is invoked when
* some data is written in the Queue. The value can be
* @p NULL.
*/
void chFDDInit(FullDuplexDriver *sd,
uint8_t *ib, size_t isize, qnotify_t inotify,
uint8_t *ob, size_t osize, qnotify_t onotify) {
chDbgCheck((sd != NULL) && (ib != NULL) && (ob != NULL) &&
(isize > 0) && (osize > 0), "chFDDInit");
sd->vmt = &vmt;
chEvtInit(&sd->d1.ievent);
chEvtInit(&sd->d1.oevent);
chEvtInit(&sd->d2.sevent);
sd->d2.flags = SD_NO_ERROR;
chIQInit(&sd->d2.iqueue, ib, isize, inotify);
chOQInit(&sd->d2.oqueue, ob, osize, onotify);
}
/**
* @brief Handles incoming data.
* @details This function must be called from the input interrupt service
* routine in order to enqueue incoming data and generate the
* related events.
* @param[in] sd pointer to a @p FullDuplexDriver structure
* @param[in] b the byte to be written in the driver's Input Queue
*/
void chFDDIncomingDataI(FullDuplexDriver *sd, uint8_t b) {
if (chIQPutI(&sd->d2.iqueue, b) < Q_OK)
chFDDAddFlagsI(sd, SD_OVERRUN_ERROR);
else
chEvtBroadcastI(&sd->d1.ievent);
}
/**
* @brief Handles outgoing data.
* @details Must be called from the output interrupt service routine in order
* to get the next byte to be transmitted.
*
* @param[in] sd pointer to a @p FullDuplexDriver structure
* @return The byte value read from the driver's output queue.
* @retval Q_EMPTY if the queue is empty (the lower driver usually disables
* the interrupt source when this happens).
*/
msg_t chFDDRequestDataI(FullDuplexDriver *sd) {
msg_t b = chOQGetI(&sd->d2.oqueue);
if (b < Q_OK)
chEvtBroadcastI(&sd->d1.oevent);
return b;
}
/**
* @brief Handles communication events/errors.
* @details Must be called from the I/O interrupt service routine in order to
* notify I/O conditions as errors, signals change etc.
*
* @param[in] sd pointer to a @p FullDuplexDriver structure
* @param[in] mask condition flags to be added to the mask
*/
void chFDDAddFlagsI(FullDuplexDriver *sd, dflags_t mask) {
sd->d2.flags |= mask;
chEvtBroadcastI(&sd->d2.sevent);
}
/**
* @brief Returns and clears the errors mask associated to the driver.
*
* @param[in] sd pointer to a @p FullDuplexDriver structure
* @return The condition flags modified since last time this function was
* invoked.
*/
dflags_t chFDDGetAndClearFlags(FullDuplexDriver *sd) {
dflags_t mask;
mask = sd->d2.flags;
sd->d2.flags = SD_NO_ERROR;
return mask;
}
#endif /* CH_USE_SERIAL_FULLDUPLEX */
/** @} */

View File

@ -1,129 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chsys.c
* @brief System related code.
* @addtogroup System
* @{
*/
#include <ch.h>
static WORKING_AREA(idle_thread_wa, IDLE_THREAD_STACK_SIZE);
/**
* @brief This function implements the idle thread infinite loop.
* @details The function puts the processor in the lowest power mode capable
* to serve interrupts.<br>
* The priority is internally set to the minimum system value so
* that this thread is executed only if there are no other ready
* threads in the system.
*
* @param[in] p the thread parameter, unused in this scenario
*/
static void idle_thread(void *p) {
while (TRUE) {
port_wait_for_interrupt();
IDLE_LOOP_HOOK();
}
}
/**
* @brief ChibiOS/RT initialization.
* @details After executing this function the current instructions stream
* becomes the main thread.
*
* @note Interrupts should be still disabled when @p chSysInit() is invoked
* and are internally enabled.
* @note The main thread is created with priority @p NORMALPRIO.
*/
void chSysInit(void) {
static Thread mainthread;
port_init();
scheduler_init();
vt_init();
#if CH_USE_HEAP
heap_init();
#endif
#if CH_DBG_ENABLE_TRACE
trace_init();
#endif
/*
* Now this instructions flow becomes the main thread.
*/
(currp = init_thread(&mainthread, NORMALPRIO))->p_state = PRCURR;
chSysEnable();
/*
* This thread has the lowest priority in the system, its role is just to
* serve interrupts in its context while keeping the lowest energy saving
* mode compatible with the system status.
*/
chThdCreateStatic(idle_thread_wa, sizeof(idle_thread_wa), IDLEPRIO,
(tfunc_t)idle_thread, NULL);
}
/**
* @brief Handles time ticks for round robin preemption and timer increments.
* @details Decrements the remaining time quantum of the running thread
* and preempts it when the quantum is used up. Increments system
* time and manages the timers.
*
* @note The frequency of the timer determines the system tick granularity and,
* together with the @p CH_TIME_QUANTUM macro, the round robin interval.
*/
void chSysTimerHandlerI(void) {
#if CH_USE_ROUNDROBIN
/* running thread has not used up quantum yet? */
if (rlist.r_preempt > 0)
/* decrement remaining quantum */
rlist.r_preempt--;
#endif
#if CH_DBG_THREADS_PROFILING
currp->p_time++;
#endif
chVTDoTickI();
}
#if CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED
void chSysLock(void) {
chDbgAssert(currp->p_locks >= 0,
"chSysLock(), #1",
"negative nesting counter");
if (currp->p_locks++ == 0)
port_lock();
}
void chSysUnlock(void) {
chDbgAssert(currp->p_locks > 0,
"chSysUnlock(), #1",
"non-positive nesting counter");
if (--currp->p_locks == 0)
port_unlock();
}
#endif /* CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED */
/** @} */

View File

@ -1,381 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chthreads.c
* @brief Threads code.
* @addtogroup Threads
* @{
*/
#include <ch.h>
/*
* Initializes a thread structure.
*/
Thread *init_thread(Thread *tp, tprio_t prio) {
tp->p_flags = P_MEM_MODE_STATIC;
tp->p_prio = prio;
tp->p_state = PRSUSPENDED;
#if CH_USE_NESTED_LOCKS
tp->p_locks = 0;
#endif
#if CH_DBG_THREADS_PROFILING
tp->p_time = 0;
#endif
#if CH_USE_MUTEXES
/* realprio is the thread's own, non-inherited, priority */
tp->p_realprio = prio;
tp->p_mtxlist = NULL;
#endif
#if CH_USE_WAITEXIT
tp->p_waiting = NULL;
#endif
#if CH_USE_MESSAGES
queue_init(&tp->p_msgqueue);
#endif
#if CH_USE_EVENTS
tp->p_epending = 0;
#endif
THREAD_EXT_INIT(tp);
return tp;
}
#if CH_DBG_FILL_THREADS
static void memfill(uint8_t *startp, uint8_t *endp, uint8_t v) {
while (startp < endp)
*startp++ = v;
}
#endif
/**
* @brief Initializes a new thread.
* @details The new thread is initialized but not inserted in the ready list,
* the initial state is @p PRSUSPENDED.
*
* @param[out] wsp pointer to a working area dedicated to the thread stack
* @param[in] size size of the working area
* @param[in] prio the priority level for the new thread
* @param[in] pf the thread function
* @param[in] arg an argument passed to the thread function. It can be @p NULL.
* @return The pointer to the @p Thread structure allocated for the
* thread into the working space area.
* @note A thread can terminate by calling @p chThdExit() or by simply
* returning from its main function.
* @note This function can be invoked from within an interrupt handler even if
* it is not an I-Class API because it does not touch any critical kernel
* data structure.
*/
Thread *chThdInit(void *wsp, size_t size, tprio_t prio, tfunc_t pf, void *arg) {
/* Thread structure is layed out in the lower part of the thread workspace */
Thread *tp = wsp;
chDbgCheck((wsp != NULL) && (size >= THD_WA_SIZE(0)) &&
(prio <= HIGHPRIO) && (pf != NULL),
"chThdInit");
#if CH_DBG_FILL_THREADS
memfill((uint8_t *)wsp, (uint8_t *)wsp + sizeof(Thread), THREAD_FILL_VALUE);
memfill((uint8_t *)wsp + sizeof(Thread),
(uint8_t *)wsp + size, STACK_FILL_VALUE);
#endif
SETUP_CONTEXT(wsp, size, pf, arg);
return init_thread(tp, prio);
}
/**
* @brief Creates a new thread into a static memory area.
*
* @param[out] wsp pointer to a working area dedicated to the thread
* stack
* @param[in] size size of the working area
* @param[in] prio the priority level for the new thread
* @param[in] pf the thread function
* @param[in] arg an argument passed to the thread function. It can be @p NULL.
* @return The pointer to the @p Thread structure allocated for the
* thread into the working space area.
* @note A thread can terminate by calling @p chThdExit() or by simply
* returning from its main function.
*/
Thread *chThdCreateStatic(void *wsp, size_t size,
tprio_t prio, tfunc_t pf, void *arg) {
return chThdResume(chThdInit(wsp, size, prio, pf, arg));
}
#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_HEAP
/**
* @brief Creates a new thread allocating the memory from the heap.
*
* @param[in] size size of the working area to be allocated
* @param[in] prio the priority level for the new thread
* @param[in] pf the thread function
* @param[in] arg an argument passed to the thread function. It can be @p NULL.
* @return The pointer to the @p Thread structure allocated for the
* thread into the working space area.
* @retval NULL if the memory cannot be allocated.
* @note A thread can terminate by calling @p chThdExit() or by simply
* returning from its main function.
* @note The memory allocated for the thread is not released when the thread
* terminates but when a @p chThdWait() is performed.
* @note The function is available only if the @p CH_USE_DYNAMIC,
* @p CH_USE_HEAP and @p CH_USE_WAITEXIT options are enabled
* in @p chconf.h.
*/
Thread *chThdCreateFromHeap(size_t size, tprio_t prio, tfunc_t pf, void *arg) {
void *wsp;
Thread *tp;
wsp = chHeapAlloc(size);
if (wsp == NULL)
return NULL;
tp = chThdInit(wsp, size, prio, pf, arg);
tp->p_flags = P_MEM_MODE_HEAP;
return chThdResume(tp);
}
#endif /* CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_HEAP */
#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_MEMPOOLS
/**
* @brief Creates a new thread allocating the memory from the specified Memory
* Pool.
*
* @param[in] mp the memory pool
* @param[in] prio the priority level for the new thread
* @param[in] pf the thread function
* @param[in] arg an argument passed to the thread function. It can be @p NULL.
* @return The pointer to the @p Thread structure allocated for the
* thread into the working space area or @p NULL if the memory cannot
* be allocated.
* @retval NULL if the memory pool is empty.
* @note A thread can terminate by calling @p chThdExit() or by simply
* returning from its main function.
* @note The memory allocated for the thread is not released when the thread
* terminates but when a @p chThdWait() is performed.
* @note The function is available only if the @p CH_USE_DYNAMIC,
* @p CH_USE_MEMPOOLS and @p CH_USE_WAITEXIT options are enabled
* in @p chconf.h.
*/
Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio,
tfunc_t pf, void *arg) {
void *wsp;
Thread *tp;
chDbgCheck(mp != NULL, "chThdCreateFromMemoryPool");
wsp = chPoolAlloc(mp);
if (wsp == NULL)
return NULL;
tp = chThdInit(wsp, mp->mp_object_size, prio, pf, arg);
tp->p_flags = P_MEM_MODE_MEMPOOL;
tp->p_mpool = mp;
return chThdResume(tp);
}
#endif /* CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_MEMPOOLS */
/**
* @brief Changes the running thread priority level then reschedules if
* necessary.
*
* @param[in] newprio the new priority level of the running thread
* @return The old priority level.
* @note The function returns the real thread priority regardless of the
* current priority that could be higher than the real priority because
* the priority inheritance mechanism.
*/
tprio_t chThdSetPriority(tprio_t newprio) {
tprio_t oldprio;
chDbgCheck((newprio >= LOWPRIO) && (newprio <= HIGHPRIO),
"chThdSetPriority");
chSysLock();
#if CH_USE_MUTEXES
oldprio = currp->p_realprio;
if ((currp->p_prio == currp->p_realprio) || (newprio > currp->p_prio))
currp->p_prio = newprio;
currp->p_realprio = newprio;
#else
oldprio = currp->p_prio;
currp->p_prio = newprio;
#endif
chSchRescheduleS();
chSysUnlock();
return oldprio;
}
/**
* @brief Resumes a suspended thread.
*
* @param[in] tp the pointer to the thread
* @return The pointer to the thread.
* @note This call is supposed to resume threads created with @p chThdInit().
* It should not be used on threads suspended using @p chThdSuspend().
*/
Thread *chThdResume(Thread *tp) {
chSysLock();
chDbgAssert(tp->p_state == PRSUSPENDED,
"chThdResume(), #1",
"thread not in PRSUSPENDED state");
chSchWakeupS(tp, RDY_OK);
chSysUnlock();
return tp;
}
/**
* @brief Requests a thread termination.
*
* @param[in] tp the pointer to the thread
* @note The thread is not termitated but a termination request is added to
* its @p p_flags field. The thread can read this status by
* invoking @p chThdShouldTerminate() and then terminate cleanly.
*/
void chThdTerminate(Thread *tp) {
chSysLock();
tp->p_flags |= P_TERMINATE;
chSysUnlock();
}
/**
* @brief Suspends the invoking thread for the specified time.
*
* @param[in] time the delay in system ticks, the special values are handled as
* follow:
* - @a TIME_INFINITE the thread enters an infinite sleep
* state.
* - @a TIME_IMMEDIATE this value is accepted but interpreted
* as a normal time specification not as an immediate timeout
* specification.
* .
*/
void chThdSleep(systime_t time) {
chDbgCheck(time != TIME_INFINITE, "chThdSleep");
chSysLock();
chThdSleepS(time);
chSysUnlock();
}
/**
* @brief Suspends the invoking thread until the system time arrives to the
* specified value.
*
* @param[in] time the absolute system time
*/
void chThdSleepUntil(systime_t time) {
chSysLock();
if ((time -= chTimeNow()) > 0)
chThdSleepS(time);
chSysUnlock();
}
/**
* @brief Terminates the current thread by specifying an exit status code.
*
* @param[in] msg the thread exit code. The code can be retrieved by using
* @p chThdWait().
*/
void chThdExit(msg_t msg) {
Thread *tp = currp;
chSysLock();
tp->p_exitcode = msg;
THREAD_EXT_EXIT(tp);
#if CH_USE_WAITEXIT
if (tp->p_waiting != NULL)
chSchReadyI(tp->p_waiting);
#endif
chSchGoSleepS(PREXIT);
}
#if CH_USE_WAITEXIT
/**
* @brief Blocks the execution of the invoking thread until the specified
* thread terminates then the exit code is returned.
* @details The memory used by the exited thread is handled in different ways
* depending on the API that spawned the thread:
* - If the thread was spawned by @p chThdCreateStatic() or by
* @p chThdInit() then nothing happens and the thread working area
* is not released or modified in any way. This is the default,
* totally static, behavior.
* - If the thread was spawned by @p chThdCreateFromHeap() then
* the working area is returned to the system heap.
* - If the thread was spawned by @p chThdCreateFromMemoryPool()
* then the working area is returned to the owning memory pool.
* .
* @param[in] tp the thread pointer
* @return The exit code from the terminated thread
* @note After invoking @p chThdWait() the thread pointer becomes invalid and
* must not be used as parameter for further system calls.
* @note The function is available only if the @p CH_USE_WAITEXIT
* option is enabled in @p chconf.h.
* @note Only one thread can be waiting for another thread at any time. You
* should imagine the threads as having a reference counter that is set
* to one when the thread is created, chThdWait() decreases the reference
* and the memory is freed when the counter reaches zero. In the current
* implementation there is no real reference counter in the thread
* structure but it is a planned extension.
*/
msg_t chThdWait(Thread *tp) {
msg_t msg;
chDbgCheck(tp != NULL, "chThdWait");
chSysLock();
chDbgAssert(tp != currp, "chThdWait(), #1", "waiting self");
chDbgAssert(tp->p_waiting == NULL, "chThdWait(), #2", "some other thread waiting");
if (tp->p_state != PREXIT) {
tp->p_waiting = currp;
chSchGoSleepS(PRWAIT);
}
msg = tp->p_exitcode;
#if !CH_USE_DYNAMIC
chSysUnlock();
return msg;
#else /* CH_USE_DYNAMIC */
/* Returning memory.*/
tmode_t mode = tp->p_flags & P_MEM_MODE_MASK;
chSysUnlock();
switch (mode) {
#if CH_USE_HEAP
case P_MEM_MODE_HEAP:
chHeapFree(tp);
break;
#endif
#if CH_USE_MEMPOOLS
case P_MEM_MODE_MEMPOOL:
chPoolFree(tp->p_mpool, tp);
break;
#endif
}
return msg;
#endif /* CH_USE_DYNAMIC */
}
#endif /* CH_USE_WAITEXIT */
/** @} */

View File

@ -1,116 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file chvt.c
* @brief Time and Virtual Timers related code.
* @addtogroup Time
* @{
*/
#include <ch.h>
VTList vtlist;
/**
* @brief Virtual Timers initialization.
*
* @note Internal use only.
*/
void vt_init(void) {
vtlist.vt_next = vtlist.vt_prev = (void *)&vtlist;
vtlist.vt_time = (systime_t)-1;
vtlist.vt_systime = 0;
}
/**
* @brief Enables a virtual timer.
*
* @param[out] vtp the @p VirtualTimer structure pointer
* @param[in] time the number of time ticks, the value @p TIME_INFINITE is not
* allowed. The value @p TIME_IMMEDIATE is allowed but
* interpreted as a normal time specification not as an
* immediate timeout specification.
* @param[in] vtfunc the timer callback function. After invoking the callback
* the timer is disabled and the structure can be disposed or
* reused.
* @param[in] par a parameter that will be passed to the callback function
* @note The associated function is invoked by an interrupt handler within
* the I-Locked state, see @ref system_states.
*/
void chVTSetI(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par) {
VirtualTimer *p;
chDbgCheck((vtp != NULL) && (vtfunc != NULL) && (time != TIME_INFINITE),
"chVTSetI");
vtp->vt_par = par;
vtp->vt_func = vtfunc;
p = vtlist.vt_next;
while (p->vt_time < time) {
time -= p->vt_time;
p = p->vt_next;
}
vtp->vt_prev = (vtp->vt_next = p)->vt_prev;
vtp->vt_prev->vt_next = p->vt_prev = vtp;
vtp->vt_time = time;
if (p != (void *)&vtlist)
p->vt_time -= time;
}
/**
* @brief Disables a Virtual Timer.
*
* @param[in] vtp the @p VirtualTimer structure pointer
* @note The timer MUST be active when this function is invoked.
*/
void chVTResetI(VirtualTimer *vtp) {
chDbgCheck(vtp != NULL, "chVTResetI");
chDbgAssert(vtp->vt_func != NULL,
"chVTResetI(), #1",
"timer not set or already triggered");
if (vtp->vt_next != (void *)&vtlist)
vtp->vt_next->vt_time += vtp->vt_time;
vtp->vt_prev->vt_next = vtp->vt_next;
vtp->vt_next->vt_prev = vtp->vt_prev;
vtp->vt_func = NULL;
}
/**
* @brief Checks if the current system time is within the specified time window.
*
* @param[in] start the start of the time window (inclusive)
* @param[in] end the end of the time window (non inclusive)
* @retval TRUE current time within the specified time window.
* @retval FALSE current time not within the specified time window.
* @note When start==end then the function returns always true because the
* whole time range is specified.
*/
bool_t chTimeIsWithin(systime_t start, systime_t end) {
systime_t time = chTimeNow();
return end > start ? (time >= start) && (time < end) :
(time >= start) || (time < end);
}
/** @} */

View File

@ -1,89 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ch.h
* @brief ChibiOS/RT main include file, it includes everything else.
* @addtogroup Kernel
* @{
*/
#ifndef _CH_H_
#define _CH_H_
/**
* ChibiOS/RT identification macro.
*/
#define _CHIBIOS_RT_
/**
* Kernel version string.
*/
#define CH_KERNEL_VERSION "1.3.2unstable"
/**
* Kernel version major number.
*/
#define CH_KERNEL_MAJOR 1
/**
* Kernel version minor number.
*/
#define CH_KERNEL_MINOR 3
/**
* Kernel version patch number.
*/
#define CH_KERNEL_PATCH 2
/*
* Common values.
*/
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE (!FALSE)
#endif
#include <chconf.h>
#include <chtypes.h>
#include "lists.h"
#include <chcore.h>
#include "sys.h"
#include "vt.h"
#include "scheduler.h"
#include "semaphores.h"
#include "mutexes.h"
#include "condvars.h"
#include "events.h"
#include "messages.h"
#include "mailboxes.h"
#include "heap.h"
#include "mempools.h"
#include "threads.h"
#include "inline.h"
#include "queues.h"
#include "channels.h"
#include "serial.h"
#include "debug.h"
#endif /* _CH_H_ */
/** @} */

View File

@ -1,292 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file channels.h
* @brief I/O channels
* @addtogroup Channels
* @{
*/
#ifndef _CHANNELS_H_
#define _CHANNELS_H_
/**
* @brief @p BaseChannel specific methods.
*/
struct _base_channel_methods {
/**
* @brief Channel output check.
* @see chIOPutWouldBlock()
*/
bool_t (*putwouldblock)(void *instance);
/**
* @brief Channel input check.
* @see chIOGetWouldBlock()
*/
bool_t (*getwouldblock)(void *instance);
/**
* @brief Channel put method with timeout specification.
* @see chIOPut()
*/
msg_t (*put)(void *instance, uint8_t b, systime_t timeout);
/**
* @brief Channel get method with timeout specification.
* @see chIOGet()
*/
msg_t (*get)(void *instance, systime_t timeout);
};
/**
* @brief @p BaseChannel specific data.
* @note It is empty because @p BaseChannel is only an interface without
* implementation.
*/
struct _base_channel_data {
};
/**
* @brief @p BaseChannel virtual methods table.
*/
struct BaseChannelVMT {
/**
* @p BaseChannel class specific methods.
*/
struct _base_channel_methods m0;
};
/**
* @brief Base channel class.
* @details This class represents a generic, byte-wide, I/O channel.
*/
typedef struct {
/**
* Virtual Methods Table.
*/
const struct BaseChannelVMT *vmt;
/**
* @p BaseChannel class specific data.
*/
struct _base_channel_data d0;
} BaseChannel;
/**
* @brief Channel output check.
* @details This function verifies if a subsequent @p chIOPut() would block.
*
* @param[in] ip pointer to a @p BaseChannel or derived class
* @return The output queue status:
* @retval FALSE if the output queue has space and would not block a write
* operation.
* @retval TRUE if the output queue is full and would block a write operation.
*/
#define chIOPutWouldBlock(ip) ((ip)->vmt->m0.putwouldblock(ip))
/**
* @brief Channel input check.
* @details This function verifies if a subsequent @p chIOGett() would block.
*
* @param[in] ip pointer to a @p BaseChannel or derived class
* @return The input queue status:
* @retval FALSE if the input queue contains data and would not block a read
* operation.
* @retval TRUE if the input queue is empty and would block a read operation.
*/
#define chIOGetWouldBlock(ip) ((ip)->vmt->m0.getwouldblock(ip))
/**
* @brief Channel blocking byte write.
* @details This function writes a byte value to a channel. If the channel
* is not ready to accept data then the calling thread is suspended.
*
* @param[in] ip pointer to a @p BaseChannel or derived class
* @param[in] b the byte value to be written to the channel
* @return The operation status:
* @retval Q_OK if the operation succeeded.
* @retval Q_RESET if the channel associated queue (if any) was reset.
*/
#define chIOPut(ip, b) ((ip)->vmt->m0.put(ip, b, TIME_INFINITE))
/**
* @brief Channel blocking byte write with timeout.
* @details This function writes a byte value to a channel. If the channel
* is not ready to accept data then the calling thread is suspended.
*
* @param[in] ip pointer to a @p BaseChannel or derived class
* @param[in] b the byte value to be written to the channel
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status:
* @retval Q_OK if the operation succeeded.
* @retval Q_TIMEOUT if the specified time expired.
* @retval Q_RESET if the channel associated queue (if any) was reset.
*/
#define chIOPutTimeout(ip, b, timeout) ((ip)->vmt->m0.put(ip, b, timeout))
/**
* @brief Channel blocking byte read.
* @details This function reads a byte value from a channel. If the data
* is not available then the calling thread is suspended.
*
* @param[in] ip pointer to a @p BaseChannel or derived class
* @return A byte value from the queue or:
* @retval Q_RESET if the channel associated queue (if any) was reset.
*/
#define chIOGet(ip) ((ip)->vmt->m0.get(ip, TIME_INFINITE))
/**
* @brief Channel blocking byte read with timeout.
* @details This function reads a byte value from a channel. If the data
* is not available then the calling thread is suspended.
*
* @param[in] ip pointer to a @p BaseChannel or derived class
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_IMMEDIATE immediate timeout.
* - @a TIME_INFINITE no timeout.
* .
* @return A byte value from the queue or:
* @retval Q_TIMEOUT if the specified time expired.
* @retval Q_RESET if the channel associated queue (if any) was reset.
*/
#define chIOGetTimeout(ip, timeout) ((ip)->vmt->m0.get(ip, timeout))
#if CH_USE_EVENTS
/**
* @brief @p BaseAsynchronousChannel specific methods.
*/
struct _base_asynchronous_channel_methods {
/**
* Channel asynchronous write method.
* @see chIOWrite()
*/
size_t (*write)(void *instance, uint8_t *buffer, size_t n);
/**
* Channel asynchronous read method.
* @see chIORead()
*/
size_t (*read)(void *instance, uint8_t *buffer, size_t n);
};
/**
* @brief @p BaseAsynchronousChannel specific data.
*/
struct _base_asynchronous_channel_data {
/**
* Data Available @p EventSource. This event is generated when some incoming
* data is inserted in the input queue.
*/
EventSource ievent;
/**
* Data Transmitted @p EventSource. This event is generated when the
* output queue is empty.
*/
EventSource oevent;
};
/**
* @brief @p BaseAsynchronousChannel virtual methods table.
*/
struct BaseAsynchronousChannelVMT {
/**
* @p BaseChannel class inherited methods.
*/
struct _base_channel_methods m0;
/**
* @p BaseAsynchronousChannel class specific methods.
*/
struct _base_asynchronous_channel_methods m1;
};
/**
* @extends BaseChannel
*
* @brief Base asynchronous channel class.
* @details This class extends @p BaseChannel by adding methods for
* asynchronous I/O in an event-driven environment.
*/
typedef struct {
/**
* Virtual Methods Table.
*/
const struct BaseAsynchronousChannelVMT *vmt;
/**
* @p BaseChannel class inherited data.
*/
struct _base_channel_data d0;
/**
* @p BaseAsynchronousChannel class specific data.
*/
struct _base_asynchronous_channel_data d1;
} BaseAsynchronousChannel;
/**
* @brief Channel non-blocking write.
* @details The function writes data from a buffer to a channel. The
* transfer is non-blocking and can return zero if the channel is
* not read to accept data.
*
* @param[in] ip pointer to a @p BaseAsynchronousChannel or derived class
* @param[out] bp pointer to the buffer where the data is stored
* @param[in] n the maximum amount of data to be transferred
* @return The number of bytes transferred.
*/
#define chIOWrite(ip, bp, n) ((ip)->vmt->m1.write(ip, bp, n))
/**
* @brief Channel non-blocking read.
* @details The function reads data from a channel into a buffer. The
* transfer is non-blocking and can return zero if the channel has
* no data immediately available.
*
* @param[in] ip pointer to a @p BaseAsynchronousChannel or derived class
* @param[out] bp pointer to the buffer where the input data is copied
* @param[in] n the maximum amount of data to be transferred
* @return The number of bytes transferred.
*/
#define chIORead(ip, bp, n) ((ip)->vmt->m1.read(ip, bp, n))
/**
* @brief Returns the write event source.
* @details The write event source is broadcasted when the channel is ready
* for write operations. This usually happens when the internal
* output queue becomes empty.
* @param[in] ip pointer to a @p BaseAsynchronousChannel or derived class
* @return A pointer to an @p EventSource object.
*/
#define chIOGetWriteEventSource(ip) (&((ip)->vmt->d1.oevent))
/**
* @brief Returns the read event source.
* @details The read event source is broadcasted when the channel is ready
* for read operations. This usually happens when the internal
* input queue becomes non-empty.
* @param[in] ip pointer to a @p BaseAsynchronousChannel or derived class
* @return A pointer to an @p EventSource object.
*/
#define chIOGetReadEventSource(ip) (&((ip)->vmt->d1.ievent))
#endif /* CH_USE_EVENTS */
#endif /* _CHANNELS_H_ */
/** @} */

View File

@ -1,80 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Concepts and parts of this file are contributed by and Copyright (C) 2008
of Leon Woestenberg.
*/
/**
* @file condvars.h
* @brief Condition Variables macros and structures.
* @addtogroup CondVars
* @{
*/
#ifndef _CONDVARS_H_
#define _CONDVARS_H_
#if CH_USE_CONDVARS && CH_USE_MUTEXES
/**
* @brief CondVar structure.
*/
typedef struct CondVar {
ThreadsQueue c_queue; /**< CondVar threads queue.*/
} CondVar;
#ifdef __cplusplus
extern "C" {
#endif
void chCondInit(CondVar *cp);
void chCondSignal(CondVar *cp);
void chCondSignalI(CondVar *cp);
void chCondBroadcast(CondVar *cp);
void chCondBroadcastI(CondVar *cp);
msg_t chCondWait(CondVar *cp);
msg_t chCondWaitS(CondVar *cp);
#if CH_USE_CONDVARS_TIMEOUT
msg_t chCondWaitTimeout(CondVar *cp, systime_t time);
msg_t chCondWaitTimeoutS(CondVar *cp, systime_t time);
#endif
#ifdef __cplusplus
}
#endif
/**
* @brief Data part of a static condition variable initializer.
* @details This macro should be used when statically initializing a condition
* variable that is part of a bigger structure.
*/
#define _CONDVAR_DATA(name) {_THREADSQUEUE_DATA(name.c_queue)}
/**
* @brief Static condition variable initializer.
* @details Statically initialized condition variables require no explicit
* initialization using @p chCondInit().
* @param name the name of the condition variable
*/
#define CONDVAR_DECL(name) CondVar name = _CONDVAR_DATA(name)
#endif /* CH_USE_CONDVARS && CH_USE_MUTEXES */
#endif /* _CONDVARS_H_ */
/** @} */

View File

@ -1,149 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file debug.h
* @brief Debug macros and structures.
* @addtogroup Debug
* @{
*/
#ifndef _DEBUG_H_
#define _DEBUG_H_
/**
* @brief Trace buffer entries.
*/
#ifndef TRACE_BUFFER_SIZE
#define TRACE_BUFFER_SIZE 64
#endif
/**
* @brief Fill value for thread stack area in debug mode.
*/
#ifndef STACK_FILL_VALUE
#define STACK_FILL_VALUE 0x55
#endif
/**
* @brief Fill value for thread area in debug mode.
* @note The chosen default value is 0xFF in order to make evident which
* thread fields were not initialized when inspecting the memory with
* a debugger. A uninitialized field is not an error in itself but it
* better to know it.
*/
#ifndef THREAD_FILL_VALUE
#define THREAD_FILL_VALUE 0xFF
#endif
/**
* @brief Trace buffer record.
*/
typedef struct {
void *cse_wtobjp; /**< Object where going to sleep.*/
systime_t cse_time; /**< Time of the switch event.*/
uint16_t cse_state: 4; /**< Switched out thread state.*/
uint16_t cse_tid: 12; /**< Switched in thdread id.*/
} CtxSwcEvent;
/**
* @brief Trace buffer header.
*/
typedef struct {
unsigned tb_size; /**< Trace buffer size (records).*/
CtxSwcEvent *tb_ptr; /**< Pointer to the ring buffer front.*/
CtxSwcEvent tb_buffer[TRACE_BUFFER_SIZE]; /**< Ring buffer.*/
} TraceBuffer;
#define __QUOTE_THIS(p) #p
#if CH_DBG_ENABLE_CHECKS
/**
* Function parameter check, if the condition check fails then the kernel
* panics.
* @param c the condition to be verified to be true
* @param func the undecorated function name
* @note The condition is tested only if the @p CH_DBG_ENABLE_CHECKS switch is
* specified in @p chconf.h else the macro does nothing.
*/
#define chDbgCheck(c, func) { \
if (!(c)) \
chDbgPanic(__QUOTE_THIS(func)"(), line "__QUOTE_THIS(__LINE__)); \
}
#else /* !CH_DBG_ENABLE_CHECKS */
#define chDbgCheck(c, func) { \
(void)(c), (void)__QUOTE_THIS(func)"(), line "__QUOTE_THIS(__LINE__); \
}
#endif /* !CH_DBG_ENABLE_CHECKS */
#if CH_DBG_ENABLE_ASSERTS
/**
* Condition assertion, if the condition check fails then the kernel panics
* with the specified message.
* @param c the condition to be verified to be true
* @param m the text message
* @param r a remark string
* @note The condition is tested only if the @p CH_DBG_ENABLE_ASSERTS switch is
* specified in @p chconf.h else the macro does nothing.
* @note The convention for the message is the following:<br>
* @<function_name@>(), #@<assert_number@>
* @note The remark string is not currently used except for putting a comment
* in the code about the assert.
*/
#define chDbgAssert(c, m, r) { \
if (!(c)) \
chDbgPanic(m); \
}
#else /* !CH_DBG_ENABLE_ASSERTS */
#define chDbgAssert(c, m, r) {(void)(c);}
#endif /* !CH_DBG_ENABLE_ASSERTS */
#if !(CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK)
/* When the debug features are disabled this function is replaced by an empty
* macro.*/
#define chDbgPanic(msg) {}
#endif
#if !CH_DBG_ENABLE_TRACE
/* When the trace feature is disabled this function is replaced by an empty
* macro.*/
#define chDbgTrace(otp, ntp) {}
#endif
#if !defined(__DOXYGEN__)
#ifdef __cplusplus
extern "C" {
#endif
#if CH_DBG_ENABLE_TRACE
extern TraceBuffer trace_buffer;
void trace_init(void);
void chDbgTrace(Thread *otp, Thread *ntp);
#endif
#if CH_DBG_ENABLE_ASSERTS || CH_DBG_ENABLE_CHECKS || CH_DBG_ENABLE_STACK_CHECK
extern char *panic_msg;
void chDbgPanic(char *msg);
#endif
#ifdef __cplusplus
}
#endif
#endif /* !defined(__DOXYGEN__) */
#endif /* _DEBUG_H_ */
/** @} */

View File

@ -1,145 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file events.h
* @brief Events macros and structures.
* @addtogroup Events
* @{
*/
#ifndef _EVENTS_H_
#define _EVENTS_H_
#if CH_USE_EVENTS
typedef struct EventListener EventListener;
/**
* @brief Event Listener structure.
*/
struct EventListener {
EventListener *el_next; /**< Next Event Listener registered on
the Event Source.*/
Thread *el_listener; /**< Thread interested in the Event
Source.*/
eventmask_t el_mask; /**< Event flags mask associated by the
thread to the Event Source.*/
};
/**
* @brief Event Source structure.
*/
typedef struct EventSource {
EventListener *es_next; /**< First Event Listener registered on
the Event Source.*/
} EventSource;
/**
* @brief Data part of a static event source initializer.
* @details This macro should be used when statically initializing an event
* source that is part of a bigger structure.
* @param name the name of the event source variable
*/
#define _EVENTSOURCE_DATA(name) {(void *)(&name)}
/**
* @brief Static event source initializer.
* @details Statically initialized event sources require no explicit
* initialization using @p chEvtInit().
* @param name the name of the event source variable
*/
#define EVENTSOURCE_DECL(name) EventSource name = _EVENTSOURCE_DATA(name)
/** All events allowed mask.*/
#define ALL_EVENTS -1
/** Returns the event mask from the event identifier.*/
#define EVENT_MASK(eid) (1 << (eid))
/**
* Registers an Event Listener on an Event Source.
* @param esp pointer to the @p EventSource structure
* @param elp pointer to the @p EventListener structure
* @param eid numeric identifier assigned to the Event Listener. The identifier
* is used as index for the event callback function.
* The value must range between zero and the size, in bit, of the
* @p eventid_t type minus one.
* @note Multiple Event Listeners can use the same event identifier, the
* listener will share the callback function.
*/
#define chEvtRegister(esp, elp, eid) chEvtRegisterMask(esp, elp, EVENT_MASK(eid))
/**
* Initializes an Event Source.
* @param esp pointer to the @p EventSource structure
* @note Can be called with interrupts disabled or enabled.
*/
#define chEvtInit(esp) \
((esp)->es_next = (EventListener *)(void *)(esp))
/**
* Verifies if there is at least one @p EventListener registered on the
* @p EventSource.
* @param esp pointer to the @p EventSource structure
* @note Can be called with interrupts disabled or enabled.
*/
#define chEvtIsListening(esp) \
((void *)(esp) != (void *)(esp)->es_next)
/** Event Handler callback function.*/
typedef void (*evhandler_t)(eventid_t);
#ifdef __cplusplus
extern "C" {
#endif
void chEvtRegisterMask(EventSource *esp, EventListener *elp, eventmask_t emask);
void chEvtUnregister(EventSource *esp, EventListener *elp);
eventmask_t chEvtClear(eventmask_t mask);
eventmask_t chEvtPend(eventmask_t mask);
void chEvtSignal(Thread *tp, eventmask_t mask);
void chEvtSignalI(Thread *tp, eventmask_t mask);
void chEvtBroadcast(EventSource *esp);
void chEvtBroadcastI(EventSource *esp);
void chEvtDispatch(const evhandler_t handlers[], eventmask_t mask);
#if CH_OPTIMIZE_SPEED || !CH_USE_EVENTS_TIMEOUT
eventmask_t chEvtWaitOne(eventmask_t ewmask);
eventmask_t chEvtWaitAny(eventmask_t ewmask);
eventmask_t chEvtWaitAll(eventmask_t ewmask);
#endif
#if CH_USE_EVENTS_TIMEOUT
eventmask_t chEvtWaitOneTimeout(eventmask_t ewmask, systime_t time);
eventmask_t chEvtWaitAnyTimeout(eventmask_t ewmask, systime_t time);
eventmask_t chEvtWaitAllTimeout(eventmask_t ewmask, systime_t time);
#endif
#ifdef __cplusplus
}
#endif
#if !CH_OPTIMIZE_SPEED && CH_USE_EVENTS_TIMEOUT
#define chEvtWaitOne(ewmask) chEvtWaitOneTimeout(ewmask, TIME_INFINITE)
#define chEvtWaitAny(ewmask) chEvtWaitAnyTimeout(ewmask, TIME_INFINITE)
#define chEvtWaitAll(ewmask) chEvtWaitAllTimeout(ewmask, TIME_INFINITE)
#endif
#endif /* CH_USE_EVENTS */
#endif /* _EVENTS_H_ */
/** @} */

View File

@ -1,43 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file heap.h
* @brief Heap macros and structures.
* @addtogroup Heap
* @{
*/
#ifndef _HEAP_H_
#define _HEAP_H_
#ifdef __cplusplus
extern "C" {
#endif
void heap_init(void);
void *chHeapAlloc(size_t size);
void chHeapFree(void *p);
size_t chHeapStatus(size_t *sizep);
#ifdef __cplusplus
}
#endif
#endif /* _HEAP_H_ */
/** @} */

View File

@ -1,72 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _INLINE_H_
#define _INLINE_H_
/**
* @file inline.h
* @brief Kernel inlined functions.
*/
/*
* Inlined functions if CH_OPTIMIZE_SPEED is enabled.
* Note: static inlined functions do not duplicate the code in every module
* this is true for GCC, not sure about other compilers.
*/
#if CH_OPTIMIZE_SPEED
static INLINE void prio_insert(Thread *tp, ThreadsQueue *tqp) {
Thread *cp = (Thread *)tqp;
do {
cp = cp->p_next;
} while ((cp != (Thread *)tqp) && (cp->p_prio >= tp->p_prio));
tp->p_prev = (tp->p_next = cp)->p_prev;
tp->p_prev->p_next = cp->p_prev = tp;
}
static INLINE void queue_insert(Thread *tp, ThreadsQueue *tqp) {
tp->p_prev = (tp->p_next = (Thread *)tqp)->p_prev;
tp->p_prev->p_next = tqp->p_prev = tp;
}
static INLINE Thread *fifo_remove(ThreadsQueue *tqp) {
Thread *tp = tqp->p_next;
(tqp->p_next = tp->p_next)->p_prev = (Thread *)tqp;
return tp;
}
static INLINE Thread *lifo_remove(ThreadsQueue *tqp) {
Thread *tp = tqp->p_prev;
(tqp->p_prev = tp->p_prev)->p_next = (Thread *)tqp;
return tp;
}
static INLINE Thread *dequeue(Thread *tp) {
tp->p_prev->p_next = tp->p_next;
tp->p_next->p_prev = tp->p_prev;
return tp;
}
#endif /* CH_OPTIMIZE_SPEED */
#endif /* _INLINE_H_ */

View File

@ -1,92 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file lists.h
* @brief Thread queues/lists macros and structures.
* @addtogroup ThreadLists
* @{
*/
#ifndef _LISTS_H_
#define _LISTS_H_
typedef struct Thread Thread;
/**
* Threads queue initialization.
*/
#define queue_init(tqp) ((tqp)->p_next = (tqp)->p_prev = (Thread *)(tqp));
/**
* Macro evaluating to @p TRUE if the specified threads queue is empty.
*/
#define isempty(p) ((p)->p_next == (Thread *)(p))
/**
* Macro evaluating to @p TRUE if the specified threads queue is not empty.
*/
#define notempty(p) ((p)->p_next != (Thread *)(p))
/**
* @brief Data part of a static threads queue initializer.
* @details This macro should be used when statically initializing a threads
* queue that is part of a bigger structure.
* @param name the name of the threads queue variable
*/
#define _THREADSQUEUE_DATA(name) {(Thread *)&name, (Thread *)&name}
/**
* @brief Static threads queue initializer.
* @details Statically initialized threads queues require no explicit
* initialization using @p queue_init().
* @param name the name of the threads queue variable
*/
#define THREADSQUEUE_DECL(name) ThreadsQueue name = _THREADSQUEUE_DATA(name)
/**
* @brief Generic threads bidirectional linked list header and element.
* @extends ThreadsList
*/
typedef struct {
Thread *p_next; /**< First @p Thread in the queue, or
@p ThreadQueue when empty.*/
Thread *p_prev; /**< Last @p Thread in the queue, or
@p ThreadQueue when empty.*/
} ThreadsQueue;
#if !CH_OPTIMIZE_SPEED
#ifdef __cplusplus
extern "C" {
#endif
void prio_insert(Thread *tp, ThreadsQueue *tqp);
void queue_insert(Thread *tp, ThreadsQueue *tqp);
Thread *fifo_remove(ThreadsQueue *tqp);
Thread *lifo_remove(ThreadsQueue *tqp);
Thread *dequeue(Thread *tp);
#ifdef __cplusplus
}
#endif
#endif /* !CH_OPTIMIZE_SPEED */
#endif /* _LISTS_H_ */
/** @} */

View File

@ -1,126 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file mailboxes.h
* @brief Mailboxes macros and structures.
* @addtogroup Mailboxes
* @{
*/
#ifndef _MAILBOXES_H_
#define _MAILBOXES_H_
#if CH_USE_MAILBOXES
typedef struct {
msg_t *mb_buffer; /**< Pointer to the mailbox buffer.*/
msg_t *mb_top; /**< Pointer to the first location
after the buffer.*/
msg_t *mb_wrptr; /**< Write pointer.*/
msg_t *mb_rdptr; /**< Read pointer.*/
Semaphore mb_fullsem; /**< Full counter @p Semaphore.*/
Semaphore mb_emptysem; /**< Empty counter @p Semaphore.*/
} Mailbox;
#ifdef __cplusplus
extern "C" {
#endif
void chMBInit(Mailbox *mbp, msg_t *buf, cnt_t n);
void chMBReset(Mailbox *mbp);
msg_t chMBPost(Mailbox *mbp, msg_t msg, systime_t timeout);
msg_t chMBPostS(Mailbox *mbp, msg_t msg, systime_t timeout);
msg_t chMBPostAhead(Mailbox *mbp, msg_t msg, systime_t timeout);
msg_t chMBPostAheadS(Mailbox *mbp, msg_t msg, systime_t timeout);
msg_t chMBFetch(Mailbox *mbp, msg_t *msgp, systime_t timeout);
msg_t chMBFetchS(Mailbox *mbp, msg_t *msgp, systime_t timeout);
#ifdef __cplusplus
}
#endif
/**
* Returns the mailbox buffer size.
* @param[in] mbp the pointer to an initialized Mailbox object
*/
#define chMBSize(mbp) \
((mbp)->mb_top - (mbp)->mb_buffer)
/**
* Returns the free space into the mailbox.
* @param[in] mbp the pointer to an initialized Mailbox object
* @return The number of empty message slots.
* @note Can be invoked in any system state but if invoked out of a locked
* state then the returned value may change after reading.
* @note The returned value can be less than zero when there are waiting
* threads on the internal semaphore.
*/
#define chMBGetEmpty(mbp) chSemGetCounterI(&(mbp)->mb_emptysem)
/**
* Returns the number of messages into the mailbox.
* @param[in] mbp the pointer to an initialized Mailbox object
* @return The number of queued messages.
* @note Can be invoked in any system state but if invoked out of a locked
* state then the returned value may change after reading.
* @note The returned value can be less than zero when there are waiting
* threads on the internal semaphore.
*/
#define chMBGetFull(mbp) chSemGetCounterI(&(mbp)->mb_fullsem)
/**
* Returns the next message in the queue without removing it.
* @note A message must be waiting in the queue for this function to work or
* it would return garbage. The correct way to use this macro is to
* use @p chMBGetFull() and then use this macro, all within a lock state.
*/
#define chMBPeek(mbp) (*(mbp)->mb_rdptr)
/**
* @brief Data part of a static mailbox initializer.
* @details This macro should be used when statically initializing a
* mailbox that is part of a bigger structure.
* @param name the name of the mailbox variable
* @param buffer pointer to the mailbox buffer area
* @param size size of the mailbox buffer area
*/
#define _MAILBOX_DATA(name, buffer, size) { \
(msg_t *)(buffer), \
(msg_t *)(buffer) + size, \
(msg_t *)(buffer), \
(msg_t *)(buffer), \
_SEMAPHORE_DATA(name.mb_fullsem, 0), \
_SEMAPHORE_DATA(name.mb_emptysem, size), \
}
/**
* @brief Static mailbox initializer.
* @details Statically initialized mailboxes require no explicit
* initialization using @p chMBInit().
* @param name the name of the mailbox variable
* @param buffer pointer to the mailbox buffer area
* @param size size of the mailbox buffer area
*/
#define MAILBOX_DECL(name, buffer, size) \
Mailbox name = _MAILBOX_DATA(name, buffer, size)
#endif /* CH_USE_MAILBOXES */
#endif /* _MAILBOXES_H_ */
/** @} */

View File

@ -1,82 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file mempools.h
* @brief Memory Pools macros and structures.
* @addtogroup MemoryPools
* @{
*/
#ifndef _MEMPOOLS_H_
#define _MEMPOOLS_H_
#if CH_USE_MEMPOOLS
/**
* @brief Memory pool free object header.
*/
struct pool_header {
struct pool_header *ph_next;
};
/**
* @brief Memory pool descriptor.
*/
typedef struct {
struct pool_header *mp_next; /**< Pointer to the header.*/
size_t mp_object_size; /**< Memory pool objects size.*/
} MemoryPool;
/**
* @brief Data part of a static memory pool initializer.
* @details This macro should be used when statically initializing a
* memory pool that is part of a bigger structure.
* @param name the name of the memory pool variable
* @param size size of the memory pool contained objects
*/
#define _MEMORYPOOL_DATA(name, size) {NULL, size}
/**
* @brief Static memory pool initializer.
* @details Statically initialized memory pools require no explicit
* initialization using @p chPoolInit().
* @param name the name of the memory pool variable
* @param size size of the memory pool contained objects
*/
#define MEMORYPOOL_DECL(name, size) \
MemoryPool name = _MEMORYPOOL_DATA(name, size)
#ifdef __cplusplus
extern "C" {
#endif
void chPoolInit(MemoryPool *mp, size_t size);
void *chPoolAllocI(MemoryPool *mp);
void *chPoolAlloc(MemoryPool *mp);
void chPoolFreeI(MemoryPool *mp, void *objp);
void chPoolFree(MemoryPool *mp, void *objp);
#ifdef __cplusplus
}
#endif
#endif /* CH_USE_MEMPOOLS */
#endif /* _MEMPOOLS_H_ */
/** @} */

View File

@ -1,59 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file messages.h
* @brief Messages macros and structures.
* @addtogroup Messages
* @{
*/
#ifndef _MESSAGES_H_
#define _MESSAGES_H_
#if CH_USE_MESSAGES
/**
* Evaluates to TRUE if the thread has pending messages.
*/
#define chMsgIsPendingI(tp) \
((tp)->p_msgqueue.p_next != (Thread *)&(tp)->p_msgqueue)
/**
* Returns the first message in the queue.
*/
#define chMsgGetI(tp) \
((tp)->p_msgqueue.p_next->p_msg)
#ifdef __cplusplus
extern "C" {
#endif
msg_t chMsgSend(Thread *tp, msg_t msg);
msg_t chMsgWait(void);
msg_t chMsgGet(void);
void chMsgRelease(msg_t msg);
#ifdef __cplusplus
}
#endif
#endif /* CH_USE_MESSAGES */
#endif /* _MESSAGES_H_ */
/** @} */

View File

@ -1,84 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file mutexes.h
* @brief Mutexes macros and structures.
* @addtogroup Mutexes
* @{
*/
#ifndef _MUTEXES_H_
#define _MUTEXES_H_
#if CH_USE_MUTEXES
/**
* @brief Mutex structure.
*/
typedef struct Mutex {
ThreadsQueue m_queue; /**< Queue of the threads sleeping on
this Mutex.*/
Thread *m_owner; /**< Owner @p Thread pointer or
@p NULL.*/
struct Mutex *m_next; /**< Next @p Mutex into an owner-list
or @p NULL.*/
} Mutex;
#ifdef __cplusplus
extern "C" {
#endif
void chMtxInit(Mutex *mp);
void chMtxLock(Mutex *mp);
void chMtxLockS(Mutex *mp);
bool_t chMtxTryLock(Mutex *mp);
bool_t chMtxTryLockS(Mutex *mp);
Mutex *chMtxUnlock(void);
Mutex *chMtxUnlockS(void);
void chMtxUnlockAll(void);
#ifdef __cplusplus
}
#endif
/**
* @brief Data part of a static mutex initializer.
* @details This macro should be used when statically initializing a mutex
* that is part of a bigger structure.
* @param name the name of the mutex variable
*/
#define _MUTEX_DATA(name) {_THREADSQUEUE_DATA(name.m_queue), NULL, NULL}
/**
* @brief Static mutex initializer.
* @details Statically initialized mutexes require no explicit initialization
* using @p chMtxInit().
* @param name the name of the mutex variable
*/
#define MUTEX_DECL(name) Mutex name = _MUTEX_DATA(name)
/**
* Returns @p TRUE if the mutex queue contains at least a waiting thread.
*/
#define chMtxQueueNotEmptyS(mp) notempty(&(mp)->m_queue)
#endif /* CH_USE_MUTEXES */
#endif /* _MUTEXES_H_ */
/** @} */

View File

@ -1,218 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file queues.h I/O
* @brief Queues macros and structures.
* @addtogroup IOQueues
* @{
*/
#ifndef _QUEUES_H_
#define _QUEUES_H_
/** Queue notification callback type. */
typedef void (*qnotify_t)(void);
/** Returned by the queue functions if the operation is successful. */
#define Q_OK RDY_OK
/** Returned by the queue functions if a timeout occurs. */
#define Q_TIMEOUT RDY_TIMEOUT
/** Returned by the queue functions if the queue is reset. */
#define Q_RESET RDY_RESET
/** Returned by the queue functions if the queue is empty. */
#define Q_EMPTY -3
/** Returned by the queue functions if the queue is full. */
#define Q_FULL -4
#if CH_USE_QUEUES
/**
* @brief Generic I/O queue structure.
* @details This structure represents a generic Input or Output asymmetrical
* queue. The queue is asymmetrical because one end is meant to be
* accessed from a thread context, and thus can be blocking, the other
* end is accessible from interrupt handlers or from within a kernel
* lock zone (see <b>I-Locked</b> and <b>S-Locked</b> states in
* @ref system_states) and is non-blocking.
*/
typedef struct {
uint8_t *q_buffer; /**< Pointer to the queue buffer.*/
uint8_t *q_top; /**< Pointer to the first location
after the buffer.*/
uint8_t *q_wrptr; /**< Write pointer.*/
uint8_t *q_rdptr; /**< Read pointer.*/
Semaphore q_sem; /**< Counter @p Semaphore.*/
qnotify_t q_notify; /**< Data notification callback.*/
} GenericQueue;
/** Returns the queue's buffer size. */
#define chQSize(q) ((q)->q_top - (q)->q_buffer)
/**
* Returns the used space if used on an Input Queue and the empty space if
* used on an Output Queue.
* @note The returned value can be less than zero when there are waiting
* threads on the internal semaphore.
*/
#define chQSpace(q) chSemGetCounterI(&(q)->q_sem)
/**
* @brief Input queue structure.
* @details This structure represents a generic asymmetrical input queue.
* Writing in the queue is non-blocking and can be performed from
* interrupt handlers or from within a kernel lock zone (see
* <b>I-Locked</b> and <b>S-Locked</b> states in @ref system_states).
* Reading the queue can be a blocking operation and is supposed to
* be performed by a system thread.
* @extends GenericQueue
*/
typedef GenericQueue InputQueue;
/** Evaluates to @p TRUE if the specified Input Queue is empty. */
#define chIQIsEmpty(q) (chQSpace(q) <= 0)
/** Evaluates to @p TRUE if the specified Input Queue is full. */
#define chIQIsFull(q) (chQSpace(q) >= chQSize(q))
/**
* @brief Input queue read.
* @details This function reads a byte value from an input queue. If the queue
* is empty then the calling thread is suspended until a byte arrives
* in the queue.
*
* @param[in] iqp pointer to an @p InputQueue structure
* @return A byte value from the queue or:
* @retval Q_RESET if the queue was reset.
*/
#define chIQGet(iqp) chIQGetTimeout(iqp, TIME_INFINITE)
/**
* @brief Data part of a static input queue initializer.
* @details This macro should be used when statically initializing an
* input queue that is part of a bigger structure.
* @param name the name of the input queue variable
* @param buffer pointer to the queue buffer area
* @param size size of the queue buffer area
* @param inotify input notification callback pointer
*/
#define _INPUTQUEUE_DATA(name, buffer, size, inotify) { \
(uint8_t *)(buffer), \
(uint8_t *)(buffer) + size, \
(uint8_t *)(buffer), \
(uint8_t *)(buffer), \
_SEMAPHORE_DATA(name.q_sem, 0), \
inotify \
}
/**
* @brief Static input queue initializer.
* @details Statically initialized input queues require no explicit
* initialization using @p chIQInit().
* @param name the name of the input queue variable
* @param buffer pointer to the queue buffer area
* @param size size of the queue buffer area
* @param inotify input notification callback pointer
*/
#define INPUTQUEUE_DECL(name, buffer, size, inotify) \
InputQueue name = _INPUTQUEUE_DATA(name, buffer, size, inotify)
/**
* @brief Output queue structure.
* @details This structure represents a generic asymmetrical output queue.
* Reading from the queue is non-blocking and can be performed from
* interrupt handlers or from within a kernel lock zone (see
* <b>I-Locked</b> and <b>S-Locked</b> states in @ref system_states).
* Writing the queue can be a blocking operation and is supposed to
* be performed by a system thread.
* @extends GenericQueue
*/
typedef GenericQueue OutputQueue;
/** Evaluates to @p TRUE if the specified Output Queue is empty. */
#define chOQIsEmpty(q) (chQSpace(q) >= chQSize(q))
/** Evaluates to @p TRUE if the specified Output Queue is full. */
#define chOQIsFull(q) (chQSpace(q) <= 0)
/**
* @brief Output queue write.
* @details This function writes a byte value to an output queue. If the queue
* is full then the calling thread is suspended until there is space
* in the queue.
*
* @param[in] oqp pointer to an @p OutputQueue structure
* @param[in] b the byte value to be written in the queue
* @return The operation status:
* @retval Q_OK if the operation succeeded.
* @retval Q_RESET if the queue was reset.
*/
#define chOQPut(oqp, b) chOQPutTimeout(oqp, b, TIME_INFINITE)
/**
* @brief Data part of a static output queue initializer.
* @details This macro should be used when statically initializing an
* output queue that is part of a bigger structure.
* @param name the name of the output queue variable.
* @param buffer pointer to the queue buffer area
* @param size size of the queue buffer area
* @param onotify output notification callback pointer
*/
#define _OUTPUTQUEUE_DATA(name, buffer, size, onotify) { \
(uint8_t *)(buffer), \
(uint8_t *)(buffer) + size, \
(uint8_t *)(buffer), \
(uint8_t *)(buffer), \
_SEMAPHORE_DATA(name.q_sem, size), \
onotify \
}
/**
* @brief Static output queue initializer.
* @details Statically initialized output queues require no explicit
* initialization using @p chOQInit().
* @param name the name of the output queue variable
* @param buffer pointer to the queue buffer area
* @param size size of the queue buffer area
* @param onotify output notification callback pointer
*/
#define OUTPUTQUEUE_DECL(name, buffer, size, onotify) \
InputQueue name = _OUTPUTQUEUE_DATA(name, buffer, size, onotify)
#ifdef __cplusplus
extern "C" {
#endif
void chIQInit(InputQueue *qp, uint8_t *buffer, size_t size, qnotify_t inotify);
void chIQResetI(InputQueue *qp);
msg_t chIQPutI(InputQueue *qp, uint8_t b);
msg_t chIQGetTimeout(InputQueue *qp, systime_t timeout);
size_t chIQRead(InputQueue *qp, uint8_t *buffer, size_t n);
void chOQInit(OutputQueue *queue, uint8_t *buffer, size_t size, qnotify_t onotify);
void chOQResetI(OutputQueue *queue);
msg_t chOQPutTimeout(OutputQueue *queue, uint8_t b, systime_t timeout);
msg_t chOQGetI(OutputQueue *queue);
size_t chOQWrite(OutputQueue *queue, uint8_t *buffer, size_t n);
#ifdef __cplusplus
}
#endif
#endif /* CH_USE_QUEUES */
#endif /* _QUEUES_H_ */
/** @} */

View File

@ -1,110 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file scheduler.h
* @brief Scheduler macros and structures.
* @addtogroup Scheduler
* @{
*/
#ifndef _SCHEDULER_H_
#define _SCHEDULER_H_
/** Default thread wakeup low level message. */
#define RDY_OK 0
/** Low level message sent to a thread awakened by a timeout. */
#define RDY_TIMEOUT -1
/** Low level message sent to a thread awakened by a reset operation. */
#define RDY_RESET -2
#define NOPRIO 0 /**< Ready list header priority.*/
#define IDLEPRIO 1 /**< Idle thread priority.*/
#define LOWPRIO 2 /**< Lowest user priority.*/
#define NORMALPRIO 64 /**< Normal user priority.*/
#define HIGHPRIO 127 /**< Highest user priority.*/
#define ABSPRIO 255 /**< Greatest possible priority.*/
/**
* Zero time specification for some syscalls with a timeout
* specification.
* @note Not all functions accept @p TIME_IMMEDIATE as timeout parameter,
* see the specific function documentation.
*/
#define TIME_IMMEDIATE ((systime_t)-1)
/**
* Infinite time specification for all the syscalls with a timeout
* specification.
*/
#define TIME_INFINITE ((systime_t)0)
/** The priority of the first thread on the given ready list. */
#define firstprio(rlp) ((rlp)->p_next->p_prio)
/**
* @brief Ready list header.
*
* @extends ThreadsQueue
*/
typedef struct {
Thread *p_next; /**< Next @p Thread in the ready list.*/
Thread *p_prev; /**< Previous @p Thread in the ready
list.*/
/* End of the fields shared with the ThreadsQueue structure. */
tprio_t r_prio; /**< This field must be initialized to
zero.*/
/* End of the fields shared with the Thread structure. */
#if CH_USE_ROUNDROBIN
cnt_t r_preempt; /**< Round robin counter.*/
#endif
#ifndef CH_CURRP_REGISTER_CACHE
Thread *r_current; /**< The currently running thread.*/
#endif
} ReadyList;
extern ReadyList rlist;
/*
* Scheduler APIs.
*/
#ifdef __cplusplus
extern "C" {
#endif
void scheduler_init(void);
Thread *chSchReadyI(Thread *tp);
void chSchGoSleepS(tstate_t newstate);
msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t time);
void chSchWakeupS(Thread *tp, msg_t msg);
void chSchDoRescheduleI(void);
void chSchRescheduleS(void);
bool_t chSchRescRequiredI(void);
#ifdef __cplusplus
}
#endif
#ifdef CH_CURRP_REGISTER_CACHE
register Thread *currp asm(CH_CURRP_REGISTER_CACHE);
#else
#define currp rlist.r_current
#endif
#endif /* _SCHEDULER_H_ */
/** @} */

View File

@ -1,99 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file semaphores.h
* @brief Semaphores macros and structures.
* @addtogroup Semaphores
* @{
*/
#ifndef _SEMAPHORES_H_
#define _SEMAPHORES_H_
#if CH_USE_SEMAPHORES
/**
* @brief Semaphore structure.
*/
typedef struct Semaphore {
ThreadsQueue s_queue; /**< Queue of the threads sleeping on
this semaphore.*/
cnt_t s_cnt; /**< The semaphore counter.*/
} Semaphore;
#ifdef __cplusplus
extern "C" {
#endif
void chSemInit(Semaphore *sp, cnt_t n);
void chSemReset(Semaphore *sp, cnt_t n);
void chSemResetI(Semaphore *sp, cnt_t n);
msg_t chSemWait(Semaphore *sp);
msg_t chSemWaitS(Semaphore *sp);
msg_t chSemWaitTimeout(Semaphore *sp, systime_t time);
msg_t chSemWaitTimeoutS(Semaphore *sp, systime_t time);
void chSemSignal(Semaphore *sp);
void chSemSignalI(Semaphore *sp);
#if CH_USE_SEMSW
msg_t chSemSignalWait(Semaphore *sps, Semaphore *spw);
#endif
#ifdef __cplusplus
}
#endif
/**
* @brief Data part of a static semaphore initializer.
* @details This macro should be used when statically initializing a semaphore
* that is part of a bigger structure.
* @param name the name of the semaphore variable
* @param n the counter initial value, this value must be non-negative
*/
#define _SEMAPHORE_DATA(name, n) {_THREADSQUEUE_DATA(name.s_queue), n}
/**
* @brief Static semaphore initializer.
* @details Statically initialized semaphores require no explicit initialization
* using @p chSemInit().
* @param name the name of the semaphore variable
* @param n the counter initial value, this value must be non-negative
*/
#define SEMAPHORE_DECL(name, n) Semaphore name = _SEMAPHORE_DATA(name, n)
/**
* Decreases the semaphore counter, this macro can be used when it is ensured
* that the counter would not become negative.
*/
#define chSemFastWaitI(sp) ((sp)->s_cnt--)
/**
* Increases the semaphore counter, this macro can be used when the counter is
* not negative.
*/
#define chSemFastSignalI(sp) ((sp)->s_cnt++)
/**
* Returns the semaphore counter current value.
*/
#define chSemGetCounterI(sp) ((sp)->s_cnt)
#endif /* CH_USE_SEMAPHORES */
#endif /* _SEMAPHORES_H_ */
/** @} */

View File

@ -1,217 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file serial.h
* @brief Serial Drivers macros and structures.
* @addtogroup Serial
* @{
*/
#ifndef _SERIAL_H_
#define _SERIAL_H_
#if CH_USE_SERIAL_FULLDUPLEX
/** No pending conditions.*/
#define SD_NO_ERROR 0
/** Connection happened.*/
#define SD_CONNECTED 1
/** Disconnection happened.*/
#define SD_DISCONNECTED 2
/** Parity error happened.*/
#define SD_PARITY_ERROR 4
/** Framing error happened.*/
#define SD_FRAMING_ERROR 8
/** Overflow happened.*/
#define SD_OVERRUN_ERROR 16
/** Break detected.*/
#define SD_BREAK_DETECTED 32
/** Serial Driver condition flags type.*/
typedef uint8_t dflags_t;
/**
* @brief @p FullDuplexDriver specific methods.
*/
struct _full_duplex_driver_methods {
};
/**
* @brief @p FullDuplexDriver specific data.
*/
struct _full_duplex_driver_data {
/**
* Input queue, incoming data can be read from this input queue by
* using the queues APIs.
*/
InputQueue iqueue;
/**
* Output queue, outgoing data can be written to this output queue by
* using the queues APIs.
*/
OutputQueue oqueue;
/**
* Status Change @p EventSource. This event is generated when one or more
* condition flags change.
*/
EventSource sevent;
/**
* I/O driver status flags.
*/
dflags_t flags;
};
/**
* @brief @p FullDuplexDriver virtual methods table.
*/
struct FullDuplexDriverVMT {
/**
* @p BaseChannel class inherited methods.
*/
struct _base_channel_methods m0;
/**
* @p BaseAsynchronousChannel class inherited methods.
*/
struct _base_asynchronous_channel_methods m1;
/**
* @p FullDuplexDriver specific methods.
*/
struct _full_duplex_driver_methods m2;
};
/**
* @extends BaseAsynchronousChannel
*
* @brief Full duplex serial driver class.
* @details This class extends @p GenericSerialDriver by adding physical I/O
* queues.
*/
typedef struct {
/**
* Virtual Methods Table.
*/
const struct FullDuplexDriverVMT *vmt;
/**
* @p BaseChannel class inherited data.
*/
struct _base_channel_data d0;
/**
* @p BaseAsynchronousChannel class inherited data.
*/
struct _base_asynchronous_channel_data d1;
/**
* @p FullDuplexDriver specific data.
*/
struct _full_duplex_driver_data d2;
} FullDuplexDriver;
#ifdef __cplusplus
extern "C" {
#endif
void chFDDInit(FullDuplexDriver *sd,
uint8_t *ib, size_t isize, qnotify_t inotify,
uint8_t *ob, size_t osize, qnotify_t onotify);
void chFDDIncomingDataI(FullDuplexDriver *sd, uint8_t b);
msg_t chFDDRequestDataI(FullDuplexDriver *sd);
void chFDDAddFlagsI(FullDuplexDriver *sd, dflags_t mask);
dflags_t chFDDGetAndClearFlags(FullDuplexDriver *sd);
#ifdef __cplusplus
}
#endif
/**
* @brief Direct output check on a @p FullDuplexDriver.
* @details This function bypasses the indirect access to the channel and
* checks directly the output queue. This is faster but cannot
* be used to check different channels implementations.
* @see chIOPutWouldBlock()
*/
#define chFDDPutWouldBlock(sd) chOQIsFull(&(sd)->d2.oqueue)
/**
* @brief Direct input check on a @p FullDuplexDriver.
* @details This function bypasses the indirect access to the channel and
* checks directly the input queue. This is faster but cannot
* be used to check different channels implementations.
* @see chIOGetWouldBlock()
*/
#define chFDDGetWouldBlock(sd) chIQIsEmpty(&(sd)->d2.iqueue)
/**
* @brief Direct blocking write to a @p FullDuplexDriver.
* @details This function bypasses the indirect access to the channel and
* writes directly on the output queue. This is faster but cannot
* be used to write to different channels implementations.
* @see chIOPut()
*/
#define chFDDPut(sd, b) chOQPut(&(sd)->d2.oqueue, b)
/**
* @brief Direct blocking write on a @p FullDuplexDriver with timeout
* specification.
* @details This function bypasses the indirect access to the channel and
* writes directly on the output queue. This is faster but cannot
* be used to write to different channels implementations.
* @see chIOPutTimeout()
*/
#define chFDDPutTimeout(sd, b, t) chOQPutTimeout(&(sd)->d2.iqueue, b, t)
/**
* @brief Direct blocking read from a @p FullDuplexDriver.
* @details This function bypasses the indirect access to the channel and
* reads directly from the input queue. This is faster but cannot
* be used to read from different channels implementations.
* @see chIOGet()
*/
#define chFDDGet(sd) chIQGet(&(sd)->d2.iqueue)
/**
* @brief Direct blocking read from a @p FullDuplexDriver with timeout
* specification.
* @details This function bypasses the indirect access to the channel and
* reads directly from the input queue. This is faster but cannot
* be used to read from different channels implementations.
* @see chIOGetTimeout()
*/
#define chFDDGetTimeout(sd, t) chIQGetTimeout(&(sd)->d2.iqueue, t)
/**
* @brief Direct non-blocking write to a @p FullDuplexDriver.
* @details This function bypasses the indirect access to the channel and
* writes directly to the output queue. This is faster but cannot
* be used to write from different channels implementations.
* @see chIOWrite()
*/
#define chFDDWrite(sd, b, n) chOQWrite(&(sd)->d2.oqueue, b, n)
/**
* @brief Direct non-blocking read on a @p FullDuplexDriver.
* @details This function bypasses the indirect access to the channel and
* reads directly from the input queue. This is faster but cannot
* be used to read from different channels implementations.
* @see chIORead()
*/
#define chFDDRead(sd, b, n) chIQRead(&(sd)->d2.iqueue, b, n)
#endif /* CH_USE_SERIAL_FULLDUPLEX */
#endif /* _SERIAL_H_ */
/** @} */

View File

@ -1,184 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file sys.h
* @brief System related macros and structures.
* @addtogroup System
* @{
*/
#ifndef _SYS_H_
#define _SYS_H_
/**
* @brief Halts the system.
* @details This function is invoked by the operating system when an
* unrecoverable error is detected (as example because a programming error in
* the application code that triggers an assertion while in debug mode).
*/
#define chSysHalt() port_halt()
/**
* @brief Performs a context switch.
*
* @param otp the thread to be switched out
* @param ntp the thread to be switched in
*/
#define chSysSwitchI(otp, ntp) port_switch(otp, ntp)
/**
* @brief Raises the system interrupt priority mask to the maximum level.
* @details All the maskable interrupt sources are disabled regardless their
* hardware priority.
*
* @note The implementation is architecture dependent, it may just disable the
* interrupts or be exactly equivalent to @p chSysDisable().
* @note Do not invoke this API from within a kernel lock.
*/
#define chSysDisable() port_disable()
/**
* @brief Raises the system interrupt priority mask to system level.
* @details The interrupt sources that should not be able to preempt the kernel
* are disabled, interrupt sources with higher priority are still enabled.
*
* @note The implementation is architecture dependent, it may just disable the
* interrupts.
* @note Do not invoke this API from within a kernel lock.
* @note This API is no replacement for @p chSysLock(), the @p chSysLock()
* could do more than just disable the interrupts.
*/
#define chSysSuspend() port_suspend()
/**
* @brief Lowers the system interrupt priority mask to user level.
* @details All the interrupt sources are enabled.
*
* @note The implementation is architecture dependent, it may just enable the
* interrupts.
* @note Do not invoke this API from within a kernel lock.
* @note This API is no replacement for @p chSysUnlock(), the @p chSysUnlock()
* could do more than just enable the interrupts.
*/
#define chSysEnable() port_enable()
/**
* @brief Enters the kernel lock mode.
*
* @note The use of kernel lock mode is not recommended in the user code, it is
* a better idea to use the semaphores or mutexes instead.
* @see CH_USE_NESTED_LOCKS
*/
#if CH_USE_NESTED_LOCKS || defined(__DOXYGEN__)
#if CH_OPTIMIZE_SPEED || defined(__DOXYGEN__)
#define chSysLock() { \
if (currp->p_locks++ == 0) \
port_lock(); \
}
#endif /* CH_OPTIMIZE_SPEED */
#else /* !CH_USE_NESTED_LOCKS */
#define chSysLock() port_lock()
#endif /* !CH_USE_NESTED_LOCKS */
/**
* @brief Leaves the kernel lock mode.
*
* @note The use of kernel lock mode is not recommended in the user code, it is
* a better idea to use the semaphores or mutexes instead.
* @see CH_USE_NESTED_LOCKS
*/
#if CH_USE_NESTED_LOCKS || defined(__DOXYGEN__)
#if CH_OPTIMIZE_SPEED || defined(__DOXYGEN__)
#define chSysUnlock() { \
if (--currp->p_locks == 0) \
port_unlock(); \
}
#endif /* CH_OPTIMIZE_SPEED */
#else /* !CH_USE_NESTED_LOCKS */
#define chSysUnlock() port_unlock()
#endif /* !CH_USE_NESTED_LOCKS */
/**
* @brief Enters the kernel lock mode from within an interrupt handler.
*
* @note This API may do nothing on some architectures, it is required because
* on ports that support preemptable interrupt handlers it is required to
* raise the interrupt mask to the same level of the system mutual
* exclusion zone.<br>
* It is good practice to invoke this API before invoking any I-class
* syscall from an interrupt handler.
* @note This API must be invoked exclusively from interrupt handlers.
*/
#define chSysLockFromIsr() port_lock_from_isr()
/**
* @brief Leaves the kernel lock mode from within an interrupt handler.
*
* @note This API may do nothing on some architectures, it is required because
* on ports that support preemptable interrupt handlers it is required to
* raise the interrupt mask to the same level of the system mutual
* exclusion zone.<br>
* It is good practice to invoke this API after invoking any I-class
* syscall from an interrupt handler.
* @note This API must be invoked exclusively from interrupt handlers.
*/
#define chSysUnlockFromIsr() port_unlock_from_isr()
/**
* @brief IRQ handler enter code.
*
* @note Usually IRQ handlers functions are also declared naked.
* @note On some architectures this macro can be empty.
*/
#define CH_IRQ_PROLOGUE() PORT_IRQ_PROLOGUE()
/**
* @brief IRQ handler exit code.
*
* @note Usually IRQ handlers function are also declared naked.
* @note This macro usually performs the final reschedulation by using
* @p chSchRescRequiredI() and @p chSchDoRescheduleI().
*/
#define CH_IRQ_EPILOGUE() PORT_IRQ_EPILOGUE()
/**
* @brief Standard IRQ handler declaration.
*
* @note @p id can be a function name or a vector number depending on the
* port implementation.
*/
#define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id)
#ifdef __cplusplus
extern "C" {
#endif
void chSysInit(void);
void chSysTimerHandlerI(void);
#if CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED
void chSysLock(void);
void chSysUnlock(void);
#endif /* CH_USE_NESTED_LOCKS && !CH_OPTIMIZE_SPEED */
#ifdef __cplusplus
}
#endif
#endif /* _SYS_H_ */
/** @} */

View File

@ -1,269 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file threads.h
* @brief Threads macros and structures.
* @addtogroup Threads
* @{
*/
#ifndef _THREADS_H_
#define _THREADS_H_
/**
* @brief Structure representing a thread.
*
* @extends ThreadsQueue
* @note Not all the listed fields are always needed, by switching off some
* not needed ChibiOS/RT subsystems it is possible to save RAM space by
* shrinking the @p Thread structure.
*/
struct Thread {
Thread *p_next; /**< Next @p Thread in the threads
list/queue.*/
/* End of the fields shared with the ThreadsList structure. */
Thread *p_prev; /**< Previous @p Thread in the threads
queue.*/
/* End of the fields shared with the ThreadsQueue structure. */
tprio_t p_prio; /**< Thread priority.*/
/* End of the fields shared with the ReadyList structure. */
tstate_t p_state; /**< Current thread state.*/
tmode_t p_flags; /**< Various flags.*/
struct context p_ctx; /**< Processor context.*/
#if CH_USE_NESTED_LOCKS
cnt_t p_locks; /**< Number of nested locks.*/
#endif
#if CH_DBG_THREADS_PROFILING
volatile systime_t p_time; /**< Consumed time.
@note This field can overflow.*/
#endif
/*
* The following fields are merged in unions because they are all
* state-specific fields. This trick saves some extra space for each
* thread in the system.
*/
union {
msg_t p_rdymsg; /**< Thread wakeup code.*/
msg_t p_exitcode; /**< The thread exit code
(@p PREXIT state).*/
void *p_wtobjp; /**< Generic kernel object pointer used
for opaque access.*/
#if CH_USE_SEMAPHORES
Semaphore *p_wtsemp; /**< Semaphore where the thread is
waiting on (@p PRWTSEM state).*/
#endif
#if CH_USE_MUTEXES
Mutex *p_wtmtxp; /**< Mutex where the thread is waiting
on (@p PRWTMTX state).*/
#endif
#if CH_USE_CONDVARS
CondVar *p_wtcondp; /**< CondVar where the thread is
waiting on (@p PRWTCOND state).*/
#endif
#if CH_USE_MESSAGES
Thread *p_wtthdp; /**< Destination thread for message
send @p PRSNDMSG state).*/
#endif
#if CH_USE_EVENTS
eventmask_t p_ewmask; /**< Enabled events mask (@p PRWTOREVT
or @p PRWTANDEVT states).*/
#endif
};
/*
* Start of the optional fields.
*/
#if CH_USE_WAITEXIT
Thread *p_waiting; /**< Thread waiting for termination.*/
#endif
#if CH_USE_MESSAGES
ThreadsQueue p_msgqueue; /**< Message queue.*/
msg_t p_msg; /**< The message.*/
#endif
#if CH_USE_EVENTS
eventmask_t p_epending; /**< Pending events mask.*/
#endif
#if CH_USE_MUTEXES
Mutex *p_mtxlist; /**< List of the mutexes owned by this
thread, @p NULL terminated.*/
tprio_t p_realprio; /**< Thread's own, non-inherited,
priority.*/
#endif
#if CH_USE_DYNAMIC && CH_USE_MEMPOOLS
void *p_mpool; /**< Memory Pool where the thread
workspace is returned.*/
#endif
/* Extra fields defined in chconf.h */
THREAD_EXT_FIELDS
};
/** Thread state: Ready to run, waiting on the ready list.*/
#define PRREADY 0
/** Thread state: Currently running. */
#define PRCURR 1
/** Thread state: Thread created in suspended state. */
#define PRSUSPENDED 2
/** Thread state: Waiting on a semaphore. */
#define PRWTSEM 3
/** Thread state: Waiting on a mutex. */
#define PRWTMTX 4
/** Thread state: Waiting in @p chThdSleep() or @p chThdSleepUntil(). */
#define PRWTCOND 5
/** Thread state: Waiting in @p chCondWait(). */
#define PRSLEEP 6
/** Thread state: Waiting in @p chThdWait(). */
#define PRWAIT 7
/** Thread state: Waiting in @p chEvtWaitOneTimeout() or
@p chEvtWaitAnyTimeout(). */
#define PRWTOREVT 8
/** Thread state: Waiting in @p chEvtWaitAllTimeout(). */
#define PRWTANDEVT 9
/** Thread state: Waiting in @p chMsgSend(). */
#define PRSNDMSG 10
/** Thread state: Waiting in @p chMsgWait(). */
#define PRWTMSG 11
/** Thread state: After termination.*/
#define PREXIT 12
/*
* Various flags into the thread p_flags field.
*/
#define P_MEM_MODE_MASK 3 /* Thread memory mode mask. */
#define P_MEM_MODE_STATIC 0 /* Thread memory mode: static. */
#define P_MEM_MODE_HEAP 1 /* Thread memory mode: heap. */
#define P_MEM_MODE_MEMPOOL 2 /* Thread memory mode: mempool. */
#define P_TERMINATE 4 /* Termination requested. */
/* Not an API, don't use into the application code.*/
Thread *init_thread(Thread *tp, tprio_t prio);
/** Thread function.*/
typedef msg_t (*tfunc_t)(void *);
/*
* Threads APIs.
*/
#ifdef __cplusplus
extern "C" {
#endif
Thread *chThdInit(void *wsp, size_t size,
tprio_t prio, tfunc_t pf, void *arg);
Thread *chThdCreateStatic(void *wsp, size_t size,
tprio_t prio, tfunc_t pf, void *arg);
#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_HEAP
Thread *chThdCreateFromHeap(size_t size, tprio_t prio,
tfunc_t pf, void *arg);
#endif
#if CH_USE_DYNAMIC && CH_USE_WAITEXIT && CH_USE_MEMPOOLS
Thread *chThdCreateFromMemoryPool(MemoryPool *mp, tprio_t prio,
tfunc_t pf, void *arg);
#endif
tprio_t chThdSetPriority(tprio_t newprio);
Thread *chThdResume(Thread *tp);
void chThdTerminate(Thread *tp);
void chThdSleep(systime_t time);
void chThdSleepUntil(systime_t time);
void chThdExit(msg_t msg);
#if CH_USE_WAITEXIT
msg_t chThdWait(Thread *tp);
#endif
#ifdef __cplusplus
}
#endif
/** Returns the pointer to the @p Thread currently in execution.*/
#define chThdSelf() currp
/** Returns the current thread priority.*/
#define chThdGetPriority() (currp->p_prio)
/** Returns the pointer to the @p Thread local storage area, if any.*/
#define chThdLS() (void *)(currp + 1)
/**
* Verifies if the specified thread is in the @p PREXIT state.
*
* @param[in] tp the pointer to the thread
* @retval TRUE thread terminated.
* @retval FALSE thread not terminated.
*/
#define chThdTerminated(tp) ((tp)->p_state == PREXIT)
/**
* Verifies if the current thread has a termination request pending.
*
* @retval TRUE termination request pended.
* @retval FALSE termination request not pended.
*/
#define chThdShouldTerminate() (currp->p_flags & P_TERMINATE)
/**
* Resumes a thread created with @p chThdInit().
*
* @param[in] tp the pointer to the thread
*/
#define chThdResumeI(tp) chSchReadyI(tp)
/**
* Suspends the invoking thread for the specified time.
*
* @param[in] time the delay in system ticks, the special values are handled as
* follow:
* - @a TIME_INFINITE the thread enters an infinite sleep
* state.
* - @a TIME_IMMEDIATE this value is accepted but interpreted
* as a normal time specification not as an immediate timeout
* specification.
* .
*/
#define chThdSleepS(time) chSchGoSleepTimeoutS(PRSLEEP, time)
/**
* Delays the invoking thread for the specified number of seconds.
*
* @param[in] sec the time in seconds
* @note The specified time is rounded up to a value allowed by the real
* system clock.
* @note The maximum specified value is implementation dependent.
*/
#define chThdSleepSeconds(sec) chThdSleep(S2ST(sec))
/**
* Delays the invoking thread for the specified number of milliseconds.
*
* @param[in] msec the time in milliseconds
* @note The specified time is rounded up to a value allowed by the real
* system clock.
* @note The maximum specified value is implementation dependent.
*/
#define chThdSleepMilliseconds(msec) chThdSleep(MS2ST(msec))
/**
* Delays the invoking thread for the specified number of microseconds.
*
* @param[in] usec the time in microseconds
* @note The specified time is rounded up to a value allowed by the real
* system clock.
* @note The maximum specified value is implementation dependent.
*/
#define chThdSleepMicroseconds(usec) chThdSleep(US2ST(usec))
#endif /* _THREADS_H_ */
/** @} */

View File

@ -1,125 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file vt.h
* @brief Time macros and structures.
* @addtogroup Time
* @{
*/
#ifndef _VT_H_
#define _VT_H_
/**
* Time conversion utility. Converts from seconds to system ticks number.
*/
#define S2ST(sec) ((systime_t)((sec) * CH_FREQUENCY))
/**
* Time conversion utility. Converts from milliseconds to system ticks number.
* @note The result is rounded upward to the next tick boundary.
*/
#define MS2ST(msec) ((systime_t)(((((msec) - 1L) * CH_FREQUENCY) / 1000L) + 1L))
/**
* Time conversion utility. Converts from microseconds to system ticks number.
* @note The result is rounded upward to the next tick boundary.
*/
#define US2ST(usec) ((systime_t)(((((usec) - 1L) * CH_FREQUENCY) / 1000000L) + 1L))
/** Virtual Timer callback function.*/
typedef void (*vtfunc_t)(void *);
typedef struct VirtualTimer VirtualTimer;
/**
* @brief Virtual Timer descriptor structure.
* @extends DeltaList
*/
struct VirtualTimer {
VirtualTimer *vt_next; /**< Next timer in the delta list.*/
VirtualTimer *vt_prev; /**< Previous timer in the delta list.*/
systime_t vt_time; /**< Time delta before timeout.*/
vtfunc_t vt_func; /**< Timer callback function pointer.
The pointer is reset to zero after
the callback is invoked.*/
void *vt_par; /**< Timer callback function
parameter.*/
};
/**
* @brief Virtual timers list header.
* @note The delta list is implemented as a double link bidirectional list in
* order to make the unlink time constant, the reset of a virtual timer
* is often used in the code.
*/
typedef struct {
VirtualTimer *vt_next; /**< Next timer in the delta list (the
one that will be triggered next).*/
VirtualTimer *vt_prev; /**< Last timer in the delta list.*/
systime_t vt_time; /**< Must be initialized to -1.*/
volatile systime_t vt_systime; /**< System Time counter.*/
} VTList;
extern VTList vtlist;
#define chVTDoTickI() { \
vtlist.vt_systime++; \
if (&vtlist != (VTList *)vtlist.vt_next) { \
VirtualTimer *vtp; \
\
--vtlist.vt_next->vt_time; \
while (!(vtp = vtlist.vt_next)->vt_time) { \
vtfunc_t fn = vtp->vt_func; \
vtp->vt_func = NULL; \
(vtp->vt_next->vt_prev = (void *)&vtlist)->vt_next = vtp->vt_next;\
fn(vtp->vt_par); \
} \
} \
}
/*
* Virtual Timers APIs.
*/
#ifdef __cplusplus
extern "C" {
#endif
void vt_init(void);
void chVTSetI(VirtualTimer *vtp, systime_t time, vtfunc_t vtfunc, void *par);
void chVTResetI(VirtualTimer *vtp);
bool_t chTimeIsWithin(systime_t start, systime_t end);
#ifdef __cplusplus
}
#endif
/** Returns TRUE if the speciified timer is armed.*/
#define chVTIsArmedI(vtp) ((vtp)->vt_func != NULL)
/**
* Returns the number of system ticks since the @p chSysInit() invocation.
* @return the system ticks number
* @note The counter can reach its maximum and then returns to zero.
* @note This function is designed to work with the @p chThdSleepUntil().
*/
#define chTimeNow() (vtlist.vt_systime)
#endif /* _VT_H_ */
/** @} */

View File

@ -1,13 +0,0 @@
# List of all the ChibiOS/RT kernel files, there is no need to remove the files
# from this list, you can disable parts of the kernel by editing chconf.h.
KERNSRC = ../../src/chsys.c ../../src/chdebug.c \
../../src/chlists.c ../../src/chvt.c \
../../src/chschd.c ../../src/chthreads.c \
../../src/chsem.c ../../src/chmtx.c \
../../src/chcond.c ../../src/chevents.c \
../../src/chmsg.c ../../src/chmboxes.c \
../../src/chqueues.c ../../src/chheap.c \
../../src/chmempools.c ../../src/chserial.c
# Required include directories
KERNINC = ../../src/include

View File

@ -1,335 +0,0 @@
/*
ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio.
This file is part of ChibiOS/RT.
ChibiOS/RT is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
ChibiOS/RT is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @file ch.cpp
* @brief C++ wrapper code.
* @addtogroup CPlusPlusLibrary
* @{
*/
#include <ch.hpp>
namespace chibios_rt {
/*------------------------------------------------------------------------*
* chibios_rt::System *
*------------------------------------------------------------------------*/
void System::Init(void) {
chSysInit();
}
void System::Lock(void) {
chSysLock();
}
void System::Unlock(void) {
chSysUnlock();
}
systime_t System::GetTime(void) {
return chTimeNow();
}
/*------------------------------------------------------------------------*
* chibios_rt::Timer *
*------------------------------------------------------------------------*/
void Timer::Set(systime_t time, vtfunc_t vtfunc, void *par) {
chVTSetI(&timer, time, vtfunc, par);
}
void Timer::Reset() {
chVTResetI(&timer);
}
bool Timer::IsArmed(void) {
return chVTIsArmedI(&timer);
}
/*------------------------------------------------------------------------*
* chibios_rt::BaseThread *
*------------------------------------------------------------------------*/
static msg_t thdstart(void *arg) {
return ((BaseThread *)arg)->Main();
}
BaseThread::BaseThread(void *workspace, size_t wsize, tprio_t prio) {
thread_ref = chThdCreateStatic(workspace, wsize, prio, thdstart, this);
}
void BaseThread::Exit(msg_t msg) {
chThdExit(msg);
}
#if CH_USE_WAITEXIT
msg_t BaseThread::Wait(void) {
return chThdWait(thread_ref);
}
#endif /* CH_USE_WAITEXIT */
void BaseThread::SetPriority(tprio_t newprio) {
chThdSetPriority(newprio);
}
void BaseThread::Resume(void) {
chThdResume(thread_ref);
}
void BaseThread::Terminate(void) {
chThdTerminate(thread_ref);
}
void BaseThread::Sleep(systime_t n) {
chThdSleep(n);
}
void BaseThread::SleepUntil(systime_t time) {
chThdSleepUntil(time);
}
#if CH_USE_MESSAGES
msg_t BaseThread::SendMessage(::Thread* tp, msg_t msg) {
return chMsgSend(tp, msg);
}
msg_t BaseThread::SendMessage(msg_t msg) {
return chMsgSend(thread_ref, msg);
}
msg_t BaseThread::WaitMessage(void) {
return chMsgWait();
}
msg_t BaseThread::GetMessage(void) {
return chMsgGet();
}
void BaseThread::ReleaseMessage(msg_t msg) {
chMsgRelease(msg);
}
bool BaseThread::IsPendingMessage(void) {
return chMsgIsPendingI(currp);
}
#endif /* CH_USE_MESSAGES */
msg_t BaseThread::Main(void) {
return 0;
}
#if CH_USE_SEMAPHORES
/*------------------------------------------------------------------------*
* chibios_rt::Semaphore *
*------------------------------------------------------------------------*/
Semaphore::Semaphore(cnt_t n) {
chSemInit(&sem, n);
}
void Semaphore::Reset(cnt_t n) {
chSemReset(&sem, n);
}
msg_t Semaphore::Wait(void) {
return chSemWait(&sem);
}
msg_t Semaphore::WaitTimeout(systime_t time) {
return chSemWaitTimeout(&sem, time);
}
void Semaphore::Signal(void) {
chSemSignal(&sem);
}
#if CH_USE_SEMSW
msg_t Semaphore::SignalWait(Semaphore *ssem, Semaphore *wsem) {
return chSemSignalWait(&ssem->sem, &wsem->sem);
}
#endif /* CH_USE_SEMSW */
#endif /* CH_USE_SEMAPHORES */
#if CH_USE_MUTEXES
/*------------------------------------------------------------------------*
* chibios_rt::Mutex *
*------------------------------------------------------------------------*/
Mutex::Mutex(void) {
chMtxInit(&mutex);
}
bool Mutex::TryLock(void) {
return chMtxTryLock(&mutex);
}
void Mutex::Lock(void) {
chMtxLock(&mutex);
}
void Mutex::Unlock(void) {
chMtxUnlock();
}
void UnlockAll(void) {
chMtxUnlockAll();
}
#if CH_USE_CONDVARS
/*------------------------------------------------------------------------*
* chibios_rt::CondVar *
*------------------------------------------------------------------------*/
CondVar::CondVar(void) {
chCondInit(&condvar);
}
void CondVar::Signal(void) {
chCondSignal(&condvar);
}
void CondVar::Broadcast(void) {
chCondBroadcast(&condvar);
}
msg_t CondVar::Wait(void) {
return chCondWait(&condvar);
}
#if CH_USE_CONDVARS_TIMEOUT
msg_t CondVar::WaitTimeout(systime_t time) {
return chCondWaitTimeout(&condvar, time);
}
#endif /* CH_USE_CONDVARS_TIMEOUT */
#endif /* CH_USE_CONDVARS */
#endif /* CH_USE_MUTEXES */
#if CH_USE_EVENTS
/*------------------------------------------------------------------------*
* chibios_rt::Event *
*------------------------------------------------------------------------*/
Event::Event(void) {
chEvtInit(&event);
}
void Event::Register(EventListener *elp, eventid_t eid) {
chEvtRegister(&event,elp, eid);
}
void Event::RegisterMask(EventListener *elp, eventmask_t emask) {
chEvtRegisterMask(&event,elp, emask);
}
void Event::Unregister(EventListener *elp) {
chEvtUnregister(&event, elp);
}
void Event::Broadcast(void) {
chEvtBroadcast(&event);
}
eventmask_t Event::Clear(eventmask_t mask) {
return chEvtClear(mask);
}
eventmask_t Event::Pend(eventmask_t mask) {
return chEvtPend(mask);
}
void Event::Dispatch(const evhandler_t handlers[], eventmask_t mask) {
chEvtDispatch(handlers, mask);
}
eventmask_t Event::WaitOne(eventmask_t ewmask) {
return chEvtWaitOne(ewmask);
}
eventmask_t Event::WaitAny(eventmask_t ewmask) {
return chEvtWaitAny(ewmask);
}
eventmask_t Event::WaitAll(eventmask_t ewmask) {
return chEvtWaitAll(ewmask);
}
#if CH_USE_EVENTS_TIMEOUT
eventmask_t Event::WaitOneTimeout(eventmask_t ewmask, systime_t time) {
return chEvtWaitOneTimeout(ewmask, time);
}
eventmask_t Event::WaitAnyTimeout(eventmask_t ewmask, systime_t time) {
return chEvtWaitAnyTimeout(ewmask, time);
}
eventmask_t Event::WaitAllTimeout(eventmask_t ewmask, systime_t time) {
return chEvtWaitAllTimeout(ewmask, time);
}
#endif /* CH_USE_EVENTS_TIMEOUT */
#endif /* CH_USE_EVENTS */
}
/** @} */

Some files were not shown because too many files have changed in this diff Show More