git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1149 35acf78f-673a-0410-8e92-d51de3d6d3f4
parent
7dfa36f86d
commit
e8e651a11d
|
@ -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 ***
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
*/
|
|
@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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
|
|
@ -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_ */
|
|
@ -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_ */
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_*/
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_*/
|
||||
|
||||
/** @} */
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
*/
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
|
@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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 */
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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 */
|
||||
/** @} */
|
|
@ -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.
|
||||
*/
|
|
@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
*/
|
||||
|
|
@ -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
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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
|
@ -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 */
|
||||
/** @} */
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
*/
|
|
@ -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
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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");
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
*/
|
|
@ -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");
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
*/
|
|
@ -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 ***
|
|
@ -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);
|
||||
}
|
227
src/chcond.c
227
src/chcond.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
|
@ -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 */
|
||||
|
||||
/** @} */
|
392
src/chevents.c
392
src/chevents.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
276
src/chheap.c
276
src/chheap.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
111
src/chlists.c
111
src/chlists.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
244
src/chmboxes.c
244
src/chmboxes.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
112
src/chmempools.c
112
src/chmempools.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
125
src/chmsg.c
125
src/chmsg.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
299
src/chmtx.c
299
src/chmtx.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
304
src/chqueues.c
304
src/chqueues.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
242
src/chschd.c
242
src/chschd.c
|
@ -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
|
||||
}
|
||||
|
||||
/** @} */
|
257
src/chsem.c
257
src/chsem.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
168
src/chserial.c
168
src/chserial.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
129
src/chsys.c
129
src/chsys.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
381
src/chthreads.c
381
src/chthreads.c
|
@ -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 */
|
||||
|
||||
/** @} */
|
116
src/chvt.c
116
src/chvt.c
|
@ -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);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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_ */
|
||||
|
||||
/** @} */
|
125
src/include/vt.h
125
src/include/vt.h
|
@ -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_ */
|
||||
|
||||
/** @} */
|
|
@ -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
|
335
src/lib/ch.cpp
335
src/lib/ch.cpp
|
@ -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
Loading…
Reference in New Issue