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

master
gdisirio 2009-11-29 08:26:06 +00:00
parent 0d0e4d6191
commit 408aa71c97
97 changed files with 40020 additions and 0 deletions

388
os/haltmp/hal.dox Normal file
View File

@ -0,0 +1,388 @@
/*
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 IO HAL
* @brief Hardware Abstraction Layer.
* @details Under ChibiOS/RT the set of the various device driver interfaces
* is called the HAL subsystem: Hardware Abstraction Layer.<br>
* A device driver is usually split in two layers:
* - High Level Device Driver (<b>HLD</b>). This layer contains the definitions
* of the driver's APIs and the platform independent part of the driver.<br>
* An HLD is composed by two files:
* - @<driver@>.c, the high level implementation file. This file must be
* included in the Makefile in order to use the driver.
* - @<driver@>.h, the high level header file. This file must be included
* by the application code in order to access the driver's APIs.
* .
* - Low Level Device Driver (<b>LLD</b>). This layer contains the platform
* dependent part of the driver.<br>
* A LLD is composed by two files:
* - @<driver@>_lld.c, the low level implementation file. This file must be
* included in the Makefile in order to use the driver.
* - @<driver@>_lld.h, the high level header file. This file is implicitly
* included by the HLD header file.
* .
* The LLD may be not present in those drivers that do not access the
* hardware directly but through other device drivers, as example the
* @ref MMC_SPI driver uses the @ref SPI and @ref PAL drivers in order
* to implement its functionalities.
* .
* <h2>Available Device Drivers</h2>
* The I/O subsystem currently includes support for:
* - @ref HAL.
* - @ref PAL.
* - @ref SERIAL.
* - @ref ADC.
* - @ref CAN.
* - @ref MAC.
* - @ref MII.
* - @ref MMC_SPI.
* - @ref SPI.
* .
*/
/**
* @defgroup HAL HAL Driver
* @brief Hardware Abstraction Layer.
* @details The HAL driver performs the system initialization and includes
* the platform support code shared by the other drivers.
*
* @ingroup IO
*/
/**
* @defgroup HAL_LLD HAL Low Level Driver
* @brief @ref HAL low level driver template.
*
* @ingroup HAL
*/
/**
* @defgroup HAL_CONF Configuration
* @brief @ref HAL Configuration.
*
* @ingroup HAL
*/
/**
* @defgroup PAL PAL Driver
* @brief I/O Ports Abstraction Layer
* @details This module defines an abstract interface for digital I/O ports.
* Note that most I/O ports functions are just macros. The macros
* have default software implementations that can be redefined in a
* @ref PAL_LLD if the target hardware supports special features like, as
* example, atomic bit set/reset/masking. Please refer to the ports specific
* documentation for details.<br>
* The @ref PAL has the advantage to make the access to the I/O ports platform
* independent and still be optimized for the specific architectures.<br>
* Note that the @ref PAL_LLD may also offer non standard macro and functions
* in order to support specific features but, of course, the use of such
* interfaces would not be portable. Such interfaces shall be marked with
* the architecture name inside the function names.
*
* <h2>Implementation Rules</h2>
* In implementing an @ref PAL_LLD there are some rules/behaviors that
* should be respected.
*
* <h3>Writing on input pads</h3>
* The behavior is not specified but there are implementations better than
* others, this is the list of possible implementations, preferred options
* are on top:
* -# The written value is not actually output but latched, should the pads
* be reprogrammed as outputs the value would be in effect.
* -# The write operation is ignored.
* -# The write operation has side effects, as example disabling/enabling
* pull up/down resistors or changing the pad direction. This scenario is
* discouraged, please try to avoid this scenario.
* .
* <h3>Reading from output pads</h3>
* The behavior is not specified but there are implementations better than
* others, this is the list of possible implementations, preferred options
* are on top:
* -# The actual pads states are read (not the output latch).
* -# The output latch value is read (regardless of the actual pads states).
* -# Unspecified, please try to avoid this scenario.
* .
* <h3>Writing unused or unimplemented port bits</h3>
* The behavior is not specified.
*
* <h3>Reading from unused or unimplemented port bits</h3>
* The behavior is not specified.
*
* <h3>Reading or writing on pins associated to other functionalities</h3>
* The behavior is not specified.
*
* <h2>Usage</h2>
* The use of I/O ports requires the inclusion of the header file @p pal.h,
* this file is not automatically included @p ch.h like the other header
* files.
*
* @ingroup IO
*/
/**
* @defgroup PAL_LLD PAL Low Level Driver
* @brief @ref PAL low level driver template.
* @details This file is a template for an I/O port low level driver.
*
* @ingroup PAL
*/
/**
* @defgroup SERIAL Serial Driver
* @brief Generic Serial Driver.
* @details This module implements a generic full duplex serial driver. The
* driver implements a @p SerialDriver interface and uses I/O Queues for
* communication between the upper and the lower driver. Event flags are used
* to notify the application about incoming data, outgoing data and other I/O
* events.<br>
* The module also contains functions that make the implementation of the
* interrupt service routines much easier.
*
* @ingroup IO
*/
/**
* @defgroup SERIAL_LLD Serial Low Level Driver
* @brief @ref SERIAL low level driver template.
* @details This file is a template for a serial low level driver.
*
* @ingroup SERIAL
*/
/**
* @defgroup SPI SPI Driver
* @brief Generic SPI Driver.
* @details This module implements a generic SPI driver. The driver implements
* a state machine internally:
* @dot
digraph example {
rankdir="LR";
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.75"];
edge [fontname=Helvetica, fontsize=8];
uninit [label="SPI_UNINIT", style="bold"];
stop [label="SPI_STOP\nLow Power"];
ready [label="SPI_READY\nClock Enabled"];
active [label="SPI_ACTIVE\nBus Active"];
uninit -> stop [label="spiObjectInit()"];
stop -> ready [label="spiStart()"];
ready -> ready [label="spiStart()"];
ready -> ready [label="spiIgnore()"];
ready -> stop [label="spiStop()"];
stop -> stop [label="spiStop()"];
ready -> active [label="spiSelect()"];
active -> active [label="spiSelect()"];
active -> ready [label="spiUnselect()"];
ready -> ready [label="spiUnselect()"];
active -> active [label="spiIgnore()\nspiExchange()\nspiSend()\nspiReceive()"];
}
* @enddot
*
* The driver is not thread safe for performance reasons, if you need to access
* the SPI bus from multiple thread then use the @p spiAcquireBus() and
* @p spiReleaseBus() APIs in order to gain exclusive access.
*
* @ingroup IO
*/
/**
* @defgroup SPI_LLD SPI Low Level Driver
* @brief @ref SPI low level driver template.
* @details This file is a template for a SPI low level driver.
*
* @ingroup SPI
*/
/**
* @defgroup ADC ADC Driver
* @brief Generic ADC Driver.
* @details This module implements a generic ADC driver. The driver implements
* a state machine internally:
* @dot
digraph example {
rankdir="LR";
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.8", height="0.8"];
edge [fontname=Helvetica, fontsize=8];
uninit [label="ADC_UNINIT", style="bold"];
stop [label="ADC_STOP\nLow Power"];
ready [label="ADC_READY\nClock Enabled"];
running [label="ADC_RUNNING"];
complete [label="ADC_COMPLETE"];
uninit -> stop [label="adcObjectInit()"];
stop -> ready [label="adcStart()"];
ready -> ready [label="adcStart()"];
ready -> ready [label="adcWaitConversion()"];
ready -> stop [label="adcStop()"];
stop -> stop [label="adcStop()"];
ready -> running [label="adcStartConversion()"];
running -> ready [label="adcStopConversion()"];
running -> complete [label="End of Conversion"];
complete -> running [label="adcStartConversion()"];
complete -> ready [label="adcStopConversion()"];
complete -> ready [label="adcWaitConversion()"];
complete -> stop [label="adcStop()"];
}
* @enddot
*
* The driver supports a continuous conversion mode with circular buffer,
* callback functions allow to process the converted data in real time.
* Please refer to the documentation of the function @p adcStartConversion().
*
* @ingroup IO
*/
/**
* @defgroup ADC_LLD ADC Low Level Driver
* @brief @ref ADC low level driver template.
* @details This file is a template for a ADC low level driver.
*
* @ingroup ADC
*/
/**
* @defgroup CAN CAN Driver
* @brief Generic ADC Driver.
* @details This module implements a generic ADC driver. The driver implements
* a state machine internally:
* @dot
digraph example {
rankdir="LR";
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.8", height="0.8"];
edge [fontname=Helvetica, fontsize=8];
uninit [label="CAN_UNINIT", style="bold"];
stop [label="CAN_STOP\nLow Power"];
ready [label="CAN_READY\nClock Enabled"];
sleep [label="CAN_SLEEP\nLow Power"];
uninit -> stop [label="canObjectInit()"];
stop -> stop [label="canStop()"];
stop -> ready [label="canStart()"];
ready -> stop [label="canStop()"];
ready -> ready [label="canReceive()\ncanTransmit()"];
ready -> ready [label="canStart()"];
ready -> sleep [label="canSleep()"];
sleep -> sleep [label="canSleep()"];
sleep -> ready [label="canWakeup()"];
sleep -> ready [label="wakeup event"];
}
* @enddot
*
* @ingroup IO
*/
/**
* @defgroup CAN_LLD CAN Low Level Driver
* @brief @ref HAL low level driver template.
*
* @ingroup CAN
*/
/**
* @defgroup MAC MAC Driver
* @brief Generic MAC driver.
* @details This module implements a generic interface for MAC (Media
* Access Control) drivers, as example Ethernet controllers.
*
* @ingroup IO
*/
/**
* @defgroup MAC_LLD MAC Low Level Driver
* @brief @ref MAC low level driver template.
* @details This file is a template for a MAC low level driver.
*
* @ingroup MAC
*/
/**
* @defgroup MII MII Driver
* @brief Generic MII driver.
* @details This module implements a generic interface for MII (Media
* Independent Interface) drivers.
* The MII/RMII/GMII/RGMII/SGMII buses are standard interfaces meant
* to connect a MAC block to a PHY transceiver.<br>
* A @ref MII is usually used from within a @ref MAC and is not
* meant to be used directly from the application code.
*
* @ingroup IO
*/
/**
* @defgroup MII_LLD MII Low Level Driver
* @brief @ref MII low level driver template.
* @details This file is a template for a MII low level driver.
*
* @ingroup MII
*/
/**
* @defgroup MMC_SPI MMC over SPI Driver
* @brief Generic MMC driver.
* @details This module implements a portable MMC driver that uses a SPI
* driver as physical layer.<br>
* The driver implements the following state machine:
* @dot
digraph example {
rankdir="LR";
node [shape=circle, fontname=Helvetica, fontsize=8, fixedsize="true", width="0.75", height="0.8"];
edge [fontname=Helvetica, fontsize=8];
any [label="Any State"];
stop2 [label="MMC_STOP\nLow Power"];
uninit [label="MMC_UNINIT", style="bold"];
stop [label="MMC_STOP\nLow Power"];
wait [label="MMC_WAIT\nWaiting Card"];
inserted [label="MMC_INSERTED\nCard Inserted"];
ready [label="MMC_READY\nCard Ready"];
reading [label="MMC_READING\nReading"];
writing [label="MMC_WRITING\nWriting"];
uninit -> stop [label="mmcObjectInit()"];
stop -> wait [label="mmcStart()", constraint=false];
wait -> inserted [label="insertion (inserted event)"];
inserted -> inserted [label="mmcDisconnect()"];
inserted -> ready [label="mmcConnect()"];
ready -> ready [label="mmcConnect()"];
ready -> inserted [label="mmcDisconnect()"];
ready -> reading [label="mmcStartSequentialRead()"];
reading -> reading [label="mmcSequentialRead()"];
reading -> ready [label="mmcStopSequentialRead()"];
reading -> ready [label="read error"];
ready -> writing [label="mmcStartSequentialWrite()"];
writing -> writing [label="mmcSequentialWrite()"];
writing -> ready [label="mmcStopSequentialWrite()"];
writing -> ready [label="write error"];
inserted -> wait [label="removal (removed event)"];
ready -> wait [label="removal (removed event)"];
reading -> wait [label="removal (removed event)"];
writing -> wait [label="removal (removed event)"];
any -> stop2 [label="mmcStop()"];
}
* @enddot
*
* The MMC drivers currently supports only cards with capacity up to 2GB
* and does not implement CRC checking. Hot plugging and removal are supported
* through kernel events.
*
* @ingroup IO
*/

13
os/haltmp/hal.mk Normal file
View File

@ -0,0 +1,13 @@
# List of all the ChibiOS/RT HAL files, there is no need to remove the files
# from this list, you can disable parts of the kernel by editing halconf.h.
HALSRC = ${CHIBIOS}/os/hal/src/hal.c \
${CHIBIOS}/os/hal/src/adc.c \
${CHIBIOS}/os/hal/src/can.c \
${CHIBIOS}/os/hal/src/mac.c \
${CHIBIOS}/os/hal/src/pal.c \
${CHIBIOS}/os/hal/src/serial.c \
${CHIBIOS}/os/hal/src/spi.c \
${CHIBIOS}/os/hal/src/mmc_spi.c
# Required include directories
HALINC = ${CHIBIOS}/os/hal/include

71
os/haltmp/include/adc.h Normal file
View File

@ -0,0 +1,71 @@
/*
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 adc.h
* @brief ADC Driver macros and structures.
* @addtogroup ADC
* @{
*/
#ifndef _ADC_H_
#define _ADC_H_
#if CH_HAL_USE_ADC
#if !CH_USE_SEMAPHORES
#error "ADC driver requires CH_USE_SEMAPHORES"
#endif
/**
* @brief Driver state machine possible states.
*/
typedef enum {
ADC_UNINIT = 0, /**< @brief Not initialized. */
ADC_STOP = 1, /**< @brief Stopped. */
ADC_READY = 2, /**< @brief Ready. */
ADC_RUNNING = 3, /**< @brief Conversion running. */
ADC_COMPLETE = 4 /**< @brief Conversion complete.*/
} adcstate_t;
#include "adc_lld.h"
#ifdef __cplusplus
extern "C" {
#endif
void adcInit(void);
void adcObjectInit(ADCDriver *adcp);
void adcStart(ADCDriver *adcp, const ADCConfig *config);
void adcStop(ADCDriver *adcp);
bool_t adcStartConversion(ADCDriver *adcp,
const ADCConversionGroup *grpp,
adcsample_t *samples,
size_t depth,
adccallback_t callback);
void adcStopConversion(ADCDriver *adcp);
msg_t adcWaitConversion(ADCDriver *adcp, systime_t timeout);
#ifdef __cplusplus
}
#endif
#endif /* CH_HAL_USE_ADC */
#endif /* _ADC_H_ */
/** @} */

65
os/haltmp/include/can.h Normal file
View File

@ -0,0 +1,65 @@
/*
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 can.h
* @brief CAN Driver macros and structures.
* @addtogroup CAN
* @{
*/
#ifndef _CAN_H_
#define _CAN_H_
#if CH_HAL_USE_CAN
/**
* @brief Driver state machine possible states.
*/
typedef enum {
CAN_UNINIT = 0, /**< @brief Not initialized. */
CAN_STOP = 1, /**< @brief Stopped. */
CAN_READY = 2, /**< @brief Ready. */
CAN_SLEEP = 3 /**< @brief Sleep state. */
} canstate_t;
#include "can_lld.h"
#ifdef __cplusplus
extern "C" {
#endif
void canInit(void);
void canObjectInit(CANDriver *canp);
void canStart(CANDriver *canp, const CANConfig *config);
void canStop(CANDriver *canp);
msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout);
msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout);
#if CAN_USE_SLEEP_MODE
void canSleep(CANDriver *canp);
void canWakeup(CANDriver *canp);
#endif /* CAN_USE_SLEEP_MODE */
#ifdef __cplusplus
}
#endif
#endif /* CH_HAL_USE_CAN */
#endif /* _CAN_H_ */
/** @} */

59
os/haltmp/include/hal.h Normal file
View File

@ -0,0 +1,59 @@
/*
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 hal.h
* @brief HAL subsystem header.
* @addtogroup HAL
* @{
*/
#ifndef _HAL_H_
#define _HAL_H_
#include "halconf.h"
#include "board.h"
#include "hal_lld.h"
#include "pal.h"
#include "adc.h"
#include "can.h"
#include "mac.h"
#include "serial.h"
#include "spi.h"
#include "mmc_spi.h"
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
extern const STM32GPIOConfig pal_default_config;
#ifdef __cplusplus
extern "C" {
#endif
void halInit(void);
#ifdef __cplusplus
}
#endif
#endif /* _HAL_H_ */
/** @} */

93
os/haltmp/include/mac.h Normal file
View File

@ -0,0 +1,93 @@
/*
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 mac.h
* @brief MAC Driver macros and structures.
* @addtogroup MAC
* @{
*/
#ifndef _MAC_H_
#define _MAC_H_
#if CH_HAL_USE_MAC
#include "mac_lld.h"
/**
* @brief Returns the received frames event source.
*
* @param[in] macp pointer to the @p MACDriver object
* @return The pointer to the @p EventSource structure.
*/
#if CH_USE_EVENTS || defined(__DOXYGEN__)
#define macGetReceiveEventSource(macp) (&(macp)->md_rdevent)
#endif
/**
* @brief Writes to a transmit descriptor's stream.
*
* @param[in] tdp pointer to a @p MACTransmitDescriptor structure
* @param[in] buf pointer to the buffer containing the data to be written
* @param[in] size number of bytes to be written
* @return The number of bytes written into the descriptor's stream, this
* value can be less than the amount specified in the parameter
* @p size if the maximum frame size is reached.
*/
#define macWriteTransmitDescriptor(tdp, buf, size) \
mac_lld_write_transmit_descriptor(tdp, buf, size)
/**
* @brief Reads from a receive descriptor's stream.
*
* @param[in] rdp pointer to a @p MACReceiveDescriptor structure
* @param[in] buf pointer to the buffer that will receive the read data
* @param[in] size number of bytes to be read
* @return The number of bytes read from the descriptor's stream, this
* value can be less than the amount specified in the parameter
* @p size if there are no more bytes to read.
*/
#define macReadReceiveDescriptor(rdp, buf, size) \
mac_lld_read_receive_descriptor(rdp, buf, size)
#ifdef __cplusplus
extern "C" {
#endif
void macInit(void);
void macObjectInit(MACDriver *macp);
void macSetAddress(MACDriver *macp, const uint8_t *p);
msg_t macWaitTransmitDescriptor(MACDriver *macp,
MACTransmitDescriptor *tdp,
systime_t time);
void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp);
msg_t macWaitReceiveDescriptor(MACDriver *macp,
MACReceiveDescriptor *rdp,
systime_t time);
void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp);
bool_t macPollLinkStatus(MACDriver *macp);
#ifdef __cplusplus
}
#endif
#endif /* CH_HAL_USE_MAC */
#endif /* _MAC_H_ */
/** @} */

220
os/haltmp/include/mii.h Normal file
View File

@ -0,0 +1,220 @@
/*
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)
*/
/**
* @file mii.h
* @brief MII Driver macros and structures.
* @addtogroup MII
* @{
*/
#ifndef _MII_H_
#define _MII_H_
#include "mac_lld.h"
#include "mii_lld.h"
/*
* Generic MII registers. Note, not all registers are present on all PHY
* devices and some extra registers may be present.
*/
#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. */
#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. */
/*
* 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.*/
/*
* PHY identifiers.
*/
#define MII_DM9161_ID 0x0181b8a0
#define MII_AM79C875_ID 0x00225540
#define MII_KS8721_ID 0x00221610
/**
* @brief MII Driver initialization.
*/
#define miiInit() mii_lld_init()
/**
* Resets a MII device.
*
* @param[in] macp pointer to the @p MACDriver object
*/
#define miiReset(macp) mii_lld_reset(macp)
/**
* @brief Reads a MII register.
*
* @param[in] macp pointer to the @p MACDriver object
* @param addr the register address
* @return The register value.
*/
#define miiGet(macp, addr) mii_lld_get(macp, addr)
/**
* @brief Writes a MII register.
*
* @param[in] macp pointer to the @p MACDriver object
* @param addr the register address
* @param value the new register value
*/
#define miiPut(macp, addr, value) mii_lld_put(macp, addr, value)
#endif /**< _MII_H_ */
/** @} */

208
os/haltmp/include/mmc_spi.h Normal file
View File

@ -0,0 +1,208 @@
/*
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 mmc_spi.h
* @brief MMC over SPI driver header.
* @addtogroup MMC_SPI
* @{
*/
#ifndef _MMC_SPI_H_
#define _MMC_SPI_H_
#if CH_HAL_USE_MMC_SPI
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Block size for MMC transfers.
*/
#if !defined(MMC_SECTOR_SIZE) || defined(__DOXYGEN__)
#define MMC_SECTOR_SIZE 512
#endif
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
* This option is recommended also if the SPI driver does not
* use a DMA channel and heavily loads the CPU.
*/
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
#define MMC_NICE_WAITING TRUE
#endif
/**
* @brief Number of positive insertion queries before generating the
* insertion event.
*/
#if !defined(MMC_POLLING_INTERVAL) || defined(__DOXYGEN__)
#define MMC_POLLING_INTERVAL 10
#endif
/**
* @brief Interval, in milliseconds, between insertion queries.
*/
#if !defined(MMC_POLLING_DELAY) || defined(__DOXYGEN__)
#define MMC_POLLING_DELAY 10
#endif
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define MMC_CMD0_RETRY 10
#define MMC_CMD1_RETRY 100
#define MMC_WAIT_DATA 10000
#define MMC_CMDGOIDLE 0
#define MMC_CMDINIT 1
#define MMC_CMDREADCSD 9
#define MMC_CMDSTOP 12
#define MMC_CMDSETBLOCKLEN 16
#define MMC_CMDREAD 17
#define MMC_CMDREADMULTIPLE 18
#define MMC_CMDWRITE 24
#define MMC_CMDWRITEMULTIPLE 25
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Driver state machine possible states.
*/
typedef enum {
MMC_UNINIT = 0, /**< @brief Not initialized. */
MMC_STOP = 1, /**< @brief Stopped. */
MMC_WAIT = 2, /**< @brief Waiting card. */
MMC_INSERTED = 3, /**< @brief Card inserted. */
MMC_READY = 4, /**< @brief Card ready. */
MMC_READING = 5, /**< @brief Reading. */
MMC_WRITING = 6 /**< @brief Writing. */
} mmcstate_t;
/**
* @brief Function used to query some hardware status bits.
*
* @return The status.
*/
typedef bool_t (*mmcquery_t)(void);
/**
* @brief Driver configuration structure.
*/
typedef struct {
} MMCConfig;
/**
* @brief Structure representing a MMC driver.
*/
typedef struct {
/**
* @brief Driver state.
*/
mmcstate_t mmc_state;
/**
* @brief Current configuration data.
*/
const MMCConfig *mmc_config;
/**
* @brief SPI driver associated to this MMC driver.
*/
SPIDriver *mmc_spip;
/**
* @brief SPI low speed configuration used during initialization.
*/
const SPIConfig *mmc_lscfg;
/**
* @brief SPI high speed configuration used during transfers.
*/
const SPIConfig *mmc_hscfg;
/**
* @brief Write protect status query function.
*/
mmcquery_t mmc_is_protected;
/**
* @brief Insertion status query function.
*/
mmcquery_t mmc_is_inserted;
/**
* @brief Card insertion event source.
*/
EventSource mmc_inserted_event;
/**
* @brief Card removal event source.
*/
EventSource mmc_removed_event;
/**
* @brief MMC insertion polling timer.
*/
VirtualTimer mmc_vt;
/**
* @brief Insertion counter.
*/
uint_fast8_t mmc_cnt;
} MMCDriver;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/**
* @brief Returns the driver state.
*/
#define mmcGetDriverState(mmcp) ((mmcp)->mmc_state)
/**
* @brief Returns the write protect status.
*/
#define mmcIsWriteProtected(mmcp) ((mmcp)->mmc_is_protected())
#ifdef __cplusplus
extern "C" {
#endif
void mmcInit(void);
void mmcObjectInit(MMCDriver *mmcp, SPIDriver *spip,
const SPIConfig *lscfg, const SPIConfig *hscfg,
mmcquery_t is_protected, mmcquery_t is_inserted);
void mmcStart(MMCDriver *mmcp, const MMCConfig *config);
void mmcStop(MMCDriver *mmcp);
bool_t mmcConnect(MMCDriver *mmcp);
bool_t mmcDisconnect(MMCDriver *mmcp);
bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk);
bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer);
bool_t mmcStopSequentialRead(MMCDriver *mmcp);
bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk);
bool_t mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer);
bool_t mmcStopSequentialWrite(MMCDriver *mmcp);
#ifdef __cplusplus
}
#endif
#endif /* CH_HAL_USE_MMC_SPI */
#endif /* _MMC_SPI_H_ */
/** @} */

469
os/haltmp/include/pal.h Normal file
View File

@ -0,0 +1,469 @@
/*
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 pal.h
* @brief I/O Ports Abstraction Layer macros, types and structures
* @addtogroup PAL
* @{
*/
#ifndef _PAL_H_
#define _PAL_H_
#if CH_HAL_USE_PAL
/**
* @brief Bits in a mode word dedicated as mode selector.
* @details The other bits are not defined and may be used as device-specific
* option bits.
*/
#define PAL_MODE_MASK 0xF
/**
* @brief After reset state.
* @details The state itself is not specified and is architecture dependent,
* it is guaranteed to be equal to the after-reset state. It is
* usually an input state.
*/
#define PAL_MODE_RESET 0
/**
* @brief Safe state for <b>unconnected</b> pads.
* @details The state itself is not specified and is architecture dependent,
* it may be mapped on @p PAL_MODE_INPUT_PULLUP,
* @p PAL_MODE_INPUT_PULLDOWN or @p PAL_MODE_OUTPUT_PUSHPULL as
* example.
*/
#define PAL_MODE_UNCONNECTED 1
/**
* @brief Regular input high-Z pad.
*/
#define PAL_MODE_INPUT 2
/**
* @brief Input pad with weak pull up resistor.
*/
#define PAL_MODE_INPUT_PULLUP 3
/**
* @brief Input pad with weak pull down resistor.
*/
#define PAL_MODE_INPUT_PULLDOWN 4
/**
* @brief Analog input mode.
*/
#define PAL_MODE_INPUT_ANALOG 5
/**
* @brief Push-pull output pad.
*/
#define PAL_MODE_OUTPUT_PUSHPULL 6
/**
* @brief Open-drain output pad.
*/
#define PAL_MODE_OUTPUT_OPENDRAIN 7
#include "pal_lld.h"
/**
* @brief Logical low state.
*/
#define PAL_LOW 0
/**
* @brief Logical high state.
*/
#define PAL_HIGH 1
/**
* @brief Port bit helper macro.
* @details This macro calculates the mask of a bit within a port.
*
* @param[in] n the bit position within the port
* @return The bit mask.
*/
#define PAL_PORT_BIT(n) ((ioportmask_t)(1 << (n)))
/**
* @brief Bits group mask helper.
* @details This macro calculates the mask of a bits group.
*
* @param[in] width the group width
* @return The group mask.
*/
#define PAL_GROUP_MASK(width) ((ioportmask_t)(1 << (width)) - 1)
/**
* @brief Data part of a static I/O bus initializer.
* @details This macro should be used when statically initializing an I/O bus
* that is part of a bigger structure.
*
* @param name the name of the IOBus variable
* @param port the I/O port descriptor
* @param width the bus width in bits
* @param offset the bus bit offset within the port
*/
#define _IOBUS_DATA(name, port, width, offset) \
{port, PAL_GROUP_MASK(width), offset}
/**
* @brief Static I/O bus initializer.
*
* @param name the name of the IOBus variable
* @param port the I/O port descriptor
* @param width the bus width in bits
* @param offset the bus bit offset within the port
*/
#define IOBUS_DECL(name, port, width, offset) \
IOBus name = _IOBUS_DATA(name, port, width, offset)
/**
* @brief I/O bus descriptor.
* @details This structure describes a group of contiguous digital I/O lines
* that have to be handled as bus.
* @note I/O operations on a bus do not affect I/O lines on the same port but
* not belonging to the bus.
*/
typedef struct {
/** Port identifier.*/
ioportid_t bus_portid;
/** Bus mask aligned to port bit 0. The bus mask implicitly define the bus
width. A logical AND is performed on the bus data.*/
ioportmask_t bus_mask;
/** Offset, within the port, of the least significant bit of the bus.*/
uint_fast8_t bus_offset;
} IOBus;
/**
* @brief PAL subsystem initialization.
*
* @param[in] config pointer to an architecture specific configuration
* structure. This structure is defined in the low level driver
* header.
*/
#define palInit(config) pal_lld_init(config)
/**
* @brief Reads the physical I/O port states.
*
* @param[in] port the port identifier
* @return The port logical states.
*
* @note The default implementation always return zero and computes the
* parameter eventual side effects.
*/
#if !defined(pal_lld_readport) || defined(__DOXYGEN__)
#define palReadPort(port) ((void)(port), 0)
#else
#define palReadPort(port) pal_lld_readport(port)
#endif
/**
* @brief Reads the output latch.
* @details The purpose of this function is to read back the latched output
* value.
*
* @param[in] port the port identifier
* @return The latched logical states.
*
* @note The default implementation always return zero and computes the
* parameter eventual side effects.
*/
#if !defined(pal_lld_readlatch) || defined(__DOXYGEN__)
#define palReadLatch(port) ((void)(port), 0)
#else
#define palReadLatch(port) pal_lld_readlatch(port)
#endif
/**
* @brief Writes a bits mask on a I/O port.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be written on the specified port
*
* @note The default implementation does nothing except computing the
* parameters eventual side effects.
*/
#if !defined(pal_lld_writeport) || defined(__DOXYGEN__)
#define palWritePort(port, bits) ((void)(port), (void)(bits))
#else
#define palWritePort(port, bits) pal_lld_writeport(port, bits)
#endif
/**
* @brief Sets a bits mask on a I/O port.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be ORed on the specified port
*
* @note The operation is not guaranteed to be atomic on all the architectures,
* for atomicity and/or portability reasons you may need to enclose port
* I/O operations between @p chSysLock() and @p chSysUnlock().
* @note The default implementation is non atomic and not necessarily
* optimal. Low level drivers may optimize the function by using
* specific hardware or coding.
*/
#if !defined(pal_lld_setport) || defined(__DOXYGEN__)
#define palSetPort(port, bits) { \
palWritePort(port, palReadLatch(port) | (bits)); \
}
#else
#define palSetPort(port, bits) pal_lld_setport(port, bits)
#endif
/**
* @brief Clears a bits mask on a I/O port.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be cleared on the specified port
*
* @note The operation is not guaranteed to be atomic on all the architectures,
* for atomicity and/or portability reasons you may need to enclose port
* I/O operations between @p chSysLock() and @p chSysUnlock().
* @note The default implementation is non atomic and not necessarily
* optimal. Low level drivers may optimize the function by using
* specific hardware or coding.
*/
#if !defined(pal_lld_clearport) || defined(__DOXYGEN__)
#define palClearPort(port, bits) { \
palWritePort(port, palReadLatch(port) & ~(bits)); \
}
#else
#define palClearPort(port, bits) pal_lld_clearport(port, bits)
#endif
/**
* @brief Toggles a bits mask on a I/O port.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be XORed on the specified port
*
* @note The operation is not guaranteed to be atomic on all the architectures,
* for atomicity and/or portability reasons you may need to enclose port
* I/O operations between @p chSysLock() and @p chSysUnlock().
* @note The default implementation is non atomic and not necessarily
* optimal. Low level drivers may optimize the function by using
* specific hardware or coding.
*/
#if !defined(pal_lld_toggleport) || defined(__DOXYGEN__)
#define palTogglePort(port, bits) { \
palWritePort(port, palReadLatch(port) ^ (bits)); \
}
#else
#define palTogglePort(port, bits) pal_lld_toggleport(port, bits)
#endif
/**
* @brief Reads a group of bits.
*
* @param[in] port the port identifier
* @param[in] mask the group mask, a logical AND is performed on the input
* data
* @param[in] offset the group bit offset within the port
* @return The group logical states.
*/
#if !defined(pal_lld_readgroup) || defined(__DOXYGEN__)
#define palReadGroup(port, mask, offset) \
((palReadPort(port) >> (offset)) & (mask))
#else
#define palReadGroup(port, mask, offset) pal_lld_readgroup(port, mask, offset)
#endif
/**
* @brief Writes a group of bits.
*
* @param[in] port the port identifier
* @param[in] mask the group mask, a logical AND is performed on the output
* data
* @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.
*/
#if !defined(pal_lld_writegroup) || defined(__DOXYGEN__)
#define palWriteGroup(port, mask, offset, bits) { \
palWritePort(port, (palReadLatch(port) & ~((mask) << (offset))) | \
(((bits) & (mask)) << (offset))); \
}
#else
#define palWriteGroup(port, mask, offset, bits) \
pal_lld_writegroup(port, mask, offset, bits)
#endif
/**
* @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 setup mode
*
* @note Programming an unknown or unsupported mode is silently ignored.
*/
#if !defined(pal_lld_setgroupmode) || defined(__DOXYGEN__)
#define palSetGroupMode(port, mask, mode)
#else
#define palSetGroupMode(port, mask, mode) pal_lld_setgroupmode(port, mask, mode)
#endif
/**
* @brief Reads an input pad logical state.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
* @return The logical state.
* @retval 0 low logical state.
* @retval 1 high logical state.
*
* @note The default implementation not necessarily optimal. Low level drivers
* may optimize the function by using specific hardware or coding.
* @note The default implementation internally uses the @p palReadPort().
*/
#if !defined(pal_lld_readpad) || defined(__DOXYGEN__)
#define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1)
#else
#define palReadPad(port, pad) pal_lld_readpad(port, pad)
#endif
/**
* @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 The operation is not guaranteed to be atomic on all the architectures,
* for atomicity and/or portability reasons you may need to enclose port
* I/O operations between @p chSysLock() and @p chSysUnlock().
* @note The default implementation is non atomic and not necessarily
* optimal. Low level drivers may optimize the function by using
* specific hardware or coding.
* @note The default implementation internally uses the @p palReadLatch() and
* @p palWritePort().
*/
#if !defined(pal_lld_writepad) || defined(__DOXYGEN__)
#define palWritePad(port, pad, bit) { \
palWritePort(port, (palReadLatch(port) & ~PAL_PORT_BIT(pad)) | \
(((bit) & 1) << pad)); \
}
#else
#define palWritePad(port, pad, bit) pal_lld_writepad(port, pad, bit)
#endif
/**
* @brief Sets a pad logical state to @p 1.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
*
* @note The operation is not guaranteed to be atomic on all the architectures,
* for atomicity and/or portability reasons you may need to enclose port
* I/O operations between @p chSysLock() and @p chSysUnlock().
* @note The default implementation is non atomic and not necessarily
* optimal. Low level drivers may optimize the function by using
* specific hardware or coding.
* @note The default implementation internally uses the @p palSetPort().
*/
#if !defined(pal_lld_setpad) || defined(__DOXYGEN__)
#define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad))
#else
#define palSetPad(port, pad) pal_lld_setpad(port, pad)
#endif
/**
* @brief Clears a pad logical state to @p 0.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
*
* @note The operation is not guaranteed to be atomic on all the architectures,
* for atomicity and/or portability reasons you may need to enclose port
* I/O operations between @p chSysLock() and @p chSysUnlock().
* @note The default implementation is non atomic and not necessarily
* optimal. Low level drivers may optimize the function by using
* specific hardware or coding.
* @note The default implementation internally uses the @p palClearPort().
*/
#if !defined(pal_lld_clearpad) || defined(__DOXYGEN__)
#define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad))
#else
#define palClearPad(port, pad) pal_lld_clearpad(port, pad)
#endif
/**
* @brief Toggles a pad logical state.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
*
* @note The operation is not guaranteed to be atomic on all the architectures,
* for atomicity and/or portability reasons you may need to enclose port
* I/O operations between @p chSysLock() and @p chSysUnlock().
* @note The default implementation is non atomic and not necessarily
* optimal. Low level drivers may optimize the function by using
* specific hardware or coding.
* @note The default implementation internally uses the @p palTogglePort().
*/
#if !defined(pal_lld_togglepad) || defined(__DOXYGEN__)
#define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad))
#else
#define palTogglePad(port, pad) pal_lld_togglepad(port, pad)
#endif
/**
* @brief Pad mode setup.
* @details This function programs a pad with the specified mode.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
* @param[in] mode the setup mode
*
* @note The default implementation not necessarily optimal. Low level drivers
* may optimize the function by using specific hardware or coding.
* @note Programming an unknown or unsupported mode is silently ignored.
*/
#if !defined(pal_lld_setpadmode) || defined(__DOXYGEN__)
#define palSetPadMode(port, pad, mode) \
palSetGroupMode(port, PAL_PORT_BIT(pad), mode)
#else
#define palSetPadMode(port, pad, mode) pal_lld_setpadmode(port, pad, mode)
#endif
#ifdef __cplusplus
extern "C" {
#endif
ioportmask_t palReadBus(IOBus *bus);
void palWriteBus(IOBus *bus, ioportmask_t bits);
void palSetBusMode(IOBus *bus, uint_fast8_t mode);
#ifdef __cplusplus
}
#endif
#endif /* _PAL_H_ */
#endif /* CH_HAL_USE_PAL */
/** @} */

197
os/haltmp/include/serial.h Normal file
View File

@ -0,0 +1,197 @@
/*
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 Driver macros and structures.
* @addtogroup SERIAL
* @{
*/
#ifndef _SERIAL_H_
#define _SERIAL_H_
#if CH_HAL_USE_SERIAL
/** 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
/**
* @brief Structure representing a serial driver.
*/
typedef struct _SerialDriver SerialDriver;
#include "serial_lld.h"
/**
* @brief @p SerialDriver specific methods.
*/
struct _serial_driver_methods {
};
/**
* @brief @p SerialDriver virtual methods table.
*/
struct SerialDriverVMT {
/**
* @p BaseChannel class inherited methods.
*/
struct _base_channel_methods m0;
/**
* @p BaseAsynchronousChannel class inherited methods.
*/
struct _base_asynchronous_channel_methods m1;
/**
* @p SerialDriver specific methods.
*/
struct _serial_driver_methods m2;
};
/**
* @extends BaseAsynchronousChannel
*
* @brief Full duplex serial driver class.
* @details This class extends @p BaseAsynchronousChannel by adding physical
* I/O queues.
*/
struct _SerialDriver {
/**
* Virtual Methods Table.
*/
const struct SerialDriverVMT *vmt;
/**
* @p BaseChannel class inherited data.
*/
struct _base_channel_data d0;
/**
* @p BaseAsynchronousChannel class inherited data.
*/
struct _base_asynchronous_channel_data d1;
/**
* @p SerialDriver specific data.
*/
struct _serial_driver_data d2;
};
#ifdef __cplusplus
extern "C" {
#endif
void sdInit(void);
void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify);
void sdStart(SerialDriver *sdp, const SerialDriverConfig *config);
void sdStop(SerialDriver *sdp);
void sdIncomingDataI(SerialDriver *sdp, uint8_t b);
msg_t sdRequestDataI(SerialDriver *sdp);
void sdAddFlagsI(SerialDriver *sdp, sdflags_t mask);
sdflags_t sdGetAndClearFlags(SerialDriver *sdp);
#ifdef __cplusplus
}
#endif
/**
* @brief Direct output check on a @p SerialDriver.
* @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 sdPutWouldBlock(sdp) chOQIsFull(&(sdp)->d2.oqueue)
/**
* @brief Direct input check on a @p SerialDriver.
* @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 sdGetWouldBlock(sdp) chIQIsEmpty(&(sdp)->d2.iqueue)
/**
* @brief Direct blocking write to a @p SerialDriver.
* @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 sdPut(sdp, b) chOQPut(&(sdp)->d2.oqueue, b)
/**
* @brief Direct blocking write on a @p SerialDriver 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 sdPutTimeout(sdp, b, t) chOQPutTimeout(&(sdp)->d2.iqueue, b, t)
/**
* @brief Direct blocking read from a @p SerialDriver.
* @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 sdGet(sdp) chIQGet(&(sdp)->d2.iqueue)
/**
* @brief Direct blocking read from a @p SerialDriver 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 sdGetTimeout(sdp, t) chIQGetTimeout(&(sdp)->d2.iqueue, t)
/**
* @brief Direct non-blocking write to a @p SerialDriver.
* @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 sdWrite(sdp, b, n) chOQWrite(&(sdp)->d2.oqueue, b, n)
/**
* @brief Direct non-blocking read on a @p SerialDriver.
* @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 sdRead(sdp, b, n) chIQRead(&(sdp)->d2.iqueue, b, n)
#endif /* CH_HAL_USE_SERIAL */
#endif /* _SERIAL_H_ */
/** @} */

80
os/haltmp/include/spi.h Normal file
View File

@ -0,0 +1,80 @@
/*
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 spi.h
* @brief SPI Driver macros and structures.
* @addtogroup SPI
* @{
*/
#ifndef _SPI_H_
#define _SPI_H_
#if CH_HAL_USE_SPI
/**
* @brief Enables the mutual exclusion APIs on the SPI bus.
*/
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define SPI_USE_MUTUAL_EXCLUSION TRUE
#endif
#if SPI_USE_MUTUAL_EXCLUSION && !CH_USE_MUTEXES && !CH_USE_SEMAPHORES
#error "SPI_USE_MUTUAL_EXCLUSION requires CH_USE_MUTEXES and/or CH_USE_SEMAPHORES"
#endif
/**
* @brief Driver state machine possible states.
*/
typedef enum {
SPI_UNINIT = 0, /**< @brief Not initialized. */
SPI_STOP = 1, /**< @brief Stopped. */
SPI_READY = 2, /**< @brief Ready. */
SPI_ACTIVE = 3 /**< @brief Slave selected. */
} spistate_t;
#include "spi_lld.h"
#ifdef __cplusplus
extern "C" {
#endif
void spiInit(void);
void spiObjectInit(SPIDriver *spip);
void spiStart(SPIDriver *spip, const SPIConfig *config);
void spiStop(SPIDriver *spip);
void spiSelect(SPIDriver *spip);
void spiUnselect(SPIDriver *spip);
void spiIgnore(SPIDriver *spip, size_t n);
void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf);
void spiSend(SPIDriver *spip, size_t n, const void *txbuf);
void spiReceive(SPIDriver *spip, size_t n, void *rxbuf);
#if SPI_USE_MUTUAL_EXCLUSION
void spiAcquireBus(SPIDriver *spip);
void spiReleaseBus(SPIDriver *spip);
#endif /* SPI_USE_MUTUAL_EXCLUSION */
#ifdef __cplusplus
}
#endif
#endif /* CH_HAL_USE_SPI */
#endif /* _SPI_H_ */
/** @} */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support - ROUSSET -
* ----------------------------------------------------------------------------
* Copyright (c) 2006, Atmel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaiimer below.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the disclaimer below in the documentation and/or
* other materials provided with the distribution.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "aic.h"
#include <board.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures the interrupt associated with the given source, using the
/// specified mode and interrupt handler.
/// \param source Interrupt source to configure.
/// \param mode Triggering mode of the interrupt.
/// \param handler Interrupt handler function.
//------------------------------------------------------------------------------
void AIC_ConfigureIT(unsigned int source,
unsigned int mode,
void (*handler)( void ))
{
// Disable the interrupt first
AT91C_BASE_AIC->AIC_IDCR = 1 << source;
// Configure mode and handler
AT91C_BASE_AIC->AIC_SMR[source] = mode;
AT91C_BASE_AIC->AIC_SVR[source] = (unsigned int) handler;
// Clear interrupt
AT91C_BASE_AIC->AIC_ICCR = 1 << source;
}
//------------------------------------------------------------------------------
/// Enables interrupts coming from the given (unique) source.
/// \param source Interrupt source to enable.
//------------------------------------------------------------------------------
void AIC_EnableIT(unsigned int source)
{
AT91C_BASE_AIC->AIC_IECR = 1 << source;
}
//------------------------------------------------------------------------------
/// Disables interrupts coming from the given (unique) source.
/// \param source Interrupt source to enable.
//------------------------------------------------------------------------------
void AIC_DisableIT(unsigned int source)
{
AT91C_BASE_AIC->AIC_IDCR = 1 << source;
}

View File

@ -0,0 +1,78 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support - ROUSSET -
* ----------------------------------------------------------------------------
* Copyright (c) 2006, Atmel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaiimer below.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the disclaimer below in the documentation and/or
* other materials provided with the distribution.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \dir
/// !Purpose
///
/// Methods and definitions for configuring interrupts using the Advanced
/// Interrupt Controller (AIC).
///
/// !Usage
/// -# Configure an interrupt source using AIC_ConfigureIT
/// -# Enable or disable interrupt generation of a particular source with
/// AIC_EnableIT and AIC_DisableIT.
//------------------------------------------------------------------------------
#ifndef AIC_H
#define AIC_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#ifndef AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL
/// Redefinition of missing constant.
#define AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE
#endif
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void AIC_ConfigureIT(unsigned int source,
unsigned int mode,
void (*handler)( void ));
extern void AIC_EnableIT(unsigned int source);
extern void AIC_DisableIT(unsigned int source);
#endif //#ifndef AIC_H

View File

@ -0,0 +1,56 @@
/*
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 _AT91SAM7_H_
#define _AT91SAM7_H_
/*
* Supported platforms.
*/
#define SAM7S64 0
#define SAM7S128 1
#define SAM7S256 2
#define SAM7S512 3
#define SAM7X128 4
#define SAM7X256 5
#define SAM7X512 6
#ifndef SAM7_PLATFORM
#error "SAM7 platform not defined"
#endif
#if SAM7_PLATFORM == SAM7S64
#include "at91lib/AT91SAM7S64.h"
#elif SAM7_PLATFORM == SAM7S128
#include "at91lib/AT91SAM7S128.h"
#elif SAM7_PLATFORM == SAM7S256
#include "at91lib/AT91SAM7S256.h"
#elif SAM7_PLATFORM == SAM7S512
#include "at91lib/AT91SAM7S512.h"
#elif SAM7_PLATFORM == SAM7X128
#include "at91lib/AT91SAM7X128.h"
#elif SAM7_PLATFORM == SAM7X256
#include "at91lib/AT91SAM7X256.h"
#elif SAM7_PLATFORM == SAM7X512
#include "at91lib/AT91SAM7X512.h"
#else
#error "SAM7 platform not supported"
#endif
#endif /* _AT91SAM7_H_ */

View File

@ -0,0 +1,484 @@
/*
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 AT91SAM7/mac_lld.c
* @brief AT91SAM7 low level MAC driver code
* @addtogroup AT91SAM7_MAC
* @{
*/
#include <string.h>
#include <ch.h>
#include <mac.h>
#include <mii.h>
#include "at91lib/aic.h"
/**
* @brief Ethernet driver 1.
*/
MACDriver ETH1;
#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_ECRSDV | \
AT91C_PB16_ECOL | AT91C_PB17_ERXCK)
#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)
#ifndef __DOXYGEN__
static bool_t link_up;
static uint8_t default_mac[] = {0xAA, 0x55, 0x13, 0x37, 0x01, 0x10};
static EMACDescriptor *rxptr;
static EMACDescriptor *txptr;
static EMACDescriptor rd[EMAC_RECEIVE_DESCRIPTORS]
__attribute__((aligned(8)));
static EMACDescriptor td[EMAC_TRANSMIT_DESCRIPTORS]
__attribute__((aligned(8)));
static uint8_t rb[EMAC_RECEIVE_DESCRIPTORS * EMAC_RECEIVE_BUFFERS_SIZE]
__attribute__((aligned(8)));
static uint8_t tb[EMAC_TRANSMIT_DESCRIPTORS * EMAC_TRANSMIT_BUFFERS_SIZE]
__attribute__((aligned(8)));
#endif
/**
* @brief IRQ handler.
*/
/** @cond never*/
__attribute__((noinline))
/** @endcond*/
static void serve_interrupt(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) {
chSysLockFromIsr();
chSemResetI(&ETH1.md_rdsem, 0);
#if CH_USE_EVENTS
chEvtBroadcastI(&ETH1.md_rdevent);
#endif
chSysUnlockFromIsr();
}
AT91C_BASE_EMAC->EMAC_RSR = RSR_BITS;
}
if ((isr & AT91C_EMAC_TCOMP) || (tsr & TSR_BITS)) {
if (tsr & AT91C_EMAC_COMP) {
chSysLockFromIsr();
chSemResetI(&ETH1.md_tdsem, 0);
chSysUnlockFromIsr();
}
AT91C_BASE_EMAC->EMAC_TSR = TSR_BITS;
}
AT91C_BASE_AIC->AIC_EOICR = 0;
}
/**
* @brief EMAC IRQ veneer handler.
*/
CH_IRQ_HANDLER(irq_handler) {
CH_IRQ_PROLOGUE();
serve_interrupt();
CH_IRQ_EPILOGUE();
}
/**
* @brief Low level MAC initialization.
*/
void mac_lld_init(void) {
unsigned i;
miiInit();
macObjectInit(&ETH1);
/*
* Buffers initialization.
*/
for (i = 0; i < EMAC_RECEIVE_DESCRIPTORS; i++) {
rd[i].w1 = (uint32_t)&rb[i * EMAC_RECEIVE_BUFFERS_SIZE];
rd[i].w2 = 0;
}
rd[EMAC_RECEIVE_DESCRIPTORS - 1].w1 |= W1_R_WRAP;
rxptr = rd;
for (i = 0; i < EMAC_TRANSMIT_DESCRIPTORS; i++) {
td[i].w1 = (uint32_t)&tb[i * EMAC_TRANSMIT_BUFFERS_SIZE];
td[i].w2 = EMAC_TRANSMIT_BUFFERS_SIZE | W2_T_LAST_BUFFER | W2_T_USED;
}
td[EMAC_TRANSMIT_DESCRIPTORS - 1].w2 |= W2_T_WRAP;
txptr = td;
/*
* Associated PHY initialization.
*/
miiReset(&ETH1);
/*
* 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 Initial setup.
*/
AT91C_BASE_EMAC->EMAC_NCR = 0; /* Stopped but MCE active.*/
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)rd; /* RX descriptors list.*/
AT91C_BASE_EMAC->EMAC_TBQP = (AT91_REG)td; /* TX descriptors 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.*/
mac_lld_set_address(&ETH1, default_mac);
/*
* PHY device identification.
*/
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE;
if ((miiGet(&ETH1, MII_PHYSID1) != (PHY_ID >> 16)) ||
((miiGet(&ETH1, MII_PHYSID2) & 0xFFF0) != (PHY_ID & 0xFFF0)))
chSysHalt();
AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
/*
* Interrupt configuration.
*/
AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP | AT91C_EMAC_TCOMP;
AIC_ConfigureIT(AT91C_ID_EMAC,
AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | EMAC_INTERRUPT_PRIORITY,
irq_handler);
AIC_EnableIT(AT91C_ID_EMAC);
}
/**
* @brief Low level MAC address setup.
*
* @param[in] macp pointer to the @p MACDriver object
* @param[in] p pointer to a six bytes buffer containing the MAC address. If
* this parameter is set to @p NULL then a system default MAC is
* used. The MAC address must be aligned with the most significant
* byte first.
*/
void mac_lld_set_address(MACDriver *macp, const uint8_t *p) {
(void)macp;
AT91C_BASE_EMAC->EMAC_SA1L = (AT91_REG)((p[3] << 24) | (p[2] << 16) |
(p[1] << 8) | p[0]);
AT91C_BASE_EMAC->EMAC_SA1H = (AT91_REG)((p[5] << 8) | p[4]);
}
/**
* @brief Returns a transmission descriptor.
* @details One of the available transmission descriptors is locked and
* returned.
*
* @param[in] macp pointer to the @p MACDriver object
* @param[out] tdp pointer to a @p MACTransmitDescriptor structure
* @return The operation status.
* @retval RDY_OK the descriptor was obtained.
* @retval RDY_TIMEOUT descriptor not available.
*/
msg_t max_lld_get_transmit_descriptor(MACDriver *macp,
MACTransmitDescriptor *tdp) {
EMACDescriptor *edp;
(void)macp;
if (!link_up)
return RDY_TIMEOUT;
chSysLock();
edp = txptr;
if (!(edp->w2 & W2_T_USED) || (edp->w2 & W2_T_LOCKED)) {
chSysUnlock();
return RDY_TIMEOUT;
}
/*
* Set the buffer size and configuration, the buffer is also marked
* as locked.
*/
if (++txptr >= &td[EMAC_TRANSMIT_DESCRIPTORS]) {
edp->w2 = W2_T_LOCKED | W2_T_USED | W2_T_LAST_BUFFER | W2_T_WRAP;
txptr = td;
}
else
edp->w2 = W2_T_LOCKED | W2_T_USED | W2_T_LAST_BUFFER;
chSysUnlock();
tdp->td_offset = 0;
tdp->td_size = EMAC_TRANSMIT_BUFFERS_SIZE;
tdp->td_physdesc = edp;
return RDY_OK;
}
/**
* @brief Writes to a transmit descriptor's stream.
*
* @param[in] tdp pointer to a @p MACTransmitDescriptor structure
* @param[in] buf pointer to the buffer cointaining the data to be written
* @param[in] size number of bytes to be written
* @return The number of bytes written into the descriptor's stream, this
* value can be less than the amount specified in the parameter
* @p size if the maximum frame size is reached.
*/
size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp,
uint8_t *buf,
size_t size) {
if (size > tdp->td_size - tdp->td_offset)
size = tdp->td_size - tdp->td_offset;
if (size > 0) {
memcpy((uint8_t *)(tdp->td_physdesc->w1 & W1_T_ADDRESS_MASK) +
tdp->td_offset,
buf, size);
tdp->td_offset += size;
}
return size;
}
/**
* @brief Releases a transmit descriptor and starts the transmission of the
* enqueued data as a single frame.
*
* @param[in] tdp the pointer to the @p MACTransmitDescriptor structure
*/
void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) {
chSysLock();
tdp->td_physdesc->w2 = (tdp->td_physdesc->w2 &
~(W2_T_LOCKED | W2_T_USED | W2_T_LENGTH_MASK)) |
tdp->td_offset;
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TSTART;
chSysUnlock();
}
/**
* @brief Cleans an incomplete frame.
* @param from the start position of the incomplete frame
*/
static void cleanup(EMACDescriptor *from) {
while (from != rxptr) {
from->w1 &= ~W1_R_OWNERSHIP;
if (++from >= &rd[EMAC_RECEIVE_DESCRIPTORS])
from = rd;
}
}
/**
* @brief Returns a receive descriptor.
*
* @param[in] macp pointer to the @p MACDriver object
* @param[out] rdp pointer to a @p MACReceiveDescriptor structure
* @return The operation status.
* @retval RDY_OK the descriptor was obtained.
* @retval RDY_TIMEOUT descriptor not available.
*/
msg_t max_lld_get_receive_descriptor(MACDriver *macp,
MACReceiveDescriptor *rdp) {
unsigned n;
EMACDescriptor *edp;
(void)macp;
n = EMAC_RECEIVE_DESCRIPTORS;
/*
* Skips unused buffers, if any.
*/
skip:
while ((n > 0) && !(rxptr->w1 & W1_R_OWNERSHIP)) {
if (++rxptr >= &rd[EMAC_RECEIVE_DESCRIPTORS])
rxptr = rd;
n--;
}
/*
* Skips fragments, if any, cleaning them up.
*/
while ((n > 0) && (rxptr->w1 & W1_R_OWNERSHIP) &&
!(rxptr->w2 & W2_R_FRAME_START)) {
rxptr->w1 &= ~W1_R_OWNERSHIP;
if (++rxptr >= &rd[EMAC_RECEIVE_DESCRIPTORS])
rxptr = rd;
n--;
}
/*
* Now compute the total frame size skipping eventual incomplete frames
* or holes...
*/
restart:
edp = rxptr;
while (n > 0) {
if (!(rxptr->w1 & W1_R_OWNERSHIP)) {
/* Empty buffer for some reason... cleaning up the incomplete frame.*/
cleanup(edp);
goto skip;
}
/*
* End Of Frame found.
*/
if (rxptr->w2 & W2_R_FRAME_END) {
rdp->rd_offset = 0;
rdp->rd_size = rxptr->w2 & W2_T_LENGTH_MASK;
rdp->rd_physdesc = edp;
return RDY_OK;
}
if ((edp != rxptr) && (rxptr->w2 & W2_R_FRAME_START)) {
/* Found another start... cleaning up the incomplete frame.*/
cleanup(edp);
goto restart; /* Another start buffer for some reason... */
}
if (++rxptr >= &rd[EMAC_RECEIVE_DESCRIPTORS])
rxptr = rd;
n--;
}
return RDY_TIMEOUT;
}
/**
* @brief Reads from a receive descriptor's stream.
*
* @param[in] rdp pointer to a @p MACReceiveDescriptor structure
* @param[in] buf pointer to the buffer that will receive the read data
* @param[in] size number of bytes to be read
* @return The number of bytes read from the descriptor's stream, this
* value can be less than the amount specified in the parameter
* @p size if there are no more bytes to read.
*/
size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp,
uint8_t *buf,
size_t size) {
if (size > rdp->rd_size - rdp->rd_offset)
size = rdp->rd_size - rdp->rd_offset;
if (size > 0) {
uint8_t *src = (uint8_t *)(rdp->rd_physdesc->w1 & W1_R_ADDRESS_MASK) +
rdp->rd_offset;
uint8_t *limit = &rb[EMAC_RECEIVE_DESCRIPTORS * EMAC_RECEIVE_BUFFERS_SIZE];
if (src >= limit)
src -= EMAC_RECEIVE_DESCRIPTORS * EMAC_RECEIVE_BUFFERS_SIZE;
if (src + size > limit ) {
memcpy(buf, src, (size_t)(limit - src));
memcpy(buf + (size_t)(limit - src), rb, size - (size_t)(limit - src));
}
else
memcpy(buf, src, size);
rdp->rd_offset += size;
}
return size;
}
/**
* @brief Releases a receive descriptor.
* @details The descriptor and its buffer are made available for more incoming
* frames.
*
* @param[in] rdp the pointer to the @p MACReceiveDescriptor structure
*/
void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) {
bool_t done;
EMACDescriptor *edp = rdp->rd_physdesc;
unsigned n = EMAC_RECEIVE_DESCRIPTORS;
do {
done = ((edp->w2 & W2_R_FRAME_END) != 0);
chDbgAssert(edp->w1 & W1_R_OWNERSHIP,
"mac_lld_release_receive_descriptor(), #1",
"found not owned descriptor");
edp->w1 &= ~(W1_R_OWNERSHIP | W2_R_FRAME_START | W2_R_FRAME_END);
if (++edp >= &rd[EMAC_RECEIVE_DESCRIPTORS])
edp = rd;
n--;
}
while ((n > 0) && !done);
/*
* Make rxptr point to the descriptor where the next frame will most
* likely appear.
*/
rxptr = edp;
}
/**
* @brief Updates and returns the link status.
*
* @param[in] macp pointer to the @p MACDriver object
* @return The link status.
* @retval TRUE if the link is active.
* @retval FALSE if the link is down.
*/
bool_t mac_lld_poll_link_status(MACDriver *macp) {
uint32_t ncfgr, bmsr, bmcr, lpa;
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE;
(void)miiGet(macp, MII_BMSR);
bmsr = miiGet(macp, 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 = miiGet(macp, MII_BMCR);
if (bmcr & BMCR_ANENABLE) {
lpa = miiGet(macp, 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;
}
/** @} */

View File

@ -0,0 +1,192 @@
/*
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 AT91SAM7/mac_lld.h
* @brief AT91SAM7 low level MAC driver header
* @addtogroup AT91SAM7_MAC
* @{
*/
#ifndef _MAC_LLD_H_
#define _MAC_LLD_H_
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Number of available transmit buffers.
*/
#if !defined(MAC_TRANSMIT_BUFFERS) || defined(__DOXYGEN__)
#define MAC_TRANSMIT_BUFFERS 2
#endif
/**
* @brief Number of available receive buffers.
*/
#if !defined(MAC_RECEIVE_BUFFERS) || defined(__DOXYGEN__)
#define MAC_RECEIVE_BUFFERS 2
#endif
/**
* @brief Maximum supported frame size.
*/
#if !defined(MAC_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define MAC_BUFFERS_SIZE 1518
#endif
/*===========================================================================*/
/* EMAC specific settings. */
/*===========================================================================*/
/**
* @brief Interrupt priority level for the EMAC device.
*/
#if !defined(EMAC_INTERRUPT_PRIORITY) || defined(__DOXYGEN__)
#define EMAC_INTERRUPT_PRIORITY (AT91C_AIC_PRIOR_HIGHEST - 3)
#endif
/*===========================================================================*/
/* EMAC specific constants. */
/*===========================================================================*/
#define EMAC_RECEIVE_BUFFERS_SIZE 128 /* Do not modify */
#define EMAC_TRANSMIT_BUFFERS_SIZE MAC_BUFFERS_SIZE
#define EMAC_RECEIVE_DESCRIPTORS \
(((((MAC_BUFFERS_SIZE - 1) | (EMAC_RECEIVE_BUFFERS_SIZE - 1)) + 1) \
/ EMAC_RECEIVE_BUFFERS_SIZE) * MAC_RECEIVE_BUFFERS)
#define EMAC_TRANSMIT_DESCRIPTORS MAC_TRANSMIT_BUFFERS
#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 W1_T_ADDRESS_MASK 0xFFFFFFFF
#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
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Structure representing a buffer physical descriptor.
* @note It represents both descriptor types.
*/
typedef struct {
uint32_t w1;
uint32_t w2;
} EMACDescriptor;
/**
* @brief Structure representing a MAC driver.
*/
typedef struct {
Semaphore md_tdsem; /**< Transmit semaphore. */
Semaphore md_rdsem; /**< Receive semaphore. */
#if CH_USE_EVENTS
EventSource md_rdevent; /**< Receive event source. */
#endif
/* End of the mandatory fields.*/
} MACDriver;
/**
* @brief Structure representing a transmit descriptor.
*/
typedef struct {
size_t td_offset; /**< Current write offset. */
size_t td_size; /**< Available space size. */
/* End of the mandatory fields.*/
EMACDescriptor *td_physdesc; /**< Pointer to the physical
descriptor. */
} MACTransmitDescriptor;
/**
* @brief Structure representing a receive descriptor.
*/
typedef struct {
size_t rd_offset; /**< Current read offset. */
size_t rd_size; /**< Available data size. */
/* End of the mandatory fields.*/
EMACDescriptor *rd_physdesc; /**< Pointer to the first descriptor
of the buffers chain. */
} MACReceiveDescriptor;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/** @cond never*/
extern MACDriver ETH1;
#ifdef __cplusplus
extern "C" {
#endif
void mac_lld_init(void);
void mac_lld_set_address(MACDriver *macp, const uint8_t *p);
msg_t max_lld_get_transmit_descriptor(MACDriver *macp,
MACTransmitDescriptor *tdp);
size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp,
uint8_t *buf,
size_t size);
void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp);
msg_t max_lld_get_receive_descriptor(MACDriver *macp,
MACReceiveDescriptor *rdp);
size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp,
uint8_t *buf,
size_t size);
void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp);
bool_t mac_lld_poll_link_status(MACDriver *macp);
#ifdef __cplusplus
}
#endif
/** @endcond*/
#endif /* _MAC_LLD_H_ */
/** @} */

View File

@ -0,0 +1,114 @@
/*
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 AT91SAM7/mii_lld.c
* @brief AT91SAM7 low level MII driver code
* @addtogroup AT91SAM7_MII
* @{
*/
#include <ch.h>
#include <mii.h>
#include <mac.h>
/**
* @brief Low level MII driver initialization.
*/
void mii_lld_init(void) {
}
/**
* @brief Resets a PHY device.
*
* @param[in] macp pointer to the @p MACDriver object
*/
void mii_lld_reset(MACDriver *macp) {
(void)macp;
/*
* Disables the pullups on all the pins that are latched on reset by the PHY.
*/
AT91C_BASE_PIOB->PIO_PPUDR = PHY_LATCHED_PINS;
#ifdef PIOB_PHY_PD_MASK
/*
* 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.
#if (PHY_HARDWARE == PHY_DAVICOM_9161)
AT91C_BASE_PIOB->PIO_CODR = PIOB_PHY_PD_MASK; // Output to low level.
#else
AT91C_BASE_PIOB->PIO_SODR = PIOB_PHY_PD_MASK; // Output to high level.
#endif
#endif // PIOB_PHY_PD_MASK
/*
* 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))
;
}
/**
* @brief Reads a PHY register through the MII interface.
*
* @param[in] macp pointer to the @p MACDriver object
* @param addr the register address
* @return The register value.
*/
phyreg_t mii_lld_get(MACDriver *macp, phyaddr_t addr) {
(void)macp;
AT91C_BASE_EMAC->EMAC_MAN = (0b01 << 30) | /* SOF */
(0b10 << 28) | /* RW */
(PHY_ADDRESS << 23) | /* PHYA */
(addr << 18) | /* REGA */
(0b10 << 16); /* CODE */
while (!( AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE))
;
return (phyreg_t)(AT91C_BASE_EMAC->EMAC_MAN & 0xFFFF);
}
/**
* @brief Writes a PHY register through the MII interface.
*
* @param[in] macp pointer to the @p MACDriver object
* @param addr the register address
* @param value the new register value
*/
void mii_lld_put(MACDriver *macp, phyaddr_t addr, phyreg_t value) {
(void)macp;
AT91C_BASE_EMAC->EMAC_MAN = (0b01 << 30) | /* SOF */
(0b01 << 28) | /* RW */
(PHY_ADDRESS << 23) | /* PHYA */
(addr << 18) | /* REGA */
(0b10 << 16) | /* CODE */
value;
while (!( AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE))
;
}
/** @} */

View File

@ -0,0 +1,103 @@
/*
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 AT91SAM7/mii_lld.h
* @brief AT91SAM7 low level MII driver header
* @addtogroup AT91SAM7_MII
* @{
*/
#ifndef _MII_LLD_H_
#define _MII_LLD_H_
#include "board.h"
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief PHY manufacturer and model.
*/
#if !defined(PHY_HARDWARE) || defined(__DOXYGEN__)
#define PHY_HARDWARE PHY_MICREL_KS8721
#endif
/*===========================================================================*/
/* PHY specific constants. */
/*===========================================================================*/
#define PHY_MICREL_KS8721 0
#define PHY_DAVICOM_9161 1
/**
* @brief Pins latched by the PHY at reset.
*/
#if PHY_HARDWARE == PHY_MICREL_KS8721
#define PHY_ADDRESS 1
#define PHY_ID MII_KS8721_ID
#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_ECRSDV | AT91C_PB16_ECOL | \
AT91C_PIO_PB26)
#elif PHY_HARDWARE == PHY_DAVICOM_9161
#define PHY_ADDRESS 0
#define PHY_ID MII_DM9161_ID
#define PHY_LATCHED_PINS (AT91C_PB0_ETXCK_EREFCK | AT91C_PB4_ECRS | \
AT91C_PB5_ERX0 | AT91C_PB6_ERX1 | \
AT91C_PB7_ERXER | AT91C_PB13_ERX2 | \
AT91C_PB14_ERX3 | AT91C_PB15_ERXDV_ECRSDV | \
AT91C_PB16_ECOL | AT91C_PB17_ERXCK)
#endif /* PHY_HARDWARE */
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Type of a PHY register value.
*/
typedef uint16_t phyreg_t;
/**
* @brief Type of a PHY register address.
*/
typedef uint8_t phyaddr_t;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void mii_lld_init(void);
void mii_lld_reset(MACDriver *macp);
phyreg_t mii_lld_get(MACDriver *macp, phyaddr_t addr);
void mii_lld_put(MACDriver *macp, phyaddr_t addr, phyreg_t value);
#ifdef __cplusplus
}
#endif
#endif /* _MII_LLD_H_ */
/** @} */

View File

@ -0,0 +1,125 @@
/*
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 AT91SAM7/pal_lld.c
* @brief AT91SAM7 PIO low level driver code
* @addtogroup AT91SAM7_PAL
* @{
*/
#include <ch.h>
#include <pal.h>
#include "board.h"
/**
* @brief AT91SAM7 I/O ports configuration.
* @details PIO registers initialization.
*
* @param[in] config the AT91SAM7 ports configuration
*/
void _pal_lld_init(const AT91SAM7PIOConfig *config) {
unsigned int ports = (1 << AT91C_ID_PIOA);
#if defined(SAM7X128) || defined(SAM7X256) || defined(SAM7X512)
ports |= (1 << AT91C_ID_PIOB);
#endif
AT91C_BASE_PMC->PMC_PCER = ports;
/*
* PIOA setup.
*/
AT91C_BASE_PIOA->PIO_PPUER = config->P0Data.pusr; /* Pull-up as spec.*/
AT91C_BASE_PIOA->PIO_PPUDR = ~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.
*/
#if defined(SAM7X128) || defined(SAM7X256) || defined(SAM7X512)
AT91C_BASE_PIOB->PIO_PPUER = config->P1Data.pusr; /* Pull-up as spec.*/
AT91C_BASE_PIOB->PIO_PPUDR = ~config->P1Data.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.*/
#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_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:
case PAL_MODE_INPUT_ANALOG:
port->PIO_PPUDR = mask;
port->PIO_ODR = mask;
break;
case PAL_MODE_UNCONNECTED:
port->PIO_SODR = mask;
/* Falls in */
case PAL_MODE_OUTPUT_PUSHPULL:
port->PIO_PPUDR = mask;
port->PIO_OER = mask;
port->PIO_MDDR = mask;
break;
case PAL_MODE_OUTPUT_OPENDRAIN:
port->PIO_PPUER = mask;
port->PIO_OER = mask;
port->PIO_MDER = mask;
}
}
/** @} */

View File

@ -0,0 +1,251 @@
/*
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 AT91SAM7/pal_lld.h
* @brief AT91SAM7 PIO low level driver header
* @addtogroup AT91SAM7_PAL
* @{
*/
#ifndef _PAL_LLD_H_
#define _PAL_LLD_H_
#include "board.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;
} at91sam7_pio_setup_t;
/**
* @brief AT91SAM7 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.*/
at91sam7_pio_setup_t P0Data;
#if defined(SAM7X128) || defined(SAM7X256) || defined(SAM7X512) || \
defined(__DOXYGEN__)
/** @brief Port 1 setup data.*/
at91sam7_pio_setup_t P1Data;
#endif
} AT91SAM7PIOConfig;
/**
* @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 IOPORT1 AT91C_BASE_PIOA
/**
* @brief PIO port B identifier.
*/
#if defined(SAM7X128) || defined(SAM7X256) || defined(SAM7X512) || \
defined(__DOXYGEN__)
#define IOPORT2 AT91C_BASE_PIOB
#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.
*/
#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 AT91SAM7PIOConfig *config);
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode);
#ifdef __cplusplus
}
#endif
#endif /* _PAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,85 @@
/*
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 AT91SAM7 AT91SAM7 Support
* @brief AT91SAM7 specific support.
* @details The AT91SAM7 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 AT91SAM7_PAL AT91SAM7 I/O Ports Support
* @brief I/O Ports peripherals support.
* @details This module supports the AT91SAM7 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_ANALOG (same as @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 AT91SAM7
*/
/**
* @defgroup AT91SAM7_SERIAL AT91SAM7 USART Support
* @brief USART peripherals support.
* @details The serial driver supports the AT91SAM7 USART peripherals.
*
* @ingroup AT91SAM7
*/
/**
* @defgroup AT91SAM7_MAC AT91SAM7 EMAC Support
* @brief EMAC peripheral support.
* @details the @ref MAC supports the AT91SAM7 EMAC peripheral.
*
* @ingroup AT91SAM7
*/
/**
* @defgroup AT91SAM7_MII AT91SAM7 MII Support
* @brief EMAC peripheral support.
* @details the @ref MII supports the AT91SAM7 EMAC peripheral communicating
* with an external PHY transceiver. The driver currently supports
* only the Micrel KS8721 PHY module.
*
* @ingroup AT91SAM7
*/

View File

@ -0,0 +1,298 @@
/*
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 AT91SAM7/serial_lld.c
* @brief AT91SAM7 low level serial driver code
* @addtogroup AT91SAM7_SERIAL
* @{
*/
#include <ch.h>
#include <serial.h>
#include "at91lib/aic.h"
#include "at91sam7.h"
#if SAM7_PLATFORM == SAM7S256
#define SAM7_USART0_RX AT91C_PA5_RXD0
#define SAM7_USART0_TX AT91C_PA6_TXD0
#define SAM7_USART1_RX AT91C_PA21_RXD1
#define SAM7_USART1_TX AT91C_PA22_TXD1
#elif SAM7_PLATFORM == SAM7X256
#define SAM7_USART0_RX AT91C_PA0_RXD0
#define SAM7_USART0_TX AT91C_PA1_TXD0
#define SAM7_USART1_RX AT91C_PA5_RXD1
#define SAM7_USART1_TX AT91C_PA6_TXD1
#else
#error "serial lines not defined for this SAM7 version"
#endif
#if USE_SAM7_USART0 || defined(__DOXYGEN__)
/** @brief USART0 serial driver identifier.*/
SerialDriver SD1;
#endif
#if USE_SAM7_USART1 || defined(__DOXYGEN__)
/** @brief USART1 serial driver identifier.*/
SerialDriver SD2;
#endif
/** @brief Driver default configuration.*/
static const SerialDriverConfig default_config = {
38400,
AT91C_US_USMODE_NORMAL | AT91C_US_CLKS_CLOCK |
AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT
};
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/**
* @brief USART initialization.
* @param[in] u pointer to an USART I/O block
* @param[in] config the architecture-dependent serial driver configuration
*/
static void usart_init(AT91PS_USART u, const SerialDriverConfig *config) {
/* 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 (config->mr & AT91C_US_OVER)
u->US_BRGR = MCK / (config->speed * 8);
else
u->US_BRGR = MCK / (config->speed * 16);
u->US_MR = config->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 USART de-initialization.
* @param[in] u pointer to an USART I/O block
*/
static void usart_deinit(AT91PS_USART u) {
/* Disables IRQ sources and stop operations.*/
u->US_IDR = 0xFFFFFFFF;
u->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RSTSTA;
u->US_MR = 0;
u->US_RTOR = 0;
u->US_TTGR = 0;
}
/**
* @brief Error handling routine.
* @param[in] err USART CSR register value
* @param[in] sdp communication channel associated to the USART
*/
static void set_error(AT91_REG csr, SerialDriver *sdp) {
sdflags_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();
sdAddFlagsI(sdp, sts);
chSysUnlockFromIsr();
}
#if defined(__GNU__)
__attribute__((noinline))
#endif
/**
* @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 serve_interrupt(AT91PS_USART u, SerialDriver *sdp) {
if (u->US_CSR & AT91C_US_RXRDY) {
chSysLockFromIsr();
sdIncomingDataI(sdp, u->US_RHR);
chSysUnlockFromIsr();
}
if (u->US_CSR & AT91C_US_TXRDY) {
chSysLockFromIsr();
msg_t b = sdRequestDataI(sdp);
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)) {
set_error(u->US_CSR, sdp);
u->US_CR = AT91C_US_RSTSTA;
}
AT91C_BASE_AIC->AIC_EOICR = 0;
}
#if USE_SAM7_USART0 || defined(__DOXYGEN__)
static void notify1(void) {
AT91C_BASE_US0->US_IER = AT91C_US_TXRDY;
}
#endif
#if USE_SAM7_USART1 || defined(__DOXYGEN__)
static void notify2(void) {
AT91C_BASE_US1->US_IER = AT91C_US_TXRDY;
}
#endif
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
#if USE_SAM7_USART0 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(USART0IrqHandler) {
CH_IRQ_PROLOGUE();
serve_interrupt(AT91C_BASE_US0, &SD1);
CH_IRQ_EPILOGUE();
}
#endif
#if USE_SAM7_USART1 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(USART1IrqHandler) {
CH_IRQ_PROLOGUE();
serve_interrupt(AT91C_BASE_US1, &SD2);
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* Low level serial driver initialization.
*/
void sd_lld_init(void) {
#if USE_SAM7_USART0
sdObjectInit(&SD1, NULL, notify1);
AT91C_BASE_PIOA->PIO_PDR = SAM7_USART0_RX | SAM7_USART0_TX;
AT91C_BASE_PIOA->PIO_ASR = SAM7_USART0_RX | SAM7_USART0_TX;
AT91C_BASE_PIOA->PIO_PPUDR = SAM7_USART0_RX | SAM7_USART0_TX;
AIC_ConfigureIT(AT91C_ID_US0,
AT91C_AIC_SRCTYPE_HIGH_LEVEL | SAM7_USART0_PRIORITY,
USART0IrqHandler);
#endif
#if USE_SAM7_USART1
sdObjectInit(&SD2, NULL, notify2);
AT91C_BASE_PIOA->PIO_PDR = SAM7_USART1_RX | SAM7_USART1_TX;
AT91C_BASE_PIOA->PIO_ASR = SAM7_USART1_RX | SAM7_USART1_TX;
AT91C_BASE_PIOA->PIO_PPUDR = SAM7_USART1_RX | SAM7_USART1_TX;
AIC_ConfigureIT(AT91C_ID_US1,
AT91C_AIC_SRCTYPE_HIGH_LEVEL | SAM7_USART1_PRIORITY,
USART1IrqHandler);
#endif
}
/**
* @brief Low level serial driver configuration and (re)start.
*
* @param[in] sdp pointer to a @p SerialDriver object
* @param[in] config the architecture-dependent serial driver configuration.
* If this parameter is set to @p NULL then a default
* configuration is used.
*/
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config) {
if (config == NULL)
config = &default_config;
#if USE_SAM7_USART0
if (&SD1 == sdp) {
/* Starts the clock and clears possible sources of immediate interrupts.*/
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US0);
/* USART initialization.*/
usart_init(AT91C_BASE_US0, config);
/* Enables associated interrupt vector.*/
AIC_EnableIT(AT91C_ID_US0);
return;
}
#endif
#if USE_SAM7_USART1
if (&SD2 == sdp) {
/* Starts the clock and clears possible sources of immediate interrupts.*/
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US1);
/* USART initialization.*/
usart_init(AT91C_BASE_US1, config);
/* Enables associated interrupt vector.*/
AIC_EnableIT(AT91C_ID_US1);
return;
}
#endif
}
/**
* @brief Low level serial driver stop.
* @details De-initializes the USART, stops the associated clock, resets the
* interrupt vector.
*
* @param[in] sdp pointer to a @p SerialDriver object
*/
void sd_lld_stop(SerialDriver *sdp) {
#if USE_SAM7_USART0
if (&SD1 == sdp) {
usart_deinit(AT91C_BASE_US0);
AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_US0);
AIC_DisableIT(AT91C_ID_US0);
return;
}
#endif
#if USE_SAM7_USART1
if (&SD2 == sdp) {
usart_deinit(AT91C_BASE_US1);
AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_US1);
AIC_DisableIT(AT91C_ID_US1);
return;
}
#endif
}
/** @} */

View File

@ -0,0 +1,157 @@
/*
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 AT91SAM7/serial_lld.h
* @brief AT91SAM7 low level serial driver header
* @addtogroup AT91SAM7_SERIAL
* @{
*/
#ifndef _SERIAL_LLD_H_
#define _SERIAL_LLD_H_
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @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 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_SAM7_USART0) || defined(__DOXYGEN__)
#define USE_SAM7_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_SAM7_USART1) || defined(__DOXYGEN__)
#define USE_SAM7_USART1 TRUE
#endif
/**
* @brief UART1 interrupt priority level setting.
*/
#if !defined(SAM7_USART0_PRIORITY) || defined(__DOXYGEN__)
#define SAM7_USART0_PRIORITY (AT91C_AIC_PRIOR_HIGHEST - 2)
#endif
/**
* @brief UART2 interrupt priority level setting.
*/
#if !defined(SAM7_USART1_PRIORITY) || defined(__DOXYGEN__)
#define SAM7_USART1_PRIORITY (AT91C_AIC_PRIOR_HIGHEST - 2)
#endif
/*===========================================================================*/
/* Unsupported event flags and custom events. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* Serial Driver condition flags type.
*/
typedef uint32_t sdflags_t;
/**
* @brief @p SerialDriver specific data.
*/
struct _serial_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.
*/
sdflags_t flags;
/**
* Input circular buffer.
*/
uint8_t ib[SERIAL_BUFFERS_SIZE];
/**
* Output circular buffer.
*/
uint8_t ob[SERIAL_BUFFERS_SIZE];
};
/**
* @brief AT91SAM7 Serial Driver configuration structure.
* @details An instance of this structure must be passed to @p sdStart()
* in order to configure and start a serial driver operations.
*/
typedef struct {
uint32_t speed;
uint32_t mr;
} SerialDriverConfig;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/** @cond never*/
#if USE_SAM7_USART0
extern SerialDriver SD1;
#endif
#if USE_SAM7_USART1
extern SerialDriver SD2;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void sd_lld_init(void);
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config);
void sd_lld_stop(SerialDriver *sdp);
#ifdef __cplusplus
}
#endif
/** @endcond*/
#endif /* _SERIAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,34 @@
/*
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_DRIVERS AVR Drivers
* @brief Device drivers included in the AVR support.
*
* @ingroup AVR
*/
/**
* @defgroup AVR_SERIAL AVR USART Support
* @brief USART support.
* @details The serial driver supports both the AVR USARTs in asynchronous
* mode.
*
* @ingroup AVR_DRIVERS
*/

View File

@ -0,0 +1,256 @@
/*
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 AVR/serial_lld.c
* @brief AVR low level serial driver code
* @addtogroup AVR_SERIAL
* @{
*/
#include <ch.h>
#include <serial.h>
#if USE_AVR_USART0 || defined(__DOXYGEN__)
/**
* @brief USART0 serial driver identifier.
* @note The name does not follow the convention used in the other ports
* (COMn) because a name conflict with the AVR headers.
*/
SerialDriver SD1;
#endif
#if USE_AVR_USART1 || defined(__DOXYGEN__)
/**
* @brief USART1 serial driver identifier.
* @note The name does not follow the convention used in the other ports
* (COMn) because a name conflict with the AVR headers.
*/
SerialDriver SD2;
#endif
/** @brief Driver default configuration.*/
static const SerialDriverConfig default_config = {
UBRR(DEFAULT_USART_BITRATE),
(1 << UCSZ1) | (1 << UCSZ0)
};
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
static void set_error(uint8_t sra, SerialDriver *sdp) {
sdflags_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();
sdAddFlagsI(sdp, sts);
chSysUnlockFromIsr();
}
#if USE_AVR_USART0 || defined(__DOXYGEN__)
static void notify1(void) {
UCSR0B |= (1 << UDRIE);
}
/**
* @brief USART0 initialization.
* @param[in] config the architecture-dependent serial driver configuration
*/
static void usart0_init(const SerialDriverConfig *config) {
UBRR0L = config->brr;
UBRR0H = config->brr >> 8;
UCSR0A = 0;
UCSR0B = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
UCSR0C = config->csrc;
}
/**
* @brief USART0 de-initialization.
*/
static void usart0_deinit(void) {
UCSR0A = 0;
UCSR0B = 0;
UCSR0C = 0;
}
#endif
#if USE_AVR_USART1 || defined(__DOXYGEN__)
static void notify2(void) {
UCSR1B |= (1 << UDRIE);
}
/**
* @brief USART1 initialization.
* @param[in] config the architecture-dependent serial driver configuration
*/
static void usart1_init(const SerialDriverConfig *config) {
UBRR1L = config->brr;
UBRR1H = config->brr >> 8;
UCSR1A = 0;
UCSR1B = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
UCSR1C = config->csrc;
}
/**
* @brief USART1 de-initialization.
*/
static void usart1_deinit(void) {
UCSR1A = 0;
UCSR1B = 0;
UCSR1C = 0;
}
#endif
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
#if USE_AVR_USART0 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(USART0_RX_vect) {
uint8_t sra;
CH_IRQ_PROLOGUE();
sra = UCSR0A;
if (sra & ((1 << DOR) | (1 << UPE) | (1 << FE)))
set_error(sra, &SD1);
chSysLockFromIsr();
sdIncomingDataI(&SD1, UDR0);
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE();
}
CH_IRQ_HANDLER(USART0_UDRE_vect) {
msg_t b;
CH_IRQ_PROLOGUE();
chSysLockFromIsr();
b = sdRequestDataI(&SER1);
chSysUnlockFromIsr();
if (b < Q_OK)
UCSR0B &= ~(1 << UDRIE);
else
UDR0 = b;
CH_IRQ_EPILOGUE();
}
#endif /* USE_AVR_USART0 */
#if USE_AVR_USART1 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(USART1_RX_vect) {
uint8_t sra;
CH_IRQ_PROLOGUE();
sra = UCSR1A;
if (sra & ((1 << DOR) | (1 << UPE) | (1 << FE)))
set_error(sra, &SD2);
chSysLockFromIsr();
sdIncomingDataI(&SD2, UDR1);
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE();
}
CH_IRQ_HANDLER(USART1_UDRE_vect) {
msg_t b;
CH_IRQ_PROLOGUE();
chSysLockFromIsr();
b = sdRequestDataI(&SD2);
chSysUnlockFromIsr();
if (b < Q_OK)
UCSR1B &= ~(1 << UDRIE);
else
UDR1 = b;
CH_IRQ_EPILOGUE();
}
#endif /* USE_AVR_USART1 */
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* Low level serial driver initialization.
*/
void sd_lld_init(void) {
#if USE_AVR_USART0
sdObjectInit(&SD1, NULL, notify1);
#endif
#if USE_AVR_USART1
sdObjectInit(&SD2, NULL, notify2);
#endif
}
/**
* @brief Low level serial driver configuration and (re)start.
*
* @param[in] sdp pointer to a @p SerialDriver object
* @param[in] config the architecture-dependent serial driver configuration.
* If this parameter is set to @p NULL then a default
* configuration is used.
*/
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config) {
if (config == NULL)
config = &default_config;
#if USE_AVR_USART0
usart0_init(config);
#endif
#if USE_AVR_USART1
usart1_init(config);
#endif
}
/**
* @brief Low level serial driver stop.
* @details De-initializes the USART, stops the associated clock, resets the
* interrupt vector.
*
* @param[in] sdp pointer to a @p SerialDriver object
*/
void sd_lld_stop(SerialDriver *sdp) {
#if USE_AVR_USART0
usart0_deinit();
#endif
#if USE_AVR_USART1
usart1_deinit();
#endif
}
/** @} */

View File

@ -0,0 +1,161 @@
/*
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 AVR/serial_lld.h
* @brief AVR low level serial driver header
* @addtogroup AVR_SERIAL
* @{
*/
#ifndef _SERIAL_LLD_H_
#define _SERIAL_LLD_H_
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @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
/*===========================================================================*/
/* Unsupported event flags and custom events. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* Serial Driver condition flags type.
*/
typedef uint8_t sdflags_t;
/**
* @brief @p SerialDriver specific data.
*/
struct _serial_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.
*/
sdflags_t flags;
/**
* Input circular buffer.
*/
uint8_t ib[SERIAL_BUFFERS_SIZE];
/**
* Output circular buffer.
*/
uint8_t ob[SERIAL_BUFFERS_SIZE];
};
/**
* @brief Macro for baud rate computation.
* @note Make sure the final baud rate is within tolerance.
*/
#define UBRR(b) ((F_CPU / (b << 4)) - 1)
/**
* @brief AVR Serial Driver configuration structure.
* @details An instance of this structure must be passed to @p sdStart()
* in order to configure and start a serial driver operations.
*/
typedef struct {
uint16_t brr;
uint8_t csrc;
} SerialDriverConfig;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/** @cond never*/
#if USE_AVR_USART0
extern SerialDriver SD1;
#endif
#if USE_AVR_USART1
extern SerialDriver SD2;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void sd_lld_init(void);
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config);
void sd_lld_stop(SerialDriver *sdp);
#ifdef __cplusplus
}
#endif
/** @endcond*/
#endif /* _SERIAL_LLD_H_ */
/** @} */

View File

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

View File

@ -0,0 +1,133 @@
/*
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/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(IOPORT1, 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(IOPORT1, 20);
#if LPC214x_SSP_USE_MUTEX
chSemSignal(&me);
#endif
}
/**
* @brief Synchronous SSP transfer.
* @param[in] in pointer to the incoming data buffer, if this parameter is set
* to @p NULL then the incoming data is discarded
* @param[out] out pointer to the outgoing data buffer, if this parameter is
* set to @p NULL then 0xFF bytes will be output
* @param[in] n the number of bytes to be transferred
* @note The transfer is performed in a software loop and is not interrupt
* driven for performance reasons, this function should be invoked
* by a low priority thread in order to "play nice" with the
* rest of the system. This kind of peripheral would really need a
* dedicated DMA channel.
*/
void sspRW(uint8_t *in, uint8_t *out, size_t n) {
int icnt, ocnt;
SSP *ssp = SSPBase;
icnt = ocnt = n;
while (icnt) {
if (ssp->SSP_SR & SR_RNE) {
if (in)
*in++ = ssp->SSP_DR;
else
ssp->SSP_DR;
icnt--;
continue; /* Priority over transmission. */
}
if (ocnt && (ssp->SSP_SR & SR_TNF)) {
if (out)
ssp->SSP_DR = *out++;
else
ssp->SSP_DR = 0xFF;
ocnt--;
}
}
}
/**
* @brief SSP setup.
* @param[in] cpsr the value for the @p CPSR register
* @param[in] cr0 the value for the @p CR0 register
* @param[in] cr1 the value for the @p CR1 register
*/
void ssp_setup(int cpsr, int cr0, int cr1) {
SSP *ssp = SSPBase;
ssp->SSP_CR1 = 0;
ssp->SSP_CR0 = cr0;
ssp->SSP_CPSR = cpsr;
ssp->SSP_CR1 = cr1 | CR1_SSE;
}
/**
* @brief SSP subsystem initialization.
*/
void ssp_init(void) {
/* Enables the SPI1 clock */
PCONP = (PCONP & PCALL) | PCSPI1;
/* Clock = PCLK / 2 (fastest). */
ssp_setup(2, CR0_DSS8BIT | CR0_FRFSPI | CR0_CLOCKRATE(0), 0);
#if LPC214x_SSP_USE_MUTEX
chSemInit(&me, 1);
#endif
}
/** @} */

View File

@ -0,0 +1,54 @@
/*
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/lpc214x_ssp.h
* @brief LPC214x SSP driver macros and structures.
* @addtogroup LPC214x_SSP
* @{
*/
#ifndef _LPC214x_SSP_H_
#define _LPC214x_SSP_H_
/**
* @brief SSP bus mutual exclusion control.
* @details Configuration parameter, if set to @p TRUE enforces mutual
* exclusion when invoking @p sspAcquireBus() and @p sspReleaseBus().
* @note The internally used synchronization mechanism is a @p Semaphore.
*/
#if !defined(LPC214x_SSP_USE_MUTEX) || defined(__DOXYGEN__)
#define LPC214x_SSP_USE_MUTEX TRUE
#endif
#ifdef __cplusplus
}
#endif
void ssp_init(void);
void ssp_setup(int cpsr, int cr0, int cr1);
void sspAcquireBus(void);
void sspReleaseBus(void);
void sspRW(uint8_t *in, uint8_t *out, size_t n);
#ifdef __cplusplus
}
#endif
#endif /* _LPC214x_SSP_H_*/
/** @} */

View File

@ -0,0 +1,89 @@
/*
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/pal_lld.c
* @brief LPC214x FIO low level driver code
* @addtogroup LPC214x_PAL
* @{
*/
#include <ch.h>
#include <pal.h>
/**
* @brief LPC214x I/O ports configuration.
* @details FIO units and PINSEL registers initialization.
*
* @param[in] config the LPC214x ports configuration
*/
void _pal_lld_init(const LPC214xFIOConfig *config) {
/* Enables the access through the fast registers.*/
SCS = 3;
/* I/O pads initial assignment, device drivers may change this setup at a
* later time.*/
PINSEL0 = config->pinsel0;
PINSEL1 = config->pinsel1;
PINSEL2 = config->pinsel2;
/* I/O pads direction initial setting.*/
FIO0Base->FIO_MASK = 0;
FIO0Base->FIO_PIN = config->P0Data.pin;
FIO0Base->FIO_DIR = config->P0Data.dir;
FIO1Base->FIO_MASK = 0;
FIO1Base->FIO_PIN = config->P1Data.pin;
FIO1Base->FIO_DIR = config->P1Data.dir;
}
/**
* @brief Pads mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with high
* state.
* @note This function does not alter the @p PINSELx registers. Alternate
* functions setup must be handled by device-specific code.
*/
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode) {
switch (mode) {
case PAL_MODE_RESET:
case PAL_MODE_INPUT:
port->FIO_DIR &= ~mask;
break;
case PAL_MODE_UNCONNECTED:
port->FIO_PIN |= mask;
case PAL_MODE_OUTPUT_PUSHPULL:
port->FIO_DIR |= mask;
break;
}
}
/** @} */

View File

@ -0,0 +1,253 @@
/*
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/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 IOPORT1 FIO0Base
/**
* @brief FIO port 1 identifier.
*/
#define IOPORT2 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, a logical AND is performed on the output
* data
* @param[in] offset the group bit offset within the port
* @param[in] bits the bits to be written. Values exceeding the group width
* are masked.
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_writegroup(port, mask, offset, bits) { \
(port)->FIO_MASK = ~((mask) << (offset)); \
(port)->FIO_PIN = (bits) << (offset); \
(port)->FIO_MASK = 0; \
}
/**
* @brief Pads group mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note @p PAL_MODE_UNCONNECTED is implemented as push pull output with high
* state.
* @note This function does not alter the @p PINSELx registers. Alternate
* functions setup must be handled by device-specific code.
*/
#define pal_lld_setgroupmode(port, mask, mode) \
_pal_lld_setgroupmode(port, mask, mode)
/**
* @brief Writes a logical state on an output pad.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
* @param[out] bit the logical value, the value must be @p 0 or @p 1
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_writepad(port, pad, bit) pal_lld_writegroup(port, 1, pad, bit)
/**
* @brief FIO port setup.
* @details This function programs the pins direction within a port.
*/
#define pal_lld_lpc214x_set_direction(port, dir) { \
(port)->FIO_DIR = (dir); \
}
#ifdef __cplusplus
extern "C" {
#endif
void _pal_lld_init(const LPC214xFIOConfig *config);
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode);
#ifdef __cplusplus
}
#endif
#endif /* _PAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,84 @@
/*
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 LPC214x 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_INPUT_ANALOG (same as @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 LPC214x UART Support
* @brief UART peripherals support.
* @details The serial driver supports the LPC214x UART peripherals.
*
* @ingroup LPC214x
*/
/**
* @defgroup LPC214x_SSP LPC214x SSP Support
* @brief SSP peripheral support.
* @details This SPI driver supports the LPC214x SSP peripheral.
*
* @ingroup LPC214x
*/

View File

@ -0,0 +1,337 @@
/*
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/serial_lld.c
* @brief LPC214x low level serial driver code
* @addtogroup LPC214x_SERIAL
* @{
*/
#include <ch.h>
#include <serial.h>
#include "board.h"
#include "vic.h"
#if USE_LPC214x_UART0 || defined(__DOXYGEN__)
/** @brief UART0 serial driver identifier.*/
SerialDriver SD1;
#endif
#if USE_LPC214x_UART1 || defined(__DOXYGEN__)
/** @brief UART1 serial driver identifier.*/
SerialDriver SD2;
#endif
/** @brief Driver default configuration.*/
static const SerialDriverConfig default_config = {
38400,
LCR_WL8 | LCR_STOP1 | LCR_NOPARITY,
FCR_TRIGGER0
};
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/**
* @brief UART initialization.
* @param[in] u pointer to an UART I/O block
* @param[in] config the architecture-dependent serial driver configuration
*/
static void uart_init(UART *u, const SerialDriverConfig *config) {
uint32_t div = PCLK / (config->speed << 4);
u->UART_LCR = config->lcr | LCR_DLAB;
u->UART_DLL = div;
u->UART_DLM = div >> 8;
u->UART_LCR = config->lcr;
u->UART_FCR = FCR_ENABLE | FCR_RXRESET | FCR_TXRESET | config->fcr;
u->UART_ACR = 0;
u->UART_FDR = 0x10;
u->UART_TER = TER_ENABLE;
u->UART_IER = IER_RBR | IER_STATUS;
}
/**
* @brief UART de-initialization.
* @param[in] u pointer to an UART I/O block
*/
static void uart_deinit(UART *u) {
u->UART_DLL = 1;
u->UART_DLM = 0;
u->UART_FDR = 0x10;
u->UART_IER = 0;
u->UART_FCR = FCR_RXRESET | FCR_TXRESET;
u->UART_LCR = 0;
u->UART_ACR = 0;
u->UART_TER = TER_ENABLE;
}
/**
* @brief Error handling routine.
* @param[in] err UART LSR register value
* @param[in] sdp communication channel associated to the UART
*/
static void set_error(IOREG32 err, SerialDriver *sdp) {
sdflags_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();
sdAddFlagsI(sdp, sts);
chSysUnlockFromIsr();
}
#if defined(__GNU__)
__attribute__((noinline))
#endif
/**
* @brief Common IRQ handler.
* @param[in] u pointer to an UART I/O block
* @param[in] sdp 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 serve_interrupt(UART *u, SerialDriver *sdp) {
while (TRUE) {
switch (u->UART_IIR & IIR_SRC_MASK) {
case IIR_SRC_NONE:
return;
case IIR_SRC_ERROR:
set_error(u->UART_LSR, sdp);
break;
case IIR_SRC_TIMEOUT:
case IIR_SRC_RX:
while (u->UART_LSR & LSR_RBR_FULL) {
chSysLockFromIsr();
if (chIQPutI(&sdp->d2.iqueue, u->UART_RBR) < Q_OK)
sdAddFlagsI(sdp, SD_OVERRUN_ERROR);
chSysUnlockFromIsr();
}
chSysLockFromIsr();
chEvtBroadcastI(&sdp->d1.ievent);
chSysUnlockFromIsr();
break;
case IIR_SRC_TX:
{
#if UART_FIFO_PRELOAD > 0
int i = UART_FIFO_PRELOAD;
do {
chSysLockFromIsr();
msg_t b = chOQGetI(&sdp->d2.oqueue);
chSysUnlockFromIsr();
if (b < Q_OK) {
u->UART_IER &= ~IER_THRE;
chSysLockFromIsr();
chEvtBroadcastI(&sdp->d1.oevent);
chSysUnlockFromIsr();
break;
}
u->UART_THR = b;
} while (--i);
#else
chSysLockFromIsr();
msg_t b = sdRequestDataI(sdp);
chSysUnlockFromIsr();
if (b < Q_OK)
u->UART_IER &= ~IER_THRE;
else
u->UART_THR = b;
#endif
}
default:
(void) u->UART_THR;
(void) u->UART_RBR;
}
}
}
#if UART_FIFO_PRELOAD > 0
static void preload(UART *u, SerialDriver *sdp) {
if (u->UART_LSR & LSR_THRE) {
int i = UART_FIFO_PRELOAD;
do {
chSysLockFromIsr();
msg_t b = chOQGetI(&sdp->d2.oqueue);
chSysUnlockFromIsr();
if (b < Q_OK) {
chSysLockFromIsr();
chEvtBroadcastI(&sdp->d1.oevent);
chSysUnlockFromIsr();
return;
}
u->UART_THR = b;
} while (--i);
}
u->UART_IER |= IER_THRE;
}
#endif
#if USE_LPC214x_UART0 || defined(__DOXYGEN__)
static void notify1(void) {
#if UART_FIFO_PRELOAD > 0
preload(U0Base, &SD1);
#else
UART *u = U0Base;
if (u->UART_LSR & LSR_THRE) {
chSysLockFromIsr();
u->UART_THR = chOQGetI(&SD1.sd_oqueue);
chSysUnlockFromIsr();
}
u->UART_IER |= IER_THRE;
#endif
}
#endif
#if USE_LPC214x_UART1 || defined(__DOXYGEN__)
static void notify2(void) {
#if UART_FIFO_PRELOAD > 0
preload(U1Base, &SD2);
#else
UART *u = U1Base;
if (u->UART_LSR & LSR_THRE)
u->UART_THR = chOQGetI(&SD2.sd_oqueue);
u->UART_IER |= IER_THRE;
#endif
}
#endif
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
#if USE_LPC214x_UART0 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(UART0IrqHandler) {
CH_IRQ_PROLOGUE();
serve_interrupt(U0Base, &SD1);
VICVectAddr = 0;
CH_IRQ_EPILOGUE();
}
#endif
#if USE_LPC214x_UART1 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(UART1IrqHandler) {
CH_IRQ_PROLOGUE();
serve_interrupt(U1Base, &SD2);
VICVectAddr = 0;
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* Low level serial driver initialization.
*/
void sd_lld_init(void) {
#if USE_LPC214x_UART0
sdObjectInit(&SD1, NULL, notify1);
SetVICVector(UART0IrqHandler, LPC214x_UART1_PRIORITY, SOURCE_UART0);
#endif
#if USE_LPC214x_UART1
sdObjectInit(&SD2, NULL, notify2);
SetVICVector(UART1IrqHandler, LPC214x_UART2_PRIORITY, SOURCE_UART1);
#endif
}
/**
* @brief Low level serial driver configuration and (re)start.
*
* @param[in] sdp pointer to a @p SerialDriver object
* @param[in] config the architecture-dependent serial driver configuration.
* If this parameter is set to @p NULL then a default
* configuration is used.
*/
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config) {
if (config == NULL)
config = &default_config;
#if USE_LPC214x_UART1
if (&SD1 == sdp) {
PCONP = (PCONP & PCALL) | PCUART0;
uart_init(U0Base, config);
VICIntEnable = INTMASK(SOURCE_UART0);
return;
}
#endif
#if USE_LPC214x_UART2
if (&SD2 == sdp) {
PCONP = (PCONP & PCALL) | PCUART1;
uart_init(U1Base, config);
VICIntEnable = INTMASK(SOURCE_UART1);
return;
}
#endif
}
/**
* @brief Low level serial driver stop.
* @details De-initializes the UART, stops the associated clock, resets the
* interrupt vector.
*
* @param[in] sdp pointer to a @p SerialDriver object
*/
void sd_lld_stop(SerialDriver *sdp) {
#if USE_LPC214x_UART1
if (&SD1 == sdp) {
uart_deinit(U0Base);
PCONP = (PCONP & PCALL) & ~PCUART0;
VICIntEnClear = INTMASK(SOURCE_UART0);
return;
}
#endif
#if USE_LPC214x_UART2
if (&SD2 == sdp) {
uart_deinit(U1Base);
PCONP = (PCONP & PCALL) & ~PCUART1;
VICIntEnClear = INTMASK(SOURCE_UART1);
return;
}
#endif
}
/** @} */

View File

@ -0,0 +1,174 @@
/*
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/serial_lld.h
* @brief LPC214x low level serial driver header
* @addtogroup LPC214x_SERIAL
* @{
*/
#ifndef _SERIAL_LLD_H_
#define _SERIAL_LLD_H_
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @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 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
/**
* @brief UART1 interrupt priority level setting.
*/
#if !defined(LPC214x_UART1_PRIORITY) || defined(__DOXYGEN__)
#define LPC214x_UART1_PRIORITY 1
#endif
/**
* @brief UART2 interrupt priority level setting.
*/
#if !defined(LPC214x_UART2_PRIORITY) || defined(__DOXYGEN__)
#define LPC214x_UART2_PRIORITY 2
#endif
/*===========================================================================*/
/* Unsupported event flags and custom events. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* Serial Driver condition flags type.
*/
typedef uint32_t sdflags_t;
/**
* @brief @p SerialDriver specific data.
*/
struct _serial_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.
*/
sdflags_t flags;
/**
* Input circular buffer.
*/
uint8_t ib[SERIAL_BUFFERS_SIZE];
/**
* Output circular buffer.
*/
uint8_t ob[SERIAL_BUFFERS_SIZE];
};
/**
* @brief LPC214x Serial Driver configuration structure.
* @details An instance of this structure must be passed to @p sdStart()
* in order to configure and start a serial driver operations.
*/
typedef struct {
uint32_t speed;
uint32_t lcr;
uint32_t fcr;
} SerialDriverConfig;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/** @cond never*/
#if USE_LPC214x_UART0
extern SerialDriver SD1;
#endif
#if USE_LPC214x_UART1
extern SerialDriver SD2;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void sd_lld_init(void);
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config);
void sd_lld_stop(SerialDriver *sdp);
#ifdef __cplusplus
}
#endif
/** @endcond*/
#endif /* _SERIAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,63 @@
/*
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/vic.c
* @brief LPC214x VIC peripheral support code.
* @addtogroup LPC214x_VIC
* @{
*/
#include <ch.h>
#include "lpc214x.h"
/**
* @brief VIC Initialization.
* @note Better reset everything in the VIC, it is a HUGE source of trouble.
*/
void vic_init(void) {
int i;
VIC *vic = VICBase;
vic->VIC_IntSelect = 0; /* All sources assigned to IRQ. */
vic->VIC_SoftIntClear = ALLINTMASK; /* No interrupts enforced */
vic->VIC_IntEnClear = ALLINTMASK; /* All sources disabled. */
for (i = 0; i < 16; i++) {
vic->VIC_VectCntls[i] = 0;
vic->VIC_VectAddrs[i] = 0;
vic->VIC_VectAddr = 0;
}
}
/**
* @brief Initializes a VIC vector.
* @details Set a vector for an interrupt source and enables it.
* @param[in] handler the pointer to the IRQ service routine
* @param[in] vector the vector number
* @param[in] source the IRQ source to be associated to the vector
*/
void SetVICVector(void *handler, int vector, int source) {
VIC *vicp = VICBase;
vicp->VIC_VectAddrs[vector] = (IOREG32)handler;
vicp->VIC_VectCntls[vector] = (IOREG32)(source | 0x20);
}
/** @} */

View File

@ -0,0 +1,41 @@
/*
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/vic.h
* @brief LPC214x VIC peripheral support code.
* @addtogroup LPC214x_VIC
* @{
*/
#ifndef _VIC_H_
#define _VIC_H_
#ifdef __cplusplus
extern "C" {
#endif
void vic_init(void);
void SetVICVector(void *handler, int vector, int source);
#ifdef __cplusplus
}
#endif
#endif /* _VIC_H_ */
/** @} */

View File

@ -0,0 +1,115 @@
/*
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 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__)
IOPORT1->iop_full.ie.reg_p = 0;
IOPORT1->iop_full.ifg.reg_p = 0;
IOPORT1->iop_full.sel.reg_p = 0;
IOPORT1->iop_common.out = config->P1Data.out;
IOPORT1->iop_common.dir = config->P1Data.dir;
#endif
#if defined(__MSP430_HAS_PORT2__) || defined(__MSP430_HAS_PORT2_R__)
IOPORT2->iop_full.ie.reg_p = 0;
IOPORT2->iop_full.ifg.reg_p = 0;
IOPORT2->iop_full.sel.reg_p = 0;
IOPORT2->iop_common.out = config->P2Data.out;
IOPORT2->iop_common.dir = config->P2Data.dir;
#endif
#if defined(__MSP430_HAS_PORT3__) || defined(__MSP430_HAS_PORT3_R__)
IOPORT3->iop_simple.sel.reg_p = 0;
IOPORT3->iop_common.out = config->P3Data.out;
IOPORT3->iop_common.dir = config->P3Data.dir;
#endif
#if defined(__MSP430_HAS_PORT4__) || defined(__MSP430_HAS_PORT4_R__)
IOPORT4->iop_simple.sel.reg_p = 0;
IOPORT4->iop_common.out = config->P4Data.out;
IOPORT4->iop_common.dir = config->P4Data.dir;
#endif
#if defined(__MSP430_HAS_PORT5__) || defined(__MSP430_HAS_PORT5_R__)
IOPORT5->iop_simple.sel.reg_p = 0;
IOPORT5->iop_common.out = config->P5Data.out;
IOPORT5->iop_common.dir = config->P5Data.dir;
#endif
#if defined(__MSP430_HAS_PORT6__) || defined(__MSP430_HAS_PORT6_R__)
IOPORT6->iop_simple.sel.reg_p = 0;
IOPORT6->iop_common.out = config->P6Data.out;
IOPORT6->iop_common.dir = config->P6Data.dir;
#endif
}
/**
* @brief Pads mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note @p PAL_MODE_UNCONNECTED is implemented as output as recommended by
* the MSP430x1xx Family User's Guide. Unconnected pads are set to
* high logic state by default.
* @note This function does not alter the @p PxSEL registers. Alternate
* functions setup must be handled by device-specific code.
*/
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode) {
switch (mode) {
case PAL_MODE_RESET:
case PAL_MODE_INPUT:
port->iop_common.dir.reg_p &= ~mask;
break;
case PAL_MODE_UNCONNECTED:
port->iop_common.out.reg_p |= mask;
case PAL_MODE_OUTPUT_PUSHPULL:
port->iop_common.dir.reg_p |= mask;
break;
}
}
/** @} */

View File

@ -0,0 +1,293 @@
/*
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 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_INPUT_ANALOG
#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 IOPORT1 ((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 IOPORT2 ((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 IOPORT3 ((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 IOPORT4 ((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 IOPORT5 ((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 IOPORT6 ((ioportid_t)0x0034)
#endif
/*===========================================================================*/
/* Implementation, some of the following macros could be implemented as */
/* functions, if so please put them in a file named pal_lld.c. */
/*===========================================================================*/
/**
* @brief Low level PAL subsystem initialization.
* @details In MSP430 programs all the ports as input.
*
* @param[in] config the MSP430 ports configuration
*/
#define pal_lld_init(config) _pal_lld_init(config)
/**
* @brief Reads the physical I/O port states.
* @details This function is implemented by reading the PxIN register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @return The port bits.
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_readport(port) ((port)->iop_common.in.reg_p)
/**
* @brief Reads the output latch.
* @details This function is implemented by reading the PxOUT register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @return The latched logical states.
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_readlatch(port) ((port)->iop_common.out.reg_p)
/**
* @brief Writes a bits mask on a I/O port.
* @details This function is implemented by writing the PxOUT register, the
* implementation has no side effects.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be written on the specified port
*
* @note This function is not meant to be invoked directly by the application
* code.
*/
#define pal_lld_writeport(port, bits) { \
(port)->iop_common.out.reg_p = (bits); \
}
/**
* @brief Pads group mode setup.
* @details This function programs a pads group belonging to the same port
* with the specified mode.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note @p PAL_MODE_UNCONNECTED is implemented as output as recommended by
* the MSP430x1xx Family User's Guide.
* @note This function does not alter the @p PxSEL registers. Alternate
* functions setup must be handled by device-specific code.
*/
#define pal_lld_setgroupmode(port, mask, mode) \
_pal_lld_setgroupmode(port, mask, mode)
#ifdef __cplusplus
extern "C" {
#endif
void _pal_lld_init(const MSP430DIOConfig *config);
void _pal_lld_setgroupmode(ioportid_t port,
ioportmask_t mask,
uint_fast8_t mode);
#ifdef __cplusplus
}
#endif
#endif /* _PAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,60 @@
/*
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_DRIVERS MSP430 Drivers
* @brief Device drivers included in the MSP430 support.
*
* @ingroup MSP430
*/
/**
* @defgroup MSP430_PAL MSP430 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 MSP430 USART Support
* @brief USART support.
* @details The serial driver supports both the MSP430 USARTs in asynchronous
* mode.
*
* @ingroup MSP430_DRIVERS
*/

View File

@ -0,0 +1,292 @@
/*
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 MSP430/serial_lld.c
* @brief MSP430 low level serial driver code
* @addtogroup MSP430_SERIAL
* @{
*/
#include <ch.h>
#include <serial.h>
#include <signal.h>
#include "board.h"
#if USE_MSP430_USART0 || defined(__DOXYGEN__)
/** @brief USART0 serial driver identifier.*/
SerialDriver SD1;
#endif
#if USE_MSP430_USART1 || defined(__DOXYGEN__)
/** @brief USART1 serial driver identifier.*/
SerialDriver SD2;
#endif
/** @brief Driver default configuration.*/
static const SerialDriverConfig default_config = {
UBR(DEFAULT_USART_BITRATE),
0,
CHAR
};
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
static void set_error(uint8_t urctl, SerialDriver *sdp) {
sdflags_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();
sdAddFlagsI(sdp, sts);
chSysUnlockFromIsr();
}
#if USE_MSP430_USART0 || defined(__DOXYGEN__)
static void notify1(void) {
if (!(U0IE & UTXIE0)) {
chSysLockFromIsr();
U0TXBUF = (uint8_t)sdRequestDataI(&SD1);
chSysUnlockFromIsr();
U0IE |= UTXIE0;
}
}
/**
* @brief USART0 initialization.
* @param[in] config the architecture-dependent serial driver configuration
*/
static void usart0_init(const SerialDriverConfig *config) {
U0CTL = SWRST; /* Resets the USART, it should already be.*/
/* USART init */
U0TCTL = SSEL0 | SSEL1; /* SMCLK as clock source.*/
U0MCTL = config->mod; /* Modulator.*/
U0BR1 = (uint8_t)(config->div >> 8); /* Divider high.*/
U0BR0 = (uint8_t)(config->div >> 0); /* Divider low.*/
/* Clear USART status.*/
(void)U0RXBUF;
U0RCTL = 0;
/* USART enable.*/
U0ME |= UTXE0 + URXE0; /* Enables the USART.*/
U0CTL = config->ctl & ~SWRST; /* Various settings, clears reset state.*/
U0IE |= URXIE0; /* Enables RX interrupt.*/
}
/**
* @brief USART0 de-initialization.
*/
static void usart0_deinit(void) {
U0IE &= ~URXIE0;
U0CTL = SWRST;
}
#endif /* USE_MSP430_USART0 */
#if USE_MSP430_USART1 || defined(__DOXYGEN__)
static void notify2(void) {
if (!(U1IE & UTXIE1)) {
U1TXBUF = (uint8_t)sdRequestDataI(&SD2);
U1IE |= UTXIE1;
}
}
/**
* @brief USART1 initialization.
* @param[in] config the architecture-dependent serial driver configuration
*/
static void usart1_init(const SerialDriverConfig *config) {
U1CTL = SWRST; /* Resets the USART, it should already be.*/
/* USART init.*/
U1TCTL = SSEL0 | SSEL1; /* SMCLK as clock source.*/
U1MCTL = config->mod; /* Modulator.*/
U1BR1 = (uint8_t)(config->div >> 8); /* Divider high.*/
U1BR0 = (uint8_t)(config->div >> 0); /* Divider low.*/
/* Clear USART status.*/
(void)U0RXBUF;
U1RCTL = 0;
/* USART enable.*/
U1ME |= UTXE0 + URXE0; /* Enables the USART.*/
U1CTL = config->ctl & ~SWRST; /* Various settings, clears reset state.*/
U1IE |= URXIE0; /* Enables RX interrupt.*/
}
/**
* @brief USART1 de-initialization.
*/
static void usart1_deinit(void) {
U1IE &= ~URXIE0;
U1CTL = SWRST;
}
#endif /* USE_MSP430_USART1 */
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
#if USE_MSP430_USART0 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(USART0TX_VECTOR) {
msg_t b;
CH_IRQ_PROLOGUE();
chSysLockFromIsr();
b = sdRequestDataI(&SD1);
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)
set_error(urctl, &SD1);
chSysLockFromIsr();
sdIncomingDataI(&SD1, U0RXBUF);
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE();
}
#endif /* USE_MSP430_USART0 */
#if USE_MSP430_USART1 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(USART1TX_VECTOR) {
msg_t b;
CH_IRQ_PROLOGUE();
chSysLockFromIsr();
b = sdRequestDataI(&SD2);
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)
set_error(urctl, &SD2);
chSysLockFromIsr();
sdIncomingDataI(&SD2, U1RXBUF);
chSysUnlockFromIsr();
CH_IRQ_EPILOGUE();
}
#endif /* USE_MSP430_USART1 */
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* Low level serial driver initialization.
*/
void sd_lld_init(void) {
#if USE_MSP430_USART0
sdObjectInit(&SD1, NULL, notify1);
/* I/O pins for USART0.*/
P3SEL |= BV(4) + BV(5);
#endif
#if USE_MSP430_USART1
sdObjectInit(&SD2, NULL, notify2);
/* I/O pins for USART1.*/
P3SEL |= BV(6) + BV(7);
#endif
}
/**
* @brief Low level serial driver configuration and (re)start.
*
* @param[in] sdp pointer to a @p SerialDriver object
* @param[in] config the architecture-dependent serial driver configuration.
* If this parameter is set to @p NULL then a default
* configuration is used.
*/
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config) {
if (config == NULL)
config = &default_config;
#if USE_MSP430_USART0
if (&SD1 == sdp) {
usart0_init(config);
return;
}
#endif
#if USE_MSP430_USART1
if (&SD2 == sdp) {
usart1_init(config);
return;
}
#endif
}
/**
* @brief Low level serial driver stop.
* @details De-initializes the USART, stops the associated clock, resets the
* interrupt vector.
*
* @param[in] sdp pointer to a @p SerialDriver object
*/
void sd_lld_stop(SerialDriver *sdp) {
#if USE_MSP430_USART0
if (&SD1 == sdp) {
usart0_deinit();
return;
}
#endif
#if USE_MSP430_USART1
if (&SD2 == sdp) {
usart1_deinit();
return;
}
#endif
}
/** @} */

View File

@ -0,0 +1,159 @@
/*
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 MSP430/serial_lld.h
* @brief MSP430 low level serial driver header
* @addtogroup MSP430_SERIAL
* @{
*/
#ifndef _SERIAL_LLD_H_
#define _SERIAL_LLD_H_
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @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.
*/
#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
/*===========================================================================*/
/* Unsupported event flags and custom events. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* Serial Driver condition flags type.
*/
typedef uint8_t sdflags_t;
/**
* @brief @p SerialDriver specific data.
*/
struct _serial_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.
*/
sdflags_t flags;
/**
* Input circular buffer.
*/
uint8_t ib[SERIAL_BUFFERS_SIZE];
/**
* Output circular buffer.
*/
uint8_t ob[SERIAL_BUFFERS_SIZE];
};
/**
* @brief Macro for baud rate computation.
* @note Make sure the final baud rate is within tolerance.
*/
#define UBR(b) (SMCLK / (b))
/**
* @brief MSP430 Serial Driver configuration structure.
* @details An instance of this structure must be passed to @p sdStart()
* in order to configure and start a serial driver operations.
*/
typedef struct {
uint16_t div;
uint8_t mod;
uint8_t ctl;
} SerialDriverConfig;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/** @cond never*/
#if USE_MSP430_USART0
extern SerialDriver SD1;
#endif
#if USE_MSP430_USART1
extern SerialDriver SD2;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void sd_lld_init(void);
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config);
void sd_lld_stop(SerialDriver *sdp);
#ifdef __cplusplus
}
#endif
/** @endcond*/
#endif /* _SERIAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,244 @@
/*
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 STM32/adc_lld.c
* @brief STM32 ADC subsystem low level driver source
* @addtogroup STM32_ADC
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_ADC
/*===========================================================================*/
/* Low Level Driver exported variables. */
/*===========================================================================*/
#if USE_STM32_ADC1 || defined(__DOXYGEN__)
/** @brief ADC1 driver identifier.*/
ADCDriver ADCD1;
#endif
/*===========================================================================*/
/* Low Level Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
#if USE_STM32_ADC1 || defined(__DOXYGEN__)
/**
* @brief ADC1 DMA interrupt handler (channel 1).
*/
CH_IRQ_HANDLER(Vector6C) {
uint32_t isr;
CH_IRQ_PROLOGUE();
isr = DMA1->ISR;
DMA1->IFCR |= DMA_IFCR_CGIF1 | DMA_IFCR_CTCIF1 |
DMA_IFCR_CHTIF1 | DMA_IFCR_CTEIF1;
if ((isr & DMA_ISR_HTIF1) != 0) {
/* Half transfer processing.*/
if (ADCD1.ad_callback != NULL) {
/* Invokes the callback passing the 1st half of the buffer.*/
ADCD1.ad_callback(ADCD1.ad_samples, ADCD1.ad_depth / 2);
}
}
if ((isr & DMA_ISR_TCIF1) != 0) {
/* Transfer complete processing.*/
if (!ADCD1.ad_grpp->acg_circular) {
/* End conversion.*/
adc_lld_stop_conversion(&ADCD1);
ADCD1.ad_grpp = NULL;
ADCD1.ad_state = ADC_COMPLETE;
chSysLockFromIsr();
chSemResetI(&ADCD1.ad_sem, 0);
chSysUnlockFromIsr();
}
/* Callback handling.*/
if (ADCD1.ad_callback != NULL) {
if (ADCD1.ad_depth > 1) {
/* Invokes the callback passing the 2nd half of the buffer.*/
size_t half = ADCD1.ad_depth / 2;
ADCD1.ad_callback(ADCD1.ad_samples + half, half);
}
else {
/* Invokes the callback passing the whole buffer.*/
ADCD1.ad_callback(ADCD1.ad_samples, ADCD1.ad_depth);
}
}
}
if ((isr & DMA_ISR_TEIF1) != 0) {
/* DMA error processing.*/
STM32_ADC1_DMA_ERROR_HOOK();
}
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level ADC driver initialization.
*/
void adc_lld_init(void) {
#if USE_STM32_ADC1
/* ADC reset, ensures reset state in order to avoid truouble with JTAGs.*/
RCC->APB2RSTR = RCC_APB2RSTR_ADC1RST;
RCC->APB2RSTR = 0;
/* Driver initialization.*/
adcObjectInit(&ADCD1);
ADCD1.ad_adc = ADC1;
ADCD1.ad_dma = DMA1_Channel1;
ADCD1.ad_dmaprio = STM32_ADC1_DMA_PRIORITY << 12;
/* Temporary activation.*/
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
ADC1->CR1 = 0;
ADC1->CR2 = ADC_CR2_ADON;
/* Reset calibration just to be safe.*/
ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0)
;
/* Calibration.*/
ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
while ((ADC1->CR2 & ADC_CR2_CAL) != 0)
;
/* Return the ADC in low power mode.*/
ADC1->CR2 = 0;
RCC->APB2ENR &= ~RCC_APB2ENR_ADC1EN;
#endif
}
/**
* @brief Configures and activates the ADC peripheral.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
void adc_lld_start(ADCDriver *adcp) {
/* If in stopped state then enables the ADC and DMA clocks.*/
if (adcp->ad_state == ADC_STOP) {
#if USE_STM32_ADC1
if (&ADCD1 == adcp) {
dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/
NVICEnableVector(DMA1_Channel1_IRQn, STM32_ADC1_IRQ_PRIORITY);
DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
}
#endif
/* ADC activation, the calibration procedure has already been performed
during initialization.*/
adcp->ad_adc->CR1 = ADC_CR1_SCAN;
adcp->ad_adc->CR2 = ADC_CR2_ADON;
}
}
/**
* @brief Deactivates the ADC peripheral.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
void adc_lld_stop(ADCDriver *adcp) {
/* If in ready state then disables the ADC clock.*/
if (adcp->ad_state == ADC_READY) {
#if USE_STM32_ADC1
if (&ADCD1 == adcp) {
ADC1->CR1 = 0;
ADC1->CR2 = 0;
NVICDisableVector(DMA1_Channel1_IRQn);
dmaDisable(DMA1_ID);
RCC->APB2ENR &= ~RCC_APB2ENR_ADC1EN;
}
#endif
}
}
/**
* @brief Starts an ADC conversion.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
void adc_lld_start_conversion(ADCDriver *adcp) {
uint32_t ccr, n;
const ADCConversionGroup *grpp = adcp->ad_grpp;
/* DMA setup.*/
adcp->ad_dma->CMAR = (uint32_t)adcp->ad_samples;
ccr = adcp->ad_dmaprio | DMA_CCR1_EN | DMA_CCR1_MSIZE_0 | DMA_CCR1_PSIZE_0 |
DMA_CCR1_MINC | DMA_CCR1_TCIE | DMA_CCR1_TEIE;
if (grpp->acg_circular)
ccr |= DMA_CCR1_CIRC;
if (adcp->ad_depth > 1) {
/* If the buffer depth is greater than one then the half transfer interrupt
interrupt is enabled in order to allows streaming processing.*/
ccr |= DMA_CCR1_HTIE;
n = (uint32_t)grpp->acg_num_channels * (uint32_t)adcp->ad_depth;
}
else
n = (uint32_t)grpp->acg_num_channels;
adcp->ad_dma->CNDTR = n;
adcp->ad_dma->CCR = ccr;
/* ADC setup.*/
adcp->ad_adc->SMPR1 = grpp->acg_smpr1;
adcp->ad_adc->SMPR2 = grpp->acg_smpr2;
adcp->ad_adc->SQR1 = grpp->acg_sqr1;
adcp->ad_adc->SQR2 = grpp->acg_sqr2;
adcp->ad_adc->SQR3 = grpp->acg_sqr3;
adcp->ad_adc->CR1 = grpp->acg_cr1 | ADC_CR1_SCAN;
adcp->ad_adc->CR2 = grpp->acg_cr2 | ADC_CR2_DMA | ADC_CR2_ADON;
/* ADC start.*/
adcp->ad_adc->CR2 |= ADC_CR2_SWSTART | ADC_CR2_EXTTRIG;
}
/**
* @brief Stops an ongoing conversion.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
void adc_lld_stop_conversion(ADCDriver *adcp) {
adcp->ad_adc->CR2 = ADC_CR2_ADON;
adcp->ad_dma->CCR = 0;
}
#endif /* CH_HAL_USE_ADC */
/** @} */

View File

@ -0,0 +1,274 @@
/*
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 STM32/adc_lld.h
* @brief STM32 ADC subsystem low level driver header
* @addtogroup STM32_ADC
* @{
*/
#ifndef _ADC_LLD_H_
#define _ADC_LLD_H_
#if CH_HAL_USE_ADC
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief ADC1 driver enable switch.
* @details If set to @p TRUE the support for ADC1 is included.
* @note The default is @p TRUE.
*/
#if !defined(USE_STM32_ADC1) || defined(__DOXYGEN__)
#define USE_STM32_ADC1 TRUE
#endif
/**
* @brief ADC1 DMA priority (0..3|lowest..highest).
*/
#if !defined(STM32_ADC1_DMA_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC1_DMA_PRIORITY 1
#endif
/**
* @brief ADC1 interrupt priority level setting.
* @note @p BASEPRI_KERNEL >= @p STM32_ADC1_IRQ_PRIORITY > @p PRIORITY_PENDSV.
*/
#if !defined(STM32_ADC1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_ADC1_IRQ_PRIORITY 0x70
#endif
/**
* @brief ADC1 DMA error hook.
* @note The default action for DMA errors is a system halt because DMA error
* can only happen because programming errors.
*/
#if !defined(STM32_ADC1_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_ADC1_DMA_ERROR_HOOK() chSysHalt()
#endif
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
#define ADC_CR2_EXTSEL_SRC(n) ((n) << 17) /**< @brief Trigger source. */
#define ADC_CR2_EXTSEL_SWSTART (7 << 17) /**< @brief Software trigger. */
#define ADC_CHANNEL_IN0 0 /**< @brief External analog input 0. */
#define ADC_CHANNEL_IN1 1 /**< @brief External analog input 1. */
#define ADC_CHANNEL_IN2 2 /**< @brief External analog input 2. */
#define ADC_CHANNEL_IN3 3 /**< @brief External analog input 3. */
#define ADC_CHANNEL_IN4 4 /**< @brief External analog input 4. */
#define ADC_CHANNEL_IN5 5 /**< @brief External analog input 5. */
#define ADC_CHANNEL_IN6 6 /**< @brief External analog input 6. */
#define ADC_CHANNEL_IN7 7 /**< @brief External analog input 7. */
#define ADC_CHANNEL_IN8 8 /**< @brief External analog input 8. */
#define ADC_CHANNEL_IN9 9 /**< @brief External analog input 9. */
#define ADC_CHANNEL_IN10 10 /**< @brief External analog input 10. */
#define ADC_CHANNEL_IN11 11 /**< @brief External analog input 11. */
#define ADC_CHANNEL_IN12 12 /**< @brief External analog input 12. */
#define ADC_CHANNEL_IN13 13 /**< @brief External analog input 13. */
#define ADC_CHANNEL_IN14 14 /**< @brief External analog input 14. */
#define ADC_CHANNEL_IN15 15 /**< @brief External analog input 15. */
#define ADC_CHANNEL_SENSOR 16 /**< @brief Internal temperature sensor.*/
#define ADC_CHANNEL_VREFINT 17 /**< @brief Internal reference. */
#define ADC_SQR1_NUM_CH(n) (((n) - 1) << 20)
#define ADC_SQR3_SQ0_N(n) ((n) << 0)
#define ADC_SQR3_SQ1_N(n) ((n) << 5)
#define ADC_SQR3_SQ2_N(n) ((n) << 10)
#define ADC_SQR3_SQ3_N(n) ((n) << 15)
#define ADC_SQR3_SQ4_N(n) ((n) << 20)
#define ADC_SQR3_SQ5_N(n) ((n) << 25)
#define ADC_SQR2_SQ6_N(n) ((n) << 0)
#define ADC_SQR2_SQ7_N(n) ((n) << 5)
#define ADC_SQR2_SQ8_N(n) ((n) << 10)
#define ADC_SQR2_SQ9_N(n) ((n) << 15)
#define ADC_SQR2_SQ10_N(n) ((n) << 20)
#define ADC_SQR2_SQ11_N(n) ((n) << 25)
#define ADC_SQR1_SQ13_N(n) ((n) << 0)
#define ADC_SQR1_SQ14_N(n) ((n) << 5)
#define ADC_SQR1_SQ15_N(n) ((n) << 10)
#define ADC_SQR1_SQ16_N(n) ((n) << 15)
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief ADC sample data type.
*/
typedef uint16_t adcsample_t;
/**
* @brief Channels number in a conversion group.
*/
typedef uint16_t adc_channels_num_t;
/**
* @brief ADC notification callback type.
* @param[in] buffer pointer to the most recent samples data
* @param[in] n number of buffer rows available starting from @p buffer
*/
typedef void (*adccallback_t)(adcsample_t *buffer, size_t n);
/**
* @brief Conversion group configuration structure.
* @details This implementation-dependent structure describes a conversion
* operation.
*/
typedef struct {
/**
* @brief Enables the circular buffer mode for the group.
*/
bool_t acg_circular;
/**
* @brief Number of the analog channels belonging to the conversion group.
*/
adc_channels_num_t acg_num_channels;
/* End of the mandatory fields.*/
/**
* @brief ADC CR1 register initialization data.
* @note All the required bits must be defined into this field except
* @p ADC_CR1_SCAN that is enforced inside the driver.
*/
uint32_t acg_cr1;
/**
* @brief ADC CR2 register initialization data.
* @note All the required bits must be defined into this field except
* @p ADC_CR2_DMA and @p ADC_CR2_ADON that are enforced inside the
* driver.
*/
uint32_t acg_cr2;
/**
* @brief ADC SMPR1 register initialization data.
*/
uint32_t acg_smpr1;
/**
* @brief ADC SMPR2 register initialization data.
*/
uint32_t acg_smpr2;
/**
* @brief ADC SQR1 register initialization data.
*/
uint32_t acg_sqr1;
/**
* @brief ADC SQR2 register initialization data.
*/
uint32_t acg_sqr2;
/**
* @brief ADC SQR3 register initialization data.
*/
uint32_t acg_sqr3;
} ADCConversionGroup;
/**
* @brief Driver configuration structure.
* @note It could be empty on some architectures.
*/
typedef struct {
/* * <----------
* @brief ADC prescaler setting.
* @note This field can assume one of the following values:
* @p RCC_CFGR_ADCPRE_DIV2, @p RCC_CFGR_ADCPRE_DIV4,
* @p RCC_CFGR_ADCPRE_DIV6, @p RCC_CFGR_ADCPRE_DIV8.
*/
/* uint32_t ac_prescaler;*/
} ADCConfig;
/**
* @brief Structure representing an ADC driver.
*/
typedef struct {
/**
* @brief Driver state.
*/
adcstate_t ad_state;
/**
* @brief Current configuration data.
*/
const ADCConfig *ad_config;
/**
* @brief Synchronization semaphore.
*/
Semaphore ad_sem;
/**
* @brief Current callback function or @p NULL.
*/
adccallback_t ad_callback;
/**
* @brief Current samples buffer pointer or @p NULL.
*/
adcsample_t *ad_samples;
/**
* @brief Current samples buffer depth or @p 0.
*/
size_t ad_depth;
/**
* @brief Current conversion group pointer or @p NULL.
*/
const ADCConversionGroup *ad_grpp;
/* End of the mandatory fields.*/
/**
* @brief Pointer to the ADCx registers block.
*/
ADC_TypeDef *ad_adc;
/**
* @brief Pointer to the DMA channel registers block.
*/
DMA_Channel_TypeDef *ad_dma;
/**
* @brief DMA priority bit mask.
*/
uint32_t ad_dmaprio;
} ADCDriver;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/** @cond never*/
#if USE_STM32_ADC1
ADCDriver ADCD1;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void adc_lld_init(void);
void adc_lld_start(ADCDriver *adcp);
void adc_lld_stop(ADCDriver *adcp);
void adc_lld_start_conversion(ADCDriver *adcp);
void adc_lld_stop_conversion(ADCDriver *adcp);
#ifdef __cplusplus
}
#endif
/** @endcond*/
#endif /* CH_HAL_USE_ADC */
#endif /* _ADC_LLD_H_ */
/** @} */

View File

@ -0,0 +1,159 @@
/*
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 STM32/can_lld.c
* @brief STM32 CAN subsystem low level driver source
* @addtogroup STM32_CAN
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_CAN
/*===========================================================================*/
/* Low Level Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level CAN driver initialization.
*/
void can_lld_init(void) {
}
/**
* @brief Configures and activates the CAN peripheral.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void can_lld_start(CANDriver *canp) {
if (canp->can_state == CAN_STOP) {
/* Clock activation.*/
}
/* Configuration.*/
}
/**
* @brief Deactivates the CAN peripheral.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void can_lld_stop(CANDriver *canp) {
}
/**
* @brief Determines whether a frame can be transmitted.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @return The queue space availability.
* @retval FALSE no space in the transmit queue.
* @retval TRUE transmit slot available.
*/
bool_t can_lld_can_transmit(CANDriver *canp) {
return FALSE;
}
/**
* @brief Inserts a frame into the transmit queue.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] cfp pointer to the CAN frame to be transmitted
*
* @return The operation status.
* @retval RDY_OK frame transmitted.
*/
msg_t can_lld_transmit(CANDriver *canp, const CANFrame *cfp) {
return RDY_OK;
}
/**
* @brief Determines whether a frame has been received.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @return The queue space availability.
* @retval FALSE no space in the transmit queue.
* @retval TRUE transmit slot available.
*/
bool_t can_lld_can_receive(CANDriver *canp) {
return FALSE;
}
/**
* @brief Receives a frame from the input queue.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[out] cfp pointer to the buffer where the CAN frame is copied
*
* @return The operation status.
* @retval RDY_OK frame received.
*/
msg_t can_lld_receive(CANDriver *canp, CANFrame *cfp) {
return RDY_OK;
}
#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
/**
* @brief Enters the sleep mode.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void can_lld_sleep(CANDriver *canp) {
}
/**
* @brief Enforces leaving the sleep mode.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void can_lld_wakeup(CANDriver *canp) {
}
#endif /* CAN_USE_SLEEP_MODE */
#endif /* CH_HAL_USE_CAN */
/** @} */

View File

@ -0,0 +1,154 @@
/*
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 STM32/can_lld.h
* @brief STM32 CAN subsystem low level driver header
* @addtogroup STM32_CAN
* @{
*/
#ifndef _CAN_LLD_H_
#define _CAN_LLD_H_
#if CH_HAL_USE_CAN
/**
* @brief This switch defines whether the driver implementation supports
* a low power switch mode with automatic an wakeup feature.
*/
#define CAN_SUPPORTS_SLEEP TRUE
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Sleep mode related APIs inclusion switch.
* @note This switch is enforced to @p FALSE if the driver implementation
* does not support the sleep mode.
*/
#if CAN_SUPPORTS_SLEEP || defined(__DOXYGEN__)
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
#define CAN_USE_SLEEP_MODE TRUE
#endif
#else /* !CAN_SUPPORTS_SLEEP */
#define CAN_USE_SLEEP_MODE FALSE
#endif /* !CAN_SUPPORTS_SLEEP */
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief CAN frame.
* @note Accessing the frame data as word16 or word32 is not portable because
* machine data endianness, it can be still useful for a quick filling.
*/
typedef struct {
uint8_t cf_DLC:4; /**< @brief Data length. */
uint8_t cf_IDE:1; /**< @brief Identifier type. */
uint8_t cf_RTR:1; /**< @brief Frame type. */
uint32_t cf_id; /**< @brief Frame identifier. */
union {
uint8_t cf_data8[8]; /**< @brief Frame data. */
uint16_t cf_data16[4]; /**< @brief Frame data. */
uint32_t cf_data32[2]; /**< @brief Frame data. */
};
} CANFrame;
/**
* @brief Driver configuration structure.
* @note It could be empty on some architectures.
*/
typedef struct {
} CANConfig;
/**
* @brief Structure representing an CAN driver.
*/
typedef struct {
/**
* @brief Driver state.
*/
canstate_t can_state;
/**
* @brief Current configuration data.
*/
const CANConfig *can_config;
/**
* @brief Transmission queue semaphore.
*/
Semaphore can_txsem;
/**
* @brief Receive queue semaphore.
*/
Semaphore can_rxsem;
/**
* @brief One or more frames become available.
*/
EventSource can_rxfull_event;
/**
* @brief One or more transmission slots become available.
*/
EventSource can_txempty_event;
#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__)
/**
* @brief Entering sleep state event.
*/
EventSource can_sleep_event;
/**
* @brief Exiting sleep state event.
*/
EventSource can_wakeup_event;
#endif /* CAN_USE_SLEEP_MODE */
/* End of the mandatory fields.*/
} CANDriver;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void can_lld_init(void);
void can_lld_start(CANDriver *canp);
void can_lld_stop(CANDriver *canp);
bool_t can_lld_can_transmit(CANDriver *canp);
msg_t can_lld_transmit(CANDriver *canp, const CANFrame *cfp);
bool_t can_lld_can_receive(CANDriver *canp);
msg_t can_lld_receive(CANDriver *canp, CANFrame *cfp);
#if CAN_USE_SLEEP_MODE
void can_lld_sleep(CANDriver *canp);
void can_lld_wakeup(CANDriver *canp);
#endif /* CAN_USE_SLEEP_MODE */
#ifdef __cplusplus
}
#endif
#endif /* CH_HAL_USE_CAN */
#endif /* _CAN_LLD_H_ */
/** @} */

View File

@ -0,0 +1,128 @@
/*
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 STM32/hal_lld.c
* @brief STM32 HAL subsystem low level driver source
* @addtogroup STM32_HAL
* @{
*/
#include <ch.h>
#include <hal.h>
#define AIRCR_VECTKEY 0x05FA0000
/*===========================================================================*/
/* Low Level Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local variables. */
/*===========================================================================*/
/*
* Digital I/O ports static configuration as defined in @p board.h.
*/
const STM32GPIOConfig pal_default_config =
{
{VAL_GPIOAODR, VAL_GPIOACRL, VAL_GPIOACRH},
{VAL_GPIOBODR, VAL_GPIOBCRL, VAL_GPIOBCRH},
{VAL_GPIOCODR, VAL_GPIOCCRL, VAL_GPIOCCRH},
{VAL_GPIODODR, VAL_GPIODCRL, VAL_GPIODCRH},
#if !defined(STM32F10X_LD)
{VAL_GPIOEODR, VAL_GPIOECRL, VAL_GPIOECRH},
#endif
#if defined(STM32F10X_HD)
{VAL_GPIOFODR, VAL_GPIOFCRL, VAL_GPIOFCRH},
{VAL_GPIOGODR, VAL_GPIOGCRL, VAL_GPIOGCRH},
#endif
};
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level HAL driver initialization.
*/
void hal_lld_init(void) {
#if CH_HAL_USE_ADC || CH_HAL_USE_SPI
dmaInit();
#endif
}
/**
* @brief STM32 clocks and PLL initialization.
* @note All the involved constants come from the file @p board.h.
*/
void stm32_clock_init(void) {
/* HSI setup.*/
RCC->CR = RCC_CR_HSITRIM_RESET_BITS | RCC_CR_HSION;
while (!(RCC->CR & RCC_CR_HSIRDY))
; /* Waits until HSI stable. */
/* HSE setup.*/
RCC->CR |= RCC_CR_HSEON;
while (!(RCC->CR & RCC_CR_HSERDY))
; /* Waits until HSE stable. */
/* PLL setup.*/
RCC->CFGR = RCC_CFGR_PLLSRC_HSE_BITS | PLLPREBITS | PLLMULBITS;
RCC->CR |= RCC_CR_PLLON;
while (!(RCC->CR & RCC_CR_PLLRDY))
; /* Waits until PLL stable. */
/* Clock sources.*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE1_DIV2 |
RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_ADCPRE_DIV8 |
RCC_CFGR_MCO_NOCLOCK | USBPREBITS;
/* Flash setup and final clock selection. */
FLASH->ACR = FLASHBITS; /* Flash wait states depending on clock. */
RCC->CFGR |= RCC_CFGR_SW_PLL; /* Switches the PLL clock ON. */
while ((RCC->CFGR & RCC_CFGR_SW) != RCC_CFGR_SW_PLL)
;
}
/**
* @brief STM32 NVIC/SCB/SYSTICK initialization.
* @note All the involved constants come from the file @p board.h.
*/
void stm32_nvic_init(void) {
/* Note: PRIGROUP 4:0 (4:4).*/
SCB->AIRCR = AIRCR_VECTKEY | SCB_AIRCR_PRIGROUP_0 | SCB_AIRCR_PRIGROUP_1;
NVICSetSystemHandlerPriority(HANDLER_SVCALL, PRIORITY_SVCALL);
NVICSetSystemHandlerPriority(HANDLER_SYSTICK, PRIORITY_SYSTICK);
NVICSetSystemHandlerPriority(HANDLER_PENDSV, PRIORITY_PENDSV);
SysTick->LOAD = SYSCLK / (8000000 / CH_FREQUENCY) - 1;
SysTick->VAL = 0;
SysTick->CTRL = SysTick_CTRL_ENABLE | SysTick_CTRL_TICKINT;
}
/** @} */

View File

@ -0,0 +1,61 @@
/*
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 STM32/hal_lld.h
* @brief STM32 HAL subsystem low level driver header
* @addtogroup STM32_HAL
* @{
*/
#ifndef _HAL_LLD_H_
#define _HAL_LLD_H_
#include "nvic.h"
#include "stm32_dma.h"
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void hal_lld_init(void);
void stm32_clock_init(void);
void stm32_nvic_init(void);
#ifdef __cplusplus
}
#endif
#endif /* _HAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,163 @@
/*
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 STM32/pal_lld.c
* @brief STM32 GPIO low level driver code
* @addtogroup STM32_PAL
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_PAL
#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;
IOPORT1->ODR = config->PAData.odr;
IOPORT1->CRH = config->PAData.crh;
IOPORT1->CRL = config->PAData.crl;
IOPORT2->ODR = config->PBData.odr;
IOPORT2->CRH = config->PBData.crh;
IOPORT2->CRL = config->PBData.crl;
IOPORT3->ODR = config->PCData.odr;
IOPORT3->CRH = config->PCData.crh;
IOPORT3->CRL = config->PCData.crl;
IOPORT4->ODR = config->PDData.odr;
IOPORT4->CRH = config->PDData.crh;
IOPORT4->CRL = config->PDData.crl;
#if !defined(STM32F10X_LD) || defined(__DOXYGEN__)
IOPORT5->ODR = config->PEData.odr;
IOPORT5->CRH = config->PEData.crh;
IOPORT5->CRL = config->PEData.crl;
#endif
#if defined(STM32F10X_HD) || defined(__DOXYGEN__)
IOPORT6->ODR = config->PFData.odr;
IOPORT6->CRH = config->PFData.crh;
IOPORT6->CRL = config->PFData.crl;
IOPORT7->ODR = config->PGData.odr;
IOPORT7->CRH = config->PGData.crh;
IOPORT7->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 */
0, /* PAL_MODE_INPUT_ANALOG */
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 & 0x0080) == 0)
ml |= 0xf;
else
crl |= cfg;
if ((mask & 0x8000) == 0)
mh |= 0xf;
else
crh |= cfg;
mask <<= 1;
}
port->CRH = (port->CRH & mh) | crh;
port->CRL = (port->CRL & ml) | crl;
}
#endif /* CH_HAL_USE_PAL */
/** @} */

View File

@ -0,0 +1,299 @@
/*
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 STM32/pal_lld.h
* @brief STM32 GPIO low level driver header
* @addtogroup STM32_PAL
* @{
*/
#ifndef _PAL_LLD_H_
#define _PAL_LLD_H_
#if CH_HAL_USE_PAL
/*===========================================================================*/
/* 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 IOPORT1 GPIOA
/**
* @brief GPIO port B identifier.
*/
#define IOPORT2 GPIOB
/**
* @brief GPIO port C identifier.
*/
#define IOPORT3 GPIOC
/**
* @brief GPIO port D identifier.
*/
#define IOPORT4 GPIOD
/**
* @brief GPIO port E identifier.
*/
#if !defined(STM32F10X_LD) || defined(__DOXYGEN__)
#define IOPORT5 GPIOE
#endif
/**
* @brief GPIO port F identifier.
*/
#if defined(STM32F10X_HD) || defined(__DOXYGEN__)
#define IOPORT6 GPIOF
/**
* @brief GPIO port G identifier.
*/
#define IOPORT7 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 /* CH_HAL_USE_PAL */
#endif /* _PAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,103 @@
/*
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 STM32 STM32 Support
* @brief STM32 specific support.
* @details The STM32 support includes:
* - I/O ports driver.
* - Buffered, interrupt driven, serial driver.
* - DMA capable, high performance, SPI driver.
* - DMA capable, high performance, ADC driver.
* - A demo supporting the kernel test suite.
* - A demo that demonstrate the FatFs use with the MMC driver.
* .
* @ingroup ARMCM3
*/
/**
* @defgroup STM32_PAL STM32 I/O Ports Support
* @brief I/O Ports peripherals support.
* @details This module supports the STM3 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_INPUT_ANALOG.
* - @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 STM32
*/
/**
* @defgroup STM32_SERIAL STM32 USART Support
* @brief USART peripherals support.
* @details The serial driver supports the STM32 USARTs in asynchronous
* mode.
*
* @ingroup STM32
*/
/**
* @defgroup STM32_DMA STM32 DMA Support
* @brief DMA support.
* @details The DMA helper driver allows to stop the DMA clock when no other
* drivers require its services.
*
* @ingroup STM32
*/
/**
* @defgroup STM32_SPI STM32 SPI Support
* @brief SPI peripherals support.
* @details The serial driver supports the STM32 SPIs using DMA channels for
* improved performance.
*
* @ingroup STM32
*/
/**
* @defgroup STM32_ADC STM32 ADC Support
* @brief ADC peripherals support.
* @details The serial driver supports the STM32 ADCs using DMA channels for
* improved performance.
*
* @ingroup STM32
*/

View File

@ -0,0 +1,11 @@
# List of all the STM32 platform files.
PLATFORMSRC = ${CHIBIOS}/os/hal/platforms/STM32/hal_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/adc_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/can_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/pal_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/serial_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/spi_lld.c \
${CHIBIOS}/os/hal/platforms/STM32/stm32_dma.c
# Required include directories
PLATFORMINC = ${CHIBIOS}/os/hal/platforms/STM32

View File

@ -0,0 +1,305 @@
/*
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 STM32/serial_lld.c
* @brief STM32 low level serial driver code
* @addtogroup STM32_SERIAL
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_SERIAL
#if USE_STM32_USART1 || defined(__DOXYGEN__)
/** @brief USART1 serial driver identifier.*/
SerialDriver SD1;
#endif
#if USE_STM32_USART2 || defined(__DOXYGEN__)
/** @brief USART2 serial driver identifier.*/
SerialDriver SD2;
#endif
#if USE_STM32_USART3 || defined(__DOXYGEN__)
/** @brief USART3 serial driver identifier.*/
SerialDriver SD3;
#endif
/** @brief Driver default configuration.*/
static const SerialDriverConfig default_config =
{
38400,
0,
USART_CR2_STOP1_BITS | USART_CR2_LINEN,
0
};
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/**
* @brief USART initialization.
* @details This function must be invoked with interrupts disabled.
*
* @param[in] u pointer to an USART I/O block
* @param[in] config the architecture-dependent serial driver configuration
*/
static void usart_init(USART_TypeDef *u, const SerialDriverConfig *config) {
/*
* Baud rate setting.
*/
if (u == USART1)
u->BRR = APB2CLK / config->speed;
else
u->BRR = APB1CLK / config->speed;
/*
* Note that some bits are enforced.
*/
u->CR1 = config->cr1 | USART_CR1_UE | USART_CR1_PEIE | USART_CR1_RXNEIE |
USART_CR1_TE | USART_CR1_RE;
u->CR2 = config->cr2;
u->CR3 = config->cr3 | USART_CR3_EIE;
}
/**
* @brief USART de-initialization.
* @details This function must be invoked with interrupts disabled.
*
* @param[in] u pointer to an USART I/O block
*/
static void usart_deinit(USART_TypeDef *u) {
u->CR1 = 0;
u->CR2 = 0;
u->CR3 = 0;
}
/**
* @brief Error handling routine.
* @param[in] sr USART SR register value
* @param[in] com communication channel associated to the USART
*/
static void set_error(uint16_t sr, SerialDriver *sdp) {
sdflags_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();
sdAddFlagsI(sdp, 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 serve_interrupt(USART_TypeDef *u, SerialDriver *sdp) {
uint16_t sr = u->SR;
if (sr & (USART_SR_ORE | USART_SR_FE | USART_SR_PE | USART_SR_LBD))
set_error(sr, sdp);
if (sr & USART_SR_RXNE) {
chSysLockFromIsr();
sdIncomingDataI(sdp, u->DR);
chSysUnlockFromIsr();
}
if (sr & USART_SR_TXE) {
chSysLockFromIsr();
msg_t b = sdRequestDataI(sdp);
chSysUnlockFromIsr();
if (b < Q_OK)
u->CR1 &= ~USART_CR1_TXEIE;
else
u->DR = b;
}
}
#if USE_STM32_USART1 || defined(__DOXYGEN__)
static void notify1(void) {
USART1->CR1 |= USART_CR1_TXEIE;
}
#endif
#if USE_STM32_USART2 || defined(__DOXYGEN__)
static void notify2(void) {
USART2->CR1 |= USART_CR1_TXEIE;
}
#endif
#if USE_STM32_USART3 || defined(__DOXYGEN__)
static void notify3(void) {
USART3->CR1 |= USART_CR1_TXEIE;
}
#endif
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
#if USE_STM32_USART1 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(VectorD4) {
CH_IRQ_PROLOGUE();
serve_interrupt(USART1, &SD1);
CH_IRQ_EPILOGUE();
}
#endif
#if USE_STM32_USART2 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(VectorD8) {
CH_IRQ_PROLOGUE();
serve_interrupt(USART2, &SD2);
CH_IRQ_EPILOGUE();
}
#endif
#if USE_STM32_USART3 || defined(__DOXYGEN__)
CH_IRQ_HANDLER(VectorDC) {
CH_IRQ_PROLOGUE();
serve_interrupt(USART3, &SD3);
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* Low level serial driver initialization.
*/
void sd_lld_init(void) {
#if USE_STM32_USART1
sdObjectInit(&SD1, NULL, notify1);
GPIOA->CRH = (GPIOA->CRH & 0xFFFFF00F) | 0x000004B0;
#endif
#if USE_STM32_USART2
sdObjectInit(&SD2, NULL, notify2);
GPIOA->CRL = (GPIOA->CRL & 0xFFFF00FF) | 0x00004B00;
#endif
#if USE_STM32_USART3
sdObjectInit(&SD3, NULL, notify3);
GPIOB->CRH = (GPIOB->CRH & 0xFFFF00FF) | 0x00004B00;
#endif
}
/**
* @brief Low level serial driver configuration and (re)start.
*
* @param[in] sdp pointer to a @p SerialDriver object
* @param[in] config the architecture-dependent serial driver configuration.
* If this parameter is set to @p NULL then a default
* configuration is used.
*/
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config) {
if (config == NULL)
config = &default_config;
#if USE_STM32_USART1
if (&SD1 == sdp) {
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
usart_init(USART1, config);
NVICEnableVector(USART1_IRQn, STM32_USART1_PRIORITY);
return;
}
#endif
#if USE_STM32_USART2
if (&SD2 == sdp) {
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
usart_init(USART2, config);
NVICEnableVector(USART2_IRQn, STM32_USART2_PRIORITY);
return;
}
#endif
#if USE_STM32_USART3
if (&SD3 == sdp) {
RCC->APB1ENR |= RCC_APB1ENR_USART3EN;
usart_init(USART3, config);
NVICEnableVector(USART3_IRQn, STM32_USART3_PRIORITY);
return;
}
#endif
}
/**
* @brief Low level serial driver stop.
* @details De-initializes the USART, stops the associated clock, resets the
* interrupt vector.
*
* @param[in] sdp pointer to a @p SerialDriver object
*/
void sd_lld_stop(SerialDriver *sdp) {
#if USE_STM32_USART1
if (&SD1 == sdp) {
usart_deinit(USART1);
RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN;
NVICDisableVector(USART1_IRQn);
return;
}
#endif
#if USE_STM32_USART2
if (&SD2 == sdp) {
usart_deinit(USART2);
RCC->APB1ENR &= ~RCC_APB1ENR_USART2EN;
NVICDisableVector(USART2_IRQn);
return;
}
#endif
#if USE_STM32_USART3
if (&SD3 == sdp) {
usart_deinit(USART3);
RCC->APB1ENR &= ~RCC_APB1ENR_USART3EN;
NVICDisableVector(USART3_IRQn);
return;
}
#endif
}
#endif /* CH_HAL_USE_SERIAL */
/** @} */

View File

@ -0,0 +1,198 @@
/*
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 STM32/serial_lld.h
* @brief STM32 low level serial driver header
* @addtogroup STM32_SERIAL
* @{
*/
#ifndef _SERIAL_LLD_H_
#define _SERIAL_LLD_H_
#if CH_HAL_USE_SERIAL
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Serial buffers size setting.
* @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 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
/**
* @brief USART1 interrupt priority level setting.
* @note @p BASEPRI_KERNEL >= @p STM32_USART1_PRIORITY > @p PRIORITY_PENDSV.
*/
#if !defined(STM32_USART1_PRIORITY) || defined(__DOXYGEN__)
#define STM32_USART1_PRIORITY 0xC0
#endif
/**
* @brief USART2 interrupt priority level setting.
* @note @p BASEPRI_KERNEL >= @p STM32_USART2_PRIORITY > @p PRIORITY_PENDSV.
*/
#if !defined(STM32_USART2_PRIORITY) || defined(__DOXYGEN__)
#define STM32_USART2_PRIORITY 0xC0
#endif
/**
* @brief USART3 interrupt priority level setting.
* @note @p BASEPRI_KERNEL >= @p STM32_USART3_PRIORITY > @p PRIORITY_PENDSV.
*/
#if !defined(STM32_USART3_PRIORITY) || defined(__DOXYGEN__)
#define STM32_USART3_PRIORITY 0xC0
#endif
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/*
* 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.*/
/*===========================================================================*/
/* Driver data structures. */
/*===========================================================================*/
/**
* Serial Driver condition flags type.
*/
typedef uint32_t sdflags_t;
/**
* @brief @p SerialDriver specific data.
*/
struct _serial_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.
*/
sdflags_t flags;
/**
* Input circular buffer.
*/
uint8_t ib[SERIAL_BUFFERS_SIZE];
/**
* Output circular buffer.
*/
uint8_t ob[SERIAL_BUFFERS_SIZE];
};
/**
* @brief STM32 Serial Driver configuration structure.
* @details An instance of this structure must be passed to @p sdStart()
* in order to configure and start a serial driver operations.
*
* @note This structure content is architecture dependent, each driver
* implementation defines its own version and the custom static
* initializers.
*/
typedef struct {
uint32_t speed;
uint16_t cr1;
uint16_t cr2;
uint16_t cr3;
} SerialDriverConfig;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/** @cond never*/
#if USE_STM32_USART1
extern SerialDriver SD1;
#endif
#if USE_STM32_USART2
extern SerialDriver SD2;
#endif
#if USE_STM32_USART3
extern SerialDriver SD3;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void sd_lld_init(void);
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config);
void sd_lld_stop(SerialDriver *sdp);
#ifdef __cplusplus
}
#endif
/** @endcond*/
#endif /* CH_HAL_USE_SERIAL */
#endif /* _SERIAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,368 @@
/*
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 STM32/spi_lld.c
* @brief STM32 SPI subsystem low level driver source
* @addtogroup STM32_SPI
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_SPI
/*===========================================================================*/
/* Low Level Driver exported variables. */
/*===========================================================================*/
#if USE_STM32_SPI1 || defined(__DOXYGEN__)
/** @brief SPI1 driver identifier.*/
SPIDriver SPID1;
#endif
#if USE_STM32_SPI2 || defined(__DOXYGEN__)
/** @brief SPI2 driver identifier.*/
SPIDriver SPID2;
#endif
/*===========================================================================*/
/* Low Level Driver local variables. */
/*===========================================================================*/
static uint16_t dummyrx;
static uint16_t dummytx;
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
static void spi_stop(SPIDriver *spip) {
/* Stops RX and TX DMA channels.*/
spip->spd_dmarx->CCR = 0;
spip->spd_dmatx->CCR = 0;
/* Stops SPI operations.*/
spip->spd_spi->CR1 &= ~SPI_CR1_SPE;
chSysLockFromIsr();
chSchReadyI(spip->spd_thread);
chSysUnlockFromIsr();
}
static void spi_start_wait(SPIDriver *spip, size_t n,
const void *txbuf, void *rxbuf) {
uint32_t ccr;
/* Common DMA setup.*/
ccr = spip->spd_dmaprio;
if ((spip->spd_config->spc_cr1 & SPI_CR1_DFF) != 0)
ccr |= DMA_CCR1_MSIZE_0 | DMA_CCR1_PSIZE_0; /* 16 bits transfer.*/
/* RX DMA setup.*/
spip->spd_dmarx->CMAR = (uint32_t)rxbuf;
spip->spd_dmarx->CNDTR = (uint32_t)n;
spip->spd_dmarx->CCR |= ccr;
/* TX DMA setup.*/
spip->spd_dmatx->CMAR = (uint32_t)txbuf;
spip->spd_dmatx->CNDTR = (uint32_t)n;
spip->spd_dmatx->CCR |= ccr;
/* DMAs start.*/
spip->spd_dmarx->CCR |= DMA_CCR1_EN;
spip->spd_dmatx->CCR |= DMA_CCR1_EN;
/* SPI enable.*/
chSysLock();
spip->spd_spi->CR1 |= SPI_CR1_SPE;
/* Wait for completion event.*/
spip->spd_thread = currp;
chSchGoSleepS(PRSUSPENDED);
spip->spd_thread = NULL;
chSysUnlock();
}
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
#if USE_STM32_SPI1 || defined(__DOXYGEN__)
/**
* @brief SPI1 RX DMA interrupt handler (channel 2).
*/
CH_IRQ_HANDLER(Vector70) {
CH_IRQ_PROLOGUE();
spi_stop(&SPID1);
if ((DMA1->ISR & DMA_ISR_TEIF2) != 0) {
STM32_SPI1_DMA_ERROR_HOOK();
}
DMA1->IFCR |= DMA_IFCR_CGIF2 | DMA_IFCR_CTCIF2 |
DMA_IFCR_CHTIF2 | DMA_IFCR_CTEIF2;
CH_IRQ_EPILOGUE();
}
/**
* @brief SPI1 TX DMA interrupt handler (channel 3).
*/
CH_IRQ_HANDLER(Vector74) {
CH_IRQ_PROLOGUE();
STM32_SPI1_DMA_ERROR_HOOK();
DMA1->IFCR |= DMA_IFCR_CGIF3 | DMA_IFCR_CTCIF3 |
DMA_IFCR_CHTIF3 | DMA_IFCR_CTEIF3;
CH_IRQ_EPILOGUE();
}
#endif
#if USE_STM32_SPI2 || defined(__DOXYGEN__)
/**
* @brief SPI2 RX DMA interrupt handler (channel 4).
*/
CH_IRQ_HANDLER(Vector78) {
CH_IRQ_PROLOGUE();
spi_stop(&SPID2);
if ((DMA1->ISR & DMA_ISR_TEIF4) != 0) {
STM32_SPI2_DMA_ERROR_HOOK();
}
DMA1->IFCR |= DMA_IFCR_CGIF4 | DMA_IFCR_CTCIF4 |
DMA_IFCR_CHTIF4 | DMA_IFCR_CTEIF4;
CH_IRQ_EPILOGUE();
}
/**
* @brief SPI2 TX DMA interrupt handler (channel 5).
*/
CH_IRQ_HANDLER(Vector7C) {
CH_IRQ_PROLOGUE();
STM32_SPI2_DMA_ERROR_HOOK();
DMA1->IFCR |= DMA_IFCR_CGIF5 | DMA_IFCR_CTCIF5 |
DMA_IFCR_CHTIF5 | DMA_IFCR_CTEIF5;
CH_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level SPI driver initialization.
*/
void spi_lld_init(void) {
dummytx = 0xFFFF;
#if USE_STM32_SPI1
RCC->APB2RSTR = RCC_APB2RSTR_SPI1RST;
RCC->APB2RSTR = 0;
spiObjectInit(&SPID1);
SPID1.spd_thread = NULL;
SPID1.spd_spi = SPI1;
SPID1.spd_dmarx = DMA1_Channel2;
SPID1.spd_dmatx = DMA1_Channel3;
SPID1.spd_dmaprio = STM32_SPI1_DMA_PRIORITY << 12;
GPIOA->CRL = (GPIOA->CRL & 0x000FFFFF) | 0xB4B00000;
#endif
#if USE_STM32_SPI2
RCC->APB1RSTR = RCC_APB1RSTR_SPI2RST;
RCC->APB1RSTR = 0;
spiObjectInit(&SPID2);
SPID2.spd_thread = NULL;
SPID2.spd_spi = SPI2;
SPID2.spd_dmarx = DMA1_Channel4;
SPID2.spd_dmatx = DMA1_Channel5;
SPID2.spd_dmaprio = STM32_SPI2_DMA_PRIORITY << 12;
GPIOB->CRH = (GPIOB->CRH & 0x000FFFFF) | 0xB4B00000;
#endif
}
/**
* @brief Configures and activates the SPI peripheral.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
void spi_lld_start(SPIDriver *spip) {
/* If in stopped state then enables the SPI and DMA clocks.*/
if (spip->spd_state == SPI_STOP) {
#if USE_STM32_SPI1
if (&SPID1 == spip) {
dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/
NVICEnableVector(DMA1_Channel2_IRQn, STM32_SPI1_IRQ_PRIORITY);
NVICEnableVector(DMA1_Channel3_IRQn, STM32_SPI1_IRQ_PRIORITY);
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
}
#endif
#if USE_STM32_SPI2
if (&SPID2 == spip) {
dmaEnable(DMA1_ID); /* NOTE: Must be enabled before the IRQs.*/
NVICEnableVector(DMA1_Channel4_IRQn, STM32_SPI2_IRQ_PRIORITY);
NVICEnableVector(DMA1_Channel5_IRQn, STM32_SPI2_IRQ_PRIORITY);
RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
}
#endif
}
/* SPI setup.*/
spip->spd_spi->CR1 = spip->spd_config->spc_cr1 | SPI_CR1_MSTR;
spip->spd_spi->CR2 = SPI_CR2_SSOE | SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN;
/* DMA setup.*/
spip->spd_dmarx->CPAR = (uint32_t)&spip->spd_spi->DR;
spip->spd_dmatx->CPAR = (uint32_t)&spip->spd_spi->DR;
}
/**
* @brief Deactivates the SPI peripheral.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
void spi_lld_stop(SPIDriver *spip) {
/* If in ready state then disables the SPI clock.*/
if (spip->spd_state == SPI_READY) {
#if USE_STM32_SPI1
if (&SPID1 == spip) {
NVICDisableVector(DMA1_Channel2_IRQn);
NVICDisableVector(DMA1_Channel3_IRQn);
dmaDisable(DMA1_ID);
RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN;
}
#endif
#if USE_STM32_SPI2
if (&SPID2 == spip) {
NVICDisableVector(DMA1_Channel4_IRQn);
NVICDisableVector(DMA1_Channel5_IRQn);
dmaDisable(DMA1_ID);
RCC->APB1ENR &= ~RCC_APB1ENR_SPI2EN;
}
#endif
}
}
/**
* @brief Asserts the slave select signal and prepares for transfers.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
void spi_lld_select(SPIDriver *spip) {
palClearPad(spip->spd_config->spc_ssport, spip->spd_config->spc_sspad);
}
/**
* @brief Deasserts the slave select signal.
* @details The previously selected peripheral is unselected.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
void spi_lld_unselect(SPIDriver *spip) {
palSetPad(spip->spd_config->spc_ssport, spip->spd_config->spc_sspad);
}
/**
* @brief Ignores data on the SPI bus.
* @details This function transmits a series of idle words on the SPI bus and
* ignores the received data. This function can be invoked even
* when a slave select signal has not been yet asserted.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be ignored
*/
void spi_lld_ignore(SPIDriver *spip, size_t n) {
spip->spd_dmarx->CCR = DMA_CCR1_TCIE | DMA_CCR1_TEIE;
spip->spd_dmatx->CCR = DMA_CCR1_DIR | DMA_CCR1_TEIE;
spi_start_wait(spip, n, &dummytx, &dummyrx);
}
/**
* @brief Exchanges data on the SPI bus.
* @details This function performs a simultaneous transmit/receive operation.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be exchanged
* @param[in] txbuf the pointer to the transmit buffer
* @param[out] rxbuf the pointer to the receive buffer
*
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*/
void spi_lld_exchange(SPIDriver *spip, size_t n,
const void *txbuf, void *rxbuf) {
spip->spd_dmarx->CCR = DMA_CCR1_TCIE | DMA_CCR1_MINC | DMA_CCR1_TEIE;
spip->spd_dmatx->CCR = DMA_CCR1_DIR | DMA_CCR1_MINC | DMA_CCR1_TEIE;
spi_start_wait(spip, n, txbuf, rxbuf);
}
/**
* @brief Sends data ever the SPI bus.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to send
* @param[in] txbuf the pointer to the transmit buffer
*
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*/
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
spip->spd_dmarx->CCR = DMA_CCR1_TCIE | DMA_CCR1_TEIE;
spip->spd_dmatx->CCR = DMA_CCR1_DIR | DMA_CCR1_MINC | DMA_CCR1_TEIE;
spi_start_wait(spip, n, txbuf, &dummyrx);
}
/**
* @brief Receives data from the SPI bus.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to receive
* @param[out] rxbuf the pointer to the receive buffer
*
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*/
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
spip->spd_dmarx->CCR = DMA_CCR1_TCIE | DMA_CCR1_MINC | DMA_CCR1_TEIE;
spip->spd_dmatx->CCR = DMA_CCR1_DIR | DMA_CCR1_TEIE;
spi_start_wait(spip, n, &dummytx, rxbuf);
}
#endif /* CH_HAL_USE_SPI */
/** @} */

View File

@ -0,0 +1,210 @@
/*
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 STM32/spi_lld.h
* @brief STM32 SPI subsystem low level driver header
* @addtogroup STM32_SPI
* @{
*/
#ifndef _SPI_LLD_H_
#define _SPI_LLD_H_
#if CH_HAL_USE_SPI
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief SPI1 driver enable switch.
* @details If set to @p TRUE the support for SPI1 is included.
* @note The default is @p TRUE.
*/
#if !defined(USE_STM32_SPI1) || defined(__DOXYGEN__)
#define USE_STM32_SPI1 TRUE
#endif
/**
* @brief SPI2 driver enable switch.
* @details If set to @p TRUE the support for SPI2 is included.
* @note The default is @p TRUE.
*/
#if !defined(USE_STM32_SPI2) || defined(__DOXYGEN__)
#define USE_STM32_SPI2 TRUE
#endif
/**
* @brief SPI1 DMA priority (0..3|lowest..highest).
* @note The priority level is used for both the TX and RX DMA channels but
* because of the channels ordering the RX channel has always priority
* over the TX channel.
*/
#if !defined(SPI1_DMA_PRIORITY) || defined(__DOXYGEN__)
#define STM32_SPI1_DMA_PRIORITY 2
#endif
/**
* @brief SPI2 DMA priority (0..3|lowest..highest).
* @note The priority level is used for both the TX and RX DMA channels but
* because of the channels ordering the RX channel has always priority
* over the TX channel.
*/
#if !defined(SPI2_DMA_PRIORITY) || defined(__DOXYGEN__)
#define STM32_SPI2_DMA_PRIORITY 2
#endif
/**
* @brief SPI1 interrupt priority level setting.
* @note @p BASEPRI_KERNEL >= @p STM32_SPI1_IRQ_PRIORITY > @p PRIORITY_PENDSV.
*/
#if !defined(STM32_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_SPI1_IRQ_PRIORITY 0x60
#endif
/**
* @brief SPI2 interrupt priority level setting.
* @note @p BASEPRI_KERNEL >= @p STM32_SPI2_IRQ_PRIORITY > @p PRIORITY_PENDSV.
*/
#if !defined(STM32_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define STM32_SPI2_IRQ_PRIORITY 0x60
#endif
/**
* @brief SPI1 DMA error hook.
* @note The default action for DMA errors is a system halt because DMA error
* can only happen because programming errors.
*/
#if !defined(STM32_SPI1_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_SPI1_DMA_ERROR_HOOK() chSysHalt()
#endif
/**
* @brief SPI2 DMA error hook.
* @note The default action for DMA errors is a system halt because DMA error
* can only happen because programming errors.
*/
#if !defined(STM32_SPI2_DMA_ERROR_HOOK) || defined(__DOXYGEN__)
#define STM32_SPI2_DMA_ERROR_HOOK() chSysHalt()
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Driver configuration structure.
*/
typedef struct {
/**
* @brief The chip select line port.
*/
ioportid_t spc_ssport;
/**
* @brief The chip select line pad number.
*/
uint16_t spc_sspad;
/**
* @brief SPI initialization data.
*/
uint16_t spc_cr1;
} SPIConfig;
/**
* @brief Structure representing a SPI driver.
*/
typedef struct {
/**
* @brief Driver state.
*/
spistate_t spd_state;
#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
/**
* @brief Mutex protecting the bus.
*/
Mutex spd_mutex;
#elif CH_USE_SEMAPHORES
Semaphore spd_semaphore;
#endif
#endif /* SPI_USE_MUTUAL_EXCLUSION */
/**
* @brief Current configuration data.
*/
const SPIConfig *spd_config;
/* End of the mandatory fields.*/
/**
* @brief Thread waiting for I/O completion.
*/
Thread *spd_thread;
/**
* @brief Pointer to the SPIx registers block.
*/
SPI_TypeDef *spd_spi;
/**
* @brief Pointer to the receive DMA channel registers block.
*/
DMA_Channel_TypeDef *spd_dmarx;
/**
* @brief Pointer to the transmit DMA channel registers block.
*/
DMA_Channel_TypeDef *spd_dmatx;
/**
* @brief DMA priority bit mask.
*/
uint32_t spd_dmaprio;
} SPIDriver;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/** @cond never*/
#if USE_STM32_SPI1
extern SPIDriver SPID1;
#endif
#if USE_STM32_SPI2
extern SPIDriver SPID2;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void spi_lld_init(void);
void spi_lld_start(SPIDriver *spip);
void spi_lld_stop(SPIDriver *spip);
void spi_lld_select(SPIDriver *spip);
void spi_lld_unselect(SPIDriver *spip);
void spi_lld_ignore(SPIDriver *spip, size_t n);
void spi_lld_exchange(SPIDriver *spip, size_t n,
const void *txbuf, void *rxbuf);
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
#ifdef __cplusplus
}
#endif
/** @endcond*/
#endif /* CH_HAL_USE_SPI */
#endif /* _SPI_LLD_H_ */
/** @} */

View File

@ -0,0 +1,92 @@
/*
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 stm32_dma.c
* @brief STM32 DMA helper driver code
* @addtogroup STM32_DMA
* @{
*/
#include "ch.h"
#include "hal.h"
static cnt_t dmacnt1;
#if defined(STM32F10X_HD) || defined (STM32F10X_CL)
static cnt_t dmacnt2;
#endif
/**
* @brief STM32 DMA helper initialization.
*/
void dmaInit(void) {
dmacnt1 = 0;
#if defined(STM32F10X_HD) || defined (STM32F10X_CL)
dmacnt2 = 0;
#endif
}
/**
* @brief Enables the specified DMA controller clock.
*
* @param[in] dma the DMA controller id
*/
void dmaEnable(uint32_t dma) {
switch (dma) {
case DMA1_ID:
if (dmacnt1++ == 0) {
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1->IFCR = 0x0FFFFFFF;
}
break;
#if defined(STM32F10X_HD) || defined (STM32F10X_CL)
case DMA2_ID:
if (dmacnt2++ == 0) {
RCC->AHBENR |= RCC_AHBENR_DMA2EN;
DMA2->IFCR = 0x0FFFFFFF;
}
break;
#endif
}
}
/**
* @brief Disables the specified DMA controller clock.
*
* @param[in] dma the DMA controller id
*/
void dmaDisable(uint32_t dma) {
switch (dma) {
case DMA1_ID:
if (--dmacnt1 == 0)
RCC->AHBENR &= ~RCC_AHBENR_DMA1EN;
break;
#if defined(STM32F10X_HD) || defined (STM32F10X_CL)
case DMA2_ID:
if (--dmacnt2 == 0)
RCC->AHBENR &= ~RCC_AHBENR_DMA2EN;
break;
#endif
}
}
/** @} */

View File

@ -0,0 +1,50 @@
/*
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 stm32_dma.h
* @brief STM32 DMA helper driver header
* @addtogroup STM32_DMA
* @{
*/
#ifndef _STM32_DMA_H_
#define _STM32_DMA_H_
/** @brief DMA1 identifier.*/
#define DMA1_ID 0
/** @brief DMA2 identifier.*/
#if defined(STM32F10X_HD) || defined (STM32F10X_CL) || defined(__DOXYGEN__)
#define DMA2_ID 1
#endif
#ifdef __cplusplus
extern "C" {
#endif
void dmaInit(void);
void dmaEnable(uint32_t dma);
void dmaDisable(uint32_t dma);
#ifdef __cplusplus
}
#endif
#endif /* _STM32_DMA_H_ */
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,254 @@
/*
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 Win32/serial_lld.c
* @brief Win32 low level simulated serial driver code
* @addtogroup WIN32_SERIAL
* @{
*/
#include <windows.h>
#include <stdio.h>
#include <ch.h>
#include <serial.h>
/** @brief Serial driver 1 identifier.*/
#if USE_WIN32_SERIAL1 || defined(__DOXYGEN__)
SerialDriver SD1;
#endif
/** @brief Serial driver 2 identifier.*/
#if USE_WIN32_SERIAL2 || defined(__DOXYGEN__)
SerialDriver SD2;
#endif
/** @brief Driver default configuration.*/
static const SerialDriverConfig default_config = {
};
static u_long nb = 1;
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
static void init(SerialDriver *sdp, uint16_t port) {
struct sockaddr_in sad;
struct protoent *prtp;
if ((prtp = getprotobyname("tcp")) == NULL) {
printf("%s: Error mapping protocol name to protocol number\n", sdp->d2.com_name);
goto abort;
}
sdp->d2.com_listen = socket(PF_INET, SOCK_STREAM, prtp->p_proto);
if (sdp->d2.com_listen == INVALID_SOCKET) {
printf("%s: Error creating simulator socket\n", sdp->d2.com_name);
goto abort;
}
if (ioctlsocket(sdp->d2.com_listen, FIONBIO, &nb) != 0) {
printf("%s: Unable to setup non blocking mode on socket\n", sdp->d2.com_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(sdp->d2.com_listen, (struct sockaddr *)&sad, sizeof(sad))) {
printf("%s: Error binding socket\n", sdp->d2.com_name);
goto abort;
}
if (listen(sdp->d2.com_listen, 1) != 0) {
printf("%s: Error listening socket\n", sdp->d2.com_name);
goto abort;
}
printf("Full Duplex Channel %s listening on port %d\n", sdp->d2.com_name, port);
return;
abort:
if (sdp->d2.com_listen != INVALID_SOCKET)
closesocket(sdp->d2.com_listen);
WSACleanup();
exit(1);
}
static bool_t connint(SerialDriver *sdp) {
if (sdp->d2.com_data == INVALID_SOCKET) {
struct sockaddr addr;
int addrlen = sizeof(addr);
if ((sdp->d2.com_data = accept(sdp->d2.com_listen, &addr, &addrlen)) == INVALID_SOCKET)
return FALSE;
if (ioctlsocket(sdp->d2.com_data, FIONBIO, &nb) != 0) {
printf("%s: Unable to setup non blocking mode on data socket\n", sdp->d2.com_name);
goto abort;
}
sdAddFlagsI(sdp, SD_CONNECTED);
return TRUE;
}
return FALSE;
abort:
if (sdp->d2.com_listen != INVALID_SOCKET)
closesocket(sdp->d2.com_listen);
if (sdp->d2.com_data != INVALID_SOCKET)
closesocket(sdp->d2.com_data);
WSACleanup();
exit(1);
}
static bool_t inint(SerialDriver *sdp) {
if (sdp->d2.com_data != INVALID_SOCKET) {
int i;
uint8_t data[32];
/*
* Input.
*/
int n = recv(sdp->d2.com_data, data, sizeof(data), 0);
switch (n) {
case 0:
closesocket(sdp->d2.com_data);
sdp->d2.com_data = INVALID_SOCKET;
sdAddFlagsI(sdp, SD_DISCONNECTED);
return FALSE;
case SOCKET_ERROR:
if (WSAGetLastError() == WSAEWOULDBLOCK)
return FALSE;
closesocket(sdp->d2.com_data);
sdp->d2.com_data = INVALID_SOCKET;
return FALSE;
}
for (i = 0; i < n; i++)
sdIncomingDataI(sdp, data[i]);
return TRUE;
}
return FALSE;
}
static bool_t outint(SerialDriver *sdp) {
if (sdp->d2.com_data != INVALID_SOCKET) {
int n;
uint8_t data[1];
/*
* Input.
*/
n = sdRequestDataI(sdp);
if (n < 0)
return FALSE;
data[0] = (uint8_t)n;
n = send(sdp->d2.com_data, data, sizeof(data), 0);
switch (n) {
case 0:
closesocket(sdp->d2.com_data);
sdp->d2.com_data = INVALID_SOCKET;
sdAddFlagsI(sdp, SD_DISCONNECTED);
return FALSE;
case SOCKET_ERROR:
if (WSAGetLastError() == WSAEWOULDBLOCK)
return FALSE;
closesocket(sdp->d2.com_data);
sdp->d2.com_data = INVALID_SOCKET;
return FALSE;
}
return TRUE;
}
return FALSE;
}
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* Low level serial driver initialization.
*/
void sd_lld_init(void) {
#if USE_WIN32_SERIAL1
sdObjectInit(&SD1, NULL, NULL);
SD1.d2.com_listen = INVALID_SOCKET;
SD1.d2.com_data = INVALID_SOCKET;
SD1.d2.com_name = "SD1";
#endif
#if USE_WIN32_SERIAL1
sdObjectInit(&SD2, NULL, NULL);
SD2.d2.com_listen = INVALID_SOCKET;
SD2.d2.com_data = INVALID_SOCKET;
SD2.d2.com_name = "SD2";
#endif
}
/**
* @brief Low level serial driver configuration and (re)start.
*
* @param[in] sdp pointer to a @p SerialDriver object
* @param[in] config the architecture-dependent serial driver configuration.
* If this parameter is set to @p NULL then a default
* configuration is used.
*/
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config) {
if (config == NULL)
config = &default_config;
#if USE_WIN32_SERIAL1
if (sdp == &SD1)
init(&SD1, SD1_PORT);
#endif
#if USE_WIN32_SERIAL1
if (sdp == &SD2)
init(&SD2, SD2_PORT);
#endif
}
/**
* @brief Low level serial driver stop.
* @details De-initializes the USART, stops the associated clock, resets the
* interrupt vector.
*
* @param[in] sdp pointer to a @p SerialDriver object
*/
void sd_lld_stop(SerialDriver *sdp) {
(void)sdp;
}
bool_t sd_lld_interrupt_pending(void) {
return connint(&SD1) || connint(&SD2) ||
inint(&SD1) || inint(&SD2) ||
outint(&SD1) || outint(&SD2);
}
/** @} */

View File

@ -0,0 +1,173 @@
/*
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 Win32/serial_lld.h
* @brief Win32 low level simulated serial driver header
* @addtogroup WIN32_SERIAL
* @{
*/
#ifndef _SERIAL_LLD_H_
#define _SERIAL_LLD_H_
#include <windows.h>
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 1024
#endif
/**
* @brief SD1 driver enable switch.
* @details If set to @p TRUE the support for SD1 is included.
* @note The default is @p TRUE.
*/
#if !defined(USE_WIN32_SERIAL1) || defined(__DOXYGEN__)
#define USE_WIN32_SERIAL1 TRUE
#endif
/**
* @brief SD2 driver enable switch.
* @details If set to @p TRUE the support for SD2 is included.
* @note The default is @p TRUE.
*/
#if !defined(USE_WIN32_SERIAL2) || defined(__DOXYGEN__)
#define USE_WIN32_SERIAL2 TRUE
#endif
/**
* @brief Listen port for SD1.
*/
#if !defined(SD1_PORT) || defined(__DOXYGEN__)
#define SD1_PORT 29001
#endif
/**
* @brief Listen port for SD2.
*/
#if !defined(SD2_PORT) || defined(__DOXYGEN__)
#define SD2_PORT 29002
#endif
/*===========================================================================*/
/* Unsupported event flags and custom events. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* Serial Driver condition flags type.
*/
typedef uint32_t sdflags_t;
/**
* @brief @p SerialDriver specific data.
*/
struct _serial_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.
*/
sdflags_t flags;
/**
* Input circular buffer.
*/
uint8_t ib[SERIAL_BUFFERS_SIZE];
/**
* Output circular buffer.
*/
uint8_t ob[SERIAL_BUFFERS_SIZE];
/**
* Listen socket for simulated serial port.
*/
SOCKET com_listen;
/**
* Data socket for simulated serial port.
*/
SOCKET com_data;
/**
* Port readable name.
*/
const char *com_name;
};
/**
* @brief Generic Serial Driver configuration structure.
* @details An instance of this structure must be passed to @p sdStart()
* in order to configure and start a serial driver operations.
*
* @note This structure content is architecture dependent, each driver
* implementation defines its own version and the custom static
* initializers.
*/
typedef struct {
} SerialDriverConfig;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
/** @cond never*/
#if USE_WIN32_SERIAL1
extern SerialDriver SD1;
#endif
#if USE_WIN32_SERIAL2
extern SerialDriver SD2;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void sd_lld_init(void);
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config);
void sd_lld_stop(SerialDriver *sdp);
bool_t sd_lld_interrupt_pending(void);
#ifdef __cplusplus
}
#endif
/** @endcond*/
#endif /* _SERIAL_LLD_H_ */
/** @} */

1
os/haltmp/readme.txt Normal file
View File

@ -0,0 +1 @@
ChibiOS/RT HAL code

217
os/haltmp/src/adc.c Normal file
View File

@ -0,0 +1,217 @@
/*
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 adc.c
* @brief ADC Driver code.
* @addtogroup ADC
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_ADC
/**
* @brief ADC Driver initialization.
*/
void adcInit(void) {
adc_lld_init();
}
/**
* @brief Initializes the standard part of a @p ADCDriver structure.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
void adcObjectInit(ADCDriver *adcp) {
adcp->ad_state = ADC_STOP;
adcp->ad_config = NULL;
adcp->ad_callback = NULL;
adcp->ad_samples = NULL;
adcp->ad_depth = 0;
adcp->ad_grpp = NULL;
chSemInit(&adcp->ad_sem, 0);
}
/**
* @brief Configures and activates the ADC peripheral.
*
* @param[in] adcp pointer to the @p ADCDriver object
* @param[in] config pointer to the @p ADCConfig object
*/
void adcStart(ADCDriver *adcp, const ADCConfig *config) {
chDbgCheck((adcp != NULL) && (config != NULL), "adcStart");
chSysLock();
chDbgAssert((adcp->ad_state == ADC_STOP) || (adcp->ad_state == ADC_READY),
"adcStart(), #1",
"invalid state");
adcp->ad_config = config;
adc_lld_start(adcp);
adcp->ad_state = ADC_READY;
chSysUnlock();
}
/**
* @brief Deactivates the ADC peripheral.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
void adcStop(ADCDriver *adcp) {
chDbgCheck(adcp != NULL, "adcStop");
chSysLock();
chDbgAssert((adcp->ad_state == ADC_STOP) || (adcp->ad_state == ADC_READY),
"adcStop(), #1",
"invalid state");
adc_lld_stop(adcp);
adcp->ad_state = ADC_STOP;
chSysUnlock();
}
/**
* @brief Starts an ADC conversion.
* @details Starts a conversion operation, there are two kind of conversion
* modes:
* - <b>LINEAR</b>, this mode is activated when the @p callback
* parameter is set to @p NULL, in this mode the buffer is filled
* once and then the conversion stops automatically.
* - <b>CIRCULAR</b>, when a callback function is defined the
* conversion never stops and the buffer is filled circularly.
* During the conversion the callback function is invoked when
* the buffer is 50% filled and when the buffer is 100% filled,
* this way is possible to process the conversion stream in real
* time. This kind of conversion can only be stopped by explicitly
* invoking @p adcStopConversion().
* .
*
* @param[in] adcp pointer to the @p ADCDriver object
* @param[in] grpp pointer to a @p ADCConversionGroup object
* @param[out] samples pointer to the samples buffer
* @param[in] depth buffer depth (matrix rows number). The buffer depth
* must be one or an even number.
* @param[in] callback pointer to the conversion callback function
* @return The operation status.
* @retval FALSE the conversion has been started.
* @retval TRUE the driver is busy, conversion not started.
*
* @note The buffer is organized as a matrix of M*N elements where M is the
* channels number configured into the conversion group and N is the
* buffer depth. The samples are sequentially written into the buffer
* with no gaps.
*/
bool_t adcStartConversion(ADCDriver *adcp,
const ADCConversionGroup *grpp,
adcsample_t *samples,
size_t depth,
adccallback_t callback) {
chDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) &&
((depth == 1) || ((depth & 1) == 0)),
"adcStartConversion");
chSysLock();
chDbgAssert((adcp->ad_state == ADC_READY) ||
(adcp->ad_state == ADC_RUNNING) ||
(adcp->ad_state == ADC_COMPLETE),
"adcStartConversion(), #1",
"invalid state");
if (adcp->ad_state == ADC_RUNNING) {
chSysUnlock();
return TRUE;
}
adcp->ad_callback = callback;
adcp->ad_samples = samples;
adcp->ad_depth = depth;
adcp->ad_grpp = grpp;
adc_lld_start_conversion(adcp);
adcp->ad_state = ADC_RUNNING;
chSysUnlock();
return FALSE;
}
/**
* @brief Stops an ongoing conversion.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
void adcStopConversion(ADCDriver *adcp) {
chDbgCheck(adcp != NULL, "adcStopConversion");
chSysLock();
chDbgAssert((adcp->ad_state == ADC_READY) ||
(adcp->ad_state == ADC_RUNNING) ||
(adcp->ad_state == ADC_COMPLETE),
"adcStopConversion(), #1",
"invalid state");
if (adcp->ad_state == ADC_RUNNING) {
adc_lld_stop_conversion(adcp);
adcp->ad_grpp = NULL;
adcp->ad_state = ADC_READY;
chSemResetI(&adcp->ad_sem, 0);
chSchRescheduleS();
}
else
adcp->ad_state = ADC_READY;
chSysUnlock();
}
/**
* @brief Waits for completion.
* @details If the conversion is not completed or not yet started then the
* invoking thread waits for a conversion completion event.
*
* @param[in] adcp pointer to the @p ADCDriver object
* @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 result.
* @retval RDY_OK conversion finished.
* @retval RDY_TIMEOUT conversion not finished within the specified time.
*/
msg_t adcWaitConversion(ADCDriver *adcp, systime_t timeout) {
chSysLock();
chDbgAssert((adcp->ad_state == ADC_READY) ||
(adcp->ad_state == ADC_RUNNING) ||
(adcp->ad_state == ADC_COMPLETE),
"adcWaitConversion(), #1",
"invalid state");
if (adcp->ad_state != ADC_COMPLETE) {
if (chSemWaitTimeoutS(&adcp->ad_sem, timeout) == RDY_TIMEOUT) {
chSysUnlock();
return RDY_TIMEOUT;
}
}
chSysUnlock();
return RDY_OK;
}
#endif /* CH_HAL_USE_ADC */
/** @} */

224
os/haltmp/src/can.c Normal file
View File

@ -0,0 +1,224 @@
/*
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 CAN.c
* @brief CAN Driver code.
* @addtogroup CAN
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_CAN
/**
* @brief CAN Driver initialization.
*/
void canInit(void) {
can_lld_init();
}
/**
* @brief Initializes the standard part of a @p CANDriver structure.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void canObjectInit(CANDriver *canp) {
canp->can_state = CAN_STOP;
canp->can_config = NULL;
chSemInit(&canp->can_txsem, 0);
chSemInit(&canp->can_rxsem, 0);
chEvtInit(&canp->can_rxfull_event);
chEvtInit(&canp->can_txempty_event);
#if CAN_USE_SLEEP_MODE
chEvtInit(&canp->can_sleep_event);
chEvtInit(&canp->can_wakeup_event);
#endif /* CAN_USE_SLEEP_MODE */
}
/**
* @brief Configures and activates the CAN peripheral.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] config pointer to the @p CANConfig object
*/
void canStart(CANDriver *canp, const CANConfig *config) {
chDbgCheck((canp != NULL) && (config != NULL), "canStart");
chSysLock();
chDbgAssert((canp->can_state == CAN_STOP) || (canp->can_state == CAN_READY),
"canStart(), #1",
"invalid state");
canp->can_config = config;
can_lld_start(canp);
canp->can_state = CAN_READY;
chSysUnlock();
}
/**
* @brief Deactivates the CAN peripheral.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void canStop(CANDriver *canp) {
chDbgCheck(canp != NULL, "canStop");
chSysLock();
chDbgAssert((canp->can_state == CAN_STOP) || (canp->can_state == CAN_READY),
"canStop(), #1",
"invalid state");
can_lld_stop(canp);
canp->can_state = CAN_STOP;
chSysUnlock();
}
/**
* @brief Can frame transmission.
* @details The specified frame is queued for transmission, if the hardware
* queue is full then the invoking thread is queued.
* @note Trying to transmit while in sleep mode simply enqueues the thread.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] cfp pointer to the CAN frame to be transmitted
* @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 result.
* @retval RDY_OK the frame has been queued for transmission.
* @retval RDY_TIMEOUT operation not finished within the specified time.
* @retval RDY_RESET driver stopped while waiting.
*/
msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout) {
msg_t msg;
chDbgCheck((canp != NULL) && (cfp != NULL), "canTransmit");
chSysLock();
chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP),
"canTransmit(), #1",
"invalid state");
if ((canp->can_state == CAN_SLEEP) || !can_lld_can_transmit(canp)) {
msg = chSemWaitTimeoutS(&canp->can_txsem, timeout);
if (msg != RDY_OK) {
chSysUnlock();
return msg;
}
}
msg = can_lld_transmit(canp, cfp);
chSysUnlock();
return msg;
}
/**
* @brief Can frame receive.
* @details The function waits until a frame is received.
* @note Trying to receive while in sleep mode simply enqueues the thread.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[out] cfp pointer to the buffer where the CAN frame is copied
* @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 result.
* @retval RDY_OK a frame has been received and placed in the buffer.
* @retval RDY_TIMEOUT operation not finished within the specified time.
* @retval RDY_RESET driver stopped while waiting.
*/
msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout) {
msg_t msg;
chDbgCheck((canp != NULL) && (cfp != NULL), "canReceive");
chSysLock();
chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP),
"canReceive(), #1",
"invalid state");
if ((canp->can_state == CAN_SLEEP) || !can_lld_can_receive(canp)) {
msg = chSemWaitTimeoutS(&canp->can_rxsem, timeout);
if (msg != RDY_OK) {
chSysUnlock();
return msg;
}
}
msg = can_lld_receive(canp, cfp);
chSysUnlock();
return msg;
}
#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
/**
* @brief Enters the sleep mode.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void canSleep(CANDriver *canp) {
chDbgCheck(canp != NULL, "canSleep");
chSysLock();
chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP),
"canSleep(), #1",
"invalid state");
if (canp->can_state == CAN_READY) {
can_lld_sleep(canp);
canp->can_state = CAN_SLEEP;
chEvtBroadcastI(&canp->can_sleep_event);
chSchRescheduleS();
}
chSysUnlock();
}
/**
* @brief Enforces leaving the sleep mode.
* @note The sleep mode is supposed to be usually exited automatically by an
* hardware event.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void canWakeup(CANDriver *canp) {
chDbgCheck(canp != NULL, "canWakeup");
chSysLock();
chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP),
"canWakeup(), #1",
"invalid state");
if (canp->can_state == CAN_SLEEP) {
can_lld_wakeup(canp);
canp->can_state = CAN_READY;
chEvtBroadcastI(&canp->can_wakeup_event);
chSchRescheduleS();
}
chSysUnlock();
}
#endif /* CAN_USE_SLEEP_MODE */
#endif /* CH_HAL_USE_CAN */
/** @} */

60
os/haltmp/src/hal.c Normal file
View File

@ -0,0 +1,60 @@
/*
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 hal.c
* @brief HAL subsystem code.
* @addtogroup HAL
* @{
*/
#include "ch.h"
#include "hal.h"
/**
* @brief HAL initialization.
*/
void halInit(void) {
hal_lld_init();
#if CH_HAL_USE_PAL
palInit(&pal_default_config);
#endif
#if CH_HAL_USE_ADC
adcInit();
#endif
#if CH_HAL_USE_CAN
canInit();
#endif
#if CH_HAL_USE_MAC
macInit();
#endif
#if CH_HAL_USE_SERIAL
sdInit();
#endif
#if CH_HAL_USE_SPI
spiInit();
#endif
#if CH_HAL_USE_MMC_SPI
mmcInit();
#endif
}
/** @} */

178
os/haltmp/src/mac.c Normal file
View File

@ -0,0 +1,178 @@
/*
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 mac.c
* @brief MAC Driver code.
* @addtogroup MAC
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_MAC
/**
* @brief MAC Driver initialization.
*/
void macInit(void) {
mac_lld_init();
}
/**
* @brief Initialize the standard part of a @p MACDriver structure.
*
* @param[in] macp pointer to the @p MACDriver object
*/
void macObjectInit(MACDriver *macp) {
chSemInit(&macp->md_tdsem, 0);
chSemInit(&macp->md_rdsem, 0);
#if CH_USE_EVENTS
chEvtInit(&macp->md_rdevent);
#endif
}
/**
* @brief MAC address setup.
*
* @param[in] macp pointer to the @p MACDriver object
* @param[in] p pointer to a six bytes buffer containing the MAC address. If
* this parameter is set to @p NULL then a system default MAC is
* used.
*
* @note This function must be invoked only with the driver in the stopped
* state. If invoked on an active interface then it is ignored.
*/
void macSetAddress(MACDriver *macp, const uint8_t *p) {
mac_lld_set_address(macp, p);
}
/**
* @brief Allocates a transmission descriptor.
* @details One of the available transmission descriptors is locked and
* returned. If a descriptor is not currently available then the
* invoking thread is queued until one is freed.
*
* @param[in] macp pointer to the @p MACDriver object
* @param[out] tdp pointer to a @p MACTransmitDescriptor 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.
* .
* @return The operation status.
* @retval RDY_OK the descriptor was obtained.
* @retval RDY_TIMEOUT the operation timed out, descriptor not initialized.
*/
msg_t macWaitTransmitDescriptor(MACDriver *macp,
MACTransmitDescriptor *tdp,
systime_t time) {
msg_t msg;
while (((msg = max_lld_get_transmit_descriptor(macp, tdp)) != RDY_OK) &&
(time > 0)) {
chSysLock();
systime_t now = chTimeNow();
if ((msg = chSemWaitTimeoutS(&macp->md_tdsem, time)) == RDY_TIMEOUT)
break;
if (time != TIME_INFINITE)
time -= (chTimeNow() - now);
chSysUnlock();
}
return msg;
}
/**
* @brief Releases a transmit descriptor and starts the transmission of the
* enqueued data as a single frame.
*
* @param[in] tdp the pointer to the @p MACTransmitDescriptor structure
*/
void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp) {
mac_lld_release_transmit_descriptor(tdp);
}
/**
* @brief Waits for a received frame.
* @details Stops until a frame is received and buffered. If a frame is
* not immediately available then the invoking thread is queued
* until one is received.
*
* @param[in] macp pointer to the @p MACDriver object
* @param[out] rdp pointer to a @p MACReceiveDescriptor 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.
* .
* @return The operation status.
* @retval RDY_OK the descriptor was obtained.
* @retval RDY_TIMEOUT the operation timed out, descriptor not initialized.
*/
msg_t macWaitReceiveDescriptor(MACDriver *macp,
MACReceiveDescriptor *rdp,
systime_t time) {
msg_t msg;
while (((msg = max_lld_get_receive_descriptor(macp, rdp)) != RDY_OK) &&
(time > 0)) {
chSysLock();
systime_t now = chTimeNow();
if ((msg = chSemWaitTimeoutS(&macp->md_rdsem, time)) == RDY_TIMEOUT)
break;
if (time != TIME_INFINITE)
time -= (chTimeNow() - now);
chSysUnlock();
}
return msg;
}
/**
* @brief Releases a receive descriptor.
* @details The descriptor and its buffer are made available for more incoming
* frames.
*
* @param[in] rdp the pointer to the @p MACReceiveDescriptor structure
*/
void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp) {
mac_lld_release_receive_descriptor(rdp);
}
/**
* @brief Updates and returns the link status.
*
* @param[in] macp pointer to the @p MACDriver object
* @return The link status.
* @retval TRUE if the link is active.
* @retval FALSE if the link is down.
*/
bool_t macPollLinkStatus(MACDriver *macp) {
return mac_lld_poll_link_status(macp);
}
#endif /* CH_HAL_USE_MAC */
/** @} */

37
os/haltmp/src/mii.c Normal file
View File

@ -0,0 +1,37 @@
/*
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 mii.c
* @brief mii Driver code.
* @addtogroup MII
* @{
*/
#include "ch.h"
#include "mac.h"
#include "mii.h"
/*
* Currently there is no code, everything is done in the header, you may
* omit this file from the project but this may change in future releases.
* The file is here because the driver's naming pattern.
*/
/** @} */

575
os/haltmp/src/mmc_spi.c Normal file
View File

@ -0,0 +1,575 @@
/*
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 mmc_spi.c
* @brief MMC over SPI driver code.
* @addtogroup MMC_SPI
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_MMC_SPI
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
void tmrfunc(void *p) {
MMCDriver *mmcp = p;
if (mmcp->mmc_cnt > 0) {
if (mmcp->mmc_is_inserted()) {
if (--mmcp->mmc_cnt == 0) {
mmcp->mmc_state = MMC_INSERTED;
chEvtBroadcastI(&mmcp->mmc_inserted_event);
}
}
else
mmcp->mmc_cnt = MMC_POLLING_INTERVAL;
}
else {
if (!mmcp->mmc_is_inserted()) {
mmcp->mmc_state = MMC_WAIT;
mmcp->mmc_cnt = MMC_POLLING_INTERVAL;
chEvtBroadcastI(&mmcp->mmc_removed_event);
}
}
chVTSetI(&mmcp->mmc_vt, MS2ST(MMC_POLLING_DELAY), tmrfunc, mmcp);
}
/**
* @brief Waits an idle condition.
*
* @param[in] mmcp pointer to the @p MMCDriver object
*/
static void wait(MMCDriver *mmcp) {
int i;
uint8_t buf[4];
for (i = 0; i < 16; i++) {
spiReceive(mmcp->mmc_spip, 1, buf);
if (buf[0] == 0xFF)
break;
}
/* Looks like it is a long wait.*/
while (TRUE) {
spiReceive(mmcp->mmc_spip, 1, buf);
if (buf[0] == 0xFF)
break;
#ifdef MMC_NICE_WAITING
/* Trying to be nice with the other threads.*/
chThdSleep(1);
#endif
}
}
/**
* @brief Sends a command header.
*
* @param[in] mmcp pointer to the @p MMCDriver object
* @param cmd[in] the command id
* @param arg[in] the command argument
*/
static void send_hdr(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) {
uint8_t buf[6];
/* Wait for the bus to become idle if a write operation was in progress. */
wait(mmcp);
buf[0] = 0x40 | cmd;
buf[1] = arg >> 24;
buf[2] = arg >> 16;
buf[3] = arg >> 8;
buf[4] = arg;
buf[5] = 0x95; /* Valid for CMD0 ignored by other commands. */
spiSend(mmcp->mmc_spip, 6, buf);
}
/**
* @brief Receives a single byte response.
*
* @param[in] mmcp pointer to the @p MMCDriver object
*
* @return The response as an @p uint8_t value.
* @retval 0xFF timed out.
*/
static uint8_t recvr1(MMCDriver *mmcp) {
int i;
uint8_t r1[1];
for (i = 0; i < 9; i++) {
spiReceive(mmcp->mmc_spip, 1, r1);
if (r1[0] != 0xFF)
return r1[0];
}
return 0xFF;
}
/**
* @brief Sends a command an returns a single byte response.
*
* @param[in] mmcp pointer to the @p MMCDriver object
* @param cmd[in] the command id
* @param arg[in] the command argument
*
* @return The response as an @p uint8_t value.
* @retval 0xFF timed out.
*/
static uint8_t send_command(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) {
uint8_t r1;
spiSelect(mmcp->mmc_spip);
send_hdr(mmcp, cmd, arg);
r1 = recvr1(mmcp);
spiUnselect(mmcp->mmc_spip);
return r1;
}
/**
* @brief Waits that the card reaches an idle state.
*
* @param[in] mmcp pointer to the @p MMCDriver object
*/
static void sync(MMCDriver *mmcp) {
uint8_t buf[1];
spiSelect(mmcp->mmc_spip);
while (TRUE) {
spiReceive(mmcp->mmc_spip, 1, buf);
if (buf[0] == 0xFF)
break;
#ifdef MMC_NICE_WAITING
chThdSleep(1); /* Trying to be nice with the other threads.*/
#endif
}
spiUnselect(mmcp->mmc_spip);
}
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief MMC over SPI driver initialization.
*/
void mmcInit(void) {
}
/**
* @brief Initializes an instance.
*
* @param[in] mmcp pointer to the @p MMCDriver object
* @param[in] spip pointer to the SPI driver to be used as interface
* @param[in] lscfg low speed configuration for the SPI driver
* @param[in] hscfg high speed configuration for the SPI driver
* @param[in] is_protected function that returns the card write protection
* setting
* @param[in] is_inserted function that returns the card insertion sensor
* status
*/
void mmcObjectInit(MMCDriver *mmcp, SPIDriver *spip,
const SPIConfig *lscfg, const SPIConfig *hscfg,
mmcquery_t is_protected, mmcquery_t is_inserted) {
mmcp->mmc_state = MMC_STOP;
mmcp->mmc_config = NULL;
mmcp->mmc_spip = spip;
mmcp->mmc_lscfg = lscfg;
mmcp->mmc_hscfg = hscfg;
mmcp->mmc_is_protected = is_protected;
mmcp->mmc_is_inserted = is_inserted;
chEvtInit(&mmcp->mmc_inserted_event);
chEvtInit(&mmcp->mmc_removed_event);
}
/**
* @brief Configures and activates the MMC peripheral.
*
* @param[in] mmcp pointer to the @p MMCDriver object
* @param[in] config pointer to the @p MMCConfig object
*/
void mmcStart(MMCDriver *mmcp, const MMCConfig *config) {
chDbgCheck((mmcp != NULL) && (config != NULL), "mmcStart");
chSysLock();
chDbgAssert(mmcp->mmc_state == MMC_STOP, "mmcStart(), #1", "invalid state");
mmcp->mmc_config = config;
mmcp->mmc_state = MMC_WAIT;
mmcp->mmc_cnt = MMC_POLLING_INTERVAL;
chVTSetI(&mmcp->mmc_vt, MS2ST(MMC_POLLING_DELAY), tmrfunc, mmcp);
chSysUnlock();
}
/**
* @brief Disables the MMC peripheral.
*
* @param[in] mmcp pointer to the @p MMCDriver object
*/
void mmcStop(MMCDriver *mmcp) {
chDbgCheck(mmcp != NULL, "mmcStop");
chSysLock();
chDbgAssert((mmcp->mmc_state != MMC_UNINIT) &&
(mmcp->mmc_state != MMC_READING) &&
(mmcp->mmc_state != MMC_WRITING),
"mmcStop(), #1",
"invalid state");
if (mmcp->mmc_state != MMC_STOP) {
mmcp->mmc_state = MMC_STOP;
chVTResetI(&mmcp->mmc_vt);
}
chSysUnlock();
spiStop(mmcp->mmc_spip);
}
/**
* @brief Performs the initialization procedure on the inserted card.
* @details This function should be invoked when a card is inserted and
* brings the driver in the @p MMC_READY state where it is possible
* to perform read and write operations.
* @note It is possible to invoke this function from the insertion event
* handler.
*
* @param[in] mmcp pointer to the @p MMCDriver object
*
* @return The operation status.
* @retval FALSE the operation was successful and the driver is now
* in the @p MMC_READY state.
* @retval TRUE the operation failed.
*/
bool_t mmcConnect(MMCDriver *mmcp) {
unsigned i;
bool_t result;
chDbgCheck(mmcp != NULL, "mmcConnect");
chDbgAssert((mmcp->mmc_state != MMC_UNINIT) &&
(mmcp->mmc_state != MMC_STOP),
"mmcConnect(), #1",
"invalid state");
if (mmcp->mmc_state == MMC_INSERTED) {
/* Slow clock mode and 128 clock pulses.*/
spiStart(mmcp->mmc_spip, mmcp->mmc_lscfg);
spiIgnore(mmcp->mmc_spip, 16);
/* SPI mode selection.*/
i = 0;
while (TRUE) {
if (send_command(mmcp, MMC_CMDGOIDLE, 0) == 0x01)
break;
if (++i >= MMC_CMD0_RETRY)
return TRUE;
chThdSleepMilliseconds(10);
}
/* Initialization. */
i = 0;
while (TRUE) {
uint8_t b = send_command(mmcp, MMC_CMDINIT, 0);
if (b == 0x00)
break;
if (b != 0x01)
return TRUE;
if (++i >= MMC_CMD1_RETRY)
return TRUE;
chThdSleepMilliseconds(10);
}
/* Initialization complete, full speed. */
spiStart(mmcp->mmc_spip, mmcp->mmc_hscfg);
/* Setting block size.*/
if (send_command(mmcp, MMC_CMDSETBLOCKLEN, MMC_SECTOR_SIZE) != 0x00)
return TRUE;
/* Transition to MMC_READY state (if not extracted).*/
chSysLock();
if (mmcp->mmc_state == MMC_INSERTED) {
mmcp->mmc_state = MMC_READY;
result = FALSE;
}
else
result = TRUE;
chSysUnlock();
return result;
}
if (mmcp->mmc_state == MMC_READY)
return FALSE;
/* Any other state is invalid.*/
return TRUE;
}
/**
* @brief Brings the driver in a state safe for card removal.
*
* @param[in] mmcp pointer to the @p MMCDriver object
* @return The operation status.
* @retval FALSE the operation was successful and the driver is now
* in the @p MMC_INSERTED state.
* @retval TRUE the operation failed.
*/
bool_t mmcDisconnect(MMCDriver *mmcp) {
chDbgCheck(mmcp != NULL, "mmcConnect");
chDbgAssert((mmcp->mmc_state != MMC_UNINIT) &&
(mmcp->mmc_state != MMC_STOP),
"mmcDisconnect(), #1",
"invalid state");
switch (mmcp->mmc_state) {
case MMC_READY:
/* Wait for the pending write operations to complete.*/
sync(mmcp);
chSysLock();
if (mmcp->mmc_state == MMC_READY)
mmcp->mmc_state = MMC_INSERTED;
chSysUnlock();
case MMC_INSERTED:
return FALSE;
default:
return TRUE;
}
}
/**
* @brief Starts a sequential read.
*
* @param[in] mmcp pointer to the @p MMCDriver object
* @param[in] startblk first block to read
*
* @return The operation status.
* @retval FALSE the operation was successful.
* @retval TRUE the operation failed.
*/
bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) {
chDbgCheck(mmcp != NULL, "mmcStartSequentialRead");
chSysLock();
if (mmcp->mmc_state != MMC_READY) {
chSysUnlock();
return TRUE;
}
mmcp->mmc_state = MMC_READING;
chSysUnlock();
spiSelect(mmcp->mmc_spip);
send_hdr(mmcp, MMC_CMDREADMULTIPLE, startblk * MMC_SECTOR_SIZE);
if (recvr1(mmcp) != 0x00) {
spiUnselect(mmcp->mmc_spip);
chSysLock();
if (mmcp->mmc_state == MMC_READING)
mmcp->mmc_state = MMC_READY;
chSysUnlock();
return TRUE;
}
return FALSE;
}
/**
* @brief Reads a block within a sequential read operation.
*
* @param[in] mmcp pointer to the @p MMCDriver object
* @param[out] buffer pointer to the read buffer
*
* @return The operation status.
* @retval FALSE the operation was successful.
* @retval TRUE the operation failed.
*/
bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) {
int i;
chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialRead");
chSysLock();
if (mmcp->mmc_state != MMC_READING) {
chSysUnlock();
return TRUE;
}
chSysUnlock();
for (i = 0; i < MMC_WAIT_DATA; i++) {
spiReceive(mmcp->mmc_spip, 1, buffer);
if (buffer[0] == 0xFE) {
spiReceive(mmcp->mmc_spip, MMC_SECTOR_SIZE, buffer);
/* CRC ignored. */
spiIgnore(mmcp->mmc_spip, 2);
return FALSE;
}
}
/* Timeout.*/
spiUnselect(mmcp->mmc_spip);
chSysLock();
if (mmcp->mmc_state == MMC_READING)
mmcp->mmc_state = MMC_READY;
chSysUnlock();
return TRUE;
}
/**
* @brief Stops a sequential read gracefully.
*
* @param[in] mmcp pointer to the @p MMCDriver object
*
* @return The operation status.
* @retval FALSE the operation was successful.
* @retval TRUE the operation failed.
*/
bool_t mmcStopSequentialRead(MMCDriver *mmcp) {
static const uint8_t stopcmd[] = {0x40 | MMC_CMDSTOP, 0, 0, 0, 0, 1, 0xFF};
bool_t result;
chDbgCheck(mmcp != NULL, "mmcStopSequentialRead");
chSysLock();
if (mmcp->mmc_state != MMC_READING) {
chSysUnlock();
return TRUE;
}
chSysUnlock();
spiSend(mmcp->mmc_spip, sizeof(stopcmd), stopcmd);
result = recvr1(mmcp) != 0x00;
spiUnselect(mmcp->mmc_spip);
chSysLock();
if (mmcp->mmc_state == MMC_READING)
mmcp->mmc_state = MMC_READY;
chSysUnlock();
return result;
}
/**
* @brief Starts a sequential write.
*
* @param[in] mmcp pointer to the @p MMCDriver object
* @param[in] startblk first block to write
*
* @return The operation status.
* @retval FALSE the operation was successful.
* @retval TRUE the operation failed.
*/
bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) {
chDbgCheck(mmcp != NULL, "mmcStartSequentialWrite");
chSysLock();
if (mmcp->mmc_state != MMC_READY) {
chSysUnlock();
return TRUE;
}
mmcp->mmc_state = MMC_WRITING;
chSysUnlock();
spiSelect(mmcp->mmc_spip);
send_hdr(mmcp, MMC_CMDWRITEMULTIPLE, startblk * MMC_SECTOR_SIZE);
if (recvr1(mmcp) != 0x00) {
spiUnselect(mmcp->mmc_spip);
chSysLock();
if (mmcp->mmc_state == MMC_WRITING)
mmcp->mmc_state = MMC_READY;
chSysUnlock();
return TRUE;
}
return FALSE;
}
/**
* @brief Writes a block within a sequential write operation.
*
* @param[in] mmcp pointer to the @p MMCDriver object
* @param[out] buffer pointer to the write buffer
*
* @return The operation status.
* @retval FALSE the operation was successful.
* @retval TRUE the operation failed.
*/
bool_t mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) {
static const uint8_t start[] = {0xFF, 0xFC};
uint8_t b[1];
chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialRead");
chSysLock();
if (mmcp->mmc_state != MMC_WRITING) {
chSysUnlock();
return TRUE;
}
chSysUnlock();
spiSend(mmcp->mmc_spip, sizeof(start), start); /* Data prologue. */
spiSend(mmcp->mmc_spip, MMC_SECTOR_SIZE, buffer); /* Data. */
spiIgnore(mmcp->mmc_spip, 2); /* CRC ignored. */
spiReceive(mmcp->mmc_spip, 1, b);
if ((b[0] & 0x1F) == 0x05)
return FALSE;
/* Error.*/
spiUnselect(mmcp->mmc_spip);
chSysLock();
if (mmcp->mmc_state == MMC_WRITING)
mmcp->mmc_state = MMC_READY;
chSysUnlock();
return TRUE;
}
/**
* @brief Stops a sequential write gracefully.
*
* @param[in] mmcp pointer to the @p MMCDriver object
*
* @return The operation status.
* @retval FALSE the operation was successful.
* @retval TRUE the operation failed.
*/
bool_t mmcStopSequentialWrite(MMCDriver *mmcp) {
static const uint8_t stop[] = {0xFD, 0xFF};
chDbgCheck(mmcp != NULL, "mmcStopSequentialWrite");
chSysLock();
if (mmcp->mmc_state != MMC_WRITING) {
chSysUnlock();
return TRUE;
}
chSysUnlock();
spiSend(mmcp->mmc_spip, sizeof(stop), stop);
spiUnselect(mmcp->mmc_spip);
chSysLock();
if (mmcp->mmc_state == MMC_WRITING) {
mmcp->mmc_state = MMC_READY;
chSysUnlock();
return FALSE;
}
chSysUnlock();
return TRUE;
}
#endif /* CH_HAL_USE_MMC_SPI */
/** @} */

98
os/haltmp/src/pal.c Normal file
View File

@ -0,0 +1,98 @@
/*
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 pal.c
* @brief I/O Ports Abstraction Layer code
* @addtogroup PAL
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_PAL
/**
* @brief Read from an I/O bus.
*
* @param[in] bus the I/O bus, pointer to a @p IOBus structure
* @return The bus logical states.
*
* @note The operation is not guaranteed to be atomic on all the architectures,
* for atomicity and/or portability reasons you may need to enclose port
* I/O operations between @p chSysLock() and @p chSysUnlock().
* @note The function internally uses the @p palReadGroup() macro. The use of
* this function is preferred when you value code size, readability and
* error checking over speed.
*/
ioportmask_t palReadBus(IOBus *bus) {
chDbgCheck((bus != NULL) &&
(bus->bus_offset > PAL_IOPORTS_WIDTH), "palReadBus");
return palReadGroup(bus->bus_portid, bus->bus_mask, bus->bus_offset);
}
/**
* @brief Write to an I/O bus.
*
* @param[in] bus the I/O bus, pointer to a @p IOBus structure
* @param[in] bits the bits to be written on the I/O bus. Values exceeding
* the bus width are masked so most significant bits are lost.
*
* @note The operation is not guaranteed to be atomic on all the architectures,
* for atomicity and/or portability reasons you may need to enclose port
* I/O operations between @p chSysLock() and @p chSysUnlock().
* @note The default implementation is non atomic and not necessarily
* optimal. Low level drivers may optimize the function by using
* specific hardware or coding.
*/
void palWriteBus(IOBus *bus, ioportmask_t bits) {
chDbgCheck((bus != NULL) &&
(bus->bus_offset > PAL_IOPORTS_WIDTH), "palWriteBus");
palWriteGroup(bus->bus_portid, bus->bus_mask, bus->bus_offset, bits);
}
/**
* @brief Programs a bus with the specified mode.
*
* @param[in] bus the I/O bus, pointer to a @p IOBus structure
* @param[in] mode the mode
*
* @note The operation is not guaranteed to be atomic on all the architectures,
* for atomicity and/or portability reasons you may need to enclose port
* I/O operations between @p chSysLock() and @p chSysUnlock().
* @note The default implementation is non atomic and not necessarily
* optimal. Low level drivers may optimize the function by using
* specific hardware or coding.
*/
void palSetBusMode(IOBus *bus, uint_fast8_t mode) {
chDbgCheck((bus != NULL) &&
(bus->bus_offset > PAL_IOPORTS_WIDTH), "palSetBusMode");
palSetGroupMode(bus->bus_portid, bus->bus_mask, mode);
}
#endif /* CH_HAL_USE_PAL */
/** @} */

201
os/haltmp/src/serial.c Normal file
View File

@ -0,0 +1,201 @@
/*
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.c
* @brief Serial Driver code.
* @addtogroup SERIAL
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_SERIAL
/*
* Interface implementation, the following functions just invoke the equivalent
* queue-level function or macro.
*/
static bool_t putwouldblock(void *ip) {
return chOQIsFull(&((SerialDriver *)ip)->d2.oqueue);
}
static bool_t getwouldblock(void *ip) {
return chIQIsEmpty(&((SerialDriver *)ip)->d2.iqueue);
}
static msg_t put(void *ip, uint8_t b, systime_t timeout) {
return chOQPutTimeout(&((SerialDriver *)ip)->d2.oqueue, b, timeout);
}
static msg_t get(void *ip, systime_t timeout) {
return chIQGetTimeout(&((SerialDriver *)ip)->d2.iqueue, timeout);
}
static size_t write(void *ip, uint8_t *buffer, size_t n) {
return chOQWrite(&((SerialDriver *)ip)->d2.oqueue, buffer, n);
}
static size_t read(void *ip, uint8_t *buffer, size_t n) {
return chIQRead(&((SerialDriver *)ip)->d2.iqueue, buffer, n);
}
static const struct SerialDriverVMT vmt = {
{putwouldblock, getwouldblock, put, get},
{write, read},
{}
};
/**
* @brief Serial Driver initialization.
*/
void sdInit(void) {
sd_lld_init();
}
/**
* @brief Initializes a generic full duplex driver object.
* @details The HW dependent part of the initialization has to be performed
* outside, usually in the hardware initialization code.
*
* @param[out] sdp pointer to a @p SerialDriver structure
* @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] onotify pointer to a callback function that is invoked when
* some data is written in the Queue. The value can be
* @p NULL.
*/
void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) {
sdp->vmt = &vmt;
chEvtInit(&sdp->d1.ievent);
chEvtInit(&sdp->d1.oevent);
chEvtInit(&sdp->d2.sevent);
sdp->d2.flags = SD_NO_ERROR;
chIQInit(&sdp->d2.iqueue, sdp->d2.ib, SERIAL_BUFFERS_SIZE, inotify);
chOQInit(&sdp->d2.oqueue, sdp->d2.ob, SERIAL_BUFFERS_SIZE, onotify);
}
/**
* @brief Configures and starts the driver.
*
* @param[in] sdp pointer to a @p SerialDriver object
* @param[in] config the architecture-dependent serial driver configuration.
* If this parameter is set to @p NULL then a default
* configuration is used.
*/
void sdStart(SerialDriver *sdp, const SerialDriverConfig *config) {
chSysLock();
sd_lld_start(sdp, config);
chSysUnlock();
}
/**
* @brief Stops the driver.
* @details Any thread waiting on the driver's queues will be awakened with
* the message @p Q_RESET.
*
* @param[in] sdp pointer to a @p SerialDrive object
*/
void sdStop(SerialDriver *sdp) {
chSysLock();
sd_lld_stop(sdp);
chOQResetI(&sdp->d2.oqueue);
chIQResetI(&sdp->d2.iqueue);
chSchRescheduleS();
chSysUnlock();
}
/**
* @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 SerialDriver structure
* @param[in] b the byte to be written in the driver's Input Queue
*/
void sdIncomingDataI(SerialDriver *sd, uint8_t b) {
if (chIQPutI(&sd->d2.iqueue, b) < Q_OK)
sdAddFlagsI(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 SerialDriver 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 sdRequestDataI(SerialDriver *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 SerialDriver structure
* @param[in] mask condition flags to be added to the mask
*/
void sdAddFlagsI(SerialDriver *sd, sdflags_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 SerialDriver structure
* @return The condition flags modified since last time this function was
* invoked.
*/
sdflags_t sdGetAndClearFlags(SerialDriver *sd) {
sdflags_t mask;
mask = sd->d2.flags;
sd->d2.flags = SD_NO_ERROR;
return mask;
}
#endif /* CH_HAL_USE_SERIAL */
/** @} */

262
os/haltmp/src/spi.c Normal file
View File

@ -0,0 +1,262 @@
/*
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 spi.c
* @brief SPI Driver code.
* @addtogroup SPI
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_SPI
/**
* @brief SPI Driver initialization.
*/
void spiInit(void) {
spi_lld_init();
}
/**
* @brief Initializes the standard part of a @p SPIDriver structure.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
void spiObjectInit(SPIDriver *spip) {
spip->spd_state = SPI_STOP;
#if CH_USE_MUTEXES
chMtxInit(&spip->spd_mutex);
#elif CH_USE_SEMAPHORES
chSemInit(&spip->spd_semaphore, 1);
#endif
spip->spd_config = NULL;
}
/**
* @brief Configures and activates the SPI peripheral.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] config pointer to the @p SPIConfig object
*/
void spiStart(SPIDriver *spip, const SPIConfig *config) {
chDbgCheck((spip != NULL) && (config != NULL), "spiStart");
chSysLock();
chDbgAssert((spip->spd_state == SPI_STOP) || (spip->spd_state == SPI_READY),
"spiStart(), #1",
"invalid state");
spip->spd_config = config;
spi_lld_start(spip);
spip->spd_state = SPI_READY;
chSysUnlock();
}
/**
* @brief Deactivates the SPI peripheral.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
void spiStop(SPIDriver *spip) {
chDbgCheck(spip != NULL, "spiStop");
chSysLock();
chDbgAssert((spip->spd_state == SPI_STOP) || (spip->spd_state == SPI_READY),
"spiStop(), #1",
"invalid state");
spi_lld_stop(spip);
spip->spd_state = SPI_STOP;
chSysUnlock();
}
/**
* @brief Asserts the slave select signal and prepares for transfers.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
void spiSelect(SPIDriver *spip) {
chDbgCheck(spip != NULL, "spiSelect");
chSysLock();
chDbgAssert((spip->spd_state == SPI_READY) ||
(spip->spd_state == SPI_ACTIVE),
"spiSelect(), #1",
"not idle");
spi_lld_select(spip);
spip->spd_state = SPI_ACTIVE;
chSysUnlock();
}
/**
* @brief Deasserts the slave select signal.
* @details The previously selected peripheral is unselected.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
void spiUnselect(SPIDriver *spip) {
chDbgCheck(spip != NULL, "spiUnselect");
chSysLock();
chDbgAssert((spip->spd_state == SPI_READY) ||
(spip->spd_state == SPI_ACTIVE),
"spiUnselect(), #1",
"not locked");
spi_lld_unselect(spip);
spip->spd_state = SPI_READY;
chSysUnlock();
}
/**
* @brief Ignores data on the SPI bus.
* @details This function transmits a series of idle words on the SPI bus and
* ignores the received data. This function can be invoked even
* when a slave select signal has not been yet asserted.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be ignored
*/
void spiIgnore(SPIDriver *spip, size_t n) {
chDbgCheck((spip != NULL) && (n > 0), "spiIgnore");
chDbgAssert((spip->spd_state == SPI_READY) || (spip->spd_state == SPI_ACTIVE),
"spiIgnore(), #1",
"not active");
spi_lld_ignore(spip, n);
}
/**
* @brief Exchanges data on the SPI bus.
* @details This function performs a simultaneous transmit/receive operation.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be exchanged
* @param[in] txbuf the pointer to the transmit buffer
* @param[out] rxbuf the pointer to the receive buffer
*
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*/
void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf) {
chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL) && (txbuf != NULL),
"spiExchange");
chDbgAssert(spip->spd_state == SPI_ACTIVE,
"spiExchange(), #1",
"not active");
spi_lld_exchange(spip, n, txbuf, rxbuf);
}
/**
* @brief Sends data ever the SPI bus.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to send
* @param[in] txbuf the pointer to the transmit buffer
*
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*/
void spiSend(SPIDriver *spip, size_t n, const void *txbuf) {
chDbgCheck((spip != NULL) && (n > 0) && (txbuf != NULL),
"spiSend");
chDbgAssert(spip->spd_state == SPI_ACTIVE,
"spiSend(), #1",
"not active");
spi_lld_send(spip, n, txbuf);
}
/**
* @brief Receives data from the SPI bus.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to receive
* @param[out] rxbuf the pointer to the receive buffer
*
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*/
void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) {
chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL),
"spiReceive");
chDbgAssert(spip->spd_state == SPI_ACTIVE,
"spiReceive(), #1",
"not active");
spi_lld_receive(spip, n, rxbuf);
}
#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
/**
* @brief Gains exclusive access to the SPI bus.
* @details This function tries to gain ownership to the SPI bus, if the bus
* is already being used then the invoking thread is queued.
*
* @param[in] spip pointer to the @p SPIDriver object
*
* @note This function is only available when the @p SPI_USE_MUTUAL_EXCLUSION
* option is set to @p TRUE.
*/
void spiAcquireBus(SPIDriver *spip) {
chDbgCheck(spip != NULL, "spiAcquireBus");
#if CH_USE_MUTEXES
chMtxLock(&spip->spd_mutex);
#elif CH_USE_SEMAPHORES
chSemWait(&spip->spd_semaphore);
#endif
}
/**
* @brief Releases exclusive access to the SPI bus.
*
* @param[in] spip pointer to the @p SPIDriver object
*
* @note This function is only available when the @p SPI_USE_MUTUAL_EXCLUSION
* option is set to @p TRUE.
*/
void spiReleaseBus(SPIDriver *spip) {
chDbgCheck(spip != NULL, "spiReleaseBus");
#if CH_USE_MUTEXES
(void)spip;
chMtxUnlock();
#elif CH_USE_SEMAPHORES
chSemSignal(&spip->spd_semaphore);
#endif
}
#endif /*SPI_USE_MUTUAL_EXCLUSION */
#endif /* CH_HAL_USE_SPI */
/** @} */

View File

@ -0,0 +1,101 @@
/*
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 templates/adc_lld.c
* @brief ADC Driver subsystem low level driver source template
* @addtogroup ADC_LLD
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_ADC
/*===========================================================================*/
/* Low Level Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level ADC driver initialization.
*/
void adc_lld_init(void) {
}
/**
* @brief Configures and activates the ADC peripheral.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
void adc_lld_start(ADCDriver *adcp) {
if (adcp->adc_state == ADC_STOP) {
/* Clock activation.*/
}
/* Configuration.*/
}
/**
* @brief Deactivates the ADC peripheral.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
void adc_lld_stop(ADCDriver *adcp) {
}
/**
* @brief Starts an ADC conversion.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
void adc_lld_start_conversion(ADCDriver *adcp) {
}
/**
* @brief Stops an ongoing conversion.
*
* @param[in] adcp pointer to the @p ADCDriver object
*/
void adc_lld_stop_conversion(ADCDriver *adcp) {
}
#endif /* CH_HAL_USE_ADC */
/** @} */

View File

@ -0,0 +1,141 @@
/*
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 templates/adc_lld.h
* @brief ADC Driver subsystem low level driver header template
* @addtogroup ADC_LLD
* @{
*/
#ifndef _ADC_LLD_H_
#define _ADC_LLD_H_
#if CH_HAL_USE_ADC
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief ADC sample data type.
*/
typedef uint16_t adcsample_t;
/**
* @brief Channels number in a conversion group.
*/
typedef uint16_t adc_channels_num_t;
/**
* @brief ADC notification callback type.
* @param[in] buffer pointer to the most recent samples data
* @param[in] n number of buffer rows available starting from @p buffer
*/
typedef void (*adccallback_t)(adcsample_t *buffer, size_t n);
/**
* @brief Conversion group configuration structure.
* @details This implementation-dependent structure describes a conversion
* operation.
*/
typedef struct {
/**
* @brief Enables the circular buffer mode for the group.
*/
bool_t acg_circular;
/**
* @brief Number of the analog channels belonging to the conversion group.
*/
adc_channels_num_t acg_num_channels;
/* End of the mandatory fields.*/
} ADCConversionGroup;
/**
* @brief Driver configuration structure.
* @note It could be empty on some architectures.
*/
typedef struct {
} ADCConfig;
/**
* @brief Structure representing an ADC driver.
*/
typedef struct {
/**
* @brief Driver state.
*/
adcstate_t ad_state;
/**
* @brief Current configuration data.
*/
const ADCConfig *ad_config;
/**
* @brief Synchronization semaphore.
*/
Semaphore ad_sem;
/**
* @brief Current callback function or @p NULL.
*/
adccallback_t ad_callback;
/**
* @brief Current samples buffer pointer or @p NULL.
*/
adcsample_t *ad_samples;
/**
* @brief Current samples buffer depth or @p 0.
*/
size_t ad_depth;
/**
* @brief Current conversion group pointer or @p NULL.
*/
const ADCConversionGroup *ad_grpp;
/* End of the mandatory fields.*/
} ADCDriver;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void adc_lld_init(void);
void adc_lld_start(ADCDriver *adcp);
void adc_lld_stop(ADCDriver *adcp);
void adc_lld_start_conversion(ADCDriver *adcp);
void adc_lld_stop_conversion(ADCDriver *adcp);
#ifdef __cplusplus
}
#endif
#endif /* CH_HAL_USE_ADC */
#endif /* _ADC_LLD_H_ */
/** @} */

View File

@ -0,0 +1,159 @@
/*
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 templates/can_lld.c
* @brief CAN Driver subsystem low level driver source template
* @addtogroup CAN_LLD
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_CAN
/*===========================================================================*/
/* Low Level Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level CAN driver initialization.
*/
void can_lld_init(void) {
}
/**
* @brief Configures and activates the CAN peripheral.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void can_lld_start(CANDriver *canp) {
if (canp->can_state == CAN_STOP) {
/* Clock activation.*/
}
/* Configuration.*/
}
/**
* @brief Deactivates the CAN peripheral.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void can_lld_stop(CANDriver *canp) {
}
/**
* @brief Determines whether a frame can be transmitted.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @return The queue space availability.
* @retval FALSE no space in the transmit queue.
* @retval TRUE transmit slot available.
*/
bool_t can_lld_can_transmit(CANDriver *canp) {
return FALSE;
}
/**
* @brief Inserts a frame into the transmit queue.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[in] cfp pointer to the CAN frame to be transmitted
*
* @return The operation status.
* @retval RDY_OK frame transmitted.
*/
msg_t can_lld_transmit(CANDriver *canp, const CANFrame *cfp) {
return RDY_OK;
}
/**
* @brief Determines whether a frame has been received.
*
* @param[in] canp pointer to the @p CANDriver object
*
* @return The queue space availability.
* @retval FALSE no space in the transmit queue.
* @retval TRUE transmit slot available.
*/
bool_t can_lld_can_receive(CANDriver *canp) {
return FALSE;
}
/**
* @brief Receives a frame from the input queue.
*
* @param[in] canp pointer to the @p CANDriver object
* @param[out] cfp pointer to the buffer where the CAN frame is copied
*
* @return The operation status.
* @retval RDY_OK frame received.
*/
msg_t can_lld_receive(CANDriver *canp, CANFrame *cfp) {
return RDY_OK;
}
#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__)
/**
* @brief Enters the sleep mode.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void can_lld_sleep(CANDriver *canp) {
}
/**
* @brief Enforces leaving the sleep mode.
*
* @param[in] canp pointer to the @p CANDriver object
*/
void can_lld_wakeup(CANDriver *canp) {
}
#endif /* CAN_USE_SLEEP_MODE */
#endif /* CH_HAL_USE_CAN */
/** @} */

View File

@ -0,0 +1,154 @@
/*
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 templates/can_lld.h
* @brief CAN Driver subsystem low level driver header template
* @addtogroup CAN_LLD
* @{
*/
#ifndef _CAN_LLD_H_
#define _CAN_LLD_H_
#if CH_HAL_USE_CAN
/**
* @brief This switch defines whether the driver implementation supports
* a low power switch mode with automatic an wakeup feature.
*/
#define CAN_SUPPORTS_SLEEP TRUE
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Sleep mode related APIs inclusion switch.
* @note This switch is enforced to @p FALSE if the driver implementation
* does not support the sleep mode.
*/
#if CAN_SUPPORTS_SLEEP || defined(__DOXYGEN__)
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
#define CAN_USE_SLEEP_MODE TRUE
#endif
#else /* !CAN_SUPPORTS_SLEEP */
#define CAN_USE_SLEEP_MODE FALSE
#endif /* !CAN_SUPPORTS_SLEEP */
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief CAN frame.
* @note Accessing the frame data as word16 or word32 is not portable because
* machine data endianness, it can be still useful for a quick filling.
*/
typedef struct {
uint8_t cf_DLC:4; /**< @brief Data length. */
uint8_t cf_IDE:1; /**< @brief Identifier type. */
uint8_t cf_RTR:1; /**< @brief Frame type. */
uint32_t cf_id; /**< @brief Frame identifier. */
union {
uint8_t cf_data8[8]; /**< @brief Frame data. */
uint16_t cf_data16[4]; /**< @brief Frame data. */
uint32_t cf_data32[2]; /**< @brief Frame data. */
};
} CANFrame;
/**
* @brief Driver configuration structure.
* @note It could be empty on some architectures.
*/
typedef struct {
} CANConfig;
/**
* @brief Structure representing an CAN driver.
*/
typedef struct {
/**
* @brief Driver state.
*/
canstate_t can_state;
/**
* @brief Current configuration data.
*/
const CANConfig *can_config;
/**
* @brief Transmission queue semaphore.
*/
Semaphore can_txsem;
/**
* @brief Receive queue semaphore.
*/
Semaphore can_rxsem;
/**
* @brief One or more frames become available.
*/
EventSource can_rxfull_event;
/**
* @brief One or more transmission slots become available.
*/
EventSource can_txempty_event;
#if CAN_USE_SLEEP_MODE || defined (__DOXYGEN__)
/**
* @brief Entering sleep state event.
*/
EventSource can_sleep_event;
/**
* @brief Exiting sleep state event.
*/
EventSource can_wakeup_event;
#endif /* CAN_USE_SLEEP_MODE */
/* End of the mandatory fields.*/
} CANDriver;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void can_lld_init(void);
void can_lld_start(CANDriver *canp);
void can_lld_stop(CANDriver *canp);
bool_t can_lld_can_transmit(CANDriver *canp);
msg_t can_lld_transmit(CANDriver *canp, const CANFrame *cfp);
bool_t can_lld_can_receive(CANDriver *canp);
msg_t can_lld_receive(CANDriver *canp, CANFrame *cfp);
#if CAN_USE_SLEEP_MODE
void can_lld_sleep(CANDriver *canp);
void can_lld_wakeup(CANDriver *canp);
#endif /* CAN_USE_SLEEP_MODE */
#ifdef __cplusplus
}
#endif
#endif /* CH_HAL_USE_CAN */
#endif /* _CAN_LLD_H_ */
/** @} */

View File

@ -0,0 +1,57 @@
/*
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 templates/hal_lld.c
* @brief HAL Driver subsystem low level driver source template
* @addtogroup HAL_LLD
* @{
*/
#include <ch.h>
#include <hal.h>
/*===========================================================================*/
/* Low Level Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level HAL driver initialization.
*/
void hal_lld_init(void) {
}
/** @} */

View File

@ -0,0 +1,56 @@
/*
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 templates/hal_lld.h
* @brief HAL subsystem low level driver header template
* @addtogroup HAL_LLD
* @{
*/
#ifndef _HAL_LLD_H_
#define _HAL_LLD_H_
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void hal_lld_init(void);
#ifdef __cplusplus
}
#endif
#endif /* _HAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,88 @@
/*
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 templates/halconf.h
* @brief HAL configuration header.
* @addtogroup HAL_CONF
* @{
*/
#ifndef _HALCONF_H_
#define _HALCONF_H_
/**
* @brief Enables the PAL subsystem.
*/
#if !defined(CH_HAL_USE_PAL) || defined(__DOXYGEN__)
#define CH_HAL_USE_PAL TRUE
#endif
/**
* @brief Enables the ADC subsystem.
*/
#if !defined(CH_HAL_USE_ADC) || defined(__DOXYGEN__)
#define CH_HAL_USE_ADC TRUE
#endif
/**
* @brief Enables the CAN subsystem.
*/
#if !defined(CH_HAL_USE_CAN) || defined(__DOXYGEN__)
#define CH_HAL_USE_CAN TRUE
#endif
/**
* @brief Enables the MAC subsystem.
*/
#if !defined(CH_HAL_USE_MAC) || defined(__DOXYGEN__)
#define CH_HAL_USE_MAC TRUE
#endif
/**
* @brief Enables the MII subsystem.
*/
#if !defined(CH_HAL_USE_MII) || defined(__DOXYGEN__)
#define CH_HAL_USE_MII TRUE
#endif
/**
* @brief Enables the SERIAL subsystem.
*/
#if !defined(CH_HAL_USE_SERIAL) || defined(__DOXYGEN__)
#define CH_HAL_USE_SERIAL TRUE
#endif
/**
* @brief Enables the SPI subsystem.
*/
#if !defined(CH_HAL_USE_SPI) || defined(__DOXYGEN__)
#define CH_HAL_USE_SPI TRUE
#endif
/**
* @brief Enables the MMC_SPI subsystem.
*/
#if !defined(CH_HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
#define CH_HAL_USE_MMC_SPI TRUE
#endif
#endif /* _HALCONF_H_ */
/** @} */

View File

@ -0,0 +1,153 @@
/*
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 templates/mac_lld.c
* @brief MAC Driver subsystem low level driver source template
* @addtogroup MAC_LLD
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_MAC
/**
* @brief Low level MAC initialization.
*/
void mac_lld_init(void) {
}
/**
* @brief Low level MAC address setup.
*
* @param[in] macp pointer to the @p MACDriver object
* @param[in] p pointer to a six bytes buffer containing the MAC address. If
* this parameter is set to @p NULL then a system default MAC is
* used.
*/
void mac_lld_set_address(MACDriver *macp, const uint8_t *p) {
}
/**
* @brief Returns a transmission descriptor.
* @details One of the available transmission descriptors is locked and
* returned.
*
* @param[in] macp pointer to the @p MACDriver object
* @param[out] tdp pointer to a @p MACTransmitDescriptor structure
* @return The operation status.
* @retval RDY_OK the descriptor was obtained.
* @retval RDY_TIMEOUT descriptor not available.
*/
msg_t max_lld_get_transmit_descriptor(MACDriver *macp,
MACTransmitDescriptor *tdp) {
return RDY_OK;
}
/**
* @brief Writes to a transmit descriptor's stream.
*
* @param[in] tdp pointer to a @p MACTransmitDescriptor structure
* @param[in] buf pointer to the buffer cointaining the data to be written
* @param[in] size number of bytes to be written
* @return The number of bytes written into the descriptor's stream, this
* value can be less than the amount specified in the parameter
* @p size if the maximum frame size is reached.
*/
size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp,
uint8_t *buf,
size_t size) {
return 0;
}
/**
* @brief Releases a transmit descriptor and starts the transmission of the
* enqueued data as a single frame.
*
* @param[in] tdp the pointer to the @p MACTransmitDescriptor structure
*/
void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) {
}
/**
* @brief Returns a receive descriptor.
*
* @param[in] macp pointer to the @p MACDriver object
* @param[out] rdp pointer to a @p MACReceiveDescriptor structure
* @return The operation status.
* @retval RDY_OK the descriptor was obtained.
* @retval RDY_TIMEOUT descriptor not available.
*/
msg_t max_lld_get_receive_descriptor(MACDriver *macp,
MACReceiveDescriptor *rdp) {
return RDY_OK;
}
/**
* @brief Reads from a receive descriptor's stream.
*
* @param[in] rdp pointer to a @p MACReceiveDescriptor structure
* @param[in] buf pointer to the buffer that will receive the read data
* @param[in] size number of bytes to be read
* @return The number of bytes read from the descriptor's stream, this
* value can be less than the amount specified in the parameter
* @p size if there are no more bytes to read.
*/
size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp,
uint8_t *buf,
size_t size) {
return 0;
}
/**
* @brief Releases a receive descriptor.
* @details The descriptor and its buffer are made available for more incoming
* frames.
*
* @param[in] rdp the pointer to the @p MACReceiveDescriptor structure
*/
void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) {
}
/**
* @brief Updates and returns the link status.
*
* @param[in] macp pointer to the @p MACDriver object
* @return The link status.
* @retval TRUE if the link is active.
* @retval FALSE if the link is down.
*/
bool_t mac_lld_poll_link_status(MACDriver *macp) {
return FALSE;
}
#endif /* CH_HAL_USE_MAC */
/** @} */

View File

@ -0,0 +1,121 @@
/*
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 templates/mac_lld.h
* @brief MAC Driver subsystem low level driver header template
* @addtogroup MAC_LLD
* @{
*/
#ifndef _MAC_LLD_H_
#define _MAC_LLD_H_
#if CH_HAL_USE_MAC
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Number of available transmit buffers.
*/
#if !defined(MAC_TRANSMIT_BUFFERS) || defined(__DOXYGEN__)
#define MAC_TRANSMIT_BUFFERS 2
#endif
/**
* @brief Number of available receive buffers.
*/
#if !defined(MAC_RECEIVE_BUFFERS) || defined(__DOXYGEN__)
#define MAC_RECEIVE_BUFFERS 2
#endif
/**
* @brief Maximum supported frame size.
*/
#if !defined(MAC_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define MAC_BUFFERS_SIZE 1518
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Structure representing a MAC driver.
*/
typedef struct {
Semaphore md_tdsem; /**< Transmit semaphore. */
Semaphore md_rdsem; /**< Receive semaphore. */
#if CH_USE_EVENTS
EventSource md_rdevent; /**< Receive event source. */
#endif
/* End of the mandatory fields.*/
} MACDriver;
/**
* @brief Structure representing a transmit descriptor.
*/
typedef struct {
size_t td_offset; /**< Current write offset. */
size_t td_size; /**< Available space size. */
/* End of the mandatory fields.*/
} MACTransmitDescriptor;
/**
* @brief Structure representing a receive descriptor.
*/
typedef struct {
size_t rd_offset; /**< Current read offset. */
size_t rd_size; /**< Available data size. */
/* End of the mandatory fields.*/
} MACReceiveDescriptor;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void mac_lld_init(void);
void mac_lld_set_address(MACDriver *macp, const uint8_t *p);
msg_t max_lld_get_transmit_descriptor(MACDriver *macp,
MACTransmitDescriptor *tdp);
size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp,
uint8_t *buf,
size_t size);
void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp);
msg_t max_lld_get_receive_descriptor(MACDriver *macp,
MACReceiveDescriptor *rdp);
size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp,
uint8_t *buf,
size_t size);
void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp);
bool_t mac_lld_poll_link_status(MACDriver *macp);
#ifdef __cplusplus
}
#endif
#endif /* CH_HAL_USE_MAC */
#endif /* _MAC_LLD_H_ */
/** @} */

View File

@ -0,0 +1,87 @@
/*
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 XXX.c
* @brief XXX Driver code.
* @addtogroup XXX
* @{
*/
#include <ch.h>
#include <xxx.h>
/**
* @brief XXX Driver initialization.
*/
void xxxInit(void) {
xxx_lld_init();
}
/**
* @brief Initializes the standard part of a @p XXXDriver structure.
*
* @param[in] xxxp pointer to the @p XXXDriver object
*/
void xxxObjectInit(XXXDriver *xxxp) {
xxxp->xxx_state = XXX_STOP;
xxxp->xxx_config = NULL;
}
/**
* @brief Configures and activates the XXX peripheral.
*
* @param[in] xxxp pointer to the @p XXXDriver object
* @param[in] config pointer to the @p XXXConfig object
*/
void xxxStart(XXXDriver *xxxp, const XXXConfig *config) {
chDbgCheck((xxxp != NULL) && (config != NULL), "xxxStart");
chSysLock();
chDbgAssert((xxxp->xxx_state == XXX_STOP) || (xxxp->xxx_state == XXX_READY),
"xxxStart(), #1",
"invalid state");
xxxp->xxx_config = config;
xxx_lld_start(xxxp);
xxxp->xxx_state = XXX_READY;
chSysUnlock();
}
/**
* @brief Deactivates the XXX peripheral.
*
* @param[in] xxxp pointer to the @p XXXDriver object
*/
void xxxStop(XXXDriver *xxxp) {
chDbgCheck(xxxp != NULL, "xxxStop");
chSysLock();
chDbgAssert((xxxp->xxx_state == XXX_STOP) || (xxxp->xxx_state == XXX_READY),
"xxxStop(), #1",
"invalid state");
xxx_lld_stop(xxxp);
xxxp->xxx_state = XXX_STOP;
chSysUnlock();
}
/** @} */

View File

@ -0,0 +1,54 @@
/*
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 xxx.h
* @brief XXX Driver macros and structures.
* @addtogroup XXX
* @{
*/
#ifndef _XXX_H_
#define _XXX_H_
/**
* @brief Driver state machine possible states.
*/
typedef enum {
XXX_UNINIT = 0, /**< @brief Not initialized. */
XXX_STOP = 1, /**< @brief Stopped. */
XXX_READY = 2, /**< @brief Ready. */
} xxxstate_t;
#include "xxx_lld.h"
#ifdef __cplusplus
extern "C" {
#endif
void xxxInit(void);
void xxxObjectInit(XXXDriver *xxxp);
void xxxStart(XXXDriver *xxxp, const XXXConfig *config);
void xxxStop(XXXDriver *xxxp);
#ifdef __cplusplus
}
#endif
#endif /* _XXX_H_ */
/** @} */

View File

@ -0,0 +1,79 @@
/*
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 templates/xxx_lld.c
* @brief XXX Driver subsystem low level driver source template
* @addtogroup XXX_LLD
* @{
*/
#include <ch.h>
#include <xxx.h>
/*===========================================================================*/
/* Low Level Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level XXX driver initialization.
*/
void xxx_lld_init(void) {
}
/**
* @brief Configures and activates the XXX peripheral.
*
* @param[in] xxxp pointer to the @p XXXDriver object
*/
void xxx_lld_start(XXXDriver *xxxp) {
if (xxxp->xxx_state == XXX_STOP) {
/* Clock activation.*/
}
/* Configuration.*/
}
/**
* @brief Deactivates the XXX peripheral.
*
* @param[in] xxxp pointer to the @p XXXDriver object
*/
void xxx_lld_stop(XXXDriver *xxxp) {
}
/** @} */

View File

@ -0,0 +1,81 @@
/*
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 templates/xxx_lld.h
* @brief XXX Driver subsystem low level driver header template
* @addtogroup XXX_LLD
* @{
*/
#ifndef _XXX_LLD_H_
#define _XXX_LLD_H_
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Driver configuration structure.
* @note It could be empty on some architectures.
*/
typedef struct {
} XXXConfig;
/**
* @brief Structure representing an XXX driver.
*/
typedef struct {
/**
* @brief Driver state.
*/
xxxstate_t xxx_state;
/**
* @brief Current configuration data.
*/
const XXXConfig *xxx_config;
/* End of the mandatory fields.*/
} XXXDriver;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void xxx_lld_init(void);
void xxx_lld_start(XXXDriver *xxxp);
void xxx_lld_stop(XXXDriver *xxxp);
#ifdef __cplusplus
}
#endif
#endif /* _XXX_LLD_H_ */
/** @} */

View File

@ -0,0 +1,70 @@
/*
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 templates/mii_lld.c
* @brief MII Driver subsystem low level driver source template
* @addtogroup MII_LLD
* @{
*/
#include "ch.h"
#include "mac.h"
#include "mii.h"
/**
* @brief Low level MII driver initialization.
*/
void mii_lld_init(void) {
}
/**
* Resets a PHY device.
*
* @param[in] macp pointer to the @p MACDriver object
*/
void mii_lld_reset(MACDriver *macp) {
}
/**
* @brief Reads a PHY register through the MII interface.
*
* @param[in] macp pointer to the @p MACDriver object
* @param addr the register address
* @return The register value.
*/
phyreg_t mii_lld_get(MACDriver *macp, phyaddr_t addr) {
return 0;
}
/**
* @brief Writes a PHY register through the MII interface.
*
* @param[in] macp pointer to the @p MACDriver object
* @param addr the register address
* @param value the new register value
*/
void mii_lld_put(MACDriver *macp, phyaddr_t addr, phyreg_t value) {
}
/** @} */

View File

@ -0,0 +1,54 @@
/*
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 templates/pal_lld.c
* @brief PAL subsystem low level driver template
* @addtogroup PAL_LLD
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_PAL
/*===========================================================================*/
/* Low Level Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
#endif /* CH_HAL_USE_PAL */
/** @} */

View File

@ -0,0 +1,326 @@
/*
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 templates/pal_lld.h
* @brief PAL subsystem low level driver header template
* @addtogroup PAL_LLD
* @{
*/
#ifndef _PAL_LLD_H_
#define _PAL_LLD_H_
#if CH_HAL_USE_PAL
/*===========================================================================*/
/* Unsupported modes and specific modes */
/*===========================================================================*/
/*===========================================================================*/
/* I/O Ports Types and constants. */
/*===========================================================================*/
/**
* @brief Generic 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.
*
* @note This structure content is architecture dependent. The nome should be
* changed to include the architecture name following this pattern:<br>
* - [ARCH][CELL]Config.
* .
* As example:<br>
* - MSP430DIOConfig.
* .
*/
typedef struct {
} GenericConfig;
/**
* @brief Width, in bits, of an I/O port.
*/
#define PAL_IOPORTS_WIDTH 32
/**
* @brief Whole port mask.
* @brief This macro specifies all the valid bits into a port.
*/
#define PAL_WHOLE_PORT ((ioportmask_t)0xFFFFFFFF)
/**
* @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 uint32_t ioportid_t;
/*===========================================================================*/
/* I/O Ports Identifiers. */
/*===========================================================================*/
/**
* @brief First I/O port identifier.
* @details Low level drivers can define multiple ports, it is suggested to
* use this naming convention.
*/
#define IOPORT1 0
/*===========================================================================*/
/* Implementation, some of the following macros could be implemented as */
/* functions, if so please put them in pal_lld.c. */
/*===========================================================================*/
/**
* @brief Low level PAL subsystem initialization.
*
* @param[in] config the architecture-dependent ports configuration
*/
#define pal_lld_init(config)
/**
* @brief Reads the physical I/O port states.
*
* @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)
/**
* @brief Reads the output latch.
* @details The purpose of this function is to read back the latched output
* value.
*
* @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)
/**
* @brief Writes a bits mask on a I/O port.
*
* @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)
/**
* @brief Sets a bits mask on a I/O port.
*
* @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 The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*/
#define pal_lld_setport(port, bits)
/**
* @brief Clears a bits mask on a I/O port.
*
* @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 The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*/
#define pal_lld_clearport(port, bits)
/**
* @brief Toggles a bits mask on a I/O port.
*
* @param[in] port the port identifier
* @param[in] bits the bits to be XORed on the specified port
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*/
#define pal_lld_toggleport(port, bits)
/**
* @brief Reads a group of bits.
*
* @param[in] port the port identifier
* @param[in] mask the group mask
* @param[in] offset the group bit offset within the port
* @return The group logical states.
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*/
#define pal_lld_readgroup(port, mask, offset)
/**
* @brief Writes a group of bits.
*
* @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 The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*/
#define pal_lld_writegroup(port, mask, offset, 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 Programming an unknown or unsupported mode is silently ignored.
*/
#define pal_lld_setgroupmode(port, mask, mode)
/**
* @brief Reads a logical state from an I/O pad.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
* @return The logical state.
* @retval 0 low logical state.
* @retval 1 high logical state.
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*/
#define pal_lld_readpad(port, pad)
/**
* @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 The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*/
#define pal_lld_writepad(port, pad, bit)
/**
* @brief Sets a pad logical state to @p 1.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*/
#define pal_lld_setpad(port, pad)
/**
* @brief Clears a pad logical state to @p 0.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*/
#define pal_lld_clearpad(port, pad)
/**
* @brief Toggles a pad logical state.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
*/
#define pal_lld_togglepad(port, pad)
/**
* @brief Pad mode setup.
* @details This function programs a pad with the specified mode.
*
* @param[in] port the port identifier
* @param[in] pad the pad number within the port
* @param[in] mode the mode
*
* @note This function is not meant to be invoked directly by the application
* code.
* @note The @ref PAL provides a default software implementation of this
* functionality, implement this function if can optimize it by using
* special hardware functionalities or special coding.
* @note Programming an unknown or unsupported mode is silently ignored.
*/
#define pal_lld_setpadmode(port, pad, mode)
#endif /* CH_HAL_USE_PAL */
#endif /* _PAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,91 @@
/*
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 templates/serial_lld.c
* @brief Serial Driver subsystem low level driver source template
* @addtogroup SERIAL_LLD
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_SERIAL
/** @brief Driver default configuration.*/
static const SerialDriverConfig default_config = {
};
/*===========================================================================*/
/* Low Level Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* Low level serial driver initialization.
*/
void sd_lld_init(void) {
}
/**
* @brief Low level serial driver configuration and (re)start.
*
* @param[in] sdp pointer to a @p SerialDriver object
* @param[in] config the architecture-dependent serial driver configuration.
* If this parameter is set to @p NULL then a default
* configuration is used.
*/
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config) {
if (config == NULL)
config = &default_config;
}
/**
* @brief Low level serial driver stop.
* @details De-initializes the USART, stops the associated clock, resets the
* interrupt vector.
*
* @param[in] sdp pointer to a @p SerialDriver object
*/
void sd_lld_stop(SerialDriver *sdp) {
}
#endif /* CH_HAL_USE_SERIAL */
/** @} */

View File

@ -0,0 +1,113 @@
/*
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 templates/serial_lld.h
* @brief Serial Driver subsystem low level driver header template
* @addtogroup SERIAL_LLD
* @{
*/
#ifndef _SERIAL_LLD_H_
#define _SERIAL_LLD_H_
#if CH_HAL_USE_SERIAL
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* Serial Driver condition flags type.
*/
typedef uint8_t sdflags_t;
/**
* @brief @p SerialDriver specific data.
*/
struct _serial_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.
*/
sdflags_t flags;
/**
* Input circular buffer.
*/
uint8_t ib[SERIAL_BUFFERS_SIZE];
/**
* Output circular buffer.
*/
uint8_t ob[SERIAL_BUFFERS_SIZE];
};
/**
* @brief Generic Serial Driver configuration structure.
* @details An instance of this structure must be passed to @p sdStart()
* in order to configure and start a serial driver operations.
*
* @note This structure content is architecture dependent, each driver
* implementation defines its own version and the custom static
* initializers.
*/
typedef struct {
} SerialDriverConfig;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void sd_lld_init(void);
void sd_lld_start(SerialDriver *sdp, const SerialDriverConfig *config);
void sd_lld_stop(SerialDriver *sdp);
#ifdef __cplusplus
}
#endif
#endif /* CH_HAL_USE_SERIAL */
#endif /* _SERIAL_LLD_H_ */
/** @} */

View File

@ -0,0 +1,160 @@
/*
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 templates/spi_lld.c
* @brief SPI Driver subsystem low level driver source template
* @addtogroup SPI_LLD
* @{
*/
#include "ch.h"
#include "hal.h"
#if CH_HAL_USE_SPI
/*===========================================================================*/
/* Low Level Driver exported variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver local functions. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver interrupt handlers. */
/*===========================================================================*/
/*===========================================================================*/
/* Low Level Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level SPI driver initialization.
*/
void spi_lld_init(void) {
}
/**
* @brief Configures and activates the SPI peripheral.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
void spi_lld_start(SPIDriver *spip) {
if (spip->spd_state == SPI_STOP) {
/* Clock activation.*/
}
/* Configuration.*/
}
/**
* @brief Deactivates the SPI peripheral.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
void spi_lld_stop(SPIDriver *spip) {
}
/**
* @brief Asserts the slave select signal and prepares for transfers.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
void spi_lld_select(SPIDriver *spip) {
}
/**
* @brief Deasserts the slave select signal.
* @details The previously selected peripheral is unselected.
*
* @param[in] spip pointer to the @p SPIDriver object
*/
void spi_lld_unselect(SPIDriver *spip) {
}
/**
* @brief Ignores data on the SPI bus.
* @details This function transmits a series of idle words on the SPI bus and
* ignores the received data. This function can be invoked even
* when a slave select signal has not been yet asserted.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be ignored
*/
void spi_lld_ignore(SPIDriver *spip, size_t n) {
}
/**
* @brief Exchanges data on the SPI bus.
* @details This function performs a simultaneous transmit/receive operation.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to be exchanged
* @param[in] txbuf the pointer to the transmit buffer
* @param[out] rxbuf the pointer to the receive buffer
*
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*/
void spi_lld_exchange(SPIDriver *spip, size_t n,
const void *txbuf, void *rxbuf) {
}
/**
* @brief Sends data ever the SPI bus.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to send
* @param[in] txbuf the pointer to the transmit buffer
*
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*/
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) {
}
/**
* @brief Receives data from the SPI bus.
*
* @param[in] spip pointer to the @p SPIDriver object
* @param[in] n number of words to receive
* @param[out] rxbuf the pointer to the receive buffer
*
* @note The buffers are organized as uint8_t arrays for data sizes below or
* equal to 8 bits else it is organized as uint16_t arrays.
*/
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) {
}
#endif /* CH_HAL_USE_SPI */
/** @} */

View File

@ -0,0 +1,108 @@
/*
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 templates/spi_lld.h
* @brief SPI Driver subsystem low level driver header template
* @addtogroup SPI_LLD
* @{
*/
#ifndef _SPI_LLD_H_
#define _SPI_LLD_H_
#if CH_HAL_USE_SPI
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Enables the mutual exclusion APIs on the SPI bus.
*/
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define SPI_USE_MUTUAL_EXCLUSION TRUE
#endif
#if SPI_USE_MUTUAL_EXCLUSION && !CH_USE_MUTEXES && !CH_USE_SEMAPHORES
#error "SPI_USE_MUTUAL_EXCLUSION requires CH_USE_MUTEXES and/or CH_USE_SEMAPHORES"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Driver configuration structure.
*/
typedef struct {
} SPIConfig;
/**
* @brief Structure representing a SPI driver.
*/
typedef struct {
/**
* @brief Driver state.
*/
spistate_t spd_state;
#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
#if CH_USE_MUTEXES || defined(__DOXYGEN__)
/**
* @brief Mutex protecting the bus.
*/
Mutex spd_mutex;
#elif CH_USE_SEMAPHORES
Semaphore spd_semaphore;
#endif
#endif /* SPI_USE_MUTUAL_EXCLUSION */
/**
* @brief Current configuration data.
*/
const SPIConfig *spd_config;
/* End of the mandatory fields.*/
} SPIDriver;
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#ifdef __cplusplus
extern "C" {
#endif
void spi_lld_init(void);
void spi_lld_start(SPIDriver *spip);
void spi_lld_stop(SPIDriver *spip);
void spi_lld_select(SPIDriver *spip);
void spi_lld_unselect(SPIDriver *spip);
void spi_lld_ignore(SPIDriver *spip, size_t n);
void spi_lld_exchange(SPIDriver *spip, size_t n,
const void *txbuf, void *rxbuf);
void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf);
void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf);
#ifdef __cplusplus
}
#endif
#endif /* CH_HAL_USE_SPI */
#endif /* _SPI_LLD_H_ */
/** @} */