From 8be71e4e99543e3326eb381784025fe6cc8978ea Mon Sep 17 00:00:00 2001 From: Christina Quast Date: Tue, 2 Dec 2014 13:06:01 +0100 Subject: [PATCH] Makefile with libs and atmel source --- sam3s_example/Makefile | 6 +- .../libboard_sam3s-ek/source/ads7843.c | 197 ++ .../libboard_sam3s-ek/source/at45_spi.c | 316 +++ .../libboard_sam3s-ek/source/at45d.c | 254 +++ .../libboard_sam3s-ek/source/bmp.c | 319 +++ .../source}/board_cstartup_gnu.c | 5 +- .../source}/board_lowlevel.c | 16 +- .../libboard_sam3s-ek/source/board_memories.c | 153 ++ .../libboard_sam3s-ek/source/clock.c | 184 ++ .../libboard_sam3s-ek/source/frame_buffer.c | 435 ++++ .../libboard_sam3s-ek/source/hamming.c | 339 +++ .../libboard_sam3s-ek/source/ili9325.c | 907 ++++++++ .../libboard_sam3s-ek/source/iso7816_4.c | 611 ++++++ .../libboard_sam3s-ek/source/lcd_draw.c | 405 ++++ .../libboard_sam3s-ek/source/lcd_font.c | 133 ++ .../libboard_sam3s-ek/source/lcd_font10x14.c | 233 +++ .../libboard_sam3s-ek/source/lcdd.c | 140 ++ .../libboard_sam3s-ek/source/led.c | 168 ++ .../libboard_sam3s-ek/source/math.c | 95 + .../libboard_sam3s-ek/source/rand.c | 61 + .../libboard_sam3s-ek/source/retarget.c | 86 + .../libboard_sam3s-ek/source}/syscalls.c | 10 +- .../libboard_sam3s-ek/source/timetick.c | 117 ++ .../libboard_sam3s-ek/source/trace.c | 59 + .../libboard_sam3s-ek/source/tsd_ads7843.c | 317 +++ .../libboard_sam3s-ek/source/tsd_com.c | 369 ++++ .../libboard_sam3s-ek/source/uart_console.c | 389 ++++ .../libboard_sam3s-ek/source/wav.c | 90 + .../libboard_sam3s-ek/source/wm8731.c | 139 ++ .../libchip_sam3s/source/USBD_HAL.c | 1666 +++++++++++++++ .../libchip_sam3s/source/acc.c | 162 ++ .../libchip_sam3s/source/adc.c | 417 ++++ .../libchip_sam3s/source/async.c | 53 + .../libchip_sam3s/source/crccu.c | 112 + .../libchip_sam3s/source/dacc.c | 183 ++ .../libchip_sam3s/source/efc.c | 289 +++ .../libchip_sam3s/source}/exceptions.c | 0 .../libchip_sam3s/source/flashd.c | 512 +++++ .../libchip_sam3s/source/hsmci.c | 262 +++ .../libchip_sam3s/source/hsmci_pdc.c | 305 +++ .../libchip_sam3s/source}/pio.c | 1 - .../libchip_sam3s/source/pio_capture.c | 283 +++ .../libchip_sam3s/source/pio_it.c | 315 +++ .../libchip_sam3s/source}/pmc.c | 7 + .../libchip_sam3s/source/pwmc.c | 608 ++++++ .../libchip_sam3s/source/rtc.c | 464 +++++ .../libchip_sam3s/source/rtt.c | 132 ++ .../libchip_sam3s/source}/spi.c | 0 .../libchip_sam3s/source/spi_pdc.c | 251 +++ .../libchip_sam3s/source/ssc.c | 247 +++ .../libchip_sam3s/source/supc.c | 196 ++ .../libchip_sam3s/source/tc.c | 175 ++ .../libchip_sam3s/source/twi.c | 380 ++++ .../libchip_sam3s/source/twid.c | 342 ++++ .../libchip_sam3s/source/usart.c | 410 ++++ .../libchip_sam3s/source/wdt.c | 132 ++ sam3s_example/cmsis | 1 + sam3s_example/cmsis/core_cm3.c | 817 -------- sam3s_example/cmsis/core_cm3.h | 1818 ----------------- sam3s_example/{ => mains}/blink.c | 0 sam3s_example/{ => mains}/blink2.c | 0 sam3s_example/src_board | 1 + sam3s_example/src_sam3s | 1 + 63 files changed, 14441 insertions(+), 2654 deletions(-) create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/ads7843.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/at45_spi.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/at45d.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/bmp.c rename sam3s_example/{src => atmel_softpack_libraries/libboard_sam3s-ek/source}/board_cstartup_gnu.c (96%) rename sam3s_example/{src => atmel_softpack_libraries/libboard_sam3s-ek/source}/board_lowlevel.c (92%) create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/board_memories.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/clock.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/frame_buffer.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/hamming.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/ili9325.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/iso7816_4.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcd_draw.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcd_font.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcd_font10x14.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcdd.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/led.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/math.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/rand.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/retarget.c rename sam3s_example/{src => atmel_softpack_libraries/libboard_sam3s-ek/source}/syscalls.c (93%) create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/timetick.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/trace.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/tsd_ads7843.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/tsd_com.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/uart_console.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/wav.c create mode 100644 sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/wm8731.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/acc.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/adc.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/async.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/crccu.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/dacc.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/efc.c rename sam3s_example/{src => atmel_softpack_libraries/libchip_sam3s/source}/exceptions.c (100%) create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/flashd.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/hsmci.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/hsmci_pdc.c rename sam3s_example/{src => atmel_softpack_libraries/libchip_sam3s/source}/pio.c (96%) create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pio_capture.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pio_it.c rename sam3s_example/{src => atmel_softpack_libraries/libchip_sam3s/source}/pmc.c (86%) create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pwmc.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/rtc.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/rtt.c rename sam3s_example/{src => atmel_softpack_libraries/libchip_sam3s/source}/spi.c (100%) create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/spi_pdc.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/ssc.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/supc.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/tc.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/twi.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/twid.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/usart.c create mode 100644 sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/wdt.c create mode 120000 sam3s_example/cmsis delete mode 100644 sam3s_example/cmsis/core_cm3.c delete mode 100644 sam3s_example/cmsis/core_cm3.h rename sam3s_example/{ => mains}/blink.c (100%) rename sam3s_example/{ => mains}/blink2.c (100%) create mode 120000 sam3s_example/src_board create mode 120000 sam3s_example/src_sam3s diff --git a/sam3s_example/Makefile b/sam3s_example/Makefile index 3c646dea..3ea94e75 100644 --- a/sam3s_example/Makefile +++ b/sam3s_example/Makefile @@ -116,12 +116,12 @@ LDFLAGS = -mcpu=cortex-m3 -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-secti # Directories where source files can be found -VPATH += src cmsis lib +VPATH += src_board src_sam3s cmsis # Objects built from C source files C_CMSIS = core_cm3.o C_LOWLEVEL = board_cstartup_gnu.o board_lowlevel.o syscalls.o exceptions.o -C_LIBLEVEL = spi.o pio.o pmc.o +C_LIBLEVEL = spi.o pio.o pmc.o usart.o C_APPLEVEL = main.o C_OBJECTS = $(C_CMSIS) $(C_LOWLEVEL) $(C_LIBLEVEL) $(C_APPLEVEL) @@ -162,7 +162,7 @@ endef $(foreach MEMORY, $(MEMORIES), $(eval $(call RULES,$(MEMORY)))) program: - openocd -f /home/chrysh/ba_thesis/thesis/openocd/openocd.cfg -c "init" -c "halt" -c "flash write_bank 0 /home/chrysh/ba_thesis/thesis/src/sam3s_example/bin/project-flash.bin 0" -c "reset" -c "shutdown" + openocd -f /home/chrysh/ba_thesis/thesis/openocd/openocd.cfg -c "init" -c "halt" -c "flash write_bank 0 ./bin/project-flash.bin 0" -c "reset" -c "shutdown" clean: -rm -fR $(OBJ)/*.o $(BIN)/*.bin $(BIN)/*.elf $(BIN)/*.elf.txt $(BIN)/*.map $(BIN)/*.lst diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/ads7843.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/ads7843.c new file mode 100644 index 00000000..1ad9fde2 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/ads7843.c @@ -0,0 +1,197 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implementation of ADS7843 driver. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "board.h" + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +#define ADS_CTRL_PD0 (1 << 0) /* PD0 */ +#define ADS_CTRL_PD1 (1 << 1) /* PD1 */ +#define ADS_CTRL_DFR (1 << 2) /* SER/DFR */ +#define ADS_CTRL_EIGHT_BITS_MOD (1 << 3) /* Mode */ +#define ADS_CTRL_START (1 << 7) /* Start Bit */ +#define ADS_CTRL_SWITCH_SHIFT 4 /* Address setting */ + +/* Get X position command */ +#define CMD_Y_POSITION ((1 << ADS_CTRL_SWITCH_SHIFT) | ADS_CTRL_START | ADS_CTRL_PD0 | ADS_CTRL_PD1) +/* Get Y position command */ +#define CMD_X_POSITION ((5 << ADS_CTRL_SWITCH_SHIFT) | ADS_CTRL_START | ADS_CTRL_PD0 | ADS_CTRL_PD1) + +/* Enable penIRQ */ +#define CMD_ENABLE_PENIRQ ((1 << ADS_CTRL_SWITCH_SHIFT) | ADS_CTRL_START) + + +#define ADS7843_TIMEOUT 5000000 + +#define DELAY_BEFORE_SPCK 200 /* 2us min (tCSS) <=> 200/100 000 000 = 2us */ +#define DELAY_BETWEEN_CONS_COM 0xf /* 5us min (tCSH) <=> (32 * 15) / (100 000 000) = 5us */ + +/*---------------------------------------------------------------------------- + * Local variables + *----------------------------------------------------------------------------*/ + +/** Pins used by SPI */ +static const Pin pinsSPI[] = {BOARD_TSC_SPI_PINS, BOARD_TSC_NPCS_PIN}; + +/** Touch screen BUSY pin */ +static const Pin pinBusy[] = {PIN_TSC_BUSY}; + +/*---------------------------------------------------------------------------- + * Local functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Generic function to send a command to the touchscreen controller. + * + * \param bCmd command to send + * + * \return command result + */ +static uint32_t SendCommand( uint8_t bCmd ) +{ + uint32_t uResult = 0; + uint32_t uTimeout = 0; + + /* (volatile declaration needed for code optimisation by compiler) */ + volatile uint8_t bufferRX[3]; + volatile uint8_t bufferTX[3]; + + Pdc *pPdc = (Pdc *)SPI; + uint32_t dStatus; + + bufferRX[0] = 0; + bufferRX[1] = 0; + bufferRX[2] = 0; + + bufferTX[0] = bCmd; + bufferTX[1] = 0; + bufferTX[2] = 0; + + /* Send Command and data through the SPI */ + pPdc->PERIPH_PTCR = PERIPH_PTCR_RXTDIS; + pPdc->PERIPH_RPR = (uint32_t) bufferRX; + pPdc->PERIPH_RCR = 3; + + pPdc->PERIPH_PTCR = PERIPH_PTCR_TXTDIS; + pPdc->PERIPH_TPR = (uint32_t) bufferTX; + pPdc->PERIPH_TCR = 3; + + pPdc->PERIPH_PTCR = PERIPH_PTCR_RXTEN; + pPdc->PERIPH_PTCR = PERIPH_PTCR_TXTEN; + + do + { + dStatus = REG_SPI_SR; + uTimeout++; + } + while ((( dStatus & SPI_SR_RXBUFF) != SPI_SR_RXBUFF) && (uTimeout < ADS7843_TIMEOUT)); + + pPdc->PERIPH_PTCR = PERIPH_PTCR_RXTDIS; + pPdc->PERIPH_PTCR = PERIPH_PTCR_TXTDIS; + + uResult = (uint32_t)bufferRX[1] << 8; + uResult |= (uint32_t)bufferRX[2]; + uResult = uResult >> 4; + + return uResult; +} + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Get position of the pen by ask the ADS controller (SPI). + * + * \param px_pos pointer to the horizontal position + * \param py_pos pointer to the vertical position + * + */ +extern void ADS7843_GetPosition( uint32_t *px_pos, uint32_t *py_pos ) +{ + /* Get X position */ + *px_pos = SendCommand(CMD_X_POSITION); + /* Get Y position */ + *py_pos = SendCommand(CMD_Y_POSITION); + /* Switch to full power mode */ + SendCommand(CMD_ENABLE_PENIRQ); +} + +/** + * \brief Initialization of the SPI for communication with ADS7843 component. + */ +extern void ADS7843_Initialize( void ) +{ + volatile uint32_t uDummy; + + /* Configure pins */ + PIO_Configure(pinsSPI, PIO_LISTSIZE(pinsSPI)); + + PIO_Configure(pinBusy, PIO_LISTSIZE(pinBusy)); + + SPI_Configure(BOARD_TSC_SPI_BASE, + BOARD_TSC_SPI_ID, + SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_PCS(BOARD_TSC_NPCS) /* Value of the SPI configuration register. */ + ); + + SPI_ConfigureNPCS(BOARD_TSC_SPI_BASE, BOARD_TSC_NPCS, + SPI_CSR_NCPHA | SPI_CSR_DLYBS(DELAY_BEFORE_SPCK) | + SPI_CSR_DLYBCT(DELAY_BETWEEN_CONS_COM) | SPI_CSR_SCBR(0xC8) ); + + SPI_Enable(BOARD_TSC_SPI_BASE); + + for (uDummy=0; uDummy<100000; uDummy++); + + uDummy = REG_SPI_SR; + uDummy = REG_SPI_RDR; + + SendCommand(CMD_ENABLE_PENIRQ); +} + +/** + * \brief Reset the ADS7843 + */ +void ADS7843_Reset( void ) +{ + /* Disable SPI */ + SPI_Disable( BOARD_TSC_SPI_BASE ) ; +} diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/at45_spi.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/at45_spi.c new file mode 100644 index 00000000..2d84c4c2 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/at45_spi.c @@ -0,0 +1,316 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup spi_at45_module SPI AT45 driver + * \ingroup at45d_module + * The Dataflash driver is based on top of the corresponding Spi driver. + * A Dataflash structure instance has to be initialized using the DF_Init + * function. Then basic dataflash operations can be launched using macros such + * as DF_continuous_read. These macros invoke the DF_Command() function which + * invokes the DPI low driver using the SPI_SendCommand() function. + * Beware to compute the dataflash internal address, the dataflash sector + * description must be known (DataflashDesc). Dataflash can be automatically + * detected using the DF_Scan() function. + * + * \section Usage + * + * Related files :\n + * \ref spi_at45.c\n + * \ref spi_at45.h.\n +*/ +/*@{*/ +/*@}*/ + + +/** + * \file + * + * Implementation of SPI At45 driver. + * + */ + + + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "board.h" + +#include +#include + +/*---------------------------------------------------------------------------- + * Internal definitions + *----------------------------------------------------------------------------*/ + +/** Number of dataflash which can be recognized.*/ +#define NUMDATAFLASH (sizeof(at45Devices) / sizeof(At45Desc)) + +/*---------------------------------------------------------------------------- + * Local variables + *----------------------------------------------------------------------------*/ + +/** indicate if the device is configured as binary page or not.*/ +static uint8_t configuredBinaryPage; + +/** At45 device descriptor structure. */ +static const At45Desc at45Devices[] = { + { 512, 1, 264, 9, 0x0C, "AT45DB011D"}, + { 1024, 1, 264, 9, 0x14, "AT45DB021D"}, + { 2048, 1, 264, 9, 0x1C, "AT45DB041D"}, + { 4096, 1, 264, 9, 0x24, "AT45DB081D"}, + { 4096, 1, 528, 10, 0x2C, "AT45DB161D"}, + { 8192, 1, 528, 10, 0x34, "AT45DB321D"}, + { 8192, 1, 1056, 11, 0x3C, "AT45DB642D"}, + {16384, 1, 1056, 11, 0x10, "AT45DB1282"}, + {16384, 1, 2112, 12, 0x18, "AT45DB2562"}, + {32768, 1, 2112, 12, 0x20, "AT45DB5122"} +}; + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Initializes an AT45 instance and configures SPI chip select register. + * + * \param pAt45 Pointer to the At45 instance to initialize. + * \param pSpid Pointer to the underlying SPI driver. + * \param spiCs Chip select value to connect to the At45. + * \return 0. + */ +extern uint32_t AT45_Configure( At45* pAt45, Spid* pSpid, uint8_t ucSpiCs ) +{ + SpidCmd* pCommand ; + + /* Sanity checks */ + assert( pSpid != NULL ) ; + assert( pAt45 != NULL ) ; + + /* Initialize the At45 instance */ + pAt45->pSpid = pSpid ; + pAt45->pDesc = 0 ; + memset( pAt45->pCmdBuffer, 0, 8 ) ; + + /* Initialize the spidCmd structure */ + pCommand = &(pAt45->command) ; + pCommand->pCmd = pAt45->pCmdBuffer ; + pCommand->callback = 0 ; + pCommand->pArgument = 0 ; + pCommand->spiCs = ucSpiCs ; + + return 0 ; +} + +/** + * \brief Check if the At45 driver is in busy. + * + * \param pAt45 Pointer to the At45 instance to initialize. + * \return 1 if the At45 driver is not executing any command,otherwise it returns 0. + */ +extern uint32_t AT45_IsBusy( At45* pAt45 ) +{ + return SPID_IsBusy( pAt45->pSpid ) ; +} + +/** + * \brief Sends a command to the dataflash through the SPI. + * The command is identified by its command code and the number of bytes to transfer + * (1 + number of address bytes + number of dummy bytes).If data needs to be received, + * then a data buffer must be provided. + * \note This function does not block; its optional callback will be invoked when + * the transfer completes. + * \param pAt45 Pointer to the At45 instance to initialize. + * \param cmd Command code. + * \param cmdSize Size of command code + address bytes + dummy bytes. + * \param pData Data buffer. + * \param dataSize Number of data bytes to send/receive. + * \param address Address at which the command is performed if meaningful. + * \param callback Optional callback to invoke at end of transfer. + * \param pArgument Optional parameter to the callback function. + * \return 0. + */ +extern uint32_t AT45_SendCommand( At45* pAt45, uint8_t ucCmd, uint8_t ucCmdSize, uint8_t *pucData, uint32_t dwDataSize, + uint32_t dwAddress, SpidCallback pCallback, void *pArgument ) +{ + SpidCmd *pCommand ; + const At45Desc *pDesc; + uint32_t dfAddress = 0 ; + + /* Sanity checks */ + assert( pAt45 != NULL ) ; + + pDesc = pAt45->pDesc ; + + assert( pDesc || (ucCmd == AT45_STATUS_READ) ) ; + + /* Check if the SPI driver is available*/ + if ( AT45_IsBusy( pAt45 ) ) + { + return AT45_ERROR_LOCK ; + } + + /* Compute command pattern*/ + pAt45->pCmdBuffer[0] = ucCmd ; + + /* Add address bytes if necessary*/ + if ( ucCmdSize > 1 ) + { + assert( pDesc != NULL ) ; + if ( !configuredBinaryPage ) + { + dfAddress = ((dwAddress / (pDesc->pageSize)) << pDesc->pageOffset) + + (dwAddress % (pDesc->pageSize)); + } + else + { + dfAddress = dwAddress ; + } + + /* Write address bytes */ + if ( pDesc->pageNumber >= 16384 ) + { + pAt45->pCmdBuffer[1] = ((dfAddress & 0x0F000000) >> 24); + pAt45->pCmdBuffer[2] = ((dfAddress & 0x00FF0000) >> 16); + pAt45->pCmdBuffer[3] = ((dfAddress & 0x0000FF00) >> 8); + pAt45->pCmdBuffer[4] = ((dfAddress & 0x000000FF) >> 0); + + if ( (ucCmd != AT45_CONTINUOUS_READ) && (ucCmd != AT45_PAGE_READ) ) + { + ucCmdSize++ ; + } + } + else + { + pAt45->pCmdBuffer[1] = ((dfAddress & 0x00FF0000) >> 16); + pAt45->pCmdBuffer[2] = ((dfAddress & 0x0000FF00) >> 8); + pAt45->pCmdBuffer[3] = ((dfAddress & 0x000000FF) >> 0); + } + } + + /* Update the SPI Transfer descriptors */ + pCommand = &(pAt45->command) ; + pCommand->cmdSize = ucCmdSize ; + pCommand->pData = pucData ; + pCommand->dataSize = dwDataSize ; + pCommand->callback = pCallback ; + pCommand->pArgument = pArgument ; + + /* Send Command and data through the SPI */ + if ( SPID_SendCommand( pAt45->pSpid, pCommand ) ) + { + return AT45_ERROR_SPI ; + } + + return 0 ; +} + +/** + * \brief returns the At45Desc structure corresponding to the device connected. + * It automatically initializes pAt45->pDesc field structure. + * + * \note This function shall be called by the application before AT45_SendCommand. + * + * \param pAt45 Pointer to the At45 instance to initialize. + * \param status Device status register value. + * + * \return 0 if successful; Otherwise, returns AT45_ERROR_LOCK if the At45 + * driver is in use or AT45_ERROR_SPI if there was an error with the SPI driver. + */ +extern const At45Desc * AT45_FindDevice( At45 *pAt45, uint8_t status ) +{ + uint32_t i; + uint8_t id = AT45_STATUS_ID(status); + + /* Check if status is all one; in which case, it is assumed that no device is connected*/ + if ( status == 0xFF ) + { + return 0 ; + } + + /* Look in device array */ + i = 0 ; + pAt45->pDesc = 0 ; + while ( (i < NUMDATAFLASH) && !(pAt45->pDesc) ) + { + if ( at45Devices[i].id == id ) + { + pAt45->pDesc = &(at45Devices[i]) ; + } + i++ ; + } + + configuredBinaryPage = AT45_STATUS_BINARY(status); + + return pAt45->pDesc ; +} + +/** + * \brief returns the pagesize corresponding to the device connected. + * \param pAt45 Pointer to the At45 instance to initialize. + * \return page size. + */ +extern uint32_t AT45_PageSize( At45 *pAt45 ) +{ + uint32_t dwPageSize = pAt45->pDesc->pageSize ; + + if ( ((pAt45->pDesc->hasBinaryPage) == 0) || !configuredBinaryPage ) + { + return dwPageSize ; + } + + return ((dwPageSize >> 8) << 8) ; +} diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/at45d.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/at45d.c new file mode 100644 index 00000000..71b7b76d --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/at45d.c @@ -0,0 +1,254 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \addtogroup external_component External Component + * + * \addtogroup at45d_module AT45 driver + * \ingroup external_component + * The AT45 Dataflash driver is based on the corresponding AT45 driver. + * A AT45 instance has to be initialized using the Dataflash levle function + * AT45_Configure(). AT45 Dataflash can be automatically detected using + * the AT45_FindDevice() function. Then AT45 dataflash operations such as + * read, write and erase DF can be launched using AT45_SendCommand function + * with corresponding AT45 command set. + * + * \section Usage + *
    + *
  • Reads data from the At45 at the specified address using AT45D_Read().
  • + *
  • Writes data on the At45 at the specified address using AT45D_Write().
  • + *
  • Erases a page of data at the given address using AT45D_Erase().
  • + *
  • Poll until the At45 has completed of corresponding operations using + * AT45D_WaitReady().
  • + *
  • Retrieves and returns the At45 current using AT45D_GetStatus().
  • + *
+ * Related files :\n + * \ref at45d.c\n + * \ref at45d.h.\n + */ + /*@{*/ + /*@}*/ + + +/** + * \file + * + * Implementation of At45 driver. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "board.h" + +#include +#include + +/*---------------------------------------------------------------------------- + * Local functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Wait for transfer to finish calling the SPI driver ISR (interrupts are + * disabled). + * + * \param pAt45 Pointer to an AT45 driver instance. + */ +static void AT45D_Wait( At45* pAt45 ) +{ + assert( pAt45 != NULL ) ; + + /* Wait for transfer to finish */ + while ( AT45_IsBusy( pAt45 ) ) + { + SPID_Handler( pAt45->pSpid ) ; + } +} + +/*---------------------------------------------------------------------------- + * Global functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Waits for the At45 to be ready to accept new commands. + * + * \param pAt45 Pointer to an AT45 driver instance. + */ +extern void AT45D_WaitReady( At45* pAt45 ) +{ + uint8_t ready = 0; + + assert( pAt45 != NULL ) ; + + /* Poll device until it is ready. */ + while (!ready) + { + ready = AT45_STATUS_READY(AT45D_GetStatus(pAt45)); + } +} + +/** + * \brief Retrieves and returns the At45 current status, or 0 if an error happened. + * + * \param pAt45 Pointer to an AT45 driver instance. + */ +extern uint32_t AT45D_GetStatus( At45* pAt45 ) +{ + uint32_t dwError ; + uint8_t ucStatus ; + + assert( pAt45 != NULL ) ; + + /* Issue a status register read command */ + dwError = AT45_SendCommand( pAt45, AT45_STATUS_READ, 1, &ucStatus, 1, 0, 0, 0 ) ; + assert( !dwError ) ; + + /* Wait for command to terminate */ + while ( AT45_IsBusy( pAt45 ) ) + { + AT45D_Wait( pAt45 ) ; + } + + return ucStatus ; +} + +/** + * \brief Reads data from the At45 inside the provided buffer. Since a continuous + * read command is used, there is no restriction on the buffer size and read address. + * + * \param pAt45 Pointer to an AT45 driver instance. + * \param pBuffer Data buffer. + * \param size Number of bytes to read. + * \param address Address at which data shall be read. + */ +extern void AT45D_Read( At45* pAt45, uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress ) +{ + uint32_t dwError ; + + assert( pAt45 != NULL ) ; + assert( pucBuffer != NULL ) ; + + /* Issue a continuous read array command. */ + dwError = AT45_SendCommand( pAt45, AT45_CONTINUOUS_READ_LEG, 8, pucBuffer, dwSize, dwAddress, 0, 0 ) ; + assert( !dwError ) ; + + /* Wait for the read command to execute. */ + while ( AT45_IsBusy( pAt45 ) ) + { + AT45D_Wait( pAt45 ) ; + } +} + +/** + * \brief Writes data on the At45 at the specified address. Only one page of + * data is written that way; if the address is not at the beginning of the + * page, the data is written starting from this address and wraps around to + * the beginning of the page. + * + * \param pAt45 Pointer to an AT45 driver instance. + * \param pucBuffer Data buffer. + * \param dwSize Number of bytes to write. + * \param dwAddress Destination address on the At45. + */ +extern void AT45D_Write( At45* pAt45, uint8_t *pucBuffer, uint32_t dwSize, uint32_t dwAddress ) +{ + uint8_t dwError ; + + assert( pAt45 != NULL ) ; + assert( pucBuffer != NULL ) ; + assert( dwSize <= pAt45->pDesc->pageSize ) ; + + /* Issue a page write through buffer 1 command. */ + dwError = AT45_SendCommand( pAt45, AT45_PAGE_WRITE_BUF1, 4, pucBuffer, dwSize, dwAddress, 0, 0 ) ; + assert( !dwError ) ; + + /* Wait until the command is sent. */ + while ( AT45_IsBusy( pAt45 ) ) + { + AT45D_Wait( pAt45 ) ; + } + + /* Wait until the At45 becomes ready again.*/ + AT45D_WaitReady( pAt45 ) ; +} + +/** + * \brief Erases a page of data at the given address in the At45. + * + * \param pAt45 Pointer to an AT45 driver instance. + * \param dwAddress Address of page to erase. + */ +extern void AT45D_Erase( At45* pAt45, uint32_t dwAddress ) +{ + uint32_t dwError ; + + assert( pAt45 != NULL ) ; + + /* Issue a page erase command. */ + dwError = AT45_SendCommand( pAt45, AT45_PAGE_ERASE, 4, 0, 0, dwAddress, 0, 0 ) ; + assert( !dwError ) ; + + /* Wait for end of transfer. */ + while ( AT45_IsBusy(pAt45 ) ) + { + AT45D_Wait( pAt45 ) ; + } + + /* Poll until the At45 has completed the erase operation. */ + AT45D_WaitReady( pAt45 ) ; +} + +/** + * \brief Configure power-of-2 binary page size in the At45. + * + * \param pAt45 Pointer to an AT45 driver instance. + */ +extern void AT45D_BinaryPage( At45* pAt45 ) +{ + uint8_t dwError ; + uint8_t opcode[3]= {AT45_BINARY_PAGE}; + assert( pAt45 != NULL ) ; + + /* Issue a binary page command. */ + + dwError = AT45_SendCommand( pAt45, AT45_BINARY_PAGE_FIRST_OPCODE, 1, opcode, 3, 0, 0, 0 ) ; + + assert( !dwError ) ; + + /* Wait for end of transfer.*/ + while ( AT45_IsBusy( pAt45 ) ) + { + AT45D_Wait( pAt45 ) ; + } + + /* Wait until the At45 becomes ready again.*/ + AT45D_WaitReady( pAt45 ) ; +} diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/bmp.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/bmp.c new file mode 100644 index 00000000..7637e76c --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/bmp.c @@ -0,0 +1,319 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, 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 disclaimer below. + * + * 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 "board.h" + +#include + +//----------------------------------------------------------------------------- +// Define +//----------------------------------------------------------------------------- +/// BMP offset for header +#define IMAGE_OFFSET 0x100 + + +//------------------------------------------------------------------------------ +// Internal constants +//------------------------------------------------------------------------------ + + +//------------------------------------------------------------------------------ +// Internal types +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Describe the BMP palette +//------------------------------------------------------------------------------ +typedef struct _BMPPaletteEntry +{ + /// Blue value + uint8_t b; + /// Green value + uint8_t g; + /// Red value + uint8_t r; + /// Filler character value + uint8_t filler; +} BMPPaletteEntry ; + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Test if BMP is valid +/// \param file Buffer holding the file to examinate. +/// \return 1 if the header of a BMP file is valid; otherwise returns 0. +//------------------------------------------------------------------------------ +uint8_t BMP_IsValid( void *file ) +{ + return ((BMPHeader*) file)->type == BMP_TYPE ; +} + +//------------------------------------------------------------------------------ +/// Returns the size of a BMP image given at least its header (the file does +/// not have to be complete). +/// \param file Pointer to the buffer which holds the BMP file. +/// \return size of BMP image +//------------------------------------------------------------------------------ +uint32_t BMP_GetFileSize( void *file ) +{ + return ((BMPHeader *) file)->fileSize ; +} + +//----------------------------------------------------------------------------- +/// Write a BMP header +/// \param pAddressHeader Begin address of the BMP +/// \param bmpHSize BMP heigth size +/// \param bmpVSize BMP width size +/// \param nbByte_Pixels Number of byte per pixels +//----------------------------------------------------------------------------- +void WriteBMPheader( uint32_t* pAddressHeader, uint32_t bmpHSize, uint32_t bmpVSize, uint8_t nbByte_Pixels ) +{ + uint32_t i; + uint32_t* fill; + BMPHeader *Header; + + fill = pAddressHeader; + for ( i=0 ; i < IMAGE_OFFSET ; i+=4 ) + { + *fill++ = 0; + } + + Header = (BMPHeader*) pAddressHeader; + + Header->type = BMP_TYPE; + Header->fileSize = (bmpHSize * bmpVSize * nbByte_Pixels) + IMAGE_OFFSET; + Header->reserved1 = 0; + Header->reserved2 = 0; + Header->offset = IMAGE_OFFSET; + Header->headerSize = BITMAPINFOHEADER; + Header->width = bmpHSize; + Header->height = bmpVSize; + Header->planes = 1; + Header->bits = nbByte_Pixels * 8; + Header->compression = 0; + Header->imageSize = bmpHSize * bmpVSize * nbByte_Pixels; + Header->xresolution = 0; + Header->yresolution = 0; + Header->ncolours = 0; + Header->importantcolours = 0; +} + + +//------------------------------------------------------------------------------ +/// debug function, dislay BMP header +/// \param pAddressHeader Address of the BMP +//------------------------------------------------------------------------------ +#if (TRACE_LEVEL >= TRACE_LEVEL_INFO) +void BMP_displayHeader( uint32_t* pAddressHeader ) +{ + BMPHeader *header; + + header = (BMPHeader*) pAddressHeader; + + TRACE_INFO("BMP\n\r"); + TRACE_INFO("type 0x%X \n\r", header->type); + TRACE_INFO("fileSize %d \n\r", header->fileSize); + TRACE_INFO("reserved1 %d \n\r", header->reserved1); + TRACE_INFO("reserved2 %d \n\r", header->reserved2); + TRACE_INFO("offset %d \n\r", header->offset); + TRACE_INFO("headerSize %d \n\r", header->headerSize); + TRACE_INFO("width %d \n\r", header->width); + TRACE_INFO("height %d \n\r", header->height); + TRACE_INFO("planes %d \n\r", header->planes); + TRACE_INFO("bits %d \n\r", header->bits); + TRACE_INFO("compression %d \n\r", header->compression); + TRACE_INFO("imageSize %d \n\r", header->imageSize); + TRACE_INFO("xresolution %d \n\r", header->xresolution); + TRACE_INFO("yresolution %d \n\r", header->yresolution); + TRACE_INFO("ncolours %d \n\r", header->ncolours); + TRACE_INFO("importantcolours %d\n\r", header->importantcolours); +} +#endif + +//------------------------------------------------------------------------------ +/// Loads a BMP image located at the given address, decodes it and stores the +/// resulting image inside the provided buffer. Image must have the specified +/// width & height. +/// If no buffer is provided, this function simply checks if it is able to +/// decode the image. +/// \param file Buffer which holds the BMP file. +/// \param buffer Buffer in which to store the decoded image. +/// \param width Buffer width in pixels. +/// \param height Buffer height in pixels. +/// \param bpp Number of bits per pixels that the buffer stores. +/// \return 0 if the image has been loaded; otherwise returns an error code. +//------------------------------------------------------------------------------ +uint8_t BMP_Decode( void *file, uint8_t *buffer, uint32_t width, uint32_t height, uint8_t bpp ) +{ + BMPHeader *header; + uint32_t i, j; + uint8_t r, g, b; + uint8_t *image; + + // Read header information + header = (BMPHeader*) file; + + // Verify that the file is valid + if ( !BMP_IsValid( file ) ) + { + TRACE_ERROR("BMP_Decode: File type is not 'BM' (0x%04X).\n\r",header->type); + + return 1; + } + + // Check that parameters match + if ( (header->compression != 0) || (header->width != width) || (header->height != height)) + { + TRACE_ERROR("BMP_Decode: File format not supported\n\r"); + TRACE_ERROR(" -> .compression = %u\n\r", (unsigned int)header->compression); + TRACE_ERROR(" -> .width = %u\n\r", (unsigned int)header->width); + TRACE_ERROR(" -> .height = %u\n\r", (unsigned int)header->height); + TRACE_ERROR(" -> .bits = %d\n\r", (int)header->bits); + + return 2; + } + + // Get image data + image = (uint8_t *) ((uint32_t) file + header->offset); + + // Check that the bpp resolution is supported + // Only a 24-bit output & 24- or 8-bit input are supported + if ( bpp != 24 ) + { + TRACE_ERROR("BMP_Decode: Output resolution not supported\n\r"); + + return 3; + } + else + { + if (header->bits == 24) + { + // Decoding is ok + if (!buffer) return 0; + + // Get image data (swapping red & blue) + for ( i=0 ; i < height ; i++ ) + { + for ( j=0 ; j < width; j++ ) + { + r = image[((height - i - 1) * width + j) * 3 + 2]; + g = image[((height - i - 1) * width + j) * 3 + 1]; + b = image[((height - i - 1) * width + j) * 3]; + + #if defined(BOARD_LCD_RGB565) + // Interlacing + r = ((r << 1) & 0xF0) | ((g & 0x80) >> 4) | ((r & 0x80) >> 5); + g = (g << 1) & 0xF8; + b = b & 0xF8; + + buffer[(i * width + j) * 3] = b; + buffer[(i * width + j) * 3 + 1] = g; + buffer[(i * width + j) * 3 + 2] = r; + + #else + buffer[(i * width + j) * 3] = r; + buffer[(i * width + j) * 3 + 1] = g; + buffer[(i * width + j) * 3 + 2] = b; + #endif //#if defined(BOARD_LCD_RGB565) + } + } + } + else + { + if ( header->bits == 8 ) + { + BMPPaletteEntry palette[256]; + + // Decoding is ok + if (!buffer) return 0; + + // Retrieve palette + memcpy( palette, (uint8_t *) ((uint32_t) file + sizeof( BMPHeader )), header->offset - sizeof( BMPHeader ) ) ; + + // Decode image (reversing row order) + for ( i=0 ; i < height ; i++ ) + { + for (j=0; j < width; j++) + { + r = palette[image[(height - i - 1) * width + j]].r; + g = palette[image[(height - i - 1) * width + j]].g; + b = palette[image[(height - i - 1) * width + j]].b; + + buffer[(i * width + j) * 3] = r; + buffer[(i * width + j) * 3 + 1] = g; + buffer[(i * width + j) * 3 + 2] = b; + } + } + } + else + { + + TRACE_ERROR("BMP_Decode: Input resolution not supported\n\r"); + TRACE_INFO("header->bits 0x%X \n\r", header->bits); + return 4 ; + } + } + } + + return 0 ; +} + +//------------------------------------------------------------------------------ +/// Convert RGB 565 to RGB 555 (RGB 555 is adapted to LCD) +/// \param fileSource Buffer which holds the RGB file +/// \param fileDestination Buffer in which to store the decoded image +/// \param width Buffer width in pixels. +/// \param height Buffer height in pixels. +/// \param bpp Number of bits per pixels that the buffer stores. +//------------------------------------------------------------------------------ +void RGB565toBGR555( uint8_t *fileSource, uint8_t *fileDestination, uint32_t width, uint32_t height, uint8_t bpp ) +{ + uint32_t i; + uint32_t j; + uint32_t row; + + for (i=0; i < height*(bpp/8); i++) + { + row = (i*width*(bpp/8)); + + for (j=0; j <= width*(bpp/8); j+=2) + { + fileDestination[row+j] = ((fileSource[row+j+1]>>3)&0x1F) + | (fileSource[row+j]&0xE0); + fileDestination[row+j+1] = (fileSource[row+j+1]&0x03) + | ((fileSource[row+j]&0x1F)<<2); + } + } +} diff --git a/sam3s_example/src/board_cstartup_gnu.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/board_cstartup_gnu.c similarity index 96% rename from sam3s_example/src/board_cstartup_gnu.c rename to sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/board_cstartup_gnu.c index 423e7758..3647d5e7 100644 --- a/sam3s_example/src/board_cstartup_gnu.c +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/board_cstartup_gnu.c @@ -56,9 +56,12 @@ extern uint32_t _ezero; /*---------------------------------------------------------------------------- * ProtoTypes *----------------------------------------------------------------------------*/ + +/** \cond DOXYGEN_SHOULD_SKIP_THIS */ extern int main( void ) ; -extern void __libc_init_array( void ) ; +/** \endcond */ void ResetException( void ) ; +extern void __libc_init_array( void ) ; /*------------------------------------------------------------------------------ * Exception Table diff --git a/sam3s_example/src/board_lowlevel.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/board_lowlevel.c similarity index 92% rename from sam3s_example/src/board_lowlevel.c rename to sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/board_lowlevel.c index ca9f9dc3..7c3a55d2 100644 --- a/sam3s_example/src/board_lowlevel.c +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/board_lowlevel.c @@ -38,13 +38,12 @@ *----------------------------------------------------------------------------*/ #include "board.h" -#include "board_lowlevel.h" /*---------------------------------------------------------------------------- * Local definitions *----------------------------------------------------------------------------*/ -/* Clock settings at 48MHz */ +/* Clock settings at 48MHz for 12 MHz crystal */ #if (BOARD_MCK == 48000000) #define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8)) #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ @@ -53,7 +52,7 @@ | CKGR_PLLAR_DIVA(0x1)) #define BOARD_MCKR (PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK) -/* Clock settings at 64MHz */ +/* Clock settings at 64MHz for 12 MHz crystal */ #elif (BOARD_MCK == 64000000) #define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8)) #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ @@ -78,7 +77,7 @@ * This includes EFC and master clock configuration. * It also enable a low level on the pin NRST triggers a user reset. */ -WEAK void LowLevelInit( void ) +extern WEAK void LowLevelInit( void ) { uint32_t timeout = 0; @@ -86,22 +85,21 @@ WEAK void LowLevelInit( void ) EFC->EEFC_FMR = EEFC_FMR_FWS(3); /* Select external slow clock */ -#if 0 - if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST) +/* if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST) { SUPC->SUPC_CR = (uint32_t)(SUPC_CR_XTALSEL_CRYSTAL_SEL | SUPC_CR_KEY(0xA5)); timeout = 0; while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL_CRYST) ); } -#endif +*/ /* Initialize main oscillator */ - if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) ) +/* if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) ) { PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN; timeout = 0; while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT)); - } + }*/ /* Switch to 3-20MHz Xtal oscillator */ PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/board_memories.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/board_memories.c new file mode 100644 index 00000000..ddeba30d --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/board_memories.c @@ -0,0 +1,153 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implementation of memories configuration on board. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ +#include "board.h" + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Configures the EBI for NandFlash access. + */ +extern void BOARD_ConfigureNandFlash( Smc* pSmc ) +{ + /* Enable peripheral clock */ + PMC_EnablePeripheral( ID_SMC ) ; + + /* NCS0 is assigned to a NAND Flash (NANDOE and NANWE used for NCS0) */ + MATRIX->CCFG_SMCNFCS = CCFG_SMCNFCS_SMC_NFCS0; + + pSmc->SMC_CS_NUMBER[0].SMC_SETUP = SMC_SETUP_NWE_SETUP(0) + | SMC_SETUP_NCS_WR_SETUP(1) + | SMC_SETUP_NRD_SETUP(0) + | SMC_SETUP_NCS_RD_SETUP(1); + + pSmc->SMC_CS_NUMBER[0].SMC_PULSE = SMC_PULSE_NWE_PULSE(2) + | SMC_PULSE_NCS_WR_PULSE(3) + | SMC_PULSE_NRD_PULSE(4) + | SMC_PULSE_NCS_RD_PULSE(4); + + pSmc->SMC_CS_NUMBER[0].SMC_CYCLE = SMC_CYCLE_NWE_CYCLE(4) + | SMC_CYCLE_NRD_CYCLE(7); + + pSmc->SMC_CS_NUMBER[0].SMC_MODE = SMC_MODE_READ_MODE + | SMC_MODE_WRITE_MODE + | SMC_MODE_DBW_8_BIT; +} + +/** + * \brief Configures the EBI for %NorFlash access. + */ +extern void BOARD_ConfigureNorFlash( Smc* pSmc ) +{ + /* Enable peripheral clock */ + PMC_EnablePeripheral( ID_SMC ) ; + + /* Configure SMC, NCS3 is assigned to a norflash */ + pSmc->SMC_CS_NUMBER[3].SMC_SETUP = SMC_SETUP_NWE_SETUP(2) + | SMC_SETUP_NCS_WR_SETUP(0) + | SMC_SETUP_NRD_SETUP(0) + | SMC_SETUP_NCS_RD_SETUP(0); + + pSmc->SMC_CS_NUMBER[3].SMC_PULSE = SMC_PULSE_NWE_PULSE(6) + | SMC_PULSE_NCS_WR_PULSE(0xA) + | SMC_PULSE_NRD_PULSE(0xA) + | SMC_PULSE_NCS_RD_PULSE(0xA); + + pSmc->SMC_CS_NUMBER[3].SMC_CYCLE = SMC_CYCLE_NWE_CYCLE(0xA) + | SMC_CYCLE_NRD_CYCLE(0xA); + + pSmc->SMC_CS_NUMBER[3].SMC_MODE = SMC_MODE_READ_MODE + | SMC_MODE_WRITE_MODE + | SMC_MODE_DBW_8_BIT + | SMC_MODE_EXNW_MODE_DISABLED + | SMC_MODE_TDF_CYCLES(0x1); +} + +/** + * \brief An accurate one-to-one comparison is necessary between PSRAM and SMC waveforms for + * a complete SMC configuration. + * \note The system is running at 48 MHz for the EBI Bus. + * Please refer to the "AC Characteristics" section of the customer product datasheet. + */ +extern void BOARD_ConfigurePSRAM( Smc* pSmc ) +{ + uint32_t dwTmp ; + + /* Enable peripheral clock */ + PMC_EnablePeripheral( ID_SMC ) ; + + /* Configure SMC, NCS1 is assigned to a external PSRAM */ + /** + * PSRAM IS66WV51216BLL + * 55 ns Access time + * tdoe = 25 ns max + * SMC1 (timing SAM3S read mode SMC) = 21 ns of setup + * 21 + 55 = 76 ns => at least 5 cycles at 64 MHz + * Write pulse width minimum = 45 ns (PSRAM) + */ + pSmc->SMC_CS_NUMBER[1].SMC_SETUP = SMC_SETUP_NWE_SETUP( 1 ) + | SMC_SETUP_NCS_WR_SETUP( 0 ) + | SMC_SETUP_NRD_SETUP( 2 ) + | SMC_SETUP_NCS_RD_SETUP( 0 ) ; + + pSmc->SMC_CS_NUMBER[1].SMC_PULSE = SMC_PULSE_NWE_PULSE( 3 ) + | SMC_PULSE_NCS_WR_PULSE( 4 ) + | SMC_PULSE_NRD_PULSE( 3 ) + | SMC_PULSE_NCS_RD_PULSE( 5 ) ; + + /* NWE_CYCLE: The total duration of the write cycle. + NWE_CYCLE = NWE_SETUP + NWE_PULSE + NWE_HOLD + = NCS_WR_SETUP + NCS_WR_PULSE + NCS_WR_HOLD + (tWC) Write Cycle Time min. 70ns + NRD_CYCLE: The total duration of the read cycle. + NRD_CYCLE = NRD_SETUP + NRD_PULSE + NRD_HOLD + = NCS_RD_SETUP + NCS_RD_PULSE + NCS_RD_HOLD + (tRC) Read Cycle Time min. 70ns. */ + pSmc->SMC_CS_NUMBER[1].SMC_CYCLE = SMC_CYCLE_NWE_CYCLE( 4 ) + | SMC_CYCLE_NRD_CYCLE( 5 ) ; + + dwTmp = SMC->SMC_CS_NUMBER[0].SMC_MODE & (uint32_t)(~(SMC_MODE_DBW_Msk)) ; + pSmc->SMC_CS_NUMBER[1].SMC_MODE = dwTmp + | SMC_MODE_READ_MODE + | SMC_MODE_WRITE_MODE + | SMC_MODE_DBW_8_BIT ; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/clock.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/clock.c new file mode 100644 index 00000000..fb31374f --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/clock.c @@ -0,0 +1,184 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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 "board.h" + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +/* + * \brief Describes a possible clock configuration (processor clock & master clock), + * including the necessary register values. + */ +typedef struct _ClockConfiguration +{ + + /** Processor clock frequency (in MHz). */ + uint16_t pck; + /** Master clock frequency (in MHz). */ + uint16_t mck; + /** CKGR_PLL reqister value. */ + uint32_t pllr; + /** PMC_MCKR register value. */ + uint32_t mckr; +} ClockConfiguration ; + +/*---------------------------------------------------------------------------- + * Local variables + *----------------------------------------------------------------------------*/ + +/* Clock configurations for the AT91SAM3S4-EK */ +#define CKGR_MUL_SHIFT 16 +#define CKGR_PLLCOUNT_SHIFT 8 +#define CKGR_DIV_SHIFT 0 + +/* Clock configuration for the AT91SAM3S */ +static const ClockConfiguration clockConfigurations[] = { + + /* PCK = 24 MHz, MCK = 24 MHz + * PCK = 12000000 * (7+1) / 2 / 2 = 24 MHz + */ + {24, 24, (CKGR_PLLAR_STUCKTO1 | (7 << CKGR_MUL_SHIFT) \ + | (0x3f << CKGR_PLLCOUNT_SHIFT) \ + | (2 << CKGR_DIV_SHIFT)), + ( PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK)}, + /* PCK = 48 MHz, MCK = 48 MHz + * PCK = 12000000 * (7+1) / 1 / 2 = 48 MHz + */ + {48, 48, (CKGR_PLLAR_STUCKTO1 | (7 << CKGR_MUL_SHIFT) \ + | (0x3f << CKGR_PLLCOUNT_SHIFT) \ + | (1 << CKGR_DIV_SHIFT)), + ( PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK)}, + /* PCK = 64 MHz, MCK = 64 MHz + * PCK = 12000000 * (15+1) / 3 / 1 = 64 MHz + */ + {64, 64, (CKGR_PLLAR_STUCKTO1 | (15 << CKGR_MUL_SHIFT) \ + | (0x3f << CKGR_PLLCOUNT_SHIFT) \ + | (3 << CKGR_DIV_SHIFT)), + ( PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK)} +}; + +/* Number of available clock configurations */ +#define NB_CLOCK_CONFIGURATION (sizeof(clockConfigurations)/sizeof(clockConfigurations[0])) + +/* Current clock configuration */ +uint32_t currentConfig = 0; /* 0 have to be the default configuration */ + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Sets the specified clock configuration. + * + * \param configuration Index of the configuration to set. + */ +void CLOCK_SetConfig(uint8_t configuration) +{ + TRACE_DEBUG("Setting clock configuration #%d ... ", configuration); + currentConfig = configuration; + + /* Switch to main oscillator in two operations */ + PMC->PMC_MCKR = (PMC->PMC_MCKR & (uint32_t)~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; + while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0); + + /* Configure PLL */ + PMC->CKGR_PLLAR = clockConfigurations[configuration].pllr; + while ((PMC->PMC_SR & PMC_SR_LOCKA) == 0); + + /* Configure master clock in two operations */ + PMC->PMC_MCKR = (clockConfigurations[configuration].mckr & (uint32_t)~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; + while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0); + PMC->PMC_MCKR = clockConfigurations[configuration].mckr; + while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0); + + /* DBGU reconfiguration */ + UART_Configure(115200, clockConfigurations[configuration].mck*1000000); + TRACE_DEBUG("done.\n\r"); +} + +/** + * \brief Display the user menu on the DBGU. + */ +void CLOCK_DisplayMenu(void) +{ + uint32_t i; + + printf("\n\rMenu Clock configuration:\n\r"); + for (i = 0; i < NB_CLOCK_CONFIGURATION; i++) { + + printf(" %u: Set PCK = %3u MHz, MCK = %3u MHz %s\n\r", + (unsigned int)i, + (unsigned int)clockConfigurations[i].pck, + (unsigned int)clockConfigurations[i].mck, + (currentConfig==i)?"(curr)":""); + } +} + +/** + * \brief Get the current MCK + */ +uint16_t CLOCK_GetCurrMCK(void) +{ + return clockConfigurations[currentConfig].mck; +} + +/** + * \brief Get the current PCK + */ +uint16_t CLOCK_GetCurrPCK(void) +{ + return clockConfigurations[currentConfig].pck; +} + +/** + * \brief Change clock configuration. + */ +void CLOCK_UserChangeConfig(void) +{ + uint8_t key = 0; + + while (1) + { + CLOCK_DisplayMenu(); + key = UART_GetChar(); + + if ((key >= '0') && (key <= ('0' + NB_CLOCK_CONFIGURATION - 1))) + { + CLOCK_SetConfig(key - '0'); + break; + } + } +} + diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/frame_buffer.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/frame_buffer.c new file mode 100644 index 00000000..bfc20ba4 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/frame_buffer.c @@ -0,0 +1,435 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "board.h" +#include +#include + +/** Frame buffer color cache size used to optimize memcpy */ +#define FB_COLOR_CACHE_SIZE 8 +/*---------------------------------------------------------------------------- + * Local variables + *----------------------------------------------------------------------------*/ +/** Pointer to frame buffer. It is 16 bit aligned to allow PDC operations + * LcdColor_t shall be defined in the physical lcd API (ili9225.c) +*/ +static LcdColor_t *gpBuffer; +/** Frame buffer width */ +static uint8_t gucWidth; +/** Frame buffer height */ +static uint8_t gucHeight; +/* Pixel color cache */ +static LcdColor_t gFbPixelCache[FB_COLOR_CACHE_SIZE]; + +/*---------------------------------------------------------------------------- + * Static functions + *----------------------------------------------------------------------------*/ +/** + * \brief Check Box coordinates. Return upper left and bottom right coordinates. + * + * \param pX1 X-coordinate of upper-left corner on LCD. + * \param pY1 Y-coordinate of upper-left corner on LCD. + * \param pX2 X-coordinate of lower-right corner on LCD. + * \param pY2 Y-coordinate of lower-right corner on LCD. + */ +static void CheckBoxCoordinates( uint32_t *pX1, uint32_t *pY1, uint32_t *pX2, uint32_t *pY2 ) +{ + uint32_t dw; + + if ( *pX1 >= gucWidth ) + *pX1=gucWidth-1 ; + + if ( *pX2 >= gucWidth ) + *pX2=gucWidth-1 ; + + if ( *pY1 >= gucHeight ) + *pY1=gucHeight-1 ; + + if ( *pY2 >= gucHeight ) + *pY2=gucHeight-1 ; + + if (*pX1 > *pX2) { + dw = *pX1; + *pX1 = *pX2; + *pX2 = dw; + } + if (*pY1 > *pY2) { + dw = *pY1; + *pY1 = *pY2; + *pY2 = dw; + } +} + +/* + * \brief Draw a line on LCD, which is not horizontal or vertical. + * + * \param x X-coordinate of line start. + * \param y Y-coordinate of line start. + * \param length line length. + * \param direction line direction: 0 - horizontal, 1 - vertical. + * \param color Pixel color. + */ +static uint32_t DrawLineBresenham( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 ) +{ + int dx, dy ; + int i ; + int xinc, yinc, cumul ; + int x, y ; + + x = dwX1 ; + y = dwY1 ; + dx = dwX2 - dwX1 ; + dy = dwY2 - dwY1 ; + + xinc = ( dx > 0 ) ? 1 : -1 ; + yinc = ( dy > 0 ) ? 1 : -1 ; + dx = ( dx > 0 ) ? dx : -dx ; + dy = ( dy > 0 ) ? dy : -dy ; + + FB_DrawPixel(x, y); + + if ( dx > dy ) + { + cumul = dx / 2 ; + for ( i = 1 ; i <= dx ; i++ ) + { + x += xinc ; + cumul += dy ; + + if ( cumul >= dx ) + { + cumul -= dx ; + y += yinc ; + } + FB_DrawPixel(x, y); + } + } + else + { + cumul = dy / 2 ; + for ( i = 1 ; i <= dy ; i++ ) + { + y += yinc ; + cumul += dx ; + + if ( cumul >= dy ) + { + cumul -= dy ; + x += xinc ; + } + + FB_DrawPixel(x, y); + } + } + + return 0 ; +} + +/*---------------------------------------------------------------------------- + * External functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Configure the current frame buffer. + * Next frame buffer operations will take place in this frame buffer area. + * \param pBuffer 16 bit aligned sram buffer. PDC shall be able to access this + * memory area. + * \param ucWidth frame buffer width + * \param ucHeight frame buffer height + */ +extern void FB_SetFrameBuffer(LcdColor_t *pBuffer, uint8_t ucWidth, uint8_t ucHeight) +{ + /* Sanity check */ + assert(pBuffer != NULL); + + gpBuffer = pBuffer; + gucWidth = ucWidth; + gucHeight = ucHeight; +} + + +/** + * \brief Configure the current color that will be used in the next graphical operations. + * + * \param dwRgb24Bits 24 bit rgb color + */ +extern void FB_SetColor(uint32_t dwRgb24Bits) +{ + uint16_t i; +// LcdColor_t wColor; + +// wColor = (dwRgb24Bits & 0xF80000) >> 8 | +// (dwRgb24Bits & 0x00FC00) >> 5 | +// (dwRgb24Bits & 0x0000F8) >> 3; + + /* Fill the cache with selected color */ + for (i = 0; i < FB_COLOR_CACHE_SIZE; ++i) { + gFbPixelCache[i] = dwRgb24Bits ; + } +} +/** + * \brief Draw a pixel on FB of given color. + * + * \param x X-coordinate of pixel. + * \param y Y-coordinate of pixel. + * + * \return 0 is operation is successful, 1 if pixel is out of the fb + */ +extern uint32_t FB_DrawPixel( + uint32_t dwX, + uint32_t dwY) +{ + if ((dwX >= gucWidth) || (dwY >= gucHeight)) { + return 1; + } + gpBuffer[dwX + dwY * gucWidth] = gFbPixelCache[0]; + + return 0; +} + +/** + * \brief Write several pixels with the same color to FB. + * + * Pixel color is set by the LCD_SetColor() function. + * This function is optimized using an sram buffer to transfer block instead of + * individual pixels in order to limit the number of SPI interrupts. + * \param dwX1 X-coordinate of upper-left corner on LCD. + * \param dwY1 Y-coordinate of upper-left corner on LCD. + * \param dwX2 X-coordinate of lower-right corner on LCD. + * \param dwY2 Y-coordinate of lower-right corner on LCD. + * + * \return 0 if operation is successfull + */ +extern uint32_t FB_DrawFilledRectangle( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 ) +{ + LcdColor_t *pFbBuffer, *pDestFbBuffer; + uint32_t dwY, blocks, bytes; + + /* Swap coordinates if necessary */ + CheckBoxCoordinates(&dwX1, &dwY1, &dwX2, &dwY2); + + blocks = ((dwX2 - dwX1 + 1) / FB_COLOR_CACHE_SIZE); + bytes = ((dwX2 - dwX1 + 1) % FB_COLOR_CACHE_SIZE); + + /* Each row is sent by block to benefit from memcpy optimizations */ + pFbBuffer = &(gpBuffer[dwY1 * gucWidth + dwX1]); + for (dwY = dwY1; dwY <= dwY2; ++dwY) { + pDestFbBuffer = pFbBuffer; + while (blocks--) { + memcpy(pDestFbBuffer, gFbPixelCache, FB_COLOR_CACHE_SIZE * sizeof(LcdColor_t)); + pDestFbBuffer += FB_COLOR_CACHE_SIZE; + + } + memcpy(pDestFbBuffer, gFbPixelCache, bytes * sizeof(LcdColor_t)); + pFbBuffer += gucWidth; + } + + return 0; +} + +/** + * \brief Write several pixels pre-formatted in a bufer to FB. + * + * \param dwX1 X-coordinate of upper-left corner on LCD. + * \param dwY1 Y-coordinate of upper-left corner on LCD. + * \param dwX2 X-coordinate of lower-right corner on LCD. + * \param dwY2 Y-coordinate of lower-right corner on LCD. + * \param pBuffer pixel buffer area (no constraint on alignment). + */ +extern uint32_t FB_DrawPicture( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2, const void *pBuffer ) +{ + LcdColor_t *pFbBuffer; + uint32_t dwY; + + /* Swap coordinates if necessary */ + CheckBoxCoordinates(&dwX1, &dwY1, &dwX2, &dwY2); + + pFbBuffer = &(gpBuffer[dwY1 * gucWidth + dwX1]); + for (dwY = dwY1; dwY <= dwY2; ++dwY) { + memcpy(pFbBuffer, pBuffer, (dwX2 - dwX1 + 1) * sizeof(LcdColor_t)); + pFbBuffer += gucWidth; + } + + return 0 ; +} + +/* + * \brief Draw a line on LCD, horizontal and vertical line are supported. + * + * \param dwX1 X-coordinate of line start. + * \param dwY1 Y-coordinate of line start. + * \param dwX2 X-coordinate of line end. + * \param dwY2 Y-coordinate of line end. + * + * \return 0 if operation is successful +*/ +extern uint32_t FB_DrawLine ( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 ) +{ + /* Optimize horizontal or vertical line drawing */ + if (( dwY1 == dwY2 ) || (dwX1 == dwX2)) { + FB_DrawFilledRectangle( dwX1, dwY1, dwX2, dwY2 ); + } + else { + DrawLineBresenham( dwX1, dwY1, dwX2, dwY2 ) ; + } + + return 0 ; +} + +/** + * \brief Draws a circle in FB, at the given coordinates. + * + * \param dwX X-coordinate of circle center. + * \param dwY Y-coordinate of circle center. + * \param dwR circle radius. + * + * \return 0 if operation is successful +*/ +extern uint32_t FB_DrawCircle( + uint32_t dwX, + uint32_t dwY, + uint32_t dwR) +{ + int32_t d; /* Decision Variable */ + uint32_t curX; /* Current X Value */ + uint32_t curY; /* Current Y Value */ + + if (dwR == 0) + return 0; + d = 3 - (dwR << 1); + curX = 0; + curY = dwR; + + while (curX <= curY) + { + FB_DrawPixel(dwX + curX, dwY + curY); + FB_DrawPixel(dwX + curX, dwY - curY); + FB_DrawPixel(dwX - curX, dwY + curY); + FB_DrawPixel(dwX - curX, dwY - curY); + FB_DrawPixel(dwX + curY, dwY + curX); + FB_DrawPixel(dwX + curY, dwY - curX); + FB_DrawPixel(dwX - curY, dwY + curX); + FB_DrawPixel(dwX - curY, dwY - curX); + + if (d < 0) { + d += (curX << 2) + 6; + } + else { + d += ((curX - curY) << 2) + 10; + curY--; + } + curX++; + } + return 0; +} + +/** + * \brief Draws a filled circle in FB, at the given coordinates. + * + * \param dwX X-coordinate of circle center. + * \param dwY Y-coordinate of circle center. + * \param dwR circle radius. + * + * \return 0 if operation is successful +*/ +extern uint32_t FB_DrawFilledCircle( uint32_t dwX, uint32_t dwY, uint32_t dwRadius) +{ + signed int d ; // Decision Variable + uint32_t dwCurX ; // Current X Value + uint32_t dwCurY ; // Current Y Value + uint32_t dwXmin, dwYmin; + + if (dwRadius == 0) + return 0; + d = 3 - (dwRadius << 1) ; + dwCurX = 0 ; + dwCurY = dwRadius ; + + while ( dwCurX <= dwCurY ) + { + dwXmin = (dwCurX > dwX) ? 0 : dwX-dwCurX; + dwYmin = (dwCurY > dwY) ? 0 : dwY-dwCurY; + FB_DrawFilledRectangle( dwXmin, dwYmin, dwX+dwCurX, dwYmin ) ; + FB_DrawFilledRectangle( dwXmin, dwY+dwCurY, dwX+dwCurX, dwY+dwCurY ) ; + dwXmin = (dwCurY > dwX) ? 0 : dwX-dwCurY; + dwYmin = (dwCurX > dwY) ? 0 : dwY-dwCurX; + FB_DrawFilledRectangle( dwXmin, dwYmin, dwX+dwCurY, dwYmin ) ; + FB_DrawFilledRectangle( dwXmin, dwY+dwCurX, dwX+dwCurY, dwY+dwCurX ) ; + + if ( d < 0 ) + { + d += (dwCurX << 2) + 6 ; + } + else + { + d += ((dwCurX - dwCurY) << 2) + 10; + dwCurY-- ; + } + + dwCurX++ ; + } + + return 0 ; +} + +/** +* Pixel color is set by the LCD_SetColor() function. +* This function is optimized using an sram buffer to transfer block instead of +* individual pixels in order to limit the number of SPI interrupts. +* \param dwX1 X-coordinate of upper-left corner on LCD. +* \param dwY1 Y-coordinate of upper-left corner on LCD. +* \param dwX2 X-coordinate of lower-right corner on LCD. +* \param dwY2 Y-coordinate of lower-right corner on LCD. +* +* \return 0 if operation is successfull +*/ +extern uint32_t FB_DrawRectangle( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 ) +{ + CheckBoxCoordinates(&dwX1, &dwY1, &dwX2, &dwY2); + + FB_DrawFilledRectangle( dwX1, dwY1, dwX2, dwY1 ) ; + FB_DrawFilledRectangle( dwX1, dwY2, dwX2, dwY2 ) ; + + FB_DrawFilledRectangle( dwX1, dwY1, dwX1, dwY2 ) ; + FB_DrawFilledRectangle( dwX2, dwY1, dwX2, dwY2 ) ; + + return 0 ; +} + + + diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/hamming.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/hamming.c new file mode 100644 index 00000000..4a4fc0c4 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/hamming.c @@ -0,0 +1,339 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, 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 disclaimer below. + * + * 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 "board.h" + +/*---------------------------------------------------------------------------- + * Internal function + *----------------------------------------------------------------------------*/ + +/** + * Counts and return the number of bits set to '1' in the given byte. + * \param byte Byte to count. + */ +static uint8_t CountBitsInByte(uint8_t byte) +{ + uint8_t count = 0; + + while (byte > 0) + { + if (byte & 1) + { + count++; + } + byte >>= 1; + } + + return count; +} + +/** + * Counts and return the number of bits set to '1' in the given hamming code. + * \param code Hamming code. + */ +static uint8_t CountBitsInCode256(uint8_t *code) +{ + return CountBitsInByte(code[0]) + CountBitsInByte(code[1]) + CountBitsInByte(code[2]); +} + +/** + * Calculates the 22-bit hamming code for a 256-bytes block of data. + * \param data Data buffer to calculate code for. + * \param code Pointer to a buffer where the code should be stored. + */ +static void Compute256(const uint8_t *data, uint8_t *code) +{ + uint32_t i; + uint8_t columnSum = 0; + uint8_t evenLineCode = 0; + uint8_t oddLineCode = 0; + uint8_t evenColumnCode = 0; + uint8_t oddColumnCode = 0; + + // Xor all bytes together to get the column sum; + // At the same time, calculate the even and odd line codes + for (i=0; i < 256; i++) + { + columnSum ^= data[i]; + + // If the xor sum of the byte is 0, then this byte has no incidence on + // the computed code; so check if the sum is 1. + if ((CountBitsInByte(data[i]) & 1) == 1) + { + // Parity groups are formed by forcing a particular index bit to 0 + // (even) or 1 (odd). + // Example on one byte: + // + // bits (dec) 7 6 5 4 3 2 1 0 + // (bin) 111 110 101 100 011 010 001 000 + // '---'---'---'----------. + // | + // groups P4' ooooooooooooooo eeeeeeeeeeeeeee P4 | + // P2' ooooooo eeeeeee ooooooo eeeeeee P2 | + // P1' ooo eee ooo eee ooo eee ooo eee P1 | + // | + // We can see that: | + // - P4 -> bit 2 of index is 0 --------------------' + // - P4' -> bit 2 of index is 1. + // - P2 -> bit 1 of index if 0. + // - etc... + // We deduce that a bit position has an impact on all even Px if + // the log2(x)nth bit of its index is 0 + // ex: log2(4) = 2, bit2 of the index must be 0 (-> 0 1 2 3) + // and on all odd Px' if the log2(x)nth bit of its index is 1 + // ex: log2(2) = 1, bit1 of the index must be 1 (-> 0 1 4 5) + // + // As such, we calculate all the possible Px and Px' values at the + // same time in two variables, evenLineCode and oddLineCode, such as + // evenLineCode bits: P128 P64 P32 P16 P8 P4 P2 P1 + // oddLineCode bits: P128' P64' P32' P16' P8' P4' P2' P1' + // + evenLineCode ^= (255 - i); + oddLineCode ^= i; + } + } + + // At this point, we have the line parities, and the column sum. First, We + // must caculate the parity group values on the column sum. + for (i=0; i < 8; i++) + { + if (columnSum & 1) + { + evenColumnCode ^= (7 - i); + oddColumnCode ^= i; + } + columnSum >>= 1; + } + + // Now, we must interleave the parity values, to obtain the following layout: + // Code[0] = Line1 + // Code[1] = Line2 + // Code[2] = Column + // Line = Px' Px P(x-1)- P(x-1) ... + // Column = P4' P4 P2' P2 P1' P1 PadBit PadBit + code[0] = 0; + code[1] = 0; + code[2] = 0; + + for (i=0; i < 4; i++) + { + code[0] <<= 2; + code[1] <<= 2; + code[2] <<= 2; + + // Line 1 + if ((oddLineCode & 0x80) != 0) + { + code[0] |= 2; + } + + if ((evenLineCode & 0x80) != 0) + { + code[0] |= 1; + } + + // Line 2 + if ((oddLineCode & 0x08) != 0) + { + code[1] |= 2; + } + + if ((evenLineCode & 0x08) != 0) + { + code[1] |= 1; + } + + // Column + if ((oddColumnCode & 0x04) != 0) + { + code[2] |= 2; + } + + if ((evenColumnCode & 0x04) != 0) + { + code[2] |= 1; + } + + oddLineCode <<= 1; + evenLineCode <<= 1; + oddColumnCode <<= 1; + evenColumnCode <<= 1; + } + + // Invert codes (linux compatibility) + code[0] = (~(uint32_t)code[0]); + code[1] = (~(uint32_t)code[1]); + code[2] = (~(uint32_t)code[2]); + + TRACE_DEBUG("Computed code = %02X %02X %02X\n\r", + code[0], code[1], code[2]); +} + +/** + * Verifies and corrects a 256-bytes block of data using the given 22-bits + * hamming code. + * + * \param data Data buffer to check. + * \param originalCode Hamming code to use for verifying the data. + * + * \return 0 if there is no error, otherwise returns a HAMMING_ERROR code. + */ +static uint8_t Verify256( uint8_t* pucData, const uint8_t* pucOriginalCode ) +{ + /* Calculate new code */ + uint8_t computedCode[3] ; + uint8_t correctionCode[3] ; + + Compute256( pucData, computedCode ) ; + + /* Xor both codes together */ + correctionCode[0] = computedCode[0] ^ pucOriginalCode[0] ; + correctionCode[1] = computedCode[1] ^ pucOriginalCode[1] ; + correctionCode[2] = computedCode[2] ^ pucOriginalCode[2] ; + + TRACE_DEBUG( "Correction code = %02X %02X %02X\n\r", correctionCode[0], correctionCode[1], correctionCode[2] ) ; + + // If all bytes are 0, there is no error + if ( (correctionCode[0] == 0) && (correctionCode[1] == 0) && (correctionCode[2] == 0) ) + { + return 0 ; + } + + /* If there is a single bit error, there are 11 bits set to 1 */ + if ( CountBitsInCode256( correctionCode ) == 11 ) + { + // Get byte and bit indexes + uint8_t byte ; + uint8_t bit ; + + byte = correctionCode[0] & 0x80; + byte |= (correctionCode[0] << 1) & 0x40; + byte |= (correctionCode[0] << 2) & 0x20; + byte |= (correctionCode[0] << 3) & 0x10; + + byte |= (correctionCode[1] >> 4) & 0x08; + byte |= (correctionCode[1] >> 3) & 0x04; + byte |= (correctionCode[1] >> 2) & 0x02; + byte |= (correctionCode[1] >> 1) & 0x01; + + bit = (correctionCode[2] >> 5) & 0x04; + bit |= (correctionCode[2] >> 4) & 0x02; + bit |= (correctionCode[2] >> 3) & 0x01; + + /* Correct bit */ + TRACE_DEBUG("Correcting byte #%d at bit %d\n\r", byte, bit ) ; + pucData[byte] ^= (1 << bit) ; + + return Hamming_ERROR_SINGLEBIT ; + } + + /* Check if ECC has been corrupted */ + if ( CountBitsInCode256( correctionCode ) == 1 ) + { + return Hamming_ERROR_ECC ; + } + /* Otherwise, this is a multi-bit error */ + else + { + return Hamming_ERROR_MULTIPLEBITS ; + } +} + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * Computes 3-bytes hamming codes for a data block whose size is multiple of + * 256 bytes. Each 256 bytes block gets its own code. + * \param data Data to compute code for. + * \param size Data size in bytes. + * \param code Codes buffer. + */ +void Hamming_Compute256x( const uint8_t *pucData, uint32_t dwSize, uint8_t* puCode ) +{ + TRACE_DEBUG("Hamming_Compute256x()\n\r"); + + while ( dwSize > 0 ) + { + Compute256( pucData, puCode ) ; + + pucData += 256; + puCode += 3; + dwSize -= 256; + } +} + +/** + * Verifies 3-bytes hamming codes for a data block whose size is multiple of + * 256 bytes. Each 256-bytes block is verified with its own code. + * + * \return 0 if the data is correct, Hamming_ERROR_SINGLEBIT if one or more + * block(s) have had a single bit corrected, or either Hamming_ERROR_ECC + * or Hamming_ERROR_MULTIPLEBITS. + * + * \param data Data buffer to verify. + * \param size Size of the data in bytes. + * \param code Original codes. + */ +uint8_t Hamming_Verify256x( uint8_t* pucData, uint32_t dwSize, const uint8_t* pucCode ) +{ + uint8_t error ; + uint8_t result = 0 ; + + TRACE_DEBUG( "Hamming_Verify256x()\n\r" ) ; + + while ( dwSize > 0 ) + { + error = Verify256( pucData, pucCode ) ; + + if ( error == Hamming_ERROR_SINGLEBIT ) + { + result = Hamming_ERROR_SINGLEBIT ; + } + else + { + if ( error ) + { + return error ; + } + } + + pucData += 256; + pucCode += 3; + dwSize -= 256; + } + + return result ; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/ili9325.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/ili9325.c new file mode 100644 index 00000000..1b55e249 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/ili9325.c @@ -0,0 +1,907 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implementation of ILI9325 driver. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ +#include "board.h" + +#include +#include + +#ifdef BOARD_LCD_ILI9325 + +/*---------------------------------------------------------------------------- + * Local variables + *----------------------------------------------------------------------------*/ + +/* Pixel cache used to speed up communication */ +#define LCD_DATA_CACHE_SIZE BOARD_LCD_WIDTH +static LcdColor_t gLcdPixelCache[LCD_DATA_CACHE_SIZE]; + +/*---------------------------------------------------------------------------- + * Export functions + *----------------------------------------------------------------------------*/ + + +/** + * \brief Write data to LCD Register. + * + * \param reg Register address. + * \param data Data to be written. + */ +static void LCD_WriteReg( uint8_t reg, uint16_t data ) +{ + LCD_IR() = 0; + LCD_IR() = reg; + LCD_D() = (data >> 8) & 0xFF; + LCD_D() = data & 0xFF; +} + +/** + * \brief Read data from LCD Register. + * + * \param reg Register address. + * + * \return Readed data. + */ +static uint16_t LCD_ReadReg( uint8_t reg ) +{ + uint16_t value; + + LCD_IR() = 0; + LCD_IR() = reg; + + value = LCD_D(); + value = (value << 8) | LCD_D(); + + return value; +} + + +/** + * \brief Prepare to write GRAM data. + */ +extern void LCD_WriteRAM_Prepare( void ) +{ + LCD_IR() = 0 ; + LCD_IR() = ILI9325_R22H ; /* Write Data to GRAM (R22h) */ +} + +/** + * \brief Write data to LCD GRAM. + * + * \param color 24-bits RGB color. + */ +extern void LCD_WriteRAM( LcdColor_t dwColor ) +{ + LCD_D() = ((dwColor >> 16) & 0xFF); + LCD_D() = ((dwColor >> 8) & 0xFF); + LCD_D() = (dwColor & 0xFF); +} + +/** + * \brief Write mutiple data in buffer to LCD controller. + * + * \param pBuf data buffer. + * \param size size in pixels. + */ +static void LCD_WriteRAMBuffer(const LcdColor_t *pBuf, uint32_t size) +{ + uint32_t addr ; + + for ( addr = 0 ; addr < size ; addr++ ) + { + LCD_WriteRAM(pBuf[addr]); + } +} + +/** + * \brief Prepare to read GRAM data. + */ +extern void LCD_ReadRAM_Prepare( void ) +{ + LCD_IR() = 0 ; + LCD_IR() = ILI9325_R22H ; /* Write Data to GRAM (R22h) */ +} + +/** + * \brief Read data to LCD GRAM. + * + * \note Because pixel data LCD GRAM is 18-bits, so convertion to RGB 24-bits + * will cause low color bit lose. + * + * \return color 24-bits RGB color. + */ +extern uint32_t LCD_ReadRAM( void ) +{ + uint8_t value[2]; + uint32_t color; + + value[0] = LCD_D(); /* dummy read */ + value[1] = LCD_D(); /* dummy read */ + value[0] = LCD_D(); /* data upper byte */ + value[1] = LCD_D(); /* data lower byte */ + + /* Convert RGB565 to RGB888 */ + /* For BGR format */ + color = ((value[0] & 0xF8)) | /* R */ + ((value[0] & 0x07) << 13) | ((value[1] & 0xE0) << 5) | /* G */ + ((value[1] & 0x1F) << 19); /* B */ + return color; +} + +/*---------------------------------------------------------------------------- + * Basic ILI9225 primitives + *----------------------------------------------------------------------------*/ + + +/** + * \brief Check Box coordinates. Return upper left and bottom right coordinates. + * + * \param pX1 X-coordinate of upper-left corner on LCD. + * \param pY1 Y-coordinate of upper-left corner on LCD. + * \param pX2 X-coordinate of lower-right corner on LCD. + * \param pY2 Y-coordinate of lower-right corner on LCD. + */ +static void CheckBoxCoordinates( uint32_t *pX1, uint32_t *pY1, uint32_t *pX2, uint32_t *pY2 ) +{ + uint32_t dw; + + if ( *pX1 >= BOARD_LCD_WIDTH ) + { + *pX1 = BOARD_LCD_WIDTH-1 ; + } + if ( *pX2 >= BOARD_LCD_WIDTH ) + { + *pX2 = BOARD_LCD_WIDTH-1 ; + } + if ( *pY1 >= BOARD_LCD_HEIGHT ) + { + *pY1 = BOARD_LCD_HEIGHT-1 ; + } + if ( *pY2 >= BOARD_LCD_HEIGHT ) + { + *pY2 = BOARD_LCD_HEIGHT-1 ; + } + if (*pX1 > *pX2) + { + dw = *pX1; + *pX1 = *pX2; + *pX2 = dw; + } + if (*pY1 > *pY2) + { + dw = *pY1; + *pY1 = *pY2; + *pY2 = dw; + } +} + +/** + * \brief Initialize the LCD controller. + */ +extern uint32_t LCD_Initialize( void ) +{ + uint16_t chipid ; + + /* Check ILI9325 chipid */ + chipid = LCD_ReadReg( ILI9325_R00H ) ; /* Driver Code Read (R00h) */ + if ( chipid != ILI9325_DEVICE_CODE ) + { + printf( "Read ILI9325 chip ID (0x%04x) error, skip initialization.\r\n", chipid ) ; + return 1 ; + } + + /* Turn off LCD */ + LCD_PowerDown() ; + + /* Start initial sequence */ + LCD_WriteReg(ILI9325_R10H, 0x0000); /* DSTB = LP = STB = 0 */ + LCD_WriteReg(ILI9325_R00H, 0x0001); /* start internal OSC */ + LCD_WriteReg(ILI9325_R01H, ILI9325_R01H_SS ) ; /* set SS and SM bit */ + LCD_WriteReg(ILI9325_R02H, 0x0700); /* set 1 line inversion */ + //LCD_WriteReg(ILI9325_R03H, 0xD030); /* set GRAM write direction and BGR=1. */ + LCD_WriteReg(ILI9325_R04H, 0x0000); /* Resize register */ + LCD_WriteReg(ILI9325_R08H, 0x0207); /* set the back porch and front porch */ + LCD_WriteReg(ILI9325_R09H, 0x0000); /* set non-display area refresh cycle ISC[3:0] */ + LCD_WriteReg(ILI9325_R0AH, 0x0000); /* FMARK function */ + LCD_WriteReg(ILI9325_R0CH, 0x0000); /* RGB interface setting */ + LCD_WriteReg(ILI9325_R0DH, 0x0000); /* Frame marker Position */ + LCD_WriteReg(ILI9325_R0FH, 0x0000); /* RGB interface polarity */ + + /* Power on sequence */ + LCD_WriteReg(ILI9325_R10H, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ + LCD_WriteReg(ILI9325_R11H, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */ + LCD_WriteReg(ILI9325_R12H, 0x0000); /* VREG1OUT voltage */ + LCD_WriteReg(ILI9325_R13H, 0x0000); /* VDV[4:0] for VCOM amplitude */ + Wait( 200 ) ; /* Dis-charge capacitor power voltage */ + LCD_WriteReg(ILI9325_R10H, 0x1290); /* SAP, BT[3:0], AP, DSTB, SLP, STB */ + LCD_WriteReg(ILI9325_R11H, 0x0227); /* DC1[2:0], DC0[2:0], VC[2:0] */ + Wait( 50 ) ; + LCD_WriteReg(ILI9325_R12H, 0x001B); /* Internal reference voltage= Vci; */ + Wait( 50 ) ; + LCD_WriteReg(ILI9325_R13H, 0x1100); /* Set VDV[4:0] for VCOM amplitude */ + LCD_WriteReg(ILI9325_R29H, 0x0019); /* Set VCM[5:0] for VCOMH */ + LCD_WriteReg(ILI9325_R2BH, 0x000D); /* Set Frame Rate */ + Wait( 50 ) ; + + /* Adjust the Gamma Curve */ + LCD_WriteReg(ILI9325_R30H, 0x0000); + LCD_WriteReg(ILI9325_R31H, 0x0204); + LCD_WriteReg(ILI9325_R32H, 0x0200); + LCD_WriteReg(ILI9325_R35H, 0x0007); + LCD_WriteReg(ILI9325_R36H, 0x1404); + LCD_WriteReg(ILI9325_R37H, 0x0705); + LCD_WriteReg(ILI9325_R38H, 0x0305); + LCD_WriteReg(ILI9325_R39H, 0x0707); + LCD_WriteReg(ILI9325_R3CH, 0x0701); + LCD_WriteReg(ILI9325_R3DH, 0x000e); + + LCD_SetDisplayPortrait( 0 ) ; + /* Vertical Scrolling */ + LCD_WriteReg( ILI9325_R61H, 0x0001 ) ; + LCD_WriteReg( ILI9325_R6AH, 0x0000 ) ; + + /* Partial Display Control */ + LCD_WriteReg(ILI9325_R80H, 0x0000); + LCD_WriteReg(ILI9325_R81H, 0x0000); + LCD_WriteReg(ILI9325_R82H, 0x0000); + LCD_WriteReg(ILI9325_R83H, 0x0000); + LCD_WriteReg(ILI9325_R84H, 0x0000); + LCD_WriteReg(ILI9325_R85H, 0x0000); + + /* Panel Control */ + LCD_WriteReg(ILI9325_R90H, 0x0010); + LCD_WriteReg(ILI9325_R92H, 0x0600); + LCD_WriteReg(ILI9325_R95H, 0x0110); + + LCD_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ; + LCD_SetCursor( 0, 0 ) ; + + return 0 ; +} + +/** + * \brief Turn on the LCD. + */ +extern void LCD_On( void ) +{ + /* Display Control 1 (R07h) */ + /* When BASEE = “1”, the base image is displayed. */ + /* GON and DTE Set the output level of gate driver G1 ~ G320 : Normal Display */ + /* D1=1 D0=1 BASEE=1: Base image display Operate */ + LCD_WriteReg( ILI9325_R07H, ILI9325_R07H_BASEE + | ILI9325_R07H_GON | ILI9325_R07H_DTE + | ILI9325_R07H_D1 | ILI9325_R07H_D0 ) ; +} + + +/** + * \brief Turn off the LCD. + */ +extern void LCD_Off( void ) +{ + /* Display Control 1 (R07h) */ + /* When BASEE = “0”, no base image is displayed. */ + /* When the display is turned off by setting D[1:0] = “00”, the ILI9325 internal display + operation is halted completely. */ + /* PTDE1/0 = 0: turns off partial image. */ + LCD_WriteReg( ILI9325_R07H, 0x00 ) ; +} + +/** + * \brief Power down the LCD. + */ +extern void LCD_PowerDown( void ) +{ + /* Display Control 1 (R07h) */ + /* When BASEE = “0”, no base image is displayed. */ + /* GON and DTE Set the output level of gate driver G1 ~ G320 : Normal Display */ + /* D1=1 D0=1 BASEE=1: Base image display Operate */ + LCD_WriteReg( ILI9325_R07H, ILI9325_R07H_GON | ILI9325_R07H_DTE + | ILI9325_R07H_D1 | ILI9325_R07H_D0 ) ; +} + +/** + * \brief Convert 24 bit RGB color into 5-6-5 rgb color space. + * + * Initialize the LcdColor_t cache with the color pattern. + * \param x 24-bits RGB color. + * \return 0 for successfull operation. + */ +extern uint32_t LCD_SetColor( uint32_t dwRgb24Bits ) +{ + uint32_t i ; + + /* Fill the cache with selected color */ + for ( i = 0 ; i < LCD_DATA_CACHE_SIZE ; ++i ) + { + gLcdPixelCache[i] = dwRgb24Bits ; + } + + return 0; +} + +/** + * \brief Set cursor of LCD srceen. + * + * \param x X-coordinate of upper-left corner on LCD. + * \param y Y-coordinate of upper-left corner on LCD. + */ +extern void LCD_SetCursor( uint16_t x, uint16_t y ) +{ + /* GRAM Horizontal/Vertical Address Set (R20h, R21h) */ + LCD_WriteReg( ILI9325_R20H, x ) ; /* column */ + LCD_WriteReg( ILI9325_R21H, y ) ; /* row */ +} + +extern void LCD_SetWindow( uint32_t dwX, uint32_t dwY, uint32_t dwWidth, uint32_t dwHeight ) +{ + /* Horizontal and Vertical RAM Address Position (R50h, R51h, R52h, R53h) */ + + /* Set Horizontal Address Start Position */ + LCD_WriteReg( ILI9325_R50H, (uint16_t)dwX ) ; + + /* Set Horizontal Address End Position */ + LCD_WriteReg( ILI9325_R51H, (uint16_t)dwX+dwWidth-1 ) ; + + /* Set Vertical Address Start Position */ + LCD_WriteReg( ILI9325_R52H, (uint16_t)dwY ) ; + + /* Set Vertical Address End Position */ + LCD_WriteReg( ILI9325_R53H, (uint16_t)dwY+dwHeight-1 ) ; +} + +extern void LCD_SetDisplayLandscape( uint32_t dwRGB ) +{ + uint16_t dwValue ; + + /* When AM = “1”, the address is updated in vertical writing direction. */ + /* DFM Set the mode of transferring data to the internal RAM when TRI = “1”. */ + /* When TRI = “1”, data are transferred to the internal RAM in 8-bit x 3 transfers mode via the 8-bit interface. */ + /* Use the high speed write mode (HWM=1) */ + /* ORG = “1”: The original address “00000h” moves according to the I/D[1:0] setting. */ + /* I/D[1:0] = 00 Horizontal : decrement Vertical : decrement, AM=0:Horizontal */ + dwValue = ILI9325_R03H_AM | ILI9325_R03H_DFM | ILI9325_R03H_TRI | ILI9325_R03H_HWM | ILI9325_R03H_ORG ; + + if ( dwRGB == 0 ) + { + /* BGR=”1”: Swap the RGB data to BGR in writing into GRAM. */ + dwValue |= ILI9325_R03H_BGR ; + } + LCD_WriteReg( ILI9325_R03H, dwValue ) ; + + // LCD_WriteReg( ILI9325_R60H, (0x1d<<8)|0x00 ) ; /*Gate Scan Control */ + + LCD_SetWindow( 0, 0, BOARD_LCD_HEIGHT, BOARD_LCD_WIDTH ) ; +} + +extern void LCD_SetDisplayPortrait( uint32_t dwRGB ) +{ + uint16_t dwValue ; + + /* Use the high speed write mode (HWM=1) */ + /* When TRI = “1”, data are transferred to the internal RAM in 8-bit x 3 transfers mode via the 8-bit interface. */ + /* DFM Set the mode of transferring data to the internal RAM when TRI = “1”. */ + /* I/D[1:0] = 11 Horizontal : increment Vertical : increment, AM=0:Horizontal */ + dwValue = ILI9325_R03H_HWM | ILI9325_R03H_TRI | ILI9325_R03H_DFM | ILI9325_R03H_ID1 | ILI9325_R03H_ID0 ; + + if ( dwRGB == 0 ) + { + /* BGR=”1”: Swap the RGB data to BGR in writing into GRAM. */ + dwValue |= ILI9325_R03H_BGR ; + } + LCD_WriteReg( ILI9325_R03H, dwValue ) ; + /* Gate Scan Control (R60h, R61h, R6Ah) */ + /* SCN[5:0] = 00 */ + /* NL[5:0]: Sets the number of lines to drive the LCD at an interval of 8 lines. */ + LCD_WriteReg( ILI9325_R60H, ILI9325_R60H_GS|(0x27<<8)|0x00 ) ; +} + + +extern void LCD_VerticalScroll( uint16_t wY ) +{ + /* Gate Scan Control (R60h, R61h, R6Ah) */ + /* Enables the grayscale inversion of the image by setting REV=1. */ + /* VLE: Vertical scroll display enable bit */ + LCD_WriteReg( ILI9325_R61H, 3 ) ; + LCD_WriteReg( ILI9325_R6AH, wY ) ; +} + + +extern void LCD_SetPartialImage1( uint32_t dwDisplayPos, uint32_t dwStart, uint32_t dwEnd ) +{ + assert( dwStart <= dwEnd ) ; + + /* Partial Image 1 Display Position (R80h) */ + LCD_WriteReg( ILI9325_R80H, dwDisplayPos&0x1ff ) ; + /* Partial Image 1 RAM Start/End Address (R81h, R82h) */ + LCD_WriteReg( ILI9325_R81H, dwStart&0x1ff ) ; + LCD_WriteReg( ILI9325_R82H, dwEnd&0x1ff ) ; +} + +extern void LCD_SetPartialImage2( uint32_t dwDisplayPos, uint32_t dwStart, uint32_t dwEnd ) +{ + assert( dwStart <= dwEnd ) ; + + /* Partial Image 2 Display Position (R83h) */ + LCD_WriteReg( ILI9325_R83H, dwDisplayPos&0x1ff ) ; + /* Partial Image 2 RAM Start/End Address (R84h, R85h) */ + LCD_WriteReg( ILI9325_R84H, dwStart&0x1ff ) ; + LCD_WriteReg( ILI9325_R85H, dwEnd&0x1ff ) ; +} + +/** + * \brief Draw a LcdColor_t on LCD of given color. + * + * \param x X-coordinate of pixel. + * \param y Y-coordinate of pixel. + */ +extern uint32_t LCD_DrawPixel( uint32_t x, uint32_t y ) +{ + if( (x >= BOARD_LCD_WIDTH) || (y >= BOARD_LCD_HEIGHT) ) + { + return 1; + } + + /* Set cursor */ + LCD_SetCursor( x, y ); + + /* Prepare to write in GRAM */ + LCD_WriteRAM_Prepare(); + LCD_WriteRAM( *gLcdPixelCache ); + + return 0; +} + + + +extern void LCD_TestPattern( uint32_t dwRGB ) +{ + uint32_t dwLine ; + uint32_t dw ; + + LCD_SetWindow( 10, 10, 100, 20 ) ; + LCD_SetCursor( 10, 10 ) ; + LCD_WriteRAM_Prepare() ; + + for ( dwLine=0 ; dwLine < 20 ; dwLine++ ) + { + /* Draw White bar */ + for ( dw=0 ; dw < 20 ; dw++ ) + { + LCD_D() = 0xff ; + LCD_D() = 0xff ; + LCD_D() = 0xff ; + } + /* Draw Red bar */ + for ( dw=0 ; dw < 20 ; dw++ ) + { + if ( dwRGB == 0 ) + { + LCD_D() = 0xff ; + LCD_D() = 0x00 ; + LCD_D() = 0x00 ; + } + else + { + LCD_D() = 0x00 ; + LCD_D() = 0x00 ; + LCD_D() = 0xff ; + } + } + /* Draw Green bar */ + for ( dw=0 ; dw < 20 ; dw++ ) + { + LCD_D() = 0x00 ; + LCD_D() = 0xff ; + LCD_D() = 0x00 ; + } + /* Draw Blue bar */ + for ( dw=0 ; dw < 20 ; dw++ ) + { + if ( dwRGB == 0 ) + { + LCD_D() = 0x00 ; + LCD_D() = 0x00 ; + LCD_D() = 0xff ; + } + else + { + LCD_D() = 0xff ; + LCD_D() = 0x00 ; + LCD_D() = 0x00 ; + } + } + /* Draw Black bar */ + for ( dw=0 ; dw < 20 ; dw++ ) + { + LCD_D() = 0x00 ; + LCD_D() = 0x00 ; + LCD_D() = 0x00 ; + } + } + + LCD_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ; +} + + +/** + * \brief Write several pixels with the same color to LCD GRAM. + * + * LcdColor_t color is set by the LCD_SetColor() function. + * This function is optimized using an sram buffer to transfer block instead of + * individual pixels in order to limit the number of SPI interrupts. + * \param dwX1 X-coordinate of upper-left corner on LCD. + * \param dwY1 Y-coordinate of upper-left corner on LCD. + * \param dwX2 X-coordinate of lower-right corner on LCD. + * \param dwY2 Y-coordinate of lower-right corner on LCD. + */ +extern uint32_t LCD_DrawFilledRectangle( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 ) +{ + uint32_t size, blocks; + + /* Swap coordinates if necessary */ + CheckBoxCoordinates(&dwX1, &dwY1, &dwX2, &dwY2); + + /* Determine the refresh window area */ + /* Horizontal and Vertical RAM Address Position (R50h, R51h, R52h, R53h) */ + LCD_WriteReg(ILI9325_R50H, (uint16_t)dwX1); + LCD_WriteReg(ILI9325_R51H, (uint16_t)dwX2); + LCD_WriteReg(ILI9325_R52H, (uint16_t)dwY1); + LCD_WriteReg(ILI9325_R53H, (uint16_t)dwY2); + + /* Set cursor */ + LCD_SetCursor( dwX1, dwY1 ); + + /* Prepare to write in GRAM */ + LCD_WriteRAM_Prepare(); + + size = (dwX2 - dwX1 + 1) * (dwY2 - dwY1 + 1); + /* Send pixels blocks => one SPI IT / block */ + blocks = size / LCD_DATA_CACHE_SIZE; + while (blocks--) + { + LCD_WriteRAMBuffer(gLcdPixelCache, LCD_DATA_CACHE_SIZE); + } + /* Send remaining pixels */ + LCD_WriteRAMBuffer(gLcdPixelCache, size % LCD_DATA_CACHE_SIZE); + + /* Reset the refresh window area */ + /* Horizontal and Vertical RAM Address Position (R50h, R51h, R52h, R53h) */ + LCD_WriteReg(ILI9325_R50H, (uint16_t)0 ) ; + LCD_WriteReg(ILI9325_R51H, (uint16_t)BOARD_LCD_WIDTH - 1 ) ; + LCD_WriteReg(ILI9325_R52H, (uint16_t)0) ; + LCD_WriteReg(ILI9325_R53H, (uint16_t)BOARD_LCD_HEIGHT - 1 ) ; + + return 0 ; +} + +/** + * \brief Write several pixels pre-formatted in a bufer to LCD GRAM. + * + * \param dwX1 X-coordinate of upper-left corner on LCD. + * \param dwY1 Y-coordinate of upper-left corner on LCD. + * \param dwX2 X-coordinate of lower-right corner on LCD. + * \param dwY2 Y-coordinate of lower-right corner on LCD. + * \param pBuffer LcdColor_t buffer area. + */ +extern uint32_t LCD_DrawPicture( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2, const LcdColor_t *pBuffer ) +{ + uint32_t size, blocks; + LcdColor_t currentColor; + + /* Swap coordinates if necessary */ + CheckBoxCoordinates(&dwX1, &dwY1, &dwX2, &dwY2); + + /* Determine the refresh window area */ + /* Horizontal and Vertical RAM Address Position (R50h, R51h, R52h, R53h) */ + LCD_WriteReg(ILI9325_R50H, (uint16_t)dwX1 ) ; + LCD_WriteReg(ILI9325_R51H, (uint16_t)dwX2 ) ; + LCD_WriteReg(ILI9325_R52H, (uint16_t)dwY1 ) ; + LCD_WriteReg(ILI9325_R53H, (uint16_t)dwY2 ) ; + + /* Set cursor */ + LCD_SetCursor( dwX1, dwY1 ); + + /* Prepare to write in GRAM */ + LCD_WriteRAM_Prepare(); + + size = (dwX2 - dwX1 + 1) * (dwY2 - dwY1 + 1); + + /* Check if the buffer is within the SRAM */ + if ((IRAM_ADDR <= (uint32_t)pBuffer) && ((uint32_t)pBuffer < (IRAM_ADDR+IRAM_SIZE))) + { + LCD_WriteRAMBuffer(pBuffer, size); + } + /* If the buffer is not in SRAM, transfer it in SRAM first before transfer */ + else + { + /* Use color buffer as a cache */ + currentColor = gLcdPixelCache[0]; + /* Send pixels blocks => one SPI IT / block */ + blocks = size / LCD_DATA_CACHE_SIZE; + while (blocks--) + { + memcpy(gLcdPixelCache, pBuffer, LCD_DATA_CACHE_SIZE * sizeof(LcdColor_t)); + LCD_WriteRAMBuffer(gLcdPixelCache, LCD_DATA_CACHE_SIZE); + pBuffer += LCD_DATA_CACHE_SIZE; + } + /* Send remaining pixels */ + memcpy(gLcdPixelCache, pBuffer, (size % LCD_DATA_CACHE_SIZE) * sizeof(LcdColor_t)); + LCD_WriteRAMBuffer(gLcdPixelCache, size % LCD_DATA_CACHE_SIZE); + + /* Restore the color cache */ + LCD_SetColor(currentColor); + } + + /* Reset the refresh window area */ + /* Horizontal and Vertical RAM Address Position (R50h, R51h, R52h, R53h) */ + LCD_WriteReg(ILI9325_R50H, (uint16_t)0 ) ; + LCD_WriteReg(ILI9325_R51H, (uint16_t)BOARD_LCD_WIDTH - 1 ) ; + LCD_WriteReg(ILI9325_R52H, (uint16_t)0 ) ; + LCD_WriteReg(ILI9325_R53H, (uint16_t)BOARD_LCD_HEIGHT - 1 ) ; + + return 0 ; +} + +/* + * \brief Draw a line on LCD, which is not horizontal or vertical. + * + * \param x X-coordinate of line start. + * \param y Y-coordinate of line start. + * \param length line length. + * \param direction line direction: 0 - horizontal, 1 - vertical. + * \param color LcdColor_t color. + */ +static uint32_t DrawLineBresenham( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 ) +{ + int dx, dy ; + int i ; + int xinc, yinc, cumul ; + int x, y ; + + x = dwX1 ; + y = dwY1 ; + dx = dwX2 - dwX1 ; + dy = dwY2 - dwY1 ; + + xinc = ( dx > 0 ) ? 1 : -1 ; + yinc = ( dy > 0 ) ? 1 : -1 ; + dx = ( dx > 0 ) ? dx : -dx ; + dy = ( dy > 0 ) ? dy : -dy ; + + LCD_DrawPixel( x, y ) ; + + if ( dx > dy ) + { + cumul = dx / 2 ; + for ( i = 1 ; i <= dx ; i++ ) + { + x += xinc ; + cumul += dy ; + + if ( cumul >= dx ) + { + cumul -= dx ; + y += yinc ; + } + LCD_DrawPixel( x, y ) ; + } + } + else + { + cumul = dy / 2 ; + for ( i = 1 ; i <= dy ; i++ ) + { + y += yinc ; + cumul += dx ; + + if ( cumul >= dy ) + { + cumul -= dy ; + x += xinc ; + } + + LCD_DrawPixel( x, y ) ; + } + } + + return 0 ; +} + +/* + * \brief Draw a line on LCD, horizontal and vertical line are supported. + * + * \param dwX1 X-coordinate of line start. + * \param dwY1 Y-coordinate of line start. + * \param dwX2 X-coordinate of line end. + * \param dwY2 Y-coordinate of line end. + */ +extern uint32_t LCD_DrawLine ( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 ) +{ + /* Optimize horizontal or vertical line drawing */ + if (( dwY1 == dwY2 ) || (dwX1 == dwX2)) + { + LCD_DrawFilledRectangle( dwX1, dwY1, dwX2, dwY2 ); + } + else + { + DrawLineBresenham( dwX1, dwY1, dwX2, dwY2 ) ; + } + + return 0 ; +} + +/** + * \brief Draws a circle on LCD, at the given coordinates. + * + * \param dwX X-coordinate of circle center. + * \param dwY Y-coordinate of circle center. + * \param dwR circle radius. +*/ +extern uint32_t LCD_DrawCircle( uint32_t dwX, uint32_t dwY, uint32_t dwR ) +{ + int32_t d; /* Decision Variable */ + uint32_t curX; /* Current X Value */ + uint32_t curY; /* Current Y Value */ + + if (dwR == 0) + { + return 0; + } + d = 3 - (dwR << 1); + curX = 0; + curY = dwR; + + while (curX <= curY) + { + LCD_DrawPixel(dwX + curX, dwY + curY); + LCD_DrawPixel(dwX + curX, dwY - curY); + LCD_DrawPixel(dwX - curX, dwY + curY); + LCD_DrawPixel(dwX - curX, dwY - curY); + LCD_DrawPixel(dwX + curY, dwY + curX); + LCD_DrawPixel(dwX + curY, dwY - curX); + LCD_DrawPixel(dwX - curY, dwY + curX); + LCD_DrawPixel(dwX - curY, dwY - curX); + + if (d < 0) + { + d += (curX << 2) + 6; + } + else + { + d += ((curX - curY) << 2) + 10; + curY--; + } + curX++; + } + return 0; +} + +extern uint32_t LCD_DrawFilledCircle( uint32_t dwX, uint32_t dwY, uint32_t dwRadius) +{ + signed int d ; /* Decision Variable */ + uint32_t dwCurX ; /* Current X Value */ + uint32_t dwCurY ; /* Current Y Value */ + uint32_t dwXmin, dwYmin; + + if (dwRadius == 0) + { + return 0; + } + d = 3 - (dwRadius << 1) ; + dwCurX = 0 ; + dwCurY = dwRadius ; + + while ( dwCurX <= dwCurY ) + { + dwXmin = (dwCurX > dwX) ? 0 : dwX-dwCurX; + dwYmin = (dwCurY > dwY) ? 0 : dwY-dwCurY; + LCD_DrawFilledRectangle( dwXmin, dwYmin, dwX+dwCurX, dwYmin ) ; + LCD_DrawFilledRectangle( dwXmin, dwY+dwCurY, dwX+dwCurX, dwY+dwCurY ) ; + dwXmin = (dwCurY > dwX) ? 0 : dwX-dwCurY; + dwYmin = (dwCurX > dwY) ? 0 : dwY-dwCurX; + LCD_DrawFilledRectangle( dwXmin, dwYmin, dwX+dwCurY, dwYmin ) ; + LCD_DrawFilledRectangle( dwXmin, dwY+dwCurX, dwX+dwCurY, dwY+dwCurX ) ; + + if ( d < 0 ) + { + d += (dwCurX << 2) + 6 ; + } + else + { + d += ((dwCurX - dwCurY) << 2) + 10; + dwCurY-- ; + } + + dwCurX++ ; + } + + return 0 ; +} + +extern uint32_t LCD_DrawRectangle( uint32_t dwX1, uint32_t dwY1, uint32_t dwX2, uint32_t dwY2 ) +{ + CheckBoxCoordinates(&dwX1, &dwY1, &dwX2, &dwY2); + + LCD_DrawFilledRectangle( dwX1, dwY1, dwX2, dwY1 ) ; + LCD_DrawFilledRectangle( dwX1, dwY2, dwX2, dwY2 ) ; + + LCD_DrawFilledRectangle( dwX1, dwY1, dwX1, dwY2 ) ; + LCD_DrawFilledRectangle( dwX2, dwY1, dwX2, dwY2 ) ; + + return 0 ; +} + + +/** + * \brief Set the backlight of the LCD (AAT3155). + * + * \param level Backlight brightness level [1..16], 1 means maximum brightness. + */ +extern void LCD_SetBacklight (uint32_t level) +{ + uint32_t i; + const Pin pPins[] = {BOARD_BACKLIGHT_PIN}; + + /* Ensure valid level */ + level = (level < 1) ? 1 : level; + level = (level > 16) ? 16 : level; + + /* Enable pins */ + PIO_Configure(pPins, PIO_LISTSIZE(pPins)); + + /* Switch off backlight */ + PIO_Clear(pPins); + i = 600 * (BOARD_MCK / 1000000); /* wait for at least 500us */ + while(i--); + + /* Set new backlight level */ + for (i = 0; i < level; i++) + { + PIO_Clear(pPins); + PIO_Clear(pPins); + PIO_Clear(pPins); + + PIO_Set(pPins); + PIO_Set(pPins); + PIO_Set(pPins); + } +} + +#endif diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/iso7816_4.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/iso7816_4.c new file mode 100644 index 00000000..42560a0c --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/iso7816_4.c @@ -0,0 +1,611 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * \section Purpose + * + * ISO 7816 driver + * + * \section Usage + * + * Explanation on the usage of the code made available through the header file. + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "board.h" + +/*------------------------------------------------------------------------------ + * Definitions + *------------------------------------------------------------------------------*/ +/** Case for APDU commands*/ +#define CASE1 1 +#define CASE2 2 +#define CASE3 3 + +/** Flip flop for send and receive char */ +#define USART_SEND 0 +#define USART_RCV 1 + +#if !defined(BOARD_ISO7816_BASE_USART) + #define BOARD_ISO7816_BASE_USART USART1 + #define BOARD_ISO7816_ID_USART ID_USART1 +#endif + +/*----------------------------------------------------------------------------- + * Internal variables + *-----------------------------------------------------------------------------*/ +/** Variable for state of send and receive froom USART */ +static uint8_t StateUsartGlobal = USART_RCV; +/** Pin reset master card */ +static Pin st_pinIso7816RstMC; + +/*---------------------------------------------------------------------------- + * Internal functions + *----------------------------------------------------------------------------*/ + +/** + * Get a character from ISO7816 + * \param pCharToReceive Pointer for store the received char + * \return 0: if timeout else status of US_CSR + */ +static uint32_t ISO7816_GetChar( uint8_t *pCharToReceive ) +{ + uint32_t status; + uint32_t timeout=0; + + if( StateUsartGlobal == USART_SEND ) { + while((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_TXEMPTY) == 0) {} + BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK; + StateUsartGlobal = USART_RCV; + } + + /* Wait USART ready for reception */ + while( ((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_RXRDY) == 0) ) { + if(timeout++ > 12000 * (BOARD_MCK/1000000)) { + TRACE_DEBUG("TimeOut\n\r"); + return( 0 ); + } + } + + TRACE_DEBUG("T: %u\n\r", timeout); + + + /* At least one complete character has been received and US_RHR has not yet been read. */ + + /* Get a char */ + *pCharToReceive = ((BOARD_ISO7816_BASE_USART->US_RHR) & 0xFF); + + status = (BOARD_ISO7816_BASE_USART->US_CSR&(US_CSR_OVRE|US_CSR_FRAME| + US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK| + (1<<10))); + + if (status != 0 ) { + /* TRACE_DEBUG("R:0x%X\n\r", status); */ + TRACE_DEBUG("R:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_CSR); + TRACE_DEBUG("Nb:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_NER ); + BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA; + } + + /* Return status */ + return( status ); +} + + +/** + * Send a char to ISO7816 + * \param CharToSend char to be send + * \return status of US_CSR + */ +static uint32_t ISO7816_SendChar( uint8_t CharToSend ) +{ + uint32_t status; + + if( StateUsartGlobal == USART_RCV ) { + BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK; + StateUsartGlobal = USART_SEND; + } + + /* Wait USART ready for transmit */ + while((BOARD_ISO7816_BASE_USART->US_CSR & US_CSR_TXRDY) == 0) {} + /* There is no character in the US_THR */ + + /* Transmit a char */ + BOARD_ISO7816_BASE_USART->US_THR = CharToSend; + + status = (BOARD_ISO7816_BASE_USART->US_CSR&(US_CSR_OVRE|US_CSR_FRAME| + US_CSR_PARE|US_CSR_TIMEOUT|US_CSR_NACK| + (1<<10))); + + if (status != 0 ) { + TRACE_DEBUG("E:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_CSR); + TRACE_DEBUG("Nb:0x%X\n\r", BOARD_ISO7816_BASE_USART->US_NER ); + BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA; + } + + /* Return status */ + return( status ); +} + + +/** + * Iso 7816 ICC power on + */ +static void ISO7816_IccPowerOn( void ) +{ + /* Set RESET Master Card */ + PIO_Set(&st_pinIso7816RstMC); +} + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * Iso 7816 ICC power off + */ +void ISO7816_IccPowerOff( void ) +{ + /* Clear RESET Master Card */ + PIO_Clear(&st_pinIso7816RstMC); +} + +/** + * Transfert Block TPDU T=0 + * \param pAPDU APDU buffer + * \param pMessage Message buffer + * \param wLength Block length + * \return Message index + */ +uint16_t ISO7816_XfrBlockTPDU_T0(const uint8_t *pAPDU, + uint8_t *pMessage, + uint16_t wLength ) +{ + uint16_t NeNc; + uint16_t indexApdu = 4; + uint16_t indexMessage = 0; + uint8_t SW1 = 0; + uint8_t procByte; + uint8_t cmdCase; + + TRACE_DEBUG("pAPDU[0]=0x%X\n\r",pAPDU[0]); + TRACE_DEBUG("pAPDU[1]=0x%X\n\r",pAPDU[1]); + TRACE_DEBUG("pAPDU[2]=0x%X\n\r",pAPDU[2]); + TRACE_DEBUG("pAPDU[3]=0x%X\n\r",pAPDU[3]); + TRACE_DEBUG("pAPDU[4]=0x%X\n\r",pAPDU[4]); + TRACE_DEBUG("pAPDU[5]=0x%X\n\r",pAPDU[5]); + TRACE_DEBUG("wlength=%d\n\r",wLength); + + ISO7816_SendChar( pAPDU[0] ); /* CLA */ + ISO7816_SendChar( pAPDU[1] ); /* INS */ + ISO7816_SendChar( pAPDU[2] ); /* P1 */ + ISO7816_SendChar( pAPDU[3] ); /* P2 */ + ISO7816_SendChar( pAPDU[4] ); /* P3 */ + + /* Handle the four structures of command APDU */ + indexApdu = 4; + + if( wLength == 4 ) { + cmdCase = CASE1; + NeNc = 0; + } + else if( wLength == 5) { + cmdCase = CASE2; + NeNc = pAPDU[4]; /* C5 */ + if (NeNc == 0) { + NeNc = 256; + } + } + else if( wLength == 6) { + NeNc = pAPDU[4]; /* C5 */ + cmdCase = CASE3; + } + else if( wLength == 7) { + NeNc = pAPDU[4]; /* C5 */ + if( NeNc == 0 ) { + cmdCase = CASE2; + NeNc = (pAPDU[5]<<8)+pAPDU[6]; + } + else { + cmdCase = CASE3; + } + } + else { + NeNc = pAPDU[4]; /* C5 */ + if( NeNc == 0 ) { + cmdCase = CASE3; + NeNc = (pAPDU[5]<<8)+pAPDU[6]; + } + else { + cmdCase = CASE3; + } + } + + TRACE_DEBUG("CASE=0x%X NeNc=0x%X\n\r", cmdCase, NeNc); + + /* Handle Procedure Bytes */ + do { + ISO7816_GetChar(&procByte); + /* Handle NULL */ + if ( procByte == ISO_NULL_VAL ) { + TRACE_DEBUG("INS\n\r"); + continue; + } + /* Handle SW1 */ + else if ( ((procByte & 0xF0) ==0x60) || ((procByte & 0xF0) ==0x90) ) { + TRACE_DEBUG("SW1\n\r"); + SW1 = 1; + } + /* Handle INS */ + else if ( pAPDU[1] == procByte) { + TRACE_DEBUG("HdlINS\n\r"); + if (cmdCase == CASE2) { + /* receive data from card */ + do { + ISO7816_GetChar(&pMessage[indexMessage++]); + } while( 0 != --NeNc ); + } + else { + /* Send data */ + do { + ISO7816_SendChar(pAPDU[indexApdu++]); + } while( 0 != --NeNc ); + } + } + /* Handle INS ^ 0xff */ + else if ( pAPDU[1] == (procByte ^ 0xff)) { + TRACE_DEBUG("HdlINS+\n\r"); + if (cmdCase == CASE2) { + /* receive data from card */ + ISO7816_GetChar(&pMessage[indexMessage++]); + } + else { + ISO7816_SendChar(pAPDU[indexApdu++]); + } + NeNc--; + } + else { + /* ?? */ + TRACE_DEBUG("procByte=0x%X\n\r", procByte); + break; + } + } while (NeNc != 0); + + /* Status Bytes */ + if (SW1 == 0) { + ISO7816_GetChar(&pMessage[indexMessage++]); /* SW1 */ + } + else { + pMessage[indexMessage++] = procByte; + } + ISO7816_GetChar(&pMessage[indexMessage++]); /* SW2 */ + + return( indexMessage ); + +} + +/** + * Escape ISO7816 + */ +void ISO7816_Escape( void ) +{ + TRACE_DEBUG("For user, if needed\n\r"); +} + +/** + * Restart clock ISO7816 + */ +void ISO7816_RestartClock( void ) +{ + TRACE_DEBUG("ISO7816_RestartClock\n\r"); + BOARD_ISO7816_BASE_USART->US_BRGR = 13; +} + +/** + * Stop clock ISO7816 + */ +void ISO7816_StopClock( void ) +{ + TRACE_DEBUG("ISO7816_StopClock\n\r"); + BOARD_ISO7816_BASE_USART->US_BRGR = 0; +} + +/** + * T0 APDU + */ +void ISO7816_toAPDU( void ) +{ + TRACE_DEBUG("ISO7816_toAPDU\n\r"); + TRACE_DEBUG("Not supported at this time\n\r"); +} + +/** + * Answer To Reset (ATR) + * \param pAtr ATR buffer + * \param pLength Pointer for store the ATR length + */ +void ISO7816_Datablock_ATR( uint8_t* pAtr, uint8_t* pLength ) +{ + uint32_t i; + uint32_t j; + uint32_t y; + + *pLength = 0; + + /* Read ATR TS */ + ISO7816_GetChar(&pAtr[0]); + /* Read ATR T0 */ + ISO7816_GetChar(&pAtr[1]); + y = pAtr[1] & 0xF0; + i = 2; + + /* Read ATR Ti */ + while (y) { + + if (y & 0x10) { /* TA[i] */ + ISO7816_GetChar(&pAtr[i++]); + } + if (y & 0x20) { /* TB[i] */ + ISO7816_GetChar(&pAtr[i++]); + } + if (y & 0x40) { /* TC[i] */ + ISO7816_GetChar(&pAtr[i++]); + } + if (y & 0x80) { /* TD[i] */ + ISO7816_GetChar(&pAtr[i]); + y = pAtr[i++] & 0xF0; + } + else { + y = 0; + } + } + + /* Historical Bytes */ + y = pAtr[1] & 0x0F; + for( j=0; j < y; j++ ) { + ISO7816_GetChar(&pAtr[i++]); + } + + *pLength = i; + +} + +/** + * Set data rate and clock frequency + * \param dwClockFrequency ICC clock frequency in KHz. + * \param dwDataRate ICC data rate in bpd + */ +void ISO7816_SetDataRateandClockFrequency( uint32_t dwClockFrequency, uint32_t dwDataRate ) +{ + uint8_t ClockFrequency; + + /* Define the baud rate divisor register */ + /* CD = MCK / SCK */ + /* SCK = FIDI x BAUD = 372 x 9600 */ + /* BOARD_MCK */ + /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */ + BOARD_ISO7816_BASE_USART->US_BRGR = BOARD_MCK / (dwClockFrequency*1000); + + ClockFrequency = BOARD_MCK / BOARD_ISO7816_BASE_USART->US_BRGR; + + BOARD_ISO7816_BASE_USART->US_FIDI = (ClockFrequency)/dwDataRate; + +} + +/** + * Pin status for ISO7816 RESET + * \return 1 if the Pin RstMC is high; otherwise 0. + */ +uint8_t ISO7816_StatusReset( void ) +{ + return PIO_Get(&st_pinIso7816RstMC); +} + +/** + * cold reset + */ +void ISO7816_cold_reset( void ) +{ + volatile uint32_t i; + + /* tb: wait 400 cycles*/ + for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) { + } + + BOARD_ISO7816_BASE_USART->US_RHR; + BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK; + + ISO7816_IccPowerOn(); +} + +/** + * Warm reset + */ +void ISO7816_warm_reset( void ) +{ + volatile uint32_t i; + + ISO7816_IccPowerOff(); + + /* tb: wait 400 cycles */ + for( i=0; i<(120*(BOARD_MCK/1000000)); i++ ) { + } + + BOARD_ISO7816_BASE_USART->US_RHR; + BOARD_ISO7816_BASE_USART->US_CR = US_CR_RSTSTA | US_CR_RSTIT | US_CR_RSTNACK; + + ISO7816_IccPowerOn(); +} + +/** + * Decode ATR trace + * \param pAtr pointer on ATR buffer + */ +void ISO7816_Decode_ATR( uint8_t* pAtr ) +{ + uint32_t i; + uint32_t j; + uint32_t y; + uint8_t offset; + + printf("\n\r"); + printf("ATR: Answer To Reset:\n\r"); + printf("TS = 0x%X Initial character ",pAtr[0]); + if( pAtr[0] == 0x3B ) { + + printf("Direct Convention\n\r"); + } + else { + if( pAtr[0] == 0x3F ) { + + printf("Inverse Convention\n\r"); + } + else { + printf("BAD Convention\n\r"); + } + } + + printf("T0 = 0x%X Format caracter\n\r",pAtr[1]); + printf(" Number of historical bytes: K = %d\n\r", pAtr[1]&0x0F); + printf(" Presence further interface byte:\n\r"); + if( pAtr[1]&0x80 ) { + printf("TA "); + } + if( pAtr[1]&0x40 ) { + printf("TB "); + } + if( pAtr[1]&0x20 ) { + printf("TC "); + } + if( pAtr[1]&0x10 ) { + printf("TD "); + } + if( pAtr[1] != 0 ) { + printf(" present\n\r"); + } + + i = 2; + y = pAtr[1] & 0xF0; + + /* Read ATR Ti */ + offset = 1; + while (y) { + + if (y & 0x10) { /* TA[i] */ + printf("TA[%d] = 0x%X ", offset, pAtr[i]); + if( offset == 1 ) { + printf("FI = %d ", (pAtr[i]>>8)); + printf("DI = %d", (pAtr[i]&0x0F)); + } + printf("\n\r"); + i++; + } + if (y & 0x20) { /* TB[i] */ + printf("TB[%d] = 0x%X\n\r", offset, pAtr[i]); + i++; + } + if (y & 0x40) { /* TC[i] */ + printf("TC[%d] = 0x%X ", offset, pAtr[i]); + if( offset == 1 ) { + printf("Extra Guard Time: N = %d", pAtr[i]); + } + printf("\n\r"); + i++; + } + if (y & 0x80) { /* TD[i] */ + printf("TD[%d] = 0x%X\n\r", offset, pAtr[i]); + y = pAtr[i++] & 0xF0; + } + else { + y = 0; + } + offset++; + } + + /* Historical Bytes */ + printf("Historical bytes:\n\r"); + y = pAtr[1] & 0x0F; + for( j=0; j < y; j++ ) { + + printf(" 0x%X", pAtr[i]); + if( (pAtr[i] > 0x21) && (pAtr[i] < 0x7D) ) { /* ASCII */ + printf("(%c) ", pAtr[i]); + } + i++; + } + printf("\n\r\n\r"); + +} + +/** Initializes a ISO driver + * \param pPinIso7816RstMC Pin ISO 7816 Rst MC + */ +void ISO7816_Init( const Pin pPinIso7816RstMC ) +{ + TRACE_DEBUG("ISO_Init\n\r"); + + /* Pin ISO7816 initialize */ + st_pinIso7816RstMC = pPinIso7816RstMC; + + USART_Configure( BOARD_ISO7816_BASE_USART, + US_MR_USART_MODE_IS07816_T_0 + | US_MR_USCLKS_MCK + | US_MR_NBSTOP_1_BIT + | US_MR_PAR_EVEN + | US_MR_CHRL_8_BIT + | US_MR_CLKO + | (3<<24), /* MAX_ITERATION */ + 1, + 0); + + /* Configure USART */ + PMC_EnablePeripheral(BOARD_ISO7816_ID_USART); + /* Disable interrupts */ + BOARD_ISO7816_BASE_USART->US_IDR = (uint32_t) -1; + + BOARD_ISO7816_BASE_USART->US_FIDI = 372; /* by default */ + /* Define the baud rate divisor register */ + /* CD = MCK / SCK */ + /* SCK = FIDI x BAUD = 372 x 9600 */ + /* BOARD_MCK */ + /* CD = MCK/(FIDI x BAUD) = 48000000 / (372x9600) = 13 */ + BOARD_ISO7816_BASE_USART->US_BRGR = BOARD_MCK / (372*9600); + + /* Write the Timeguard Register */ + BOARD_ISO7816_BASE_USART->US_TTGR = 5; + + USART_SetTransmitterEnabled(BOARD_ISO7816_BASE_USART, 1); + USART_SetReceiverEnabled(BOARD_ISO7816_BASE_USART, 1); + +} + diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcd_draw.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcd_draw.c new file mode 100644 index 00000000..2756365b --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcd_draw.c @@ -0,0 +1,405 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implementation of draw function on LCD, Include draw text, image + * and basic shapes (line, rectangle, circle). + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "board.h" + +#include +#include +#include + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Fills the given LCD buffer with a particular color. + * + * \param color Fill color. + */ +void LCDD_Fill( uint32_t dwColor ) +{ + uint32_t dw ; + + LCD_SetCursor( 0, 0 ) ; + LCD_WriteRAM_Prepare() ; + + for ( dw = BOARD_LCD_WIDTH * BOARD_LCD_HEIGHT; dw > 0; dw-- ) + { + LCD_WriteRAM( dwColor ) ; + } +} + +/** + * \brief Draw a pixel on LCD of given color. + * + * \param x X-coordinate of pixel. + * \param y Y-coordinate of pixel. + * \param color Pixel color. + */ +extern void LCDD_DrawPixel( uint32_t x, uint32_t y, uint32_t color ) +{ + LCD_SetCursor( x, y ) ; + LCD_WriteRAM_Prepare() ; + LCD_WriteRAM( color ) ; +} + +/** + * \brief Read a pixel from LCD. + * + * \param x X-coordinate of pixel. + * \param y Y-coordinate of pixel. + * + * \return color Readed pixel color. + */ +extern uint32_t LCDD_ReadPixel( uint32_t x, uint32_t y ) +{ + uint32_t color; + + LCD_SetCursor(x, y); + LCD_ReadRAM_Prepare(); + color = LCD_ReadRAM(); + + return color; +} + +/* + * \brief Draw a line on LCD, horizontal and vertical line are supported. + * + * \param x X-coordinate of line start. + * \param y Y-coordinate of line start. + * \param length line length. + * \param direction line direction: 0 - horizontal, 1 - vertical. + * \param color Pixel color. + */ +extern void LCDD_DrawLine( uint32_t x, uint32_t y, uint32_t length, uint32_t direction, uint32_t color ) +{ + uint32_t i = 0 ; + + LCD_SetCursor( x, y ) ; + + if ( direction == DIRECTION_HLINE ) + { + LCD_WriteRAM_Prepare() ; + for ( i = 0; i < length; i++ ) + { + LCD_WriteRAM( color ) ; + } + } + else + { + for ( i = 0; i < length; i++ ) + { + LCD_WriteRAM_Prepare() ; + LCD_WriteRAM( color ) ; + y++ ; + LCD_SetCursor( x, y ) ; + } + } +} + +/* + * \brief Draws a rectangle on LCD, at the given coordinates. + * + * \param x X-coordinate of upper-left rectangle corner. + * \param y Y-coordinate of upper-left rectangle corner. + * \param width Rectangle width in pixels. + * \param height Rectangle height in pixels. + * \param color Rectangle color. + */ +extern void LCDD_DrawRectangle( uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t color ) +{ + LCDD_DrawLine(x, y, width, DIRECTION_HLINE, color); + LCDD_DrawLine(x, (y + height), width, DIRECTION_HLINE, color); + + LCDD_DrawLine(x, y, height, DIRECTION_VLINE, color); + LCDD_DrawLine((x + width), y, height, DIRECTION_VLINE, color); +} + +/* + * \brief Draws a rectangle with fill inside on LCD, at the given coordinates. + * + * \param x X-coordinate of upper-left rectangle corner. + * \param y Y-coordinate of upper-left rectangle corner. + * \param width Rectangle width in pixels. + * \param height Rectangle height in pixels. + * \param color Rectangle color. + */ +extern void LCDD_DrawRectangleWithFill( uint32_t dwX, uint32_t dwY, uint32_t dwWidth, uint32_t dwHeight, uint32_t dwColor ) +{ + uint32_t i ; + + LCD_SetWindow( dwX, dwY, dwWidth, dwHeight ) ; + LCD_SetCursor( dwX, dwY ) ; + LCD_WriteRAM_Prepare() ; + + for ( i = dwWidth * dwHeight; i > 0; i-- ) + { + LCD_WriteRAM( dwColor ) ; + } + LCD_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ; + LCD_SetCursor( 0, 0 ) ; +} + +/** + * \brief Draws a circle on LCD, at the given coordinates. + * + * \param x X-coordinate of circle center. + * \param y Y-coordinate of circle center. + * \param r circle radius. + * \param color circle color. + */ +extern void LCDD_DrawCircle( uint32_t x, uint32_t y, uint32_t r, uint32_t color ) +{ + signed int d; /* Decision Variable */ + uint32_t curX; /* Current X Value */ + uint32_t curY; /* Current Y Value */ + + d = 3 - (r << 1); + curX = 0; + curY = r; + + while (curX <= curY) + { + LCDD_DrawPixel(x + curX, y + curY, color); + LCDD_DrawPixel(x + curX, y - curY, color); + LCDD_DrawPixel(x - curX, y + curY, color); + LCDD_DrawPixel(x - curX, y - curY, color); + LCDD_DrawPixel(x + curY, y + curX, color); + LCDD_DrawPixel(x + curY, y - curX, color); + LCDD_DrawPixel(x - curY, y + curX, color); + LCDD_DrawPixel(x - curY, y - curX, color); + + if (d < 0) { + d += (curX << 2) + 6; + } + else { + d += ((curX - curY) << 2) + 10; + curY--; + } + curX++; + } +} + +/** + * \brief Draws a string inside a LCD buffer, at the given coordinates. Line breaks + * will be honored. + * + * \param x X-coordinate of string top-left corner. + * \param y Y-coordinate of string top-left corner. + * \param pString String to display. + * \param color String color. + */ +extern void LCDD_DrawString( uint32_t x, uint32_t y, const uint8_t *pString, uint32_t color ) +{ + uint32_t xorg = x ; + + while ( *pString != 0 ) + { + if ( *pString == '\n' ) + { + y += gFont.height + 2 ; + x = xorg ; + } + else + { + LCDD_DrawChar( x, y, *pString, color ) ; + x += gFont.width + 2 ; + } + + pString++ ; + } +} + +/** + * \brief Draws a string inside a LCD buffer, at the given coordinates + * with given background color. Line breaks will be honored. + * + * \param x X-coordinate of string top-left corner. + * \param y Y-coordinate of string top-left corner. + * \param pString String to display. + * \param fontColor String color. + * \param bgColor Background color. + */ +extern void LCDD_DrawStringWithBGColor( uint32_t x, uint32_t y, const char *pString, uint32_t fontColor, uint32_t bgColor ) +{ + unsigned xorg = x; + + while ( *pString != 0 ) + { + if ( *pString == '\n' ) + { + y += gFont.height + 2 ; + x = xorg ; + } + else + { + LCDD_DrawCharWithBGColor( x, y, *pString, fontColor, bgColor ) ; + x += gFont.width + 2; + } + + pString++; + } +} + +/** + * \brief Returns the width & height in pixels that a string will occupy on the screen + * if drawn using LCDD_DrawString. + * + * \param pString String. + * \param pWidth Pointer for storing the string width (optional). + * \param pHeight Pointer for storing the string height (optional). + * + * \return String width in pixels. + */ +extern void LCDD_GetStringSize( const uint8_t *pString, uint32_t *pWidth, uint32_t *pHeight ) +{ + uint32_t width = 0; + uint32_t height = gFont.height; + + while ( *pString != 0 ) + { + if ( *pString == '\n' ) + { + height += gFont.height + 2 ; + } + else + { + width += gFont.width + 2 ; + } + + pString++ ; + } + + if ( width > 0 ) + { + width -= 2; + } + + if ( pWidth != NULL ) + { + *pWidth = width; + } + + if ( pHeight != NULL ) + { + *pHeight = height ; + } +} + +/* + * \brief Draw a raw image at given position on LCD. + * + * \param x X-coordinate of image start. + * \param y Y-coordinate of image start. + * \param pImage Image buffer. + * \param width Image width. + * \param height Image height. + */ +void LCDD_DrawImage( uint32_t dwX, uint32_t dwY, const uint8_t *pImage, uint32_t dwWidth, uint32_t dwHeight ) +{ + uint32_t dwCursor ; + + LCD_SetWindow( dwX, dwY, dwWidth, dwHeight ) ; + LCD_SetCursor( dwX, dwY ) ; + LCD_WriteRAM_Prepare() ; + + for ( dwCursor=dwWidth*dwHeight; dwCursor != 0; dwCursor-- ) + { + LCD_D() = *pImage++ ; + LCD_D() = *pImage++ ; + LCD_D() = *pImage++ ; + } + + LCD_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ; +} + +/* + * \brief Draw a raw image at given position on LCD. + * + * \param dwX X-coordinate of image start. + * \param dwY Y-coordinate of image start. + * \param pGIMPImage Image data. + */ +void LCDD_DrawGIMPImage( uint32_t dwX, uint32_t dwY, const SGIMPImage* pGIMPImage ) +{ + uint32_t dw ; + register uint32_t dwLength ; + uint8_t* pucData ; + + // Draw raw RGB bitmap + LCD_SetWindow( dwX, dwY, pGIMPImage->dwWidth, pGIMPImage->dwHeight ) ; + LCD_SetCursor( dwX, dwY ) ; + + LCD_WriteRAM_Prepare() ; + + dwLength = pGIMPImage->dwWidth*pGIMPImage->dwHeight ; + pucData = pGIMPImage->pucPixel_data ; + for ( dw=0; dw < dwLength; dw++ ) + { + LCD_D() = (*pucData++) ; + LCD_D() = (*pucData++) ; + LCD_D() = (*pucData++) ; + } + + LCD_SetWindow( 0, 0, BOARD_LCD_WIDTH, BOARD_LCD_HEIGHT ) ; +} + +/* + * \brief Clear a window with an color. + * + * \param dwX X-coordinate of the window. + * \param dwY Y-coordinate of the window. + * \param dwWidth window width. + * \param dwHeight window height. + * \param dwColor background color + */ +extern void LCDD_ClearWindow( uint32_t dwX, uint32_t dwY, uint32_t dwWidth, uint32_t dwHeight, uint32_t dwColor ) +{ + uint32_t dw ; + + LCD_SetCursor( dwX, dwY) ; + LCD_WriteRAM_Prepare() ; + + for ( dw = dwWidth * dwHeight; dw > 0; dw-- ) + { + LCD_WriteRAM( dwColor ) ; + } +} diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcd_font.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcd_font.c new file mode 100644 index 00000000..a3a2be0b --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcd_font.c @@ -0,0 +1,133 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implementation of draw font on LCD. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "board.h" + +#include +#include + +/*---------------------------------------------------------------------------- + * Local variables + *----------------------------------------------------------------------------*/ + +/** Global variable describing the font being instancied. */ +const Font gFont = {10, 14}; + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Draws an ASCII character on LCD. + * + * \param x X-coordinate of character upper-left corner. + * \param y Y-coordinate of character upper-left corner. + * \param c Character to output. + * \param color Character color. + */ +extern void LCDD_DrawChar( uint32_t x, uint32_t y, uint8_t c, uint32_t color ) +{ + uint32_t row, col ; + + assert( (c >= 0x20) && (c <= 0x7F) ) ; + + for ( col = 0 ; col < 10 ; col++ ) + { + for ( row = 0 ; row < 8 ; row++ ) + { + if ( (pCharset10x14[((c - 0x20) * 20) + col * 2] >> (7 - row)) & 0x1 ) + { + LCDD_DrawPixel( x+col, y+row, color ) ; + } + } + + for (row = 0; row < 6; row++ ) + { + if ((pCharset10x14[((c - 0x20) * 20) + col * 2 + 1] >> (7 - row)) & 0x1) + { + LCDD_DrawPixel( x+col, y+row+8, color ) ; + } + } + } +} + +/** + * \brief Draws an ASCII character on LCD with given background color. + * + * \param x X-coordinate of character upper-left corner. + * \param y Y-coordinate of character upper-left corner. + * \param c Character to output. + * \param fontColor Character color. + * \param bgColor Background color. + */ +extern void LCDD_DrawCharWithBGColor( uint32_t x, uint32_t y, uint8_t c, uint32_t fontColor, uint32_t bgColor ) +{ + uint32_t row, col ; + + assert( (c >= 0x20) && (c <= 0x7F) ) ; + + for (col = 0; col < 10; col++) + { + for (row = 0 ; row < 8 ; row++) + { + if ( (pCharset10x14[((c - 0x20) * 20) + col * 2] >> (7 - row)) & 0x1 ) + { + LCDD_DrawPixel( x+col, y+row, fontColor ) ; + } + else + { + LCDD_DrawPixel( x+col, y+row, bgColor ) ; + } + } + + for ( row = 0 ; row < 6 ; row++ ) + { + if ( (pCharset10x14[((c - 0x20) * 20) + col * 2 + 1] >> (7 - row)) & 0x1 ) + { + LCDD_DrawPixel( x+col, y+row+8, fontColor ) ; + } + else + { + LCDD_DrawPixel( x+col, y+row+8, bgColor ) ; + } + } + } +} + diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcd_font10x14.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcd_font10x14.c new file mode 100644 index 00000000..a627355d --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcd_font10x14.c @@ -0,0 +1,233 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + + /** + * \file + * + * Font 10x14 table definition. + * + */ + +#include "board.h" + +/** Char set of font 10x14 */ +const uint8_t pCharset10x14[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xCC, + 0xFF, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0xC0, 0x0C, 0xC0, 0xFF, 0xFC, 0xFF, 0xFC, 0x0C, 0xC0, + 0x0C, 0xC0, 0xFF, 0xFC, 0xFF, 0xFC, 0x0C, 0xC0, 0x0C, 0xC0, + 0x0C, 0x60, 0x1E, 0x70, 0x3F, 0x30, 0x33, 0x30, 0xFF, 0xFC, + 0xFF, 0xFC, 0x33, 0x30, 0x33, 0xF0, 0x39, 0xE0, 0x18, 0xC0, + 0x60, 0x00, 0xF0, 0x0C, 0xF0, 0x3C, 0x60, 0xF0, 0x03, 0xC0, + 0x0F, 0x00, 0x3C, 0x18, 0xF0, 0x3C, 0xC0, 0x3C, 0x00, 0x18, + 0x3C, 0xF0, 0x7F, 0xF8, 0xC3, 0x1C, 0xC7, 0x8C, 0xCF, 0xCC, + 0xDC, 0xEC, 0x78, 0x78, 0x30, 0x30, 0x00, 0xFC, 0x00, 0xCC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0xEC, 0x00, + 0xF8, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x3F, 0xF0, 0x78, 0x78, + 0x60, 0x18, 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0x60, 0x18, + 0x78, 0x78, 0x3F, 0xF0, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x60, 0x0E, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x3F, 0xF8, + 0x3F, 0xF8, 0x03, 0x80, 0x07, 0xC0, 0x0E, 0xE0, 0x0C, 0x60, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x3F, 0xF0, + 0x3F, 0xF0, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x00, 0x44, 0x00, 0xEC, 0x00, 0xF8, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x00, 0x18, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0, + 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0xFC, 0xC1, 0xCC, 0xC3, 0x8C, + 0xC7, 0x0C, 0xCE, 0x0C, 0xFC, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x0C, 0x70, 0x0C, 0xFF, 0xFC, + 0xFF, 0xFC, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x0C, 0x70, 0x1C, 0xE0, 0x3C, 0xC0, 0x7C, 0xC0, 0xEC, + 0xC1, 0xCC, 0xC3, 0x8C, 0xE7, 0x0C, 0x7E, 0x0C, 0x3C, 0x0C, + 0x30, 0x30, 0x70, 0x38, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C, + 0xC3, 0x0C, 0xC3, 0x0C, 0xE3, 0x1C, 0x7F, 0xF8, 0x3C, 0xF0, + 0x03, 0xC0, 0x07, 0xC0, 0x0E, 0xC0, 0x1C, 0xC0, 0x38, 0xC0, + 0x70, 0xC0, 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0xC0, 0x00, 0xC0, + 0xFC, 0x30, 0xFC, 0x38, 0xCC, 0x1C, 0xCC, 0x0C, 0xCC, 0x0C, + 0xCC, 0x0C, 0xCC, 0x0C, 0xCE, 0x1C, 0xC7, 0xF8, 0xC3, 0xF0, + 0x3F, 0xF0, 0x7F, 0xF8, 0xE3, 0x1C, 0xC3, 0x0C, 0xC3, 0x0C, + 0xC3, 0x0C, 0xC3, 0x0C, 0xE3, 0x9C, 0x71, 0xF8, 0x30, 0xF0, + 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC3, 0xFC, + 0xC7, 0xFC, 0xCE, 0x00, 0xDC, 0x00, 0xF8, 0x00, 0xF0, 0x00, + 0x3C, 0xF0, 0x7F, 0xF8, 0xE7, 0x9C, 0xC3, 0x0C, 0xC3, 0x0C, + 0xC3, 0x0C, 0xC3, 0x0C, 0xE7, 0x9C, 0x7F, 0xF8, 0x3C, 0xF0, + 0x3C, 0x00, 0x7E, 0x00, 0xE7, 0x0C, 0xC3, 0x0C, 0xC3, 0x1C, + 0xC3, 0x38, 0xC3, 0x70, 0xE7, 0xE0, 0x7F, 0xC0, 0x3F, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x60, 0x3C, 0xF0, + 0x3C, 0xF0, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x44, 0x3C, 0xEC, + 0x3C, 0xF8, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x0F, 0xC0, 0x1C, 0xE0, + 0x38, 0x70, 0x70, 0x38, 0xE0, 0x1C, 0xC0, 0x0C, 0x00, 0x00, + 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, + 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, + 0x00, 0x00, 0xC0, 0x0C, 0xE0, 0x1C, 0x70, 0x38, 0x38, 0x70, + 0x1C, 0xE0, 0x0F, 0xC0, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xC0, 0x00, 0xC1, 0xEC, + 0xC3, 0xEC, 0xC3, 0x00, 0xE6, 0x00, 0x7E, 0x00, 0x3C, 0x00, + 0x30, 0xF0, 0x71, 0xF8, 0xE3, 0x9C, 0xC3, 0x0C, 0xC3, 0xFC, + 0xC3, 0xFC, 0xC0, 0x0C, 0xE0, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0, + 0x3F, 0xFC, 0x7F, 0xFC, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, + 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xC0, 0x7F, 0xFC, 0x3F, 0xFC, + 0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C, + 0xC3, 0x0C, 0xC3, 0x0C, 0xE7, 0x9C, 0x7F, 0xF8, 0x3C, 0xF0, + 0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C, + 0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, 0x70, 0x38, 0x30, 0x30, + 0xFF, 0xFC, 0xFF, 0xFC, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, + 0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0, + 0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C, + 0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, + 0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x00, 0xC3, 0x00, 0xC3, 0x00, + 0xC3, 0x00, 0xC3, 0x00, 0xC3, 0x00, 0xC0, 0x00, 0xC0, 0x00, + 0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C, + 0xC3, 0x0C, 0xC3, 0x0C, 0xE3, 0x1C, 0x73, 0xF8, 0x33, 0xF0, + 0xFF, 0xFC, 0xFF, 0xFC, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xFF, 0xFC, 0xFF, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xFF, 0xFC, + 0xFF, 0xFC, 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x38, 0xC0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C, + 0xC0, 0x1C, 0xFF, 0xF8, 0xFF, 0xF0, 0xC0, 0x00, 0xC0, 0x00, + 0xFF, 0xFC, 0xFF, 0xFC, 0x07, 0x80, 0x07, 0x80, 0x0F, 0xC0, + 0x1C, 0xE0, 0x38, 0x70, 0x70, 0x38, 0xE0, 0x1C, 0xC0, 0x0C, + 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, + 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, + 0xFF, 0xFC, 0xFF, 0xFC, 0x70, 0x00, 0x38, 0x00, 0x1F, 0x00, + 0x1F, 0x00, 0x38, 0x00, 0x70, 0x00, 0xFF, 0xFC, 0xFF, 0xFC, + 0xFF, 0xFC, 0xFF, 0xFC, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, + 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0xFF, 0xFC, 0xFF, 0xFC, + 0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C, + 0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0, + 0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x00, 0xC3, 0x00, 0xC3, 0x00, + 0xC3, 0x00, 0xC3, 0x00, 0xE7, 0x00, 0x7E, 0x00, 0x3C, 0x00, + 0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0xCC, + 0xC0, 0xEC, 0xC0, 0x7C, 0xE0, 0x38, 0x7F, 0xFC, 0x3F, 0xEC, + 0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x00, 0xC3, 0x80, 0xC3, 0x80, + 0xC3, 0xC0, 0xC3, 0xC0, 0xE7, 0x70, 0x7E, 0x3C, 0x3C, 0x1C, + 0x3C, 0x18, 0x7E, 0x1C, 0xE7, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C, + 0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x9C, 0xE1, 0xF8, 0x60, 0xF0, + 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xFF, 0xFC, + 0xFF, 0xFC, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, + 0xFF, 0xF0, 0xFF, 0xF8, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x0C, + 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x1C, 0xFF, 0xF8, 0xFF, 0xF0, + 0xFF, 0xC0, 0xFF, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, + 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0xFF, 0xE0, 0xFF, 0xC0, + 0xFF, 0xF0, 0xFF, 0xF8, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0xF8, + 0x00, 0xF8, 0x00, 0x3C, 0x00, 0x1C, 0xFF, 0xF8, 0xFF, 0xF0, + 0xF0, 0x3C, 0xF8, 0x7C, 0x1C, 0xE0, 0x0F, 0xC0, 0x07, 0x80, + 0x07, 0x80, 0x0F, 0xC0, 0x1C, 0xE0, 0xF8, 0x7C, 0xF0, 0x3C, + 0xFC, 0x00, 0xFE, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xFC, + 0x01, 0xFC, 0x03, 0x80, 0x07, 0x00, 0xFE, 0x00, 0xFC, 0x00, + 0xC0, 0x3C, 0xC0, 0x7C, 0xC0, 0xEC, 0xC1, 0xCC, 0xC3, 0x8C, + 0xC7, 0x0C, 0xCE, 0x0C, 0xDC, 0x0C, 0xF8, 0x0C, 0xF0, 0x0C, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFC, 0xC0, 0x0C, + 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x30, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x30, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, + 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x00, + 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0C, 0x00, + 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, + 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, + 0x38, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x06, 0x78, 0x0E, 0xFC, 0x0C, 0xCC, 0x0C, 0xCC, + 0x0C, 0xCC, 0x0C, 0xCC, 0x0E, 0xCC, 0x07, 0xFC, 0x03, 0xF8, + 0xFF, 0xFC, 0xFF, 0xFC, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, + 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x9C, 0x01, 0xF8, 0x00, 0xF0, + 0x03, 0xF0, 0x07, 0xF8, 0x0E, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0E, 0x1C, 0x07, 0x38, 0x03, 0x30, + 0x00, 0xF0, 0x01, 0xF8, 0x03, 0x9C, 0x03, 0x0C, 0x03, 0x0C, + 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0xFF, 0xFC, 0xFF, 0xFC, + 0x03, 0xF0, 0x07, 0xF8, 0x0E, 0xDC, 0x0C, 0xCC, 0x0C, 0xCC, + 0x0C, 0xCC, 0x0C, 0xCC, 0x0E, 0xDC, 0x07, 0xD8, 0x03, 0x90, + 0x00, 0x00, 0x03, 0x00, 0x3F, 0xFC, 0x7F, 0xFC, 0xE3, 0x00, + 0xE3, 0x00, 0x70, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x18, 0x07, 0x9C, 0x0F, 0xCC, 0x0C, 0xCC, 0x0C, 0xCC, + 0x0C, 0xCC, 0x0C, 0xCC, 0x0C, 0xDC, 0x0F, 0xF8, 0x07, 0xF0, + 0xFF, 0xFC, 0xFF, 0xFC, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, + 0x03, 0x00, 0x03, 0x80, 0x01, 0xFC, 0x00, 0xFC, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xFC, + 0x1B, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0C, + 0x00, 0x0C, 0x00, 0x1C, 0xCF, 0xF8, 0xCF, 0xF0, 0x00, 0x00, + 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0xE0, 0x01, 0xE0, + 0x03, 0xF0, 0x07, 0x38, 0x0E, 0x1C, 0x0C, 0x0C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xFF, 0xFC, + 0xFF, 0xFC, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0xFC, 0x0F, 0xFC, 0x0E, 0x00, 0x07, 0x00, 0x03, 0xC0, + 0x03, 0xC0, 0x07, 0x00, 0x0E, 0x00, 0x0F, 0xFC, 0x0F, 0xFC, + 0x0F, 0xFC, 0x0F, 0xFC, 0x03, 0x00, 0x07, 0x00, 0x0E, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x07, 0xFC, 0x03, 0xFC, + 0x03, 0xF0, 0x07, 0xF8, 0x0E, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0E, 0x1C, 0x07, 0xF8, 0x03, 0xF0, + 0x0F, 0xFC, 0x0F, 0xFC, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, + 0x0C, 0xC0, 0x0C, 0xC0, 0x0F, 0xC0, 0x07, 0x80, 0x03, 0x00, + 0x03, 0x00, 0x07, 0x80, 0x0F, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, + 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0F, 0xFC, 0x0F, 0xFC, + 0x0F, 0xFC, 0x0F, 0xFC, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, + 0x0C, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x00, + 0x03, 0x18, 0x07, 0x9C, 0x0F, 0xCC, 0x0C, 0xCC, 0x0C, 0xCC, + 0x0C, 0xCC, 0x0C, 0xCC, 0x0C, 0xFC, 0x0E, 0x78, 0x06, 0x30, + 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0xFF, 0xF0, 0xFF, 0xF8, + 0x0C, 0x1C, 0x0C, 0x1C, 0x0C, 0x38, 0x0C, 0x30, 0x00, 0x00, + 0x0F, 0xF0, 0x0F, 0xF8, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x0C, + 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x1C, 0x0F, 0xF8, 0x0F, 0xF0, + 0x0F, 0xC0, 0x0F, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, + 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x0F, 0xE0, 0x0F, 0xC0, + 0x0F, 0xF0, 0x0F, 0xF8, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0xF8, + 0x00, 0xF8, 0x00, 0x1C, 0x00, 0x1C, 0x0F, 0xF8, 0x0F, 0xF0, + 0x0C, 0x0C, 0x0E, 0x1C, 0x07, 0x38, 0x03, 0xF0, 0x01, 0xE0, + 0x01, 0xE0, 0x03, 0xF0, 0x07, 0x38, 0x0E, 0x1C, 0x0C, 0x0C, + 0x0C, 0x00, 0x0E, 0x00, 0x07, 0x0C, 0x03, 0x9C, 0x01, 0xF8, + 0x01, 0xF0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x0C, 0x00, + 0x0C, 0x0C, 0x0C, 0x1C, 0x0C, 0x3C, 0x0C, 0x7C, 0x0C, 0xEC, + 0x0D, 0xCC, 0x0F, 0x8C, 0x0F, 0x0C, 0x0E, 0x0C, 0x0C, 0x0C, + 0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x3F, 0xF0, 0x7C, 0xF8, + 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, + 0x03, 0x0C, 0x03, 0x0C, 0x3F, 0xFC, 0x7F, 0xFC, 0xE3, 0x0C, + 0xC3, 0x0C, 0xC0, 0x0C, 0xE0, 0x0C, 0x70, 0x0C, 0x30, 0x0C, + 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, + 0x7C, 0xF8, 0x3F, 0xF0, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, + 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, + 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, + 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC +} ; diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcdd.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcdd.c new file mode 100644 index 00000000..49172f24 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/lcdd.c @@ -0,0 +1,140 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implementation of LCD driver, Include LCD initialization, + * LCD on/off and LCD backlight control. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ +#include "board.h" + +#include + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Initializes the LCD controller. + * Configure SMC to access LCD controller at 64MHz MCK. + */ +extern void LCDD_Initialize( void ) +{ + const Pin pPins[] = {BOARD_LCD_PINS}; + Smc *pSmc = SMC; + + /* Enable pins */ + PIO_Configure(pPins, PIO_LISTSIZE(pPins)); + + /* Enable peripheral clock */ + PMC_EnablePeripheral( ID_SMC ) ; + + /* EBI SMC Configuration */ + pSmc->SMC_CS_NUMBER[1].SMC_SETUP = SMC_SETUP_NWE_SETUP(2) + | SMC_SETUP_NCS_WR_SETUP(2) + | SMC_SETUP_NRD_SETUP(2) + | SMC_SETUP_NCS_RD_SETUP(2); + + pSmc->SMC_CS_NUMBER[1].SMC_PULSE = SMC_PULSE_NWE_PULSE(4) + | SMC_PULSE_NCS_WR_PULSE(4) + | SMC_PULSE_NRD_PULSE(10) + | SMC_PULSE_NCS_RD_PULSE(10); + + pSmc->SMC_CS_NUMBER[1].SMC_CYCLE = SMC_CYCLE_NWE_CYCLE(10) + | SMC_CYCLE_NRD_CYCLE(22); + + pSmc->SMC_CS_NUMBER[1].SMC_MODE = SMC_MODE_READ_MODE + | SMC_MODE_WRITE_MODE + | SMC_MODE_DBW_8_BIT; + + /* Initialize LCD controller */ + LCD_Initialize() ; + + /* Initialize LCD controller */ + LCD_SetDisplayPortrait( 0 ) ; + + /* Set LCD backlight */ + LCDD_SetBacklight( 2 ) ; +} + +/** + * \brief Turn on the LCD. + */ +void LCDD_On(void) +{ + LCD_On(); +} + +/** + * \brief Turn off the LCD. + */ +void LCDD_Off(void) +{ + LCD_Off(); +} + +/** + * \brief Set the backlight of the LCD. + * + * \param level Backlight brightness level [1..16], 1 means maximum brightness. + */ +void LCDD_SetBacklight (uint32_t level) +{ + uint32_t i; + const Pin pPins[] = {BOARD_BACKLIGHT_PIN}; + + /* Ensure valid level */ + level = (level < 1) ? 1 : level; + level = (level > 16) ? 16 : level; + + /* Enable pins */ + PIO_Configure(pPins, PIO_LISTSIZE(pPins)); + + /* Switch off backlight */ + PIO_Clear(pPins); + i = 600 * (BOARD_MCK / 1000000); /* wait for at least 500us */ + while(i--); + + /* Set new backlight level */ + for (i = 0; i < level; i++) { + PIO_Clear(pPins); + PIO_Clear(pPins); + PIO_Clear(pPins); + + PIO_Set(pPins); + PIO_Set(pPins); + PIO_Set(pPins); + } +} diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/led.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/led.c new file mode 100644 index 00000000..1a88e45b --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/led.c @@ -0,0 +1,168 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "board.h" + +/*------------------------------------------------------------------------------ + * Local Variables + *------------------------------------------------------------------------------*/ + +#ifdef PINS_LEDS +static const Pin pinsLeds[] = { PINS_LEDS } ; +static const uint32_t numLeds = PIO_LISTSIZE( pinsLeds ) ; +#endif + +/*------------------------------------------------------------------------------ + * Global Functions + *------------------------------------------------------------------------------*/ + +/** + * Configures the pin associated with the given LED number. If the LED does + * not exist on the board, the function does nothing. + * \param led Number of the LED to configure. + * \return 1 if the LED exists and has been configured; otherwise 0. + */ +extern uint32_t LED_Configure( uint32_t dwLed ) +{ +#ifdef PINS_LEDS + // Check that LED exists + if ( dwLed >= numLeds) + { + + return 0; + } + + // Configure LED + return ( PIO_Configure( &pinsLeds[dwLed], 1 ) ) ; +#else + return 0 ; +#endif +} + +/** + * Turns the given LED on if it exists; otherwise does nothing. + * \param led Number of the LED to turn on. + * \return 1 if the LED has been turned on; 0 otherwise. + */ +extern uint32_t LED_Set( uint32_t dwLed ) +{ +#ifdef PINS_LEDS + /* Check if LED exists */ + if ( dwLed >= numLeds ) + { + return 0 ; + } + + /* Turn LED on */ + if ( pinsLeds[dwLed].type == PIO_OUTPUT_0 ) + { + + PIO_Set( &pinsLeds[dwLed] ) ; + } + else + { + PIO_Clear( &pinsLeds[dwLed] ) ; + } + + return 1 ; +#else + return 0 ; +#endif +} + +/** + * Turns a LED off. + * + * \param led Number of the LED to turn off. + * \return 1 if the LED has been turned off; 0 otherwise. + */ +extern uint32_t LED_Clear( uint32_t dwLed ) +{ +#ifdef PINS_LEDS + /* Check if LED exists */ + if ( dwLed >= numLeds ) + { + return 0 ; + } + + /* Turn LED off */ + if ( pinsLeds[dwLed].type == PIO_OUTPUT_0 ) + { + PIO_Clear( &pinsLeds[dwLed] ) ; + } + else + { + PIO_Set( &pinsLeds[dwLed] ) ; + } + + return 1 ; +#else + return 0 ; +#endif +} + +/** + * Toggles the current state of a LED. + * + * \param led Number of the LED to toggle. + * \return 1 if the LED has been toggled; otherwise 0. + */ +extern uint32_t LED_Toggle( uint32_t dwLed ) +{ +#ifdef PINS_LEDS + /* Check if LED exists */ + if ( dwLed >= numLeds ) + { + return 0 ; + } + + /* Toggle LED */ + if ( PIO_GetOutputDataStatus( &pinsLeds[dwLed] ) ) + { + PIO_Clear( &pinsLeds[dwLed] ) ; + } + else + { + PIO_Set( &pinsLeds[dwLed] ) ; + } + + return 1 ; +#else + return 0 ; +#endif +} + diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/math.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/math.c new file mode 100644 index 00000000..2121f02d --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/math.c @@ -0,0 +1,95 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, 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 disclaimer below. + * + * 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 "board.h" + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * Returns the minimum value between two integers. + * + * \param a First integer to compare. + * \param b Second integer to compare. + */ +extern uint32_t min( uint32_t dwA, uint32_t dwB ) +{ + if ( dwA < dwB ) + { + return dwA ; + } + else + { + return dwB ; + } +} + +/*------------------------------------------------------------------------------ + * Returns the absolute value of an integer. + * + * \param value Integer value. + * + * \note Do not call this function "abs", problem with gcc ! + */ +extern uint32_t absv( int32_t lValue ) +{ + if ( lValue < 0 ) + { + return -lValue ; + } + else + { + return lValue ; + } +} + +/*------------------------------------------------------------------------------ + * Computes and returns x power of y. + * + * \param x Value. + * \param y Power. + */ +extern uint32_t power( uint32_t dwX, uint32_t dwY ) +{ + uint32_t dwResult = 1 ; + + while ( dwY > 0 ) + { + dwResult *= dwX ; + dwY-- ; + } + + return dwResult ; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/rand.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/rand.c new file mode 100644 index 00000000..371ea187 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/rand.c @@ -0,0 +1,61 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +#include "board.h" + +/*------------------------------------------------------------------------------ + * Global Variables + *------------------------------------------------------------------------------*/ + +static uint32_t _dwRandNext=1 ; + +/*------------------------------------------------------------------------------ + * Exported Functions + *------------------------------------------------------------------------------*/ + +/** + * Initialize the seed for rand generator. + * + * \param seed rand initiation seed + */ +extern void srand( uint32_t dwSeed ) +{ + _dwRandNext = dwSeed ; +} + +/** + * Return a random number, maxinum assumed to be 65536 + */ +extern int rand( void ) +{ + _dwRandNext = _dwRandNext * 1103515245 + 12345 ; + + return (uint32_t)(_dwRandNext/131072) % 65536 ; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/retarget.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/retarget.c new file mode 100644 index 00000000..cf441e5c --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/retarget.c @@ -0,0 +1,86 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/* + * This file Configures the target-dependent low level functions for character I/O. + */ + +#include "board.h" +#include + +/* Disable semihosting */ +#pragma import(__use_no_semihosting_swi) + +struct __FILE { int handle;} ; +FILE __stdout; +FILE __stderr; + +/*------------------------------------------------------------------------------ + * Outputs a character. + *------------------------------------------------------------------------------*/ +int fputc(int ch, FILE *f) +{ + if ((f == stdout) || (f == stderr)) + { + UART_PutChar( ch ) ; + return ch ; + } + else + { + return EOF ; + } +} + +/*------------------------------------------------------------------------------ + * Returns the error status accumulated during file I/O. + *------------------------------------------------------------------------------*/ +int ferror( FILE *f ) +{ + return EOF ; +} + + +void _ttywrch( int ch ) +{ + UART_PutChar( (uint8_t)ch ) ; +} + +void _sys_exit(int return_code) +{ + while ( 1 ) ; /* endless loop */ +} + +/*------------------------------------------------------------------------------ + * Low level functions I/O for assert(). + *------------------------------------------------------------------------------*/ +void __assert_puts(const char *str) +{ + printf("%s", str); +} + diff --git a/sam3s_example/src/syscalls.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/syscalls.c similarity index 93% rename from sam3s_example/src/syscalls.c rename to sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/syscalls.c index 9b3bfec5..a71173c8 100644 --- a/sam3s_example/src/syscalls.c +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/syscalls.c @@ -111,18 +111,18 @@ extern int _read(int file, char *ptr, int len) extern int _write( int file, char *ptr, int len ) { - //int iIndex ; +/* + int iIndex ; // for ( ; *ptr != 0 ; ptr++ ) -/* for ( iIndex=0 ; iIndex < len ; iIndex++, ptr++ ) + for ( iIndex=0 ; iIndex < len ; iIndex++, ptr++ ) { UART_PutChar( *ptr ) ; } - return iIndex ; - */ - return 0; +*/ + return -1; } extern void _exit( int status ) diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/timetick.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/timetick.c new file mode 100644 index 00000000..f0f3c27c --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/timetick.c @@ -0,0 +1,117 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * Implement simple system tick usage. + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "board.h" + +/*---------------------------------------------------------------------------- + * Local variables + *----------------------------------------------------------------------------*/ + +/** Tick Counter united by ms */ +static volatile uint32_t _dwTickCount=0 ; + +/*---------------------------------------------------------------------------- + * Exported Functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Handler for Sytem Tick interrupt. + */ +extern void TimeTick_Increment( void ) +{ + _dwTickCount++ ; +} + +/** + * \brief Configures the SAM3 SysTick & reset tickCount. + * Systick interrupt handler will generates 1ms interrupt and increase a + * tickCount. + * \param new_mck Current master clock. + */ +extern uint32_t TimeTick_Configure( uint32_t new_mck ) +{ + _dwTickCount = 0 ; + return SysTick_Config( new_mck/1000 ) ; +} + +/** + * \brief Get current Tick Count, in ms. + */ +extern uint32_t GetTickCount( void ) +{ + return _dwTickCount ; +} + +/** + * \brief Sync Wait for several ms + */ +extern void Wait( volatile uint32_t dwMs ) +{ + uint32_t dwStart ; + uint32_t dwCurrent ; + + dwStart = _dwTickCount ; + do + { + dwCurrent = _dwTickCount ; + } while ( dwCurrent - dwStart < dwMs ) ; +} + +/** + * \brief Sync Sleep for several ms + */ +extern void Sleep( volatile uint32_t dwMs ) +{ + uint32_t dwStart ; + uint32_t dwCurrent ; + + dwStart = _dwTickCount ; + + do + { + dwCurrent = _dwTickCount ; + + if ( dwCurrent - dwStart > dwMs ) + { + break ; + } + + __WFI() ; + } while( 1 ) ; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/trace.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/trace.c new file mode 100644 index 00000000..362539df --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/trace.c @@ -0,0 +1,59 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, 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 disclaimer below. + * + * 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 "board.h" + +/*------------------------------------------------------------------------------ + * Internal variables + *------------------------------------------------------------------------------*/ + +/** Trace level can be set at applet initialization */ +#if !defined(NOTRACE) && (DYN_TRACES == 1) + uint32_t dwTraceLevel = TRACE_LEVEL ; +#endif + +/** + * Initializes the U(S)ART Console + * + * \param dwBaudRate U(S)ART baudrate. + * \param dwMCk Master clock frequency. + */ +extern void TRACE_CONFIGURE( uint32_t dwBaudRate, uint32_t dwMCk ) +{ + const Pin pinsUART0[] = { PINS_UART } ; + + PIO_Configure( pinsUART0, PIO_LISTSIZE( pinsUART0 ) ) ; + + UART_Configure( dwBaudRate, dwMCk ) ; +} diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/tsd_ads7843.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/tsd_ads7843.c new file mode 100644 index 00000000..54838ff0 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/tsd_ads7843.c @@ -0,0 +1,317 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implementation of ADS7843 driver. + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "board.h" + +#ifdef BOARD_TSC_ADS7843 + +#include +#include + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** Delay for pushbutton debouncing (the time-base is 10 ms). */ +#define DEBOUNCE_TIME 6 /* 10 * 6 = 60 ms */ + +/** Color of calibration points. */ +#define POINTS_COLOR 0x0000FF + +/** Size in pixels of calibration points. */ +#define POINTS_SIZE 4 + +/** Maximum difference in pixels between the test point and the measured point. */ +#define POINTS_MAX_ERROR 5 + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +/** pen state */ +typedef enum { + STATE_PEN_RELEASED = 0, + STATE_PEN_PRESSED = 1, + STATE_PEN_DEBOUNCE = 2 +} e_pen_state; + +/*---------------------------------------------------------------------------- + * Local variables + *----------------------------------------------------------------------------*/ + +/** Pins used by Interrupt Signal for Touch Screen Controller */ +static const Pin pinPenIRQ = PIN_TSC_IRQ; + +/** Global timestamp in milliseconds since start of application. */ +static volatile uint32_t timestamp = 0; + +/** last time when the pen is pressed on the touchscreen */ +static volatile uint32_t timePress = 0; + +/** last time when the pen is released */ +static volatile uint32_t timeRelease = 0; + +/** pen state */ +static volatile e_pen_state penState = STATE_PEN_RELEASED; + +/** Touch screen initiallized flag */ +static uint32_t tsInitFlag = 0; + +/*---------------------------------------------------------------------------- + * Local functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Timer handler for touch screen. Increments the timestamp counter. + * Determine the state "Pen Pressed" or "Pen Released". To change state, + * the penIRQ has to keep the same value during DEBOUNCE_TIME. + * + * \note External timer interrupt should call it per 10ms. + */ +void TSD_TimerHandler( void ) +{ + uint32_t data[2]; + uint32_t timeKeep; + static uint32_t point[2]; + + if (!tsInitFlag) return; + + timestamp++; + /* Get the current position of the pen if penIRQ has low value (pen pressed) */ + if ( PIO_Get(&pinPenIRQ) == 0 ) + { + /* Get the current position of the pressed pen */ + if ( TSDCom_IsCalibrationOk() ) + { + TSD_GetRawMeasurement(data); + TSDCom_InterpolateMeasurement(data, point); + } + + /* call the callback function */ + if ( penState == STATE_PEN_PRESSED ) + { + if(TSDCom_IsCalibrationOk()) + { + TSD_PenMoved(point[0], point[1]); + } + } + } + + /* Determine the pen state */ + if ( PIO_Get( &pinPenIRQ ) == 0 ) + { + /* reinit the last time when release */ + timeRelease = timestamp; + + if ( penState == STATE_PEN_DEBOUNCE ) + { + timeKeep = timestamp; + timeKeep -= timePress; + if(timeKeep > DEBOUNCE_TIME) + { + /* pen is pressed during an enough time : the state change */ + penState = STATE_PEN_PRESSED; + /* call the callback function */ + if ( TSDCom_IsCalibrationOk() ) + { + TSD_PenPressed(point[0], point[1]); + } + } + } + } + else + { + /* reinit the last time when release */ + timePress = timestamp; + + if ( penState == STATE_PEN_DEBOUNCE ) + { + timeKeep = timestamp; + timeKeep -= timeRelease; + if ( timeKeep > DEBOUNCE_TIME ) + { + /* pen is released during an enough time : the state change */ + penState = STATE_PEN_RELEASED; + /* call the callback function */ + if ( TSDCom_IsCalibrationOk() ) + { + TSD_PenReleased(point[0], point[1]); + } + } + } + } +} + +/** + * \breif Interrupt handler for Touchscreen. + */ +static void ISR_PenIRQ( void ) +{ + /* Check if the pen has been pressed */ + if ( !PIO_Get( &pinPenIRQ ) ) + { + if ( penState == STATE_PEN_RELEASED ) + { + timePress = timestamp; + penState = STATE_PEN_DEBOUNCE; + } + } + else + { + if ( penState == STATE_PEN_PRESSED ) + { + timeRelease = timestamp; + penState = STATE_PEN_DEBOUNCE; + } + } +} + +/** + * \brief Configure PENIRQ for interrupt. + * + * \note Be sure the PIO interrupt management has been initialized by + * PIO_InitializeInterrupts() before call this function. + */ +static void ConfigurePenIRQ( void ) +{ + /* Configure pios */ + PIO_Configure(&pinPenIRQ, PIO_LISTSIZE(pinPenIRQ)); + + /* Initialize interrupts */ + PIO_ConfigureIt(&pinPenIRQ, (void (*)(const Pin *)) ISR_PenIRQ); + + /* Enable the interrupt */ + PIO_EnableIt(&pinPenIRQ); +} + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Reads and store a touchscreen measurement in the provided array. + * + * \param pData Array where the measurements will be stored + */ +extern void TSD_GetRawMeasurement( uint32_t* pdwData ) +{ + /* Get the current position of the pressed pen */ + PIO_DisableIt( &pinPenIRQ ) ; + ADS7843_GetPosition( &pdwData[0], &pdwData[1] ) ; + PIO_EnableIt( &pinPenIRQ ) ; +} + +/** + * \brief Wait pen pressed. + */ +extern void TSD_WaitPenPressed( void ) +{ + /* Wait for touch & end of conversion */ + while ( penState != STATE_PEN_RELEASED ) ; + + /* while (penState != STATE_PEN_PRESSED); */ + while ( penState != STATE_PEN_PRESSED ) + { + } +} + +/** + * \brief Wait pen released. + */ +extern void TSD_WaitPenReleased( void ) +{ + /* Wait for contact loss */ + while (penState != STATE_PEN_PRESSED); + while (penState != STATE_PEN_RELEASED); +} + +/** + * \brief Do calibration. + * + * \return 1 if calibration is Ok, 0 else. + */ +extern uint8_t TSD_Calibrate( void ) +{ + uint8_t ret = 0 ; + + /* Calibration is done only once */ + if ( TSDCom_IsCalibrationOk() ) + { + return 1; + } + + /* Do calibration */ + ret = TSDCom_Calibrate(); + + return ret; +} + +/** + * \brief Initializes the touchscreen driver and starts the calibration process. When + * finished, the touchscreen is operational. + * + * \note Important: the LCD driver must have been initialized prior to calling this + * function. + */ +extern void TSD_Initialize( int8_t calEn ) +{ + ADS7843_Initialize(); + ConfigurePenIRQ(); + + tsInitFlag = 1; + + /* Calibration */ + if(calEn) { + while (!TSD_Calibrate()); + } +} + +/** + * \brief Stop the Touchscreen, disable interrupt. + */ +extern void TSD_Reset( void ) +{ + /* Disable SPI 0 */ + ADS7843_Reset() ; + + /* Disable the interrupt */ + PIO_DisableIt( &pinPenIRQ ) ; +} + +#endif /* #ifdef BOARD_TSC_ADS7843 */ diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/tsd_com.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/tsd_com.c new file mode 100644 index 00000000..5c41cf64 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/tsd_com.c @@ -0,0 +1,369 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implementation of touchscreen driver device irrelevance code. + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "board.h" + +#include +#include +#include + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** Size in pixels of calibration points. */ +#define POINTS_SIZE 4 +/** Maximum difference in pixels between the test point and the measured point. */ +#define POINTS_MAX_ERROR 8 + +/** Delay at the end of calibartion for result display */ +#define DELAY_RESULT_DISPLAY 4000000 + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +/** \brief Point used during the touchscreen calibration process. */ +typedef struct _CalibrationPoint { + + /** Coordinate of point along the X-axis of the screen. */ + uint32_t x; + /** Coordinate of point along the Y-axis of the screen. */ + uint32_t y; + /** Calibration data of point. */ + uint32_t data[2]; + +} CalibrationPoint; + +/*---------------------------------------------------------------------------- + * Variables + *----------------------------------------------------------------------------*/ + +/** indicates if the touch screen has been calibrated. */ +/** If not, Callback functions are not called. */ +static volatile uint8_t bCalibrationOk = 0; +/** Slope for interpoling touchscreen measurements along the X-axis. */ +static int32_t xSlope; +/** Slope for interpoling touchscreen measurements along the Y-axis. */ +static int32_t ySlope; + +/** Calibration points. */ +static CalibrationPoint calibrationPoints[] = { + + /* Top-left corner calibration point */ + { + BOARD_LCD_WIDTH / 10, + BOARD_LCD_HEIGHT / 10, + {0, 0} + }, + /* Top-right corner calibration point */ + { + BOARD_LCD_WIDTH - BOARD_LCD_WIDTH / 10, + BOARD_LCD_HEIGHT / 10, + {0, 0} + }, + /* Bottom-right corner calibration point */ + { + BOARD_LCD_WIDTH - BOARD_LCD_WIDTH / 10, + BOARD_LCD_HEIGHT - BOARD_LCD_HEIGHT / 10, + {0, 0} + }, + /* Bottom-left corner calibration point */ + { + BOARD_LCD_WIDTH / 10, + BOARD_LCD_HEIGHT - BOARD_LCD_HEIGHT / 10, + {0, 0} + } +}; + +/** Test point */ +static const CalibrationPoint testPoint = { + BOARD_LCD_WIDTH / 2, + BOARD_LCD_HEIGHT / 2, + {0, 0} +}; + +/*---------------------------------------------------------------------------- + * Local functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Display a calibration point on the given buffer. + * + * \param pPoint Calibration point to display. + */ +static void DrawCalibrationPoint(const CalibrationPoint *pPoint) +{ + LCDD_DrawRectangleWithFill(pPoint->x - POINTS_SIZE / 2, + pPoint->y - POINTS_SIZE / 2, + POINTS_SIZE, + POINTS_SIZE, + COLOR_RED); +} + +/** + * \brief Clears a calibration point from the given buffer. + * + * \param pPoint Calibration point to clear. + */ +static void ClearCalibrationPoint(const CalibrationPoint *pPoint) +{ + LCDD_DrawRectangleWithFill(pPoint->x - POINTS_SIZE / 2, + pPoint->y - POINTS_SIZE / 2, + POINTS_SIZE, + POINTS_SIZE, + COLOR_WHITE); +} + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Indicates if the calibration of the touch screen is Ok. + * + * \return 1 calibration Ok, 0 if not. + */ +uint8_t TSDCom_IsCalibrationOk(void) +{ + if (bCalibrationOk == 1) { + return 1; + } else { + return 0; + } +} + +/** + * \brief Interpolates the provided raw measurements using the previously calculated + * slope. The resulting x and y coordinates are stored in an array. + * + * \param pData Raw measurement data, as returned by TSD_GetRawMeasurement(). + * \param pPoint Array in which x and y will be stored. + */ +void TSDCom_InterpolateMeasurement(const uint32_t *pData, uint32_t *pPoint) +{ + pPoint[0] = calibrationPoints[0].x + - (((int32_t) calibrationPoints[0].data[0] - (int32_t) pData[0]) * 1024) + / xSlope; + + pPoint[1] = calibrationPoints[0].y + - (((int32_t) calibrationPoints[0].data[1] - (int32_t) pData[1]) * 1024) + / ySlope; + + if(pPoint[0] & 0x80000000) /* Is pPoint[0] negative ? */ + { + pPoint[0] = 0; + } + + if(pPoint[0] > BOARD_LCD_WIDTH) /* Is pPoint[0] bigger than the LCD width ? */ + { + pPoint[0] = BOARD_LCD_WIDTH; + } + + if(pPoint[1] & 0x80000000) /* Is pPoint[1] negative ? */ + { + pPoint[1] = 0; + } + + if(pPoint[1] > BOARD_LCD_HEIGHT) /* Is pPoint[1] bigger than the LCD width ? */ + { + pPoint[1] = BOARD_LCD_HEIGHT; + } +} + +/** + * \brief Performs the calibration process using the provided buffer to display + * information. + * + * \return True if calibration was successful; otherwise false. + */ +uint8_t TSDCom_Calibrate(void) +{ + volatile uint32_t i; /* to keep the tempo with gcc code optimisation */ + int32_t slope1, slope2; + CalibrationPoint measuredPoint; + uint8_t xOk, yOk; + int32_t xDiff, yDiff; + + /* Calibration setup */ + LCDD_Fill(COLOR_WHITE); + LCDD_DrawString(30, 50, (uint8_t *)"LCD calibration", COLOR_BLACK); + LCDD_DrawString(1, 140, (uint8_t *)"Touch the dots to\ncalibrate the screen", COLOR_DARKBLUE); + + /* Calibration points */ + for (i=0; i < 4; i++) { + + DrawCalibrationPoint(&calibrationPoints[i]); + + /* Wait for touch & end of conversion */ + TSD_WaitPenPressed(); + TSD_GetRawMeasurement(calibrationPoints[i].data); + ClearCalibrationPoint(&calibrationPoints[i]); + + /* Wait for contact loss */ + TSD_WaitPenReleased(); + } + + /** + * Calculate slopes using the calibration data + * Theory behind those calculations: + * - We suppose the touchscreen measurements are linear, so the following equations are true (simple + * linear regression) for any two 'a' and 'b' points of the screen: + * dx = (a.data[0] - b.data[0]) / (a.x - b.x) + * dy = (a.data[1] - b.data[1]) / (a.y - b.y) + * + * - We calculate dx and dy (called xslope and yslope here) using the calibration points. + * + * - We can then use dx and dy to infer the position of a point 'p' given the measurements performed + * by the touchscreen ('c' is any of the calibration points): + * dx = (p.data[0] - c.data[0]) / (p.x - c.x) + * dy = (p.data[1] - c.data[1]) / (p.y - c.y) + * Thus: + * p.x = c.x - (p.data[0] - c.data[0]) / dx + * p.y = c.y - (p.data[1] - c.data[1]) / dy + * + * - Since there are four calibration points, dx and dy can be calculated twice, so we average + * the two values. + */ + slope1 = ((int32_t) calibrationPoints[0].data[0]) - ((int32_t) calibrationPoints[1].data[0]); + slope1 *= 1024; + slope1 /= ((int32_t) calibrationPoints[0].x) - ((int32_t) calibrationPoints[1].x); + slope2 = ((int32_t) calibrationPoints[2].data[0]) - ((int32_t) calibrationPoints[3].data[0]); + slope2 *= 1024; + slope2 /= ((int32_t) calibrationPoints[2].x) - ((int32_t) calibrationPoints[3].x); + xSlope = (slope1 + slope2) / 2; + + slope1 = ((int32_t) calibrationPoints[0].data[1]) - ((int32_t) calibrationPoints[2].data[1]); + slope1 *= 1024; + slope1 /= ((int32_t) calibrationPoints[0].y) - ((int32_t) calibrationPoints[2].y); + slope2 = ((int32_t) calibrationPoints[1].data[1]) - ((int32_t) calibrationPoints[3].data[1]); + slope2 *= 1024; + slope2 /= ((int32_t) calibrationPoints[1].y) - ((int32_t) calibrationPoints[3].y); + ySlope = (slope1 + slope2) / 2; + + /* Test point */ + LCDD_Fill(0xFFFFFF); + LCDD_DrawString(30, 50, (uint8_t *)"LCD calibration", COLOR_BLACK); + LCDD_DrawString(1, 100, (uint8_t *)" Touch the point to\nvalidate calibration", COLOR_DARKBLUE); + DrawCalibrationPoint(&testPoint); + + /* Wait for touch & end of conversion */ + TSD_WaitPenPressed(); + + TSD_GetRawMeasurement(measuredPoint.data); + TSDCom_InterpolateMeasurement(measuredPoint.data, (uint32_t *) &measuredPoint); + DrawCalibrationPoint(&measuredPoint); + + /* Check resulting x and y */ + xDiff = (int32_t) measuredPoint.x - (int32_t) testPoint.x; + yDiff = (int32_t) measuredPoint.y - (int32_t) testPoint.y; + xOk = (xDiff >= -POINTS_MAX_ERROR) && (xDiff <= POINTS_MAX_ERROR); + yOk = (yDiff >= -POINTS_MAX_ERROR) && (yDiff <= POINTS_MAX_ERROR); + + /* Wait for contact loss */ + TSD_WaitPenReleased(); + + /* Check calibration result */ + if (xOk && yOk) { + + bCalibrationOk = 1; + LCDD_Fill(COLOR_WHITE); + LCDD_DrawString(30, 50, (uint8_t *)"LCD calibration", COLOR_BLACK); + LCDD_DrawString(80, 140, (uint8_t *)"Success !", COLOR_GREEN); + + } + else { + + bCalibrationOk = 0; + LCDD_Fill(COLOR_WHITE); + LCDD_DrawString(30, 50, (uint8_t *)"LCD calibration", COLOR_BLACK); + LCDD_DrawString(40, 140, (uint8_t *)"Error too big", COLOR_RED); + } + + /* Slight delay */ + for (i = 0; i < DELAY_RESULT_DISPLAY; i++); + + return (xOk && yOk); +} + +/** + * \brief Read calibrate data to buffer. + * + * \param pBuffer Data buffer. + * \param size Size of data buffer in bytes. + */ +void TSDCom_ReadCalibrateData(void *pBuffer, uint32_t size) +{ + uint8_t *pDest = (uint8_t *)pBuffer; + + assert( (sizeof(bCalibrationOk) + sizeof(xSlope) + + sizeof(ySlope) + sizeof(calibrationPoints[0].data)) < size ) ; + + memcpy(pDest, (void const *)&bCalibrationOk, sizeof(bCalibrationOk)); + pDest += sizeof(bCalibrationOk); + memcpy(pDest, &xSlope, sizeof(xSlope)); + pDest += sizeof(xSlope); + memcpy(pDest, &ySlope, sizeof(ySlope)); + pDest += sizeof(ySlope); + memcpy(pDest, &calibrationPoints[0].data, sizeof(calibrationPoints[0].data)); + pDest += sizeof(calibrationPoints[0].data); +} + +/** + * \brief Restore calibrate data with buffer data. + * + * \param pBuffer Data buffer. + * \param size Size of data buffer in bytes. + */ +void TSDCom_RestoreCalibrateData(void *pBuffer, uint32_t size) +{ + uint8_t *pSrc = (uint8_t *)pBuffer; + + assert( (sizeof(bCalibrationOk) + sizeof(xSlope) + + sizeof(ySlope) + sizeof(calibrationPoints[0].data)) < size ) ; + + memcpy((void *)&bCalibrationOk, pSrc, sizeof(bCalibrationOk)); + pSrc += sizeof(bCalibrationOk); + memcpy(&xSlope, pSrc, sizeof(xSlope)); + pSrc += sizeof(xSlope); + memcpy(&ySlope, pSrc, sizeof(ySlope)); + pSrc += sizeof(ySlope); + memcpy(&calibrationPoints[0].data, pSrc, sizeof(calibrationPoints[0].data)); + pSrc += sizeof(calibrationPoints[0].data); +} diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/uart_console.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/uart_console.c new file mode 100644 index 00000000..1c4cbd92 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/uart_console.c @@ -0,0 +1,389 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implements UART console. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "board.h" + +#include +#include + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** Console baudrate always using 115200. */ +#define CONSOLE_BAUDRATE 115200 +/** Usart Hw interface used by the console (UART0). */ +#define CONSOLE_USART UART0 +/** Usart Hw ID used by the console (UART0). */ +#define CONSOLE_ID ID_UART0 +/** Pins description corresponding to Rxd,Txd, (UART pins) */ +#define CONSOLE_PINS {PINS_UART} + +/*---------------------------------------------------------------------------- + * Variables + *----------------------------------------------------------------------------*/ + +/** Is Console Initialized. */ +static uint8_t _ucIsConsoleInitialized=0 ; + +/** + * \brief Configures an USART peripheral with the specified parameters. + * + * \param baudrate Baudrate at which the USART should operate (in Hz). + * \param masterClock Frequency of the system master clock (in Hz). + */ +extern void UART_Configure( uint32_t baudrate, uint32_t masterClock) +{ + const Pin pPins[] = CONSOLE_PINS; + Uart *pUart = CONSOLE_USART; + + /* Configure PIO */ + PIO_Configure(pPins, PIO_LISTSIZE(pPins)); + + /* Configure PMC */ + PMC->PMC_PCER0 = 1 << CONSOLE_ID; + + /* Reset and disable receiver & transmitter */ + pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX + | UART_CR_RXDIS | UART_CR_TXDIS; + + /* Configure mode */ + pUart->UART_MR = UART_MR_PAR_NO; + + /* Configure baudrate */ + /* Asynchronous, no oversampling */ + pUart->UART_BRGR = (masterClock / baudrate) / 16; + + /* Disable PDC channel */ + pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS; + + /* Enable receiver and transmitter */ + pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; + + _ucIsConsoleInitialized=1 ; +} + +/** + * \brief Outputs a character on the UART line. + * + * \note This function is synchronous (i.e. uses polling). + * \param c Character to send. + */ +extern void UART_PutChar( uint8_t c ) +{ + Uart *pUart=CONSOLE_USART ; + + if ( !_ucIsConsoleInitialized ) + { + UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK); + } + + /* Wait for the transmitter to be ready */ + while ( (pUart->UART_SR & UART_SR_TXEMPTY) == 0 ) ; + + /* Send character */ + pUart->UART_THR=c ; + +} + +/** + * \brief Input a character from the UART line. + * + * \note This function is synchronous + * \return character received. + */ +extern uint32_t UART_GetChar( void ) +{ + Uart *pUart=CONSOLE_USART ; + + if ( !_ucIsConsoleInitialized ) + { + UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK); + } + + while ( (pUart->UART_SR & UART_SR_RXRDY) == 0 ) ; + + return pUart->UART_RHR ; +} + +/** + * \brief Check if there is Input from UART line. + * + * \return true if there is Input. + */ +extern uint32_t UART_IsRxReady( void ) +{ + Uart *pUart=CONSOLE_USART ; + + if ( !_ucIsConsoleInitialized ) + { + UART_Configure( CONSOLE_BAUDRATE, BOARD_MCK ) ; + } + + return (pUart->UART_SR & UART_SR_RXRDY) > 0 ; +} + +/** + * Displays the content of the given frame on the UART0. + * + * \param pucFrame Pointer to the frame to dump. + * \param dwSize Buffer size in bytes. + */ +extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize ) +{ + uint32_t dw ; + + for ( dw=0 ; dw < dwSize ; dw++ ) + { + printf( "%02X ", pucFrame[dw] ) ; + } + + printf( "\n\r" ) ; +} + +/** + * Displays the content of the given buffer on the UART0. + * + * \param pucBuffer Pointer to the buffer to dump. + * \param dwSize Buffer size in bytes. + * \param dwAddress Start address to display + */ +extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress ) +{ + uint32_t i ; + uint32_t j ; + uint32_t dwLastLineStart ; + uint8_t* pucTmp ; + + for ( i=0 ; i < (dwSize / 16) ; i++ ) + { + printf( "0x%08X: ", (unsigned int)(dwAddress + (i*16)) ) ; + pucTmp = (uint8_t*)&pucBuffer[i*16] ; + + for ( j=0 ; j < 4 ; j++ ) + { + printf( "%02X%02X%02X%02X ", pucTmp[0], pucTmp[1], pucTmp[2], pucTmp[3] ) ; + pucTmp += 4 ; + } + + pucTmp=(uint8_t*)&pucBuffer[i*16] ; + + for ( j=0 ; j < 16 ; j++ ) + { + UART_PutChar( *pucTmp++ ) ; + } + + printf( "\n\r" ) ; + } + + if ( (dwSize%16) != 0 ) + { + dwLastLineStart=dwSize - (dwSize%16) ; + + printf( "0x%08X: ", (unsigned int)(dwAddress + dwLastLineStart) ) ; + for ( j=dwLastLineStart ; j < dwLastLineStart+16 ; j++ ) + { + if ( (j!=dwLastLineStart) && (j%4 == 0) ) + { + printf( " " ) ; + } + + if ( j < dwSize ) + { + printf( "%02X", pucBuffer[j] ) ; + } + else + { + printf(" ") ; + } + } + + printf( " " ) ; + for ( j=dwLastLineStart ; j < dwSize ; j++ ) + { + UART_PutChar( pucBuffer[j] ) ; + } + + printf( "\n\r" ) ; + } +} + +/** + * Reads an integer + * + * \param pdwValue Pointer to the uint32_t variable to contain the input value. + */ +extern uint32_t UART_GetInteger( uint32_t* pdwValue ) +{ + uint8_t ucKey ; + uint8_t ucNbNb=0 ; + uint32_t dwValue=0 ; + + while ( 1 ) + { + ucKey=UART_GetChar() ; + UART_PutChar( ucKey ) ; + + if ( ucKey >= '0' && ucKey <= '9' ) + { + dwValue = (dwValue * 10) + (ucKey - '0'); + ucNbNb++ ; + } + else + { + if ( ucKey == 0x0D || ucKey == ' ' ) + { + if ( ucNbNb == 0 ) + { + printf( "\n\rWrite a number and press ENTER or SPACE!\n\r" ) ; + return 0 ; + } + else + { + printf( "\n\r" ) ; + *pdwValue=dwValue ; + + return 1 ; + } + } + else + { + printf( "\n\r'%c' not a number!\n\r", ucKey ) ; + + return 0 ; + } + } + } +} + +/** + * Reads an integer and check the value + * + * \param pdwValue Pointer to the uint32_t variable to contain the input value. + * \param dwMin Minimum value + * \param dwMax Maximum value + */ +extern uint32_t UART_GetIntegerMinMax( uint32_t* pdwValue, uint32_t dwMin, uint32_t dwMax ) +{ + uint32_t dwValue=0 ; + + if ( UART_GetInteger( &dwValue ) == 0 ) + { + return 0 ; + } + + if ( dwValue < dwMin || dwValue > dwMax ) + { + printf( "\n\rThe number have to be between %d and %d\n\r", (int)dwMin, (int)dwMax ) ; + + return 0 ; + } + + printf( "\n\r" ) ; + + *pdwValue = dwValue ; + + return 1 ; +} + +/** + * Reads an hexadecimal number + * + * \param pdwValue Pointer to the uint32_t variable to contain the input value. + */ +extern uint32_t UART_GetHexa32( uint32_t* pdwValue ) +{ + uint8_t ucKey ; + uint32_t dw = 0 ; + uint32_t dwValue = 0 ; + + for ( dw=0 ; dw < 8 ; dw++ ) + { + ucKey = UART_GetChar() ; + UART_PutChar( ucKey ) ; + + if ( ucKey >= '0' && ucKey <= '9' ) + { + dwValue = (dwValue * 16) + (ucKey - '0') ; + } + else + { + if ( ucKey >= 'A' && ucKey <= 'F' ) + { + dwValue = (dwValue * 16) + (ucKey - 'A' + 10) ; + } + else + { + if ( ucKey >= 'a' && ucKey <= 'f' ) + { + dwValue = (dwValue * 16) + (ucKey - 'a' + 10) ; + } + else + { + printf( "\n\rIt is not a hexa character!\n\r" ) ; + + return 0 ; + } + } + } + } + + printf("\n\r" ) ; + *pdwValue = dwValue ; + + return 1 ; +} + +#if defined __ICCARM__ /* IAR Ewarm 5.41+ */ +/** + * \brief Outputs a character on the UART. + * + * \param c Character to output. + * + * \return The character that was output. + */ +extern WEAK signed int putchar( signed int c ) +{ + UART_PutChar( c ) ; + + return c ; +} +#endif // defined __ICCARM__ + diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/wav.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/wav.c new file mode 100644 index 00000000..be3947bd --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/wav.c @@ -0,0 +1,90 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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 "board.h" + +#include + +/*---------------------------------------------------------------------------- + * Definiation + *----------------------------------------------------------------------------*/ + +/* WAV letters "RIFF" */ +#define WAV_CHUNKID 0x46464952 +/* WAV letters "WAVE"*/ +#define WAV_FORMAT 0x45564157 +/* WAV letters "fmt "*/ +#define WAV_SUBCHUNKID 0x20746D66 + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Check if the header of a Wav file is valid ot not. + * + * \param file Buffer holding the file to examinate. + * \return 1 if the header of a Wav file is valid; otherwise returns 0. + */ +unsigned char WAV_IsValid(const WavHeader *header) +{ + return ((header->chunkID == WAV_CHUNKID) + && (header->format == WAV_FORMAT) + && (header->subchunk1Size == 0x10)); +} + +/** + * \brief Display the information of the WAV file (sample rate, stereo/mono + * and frame size). + * + * \param header Wav head information. + */ + +void WAV_DisplayInfo(const WavHeader *header) +{ + printf( "Wave file header information\n\r"); + printf( "--------------------------------\n\r"); + printf( " - Chunk ID = 0x%08X\n\r", header->chunkID); + printf( " - Chunk Size = %u\n\r", header->chunkSize); + printf( " - Format = 0x%08X\n\r", header->format); + printf( " - SubChunk ID = 0x%08X\n\r", header->subchunk1ID); + printf( " - Subchunk1 Size = %u\n\r", header->subchunk1Size); + printf( " - Audio Format = 0x%04X\n\r", header->audioFormat); + printf( " - Num. Channels = %d\n\r", header->numChannels); + printf( " - Sample Rate = %u\n\r", header->sampleRate); + printf( " - Byte Rate = %u\n\r", header->byteRate); + printf( " - Block Align = %d\n\r", header->blockAlign); + printf( " - Bits Per Sample = %d\n\r", header->bitsPerSample); + printf( " - Subchunk2 ID = 0x%08X\n\r", header->subchunk2ID); + printf( " - Subchunk2 Size = %u\n\r", header->subchunk2Size); +} diff --git a/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/wm8731.c b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/wm8731.c new file mode 100644 index 00000000..784d1c9e --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libboard_sam3s-ek/source/wm8731.c @@ -0,0 +1,139 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + + +/** + * \file + * + * Implementation WM8731 driver. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "board.h" + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Read data from WM8731 Register. + * + * \param pTwid Pointer to twi driver structure + * \param device Twi slave address. + * \param regAddr Register address to read. + * \return value in the given register. + */ +uint16_t WM8731_Read(Twid *pTwid, + uint32_t device, + uint32_t regAddr) +{ + uint16_t bitsDataRegister; + uint8_t Tdata[2]={0,0}; + + TWID_Read(pTwid, device, regAddr, 0, Tdata, 2, 0); + bitsDataRegister = (Tdata[0] << 8) | Tdata[1]; + return bitsDataRegister; +} + +/** + * \brief Write data to WM8731 Register. + * + * \param pTwid Pointer to twi driver structure + * \param device Twi slave address. + * \param regAddr Register address to read. + * \param data Data to write + */ +void WM8731_Write(Twid *pTwid, + uint32_t device, + uint32_t regAddr, + uint16_t data) +{ + uint8_t tmpData[2]; + uint16_t tmp; + tmp = ((regAddr & 0x7f) << 9) | (data & 0x1ff); + + tmpData[0] = (tmp & 0xff00) >> 8; + tmpData[1] = tmp & 0xff; + TWID_Write(pTwid, device, regAddr, 0, tmpData, 2, 0); +} + +/** + * \brief Init WM8731 to DAC mode. + * + * \param pTwid Pointer to twi driver structure + * \param device Twi slave address. + * \return 0. + */ +uint8_t WM8731_DAC_Init(Twid *pTwid, + uint32_t device) +{ + /* reset */ + WM8731_Write(pTwid, device, WM8731_REG_RESET, 0); + + /* analogue audio path control */ + WM8731_Write(pTwid, device, WM8731_REG_ANALOGUE_PATH_CTRL, 0x12); + + /* digital audio path control*/ + WM8731_Write(pTwid, device, WM8731_REG_DIGITAL_PATH_CTRL, 0x00); + + /* power down control */ + WM8731_Write(pTwid, device, WM8731_REG_PWDOWN_CTRL, 0x7); + + /* Active control*/ + WM8731_Write(pTwid, device, WM8731_REG_ACTIVE_CTRL, 0x01); + + return 0; +} + +/** + * \brief Set WM8731 volume + * + * \param pTwid Pointer to twi driver structure + * \param device Twi slave address. + * \param value Register value, valid value is between 0x30 to 0x7f + * \return 0. + */ +uint8_t WM8731_VolumeSet(Twid *pTwid, + uint32_t device, + uint16_t value) +{ + uint16_t regValue; + + value &= WM8731_LHPVOL_BITS; + regValue = WM8731_LRHPBOTH_BIT | WM8731_LZCEN_BIT | value; + WM8731_Write(pTwid, device, WM8731_REG_LEFT_HPOUT, regValue); + regValue = WM8731_RZCEN_BIT | WM8731_RLHPBOTH_BIT | value; + WM8731_Write(pTwid, device, WM8731_REG_RIGHT_HPOUT, value); + return 0; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c new file mode 100644 index 00000000..1bf3ac07 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/USBD_HAL.c @@ -0,0 +1,1666 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + + \file + + \section Purpose + + Implementation of USB device functions on a UDP controller. + + See \ref usbd_api_method USBD API Methods. +*/ + +/** \addtogroup usbd_hal + *@{*/ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include "chip.h" +#include "USBD_HAL.h" + +#include +#include +#include + +/*--------------------------------------------------------------------------- + * Definitions + *---------------------------------------------------------------------------*/ + +/** Indicates chip has an UDP Full Speed. */ +#define CHIP_USB_UDP + +/** Indicates chip has an internal pull-up. */ +#define CHIP_USB_PULLUP_INTERNAL + +/** Number of USB endpoints */ +#define CHIP_USB_NUMENDPOINTS 8 + +/** Endpoints max paxcket size */ +#define CHIP_USB_ENDPOINTS_MAXPACKETSIZE(i) \ + ((i == 0) ? 64 : \ + ((i == 1) ? 64 : \ + ((i == 2) ? 64 : \ + ((i == 3) ? 64 : \ + ((i == 4) ? 512 : \ + ((i == 5) ? 512 : \ + ((i == 6) ? 64 : \ + ((i == 7) ? 64 : 0 )))))))) + +/** Endpoints Number of Bank */ +#define CHIP_USB_ENDPOINTS_BANKS(i) \ + ((i == 0) ? 1 : \ + ((i == 1) ? 2 : \ + ((i == 2) ? 2 : \ + ((i == 3) ? 1 : \ + ((i == 4) ? 2 : \ + ((i == 5) ? 2 : \ + ((i == 6) ? 2 : \ + ((i == 7) ? 2 : 0 )))))))) + +/** + * \section UDP_registers_sec "UDP Register field values" + * + * This section lists the initialize values of UDP registers. + * + * \subsection Values + * - UDP_RXDATA + */ +/** Bit mask for both banks of the UDP_CSR register. */ +#define UDP_CSR_RXDATA_BK (UDP_CSR_RX_DATA_BK0 | UDP_CSR_RX_DATA_BK1) + +/** + * \section endpoint_states_sec "UDP Endpoint states" + * + * This page lists the endpoint states. + * + * \subsection States + * - UDP_ENDPOINT_DISABLED + * - UDP_ENDPOINT_HALTED + * - UDP_ENDPOINT_IDLE + * - UDP_ENDPOINT_SENDING + * - UDP_ENDPOINT_RECEIVING + * - UDP_ENDPOINT_SENDINGM + * - UDP_ENDPOINT_RECEIVINGM + */ + +/** Endpoint states: Endpoint is disabled */ +#define UDP_ENDPOINT_DISABLED 0 +/** Endpoint states: Endpoint is halted (i.e. STALLs every request) */ +#define UDP_ENDPOINT_HALTED 1 +/** Endpoint states: Endpoint is idle (i.e. ready for transmission) */ +#define UDP_ENDPOINT_IDLE 2 +/** Endpoint states: Endpoint is sending data */ +#define UDP_ENDPOINT_SENDING 3 +/** Endpoint states: Endpoint is receiving data */ +#define UDP_ENDPOINT_RECEIVING 4 +/** Endpoint states: Endpoint is sending MBL */ +#define UDP_ENDPOINT_SENDINGM 5 +/** Endpoint states: Endpoint is receiving MBL */ +#define UDP_ENDPOINT_RECEIVINGM 6 + +/** + * \section udp_csr_register_access_sec "UDP CSR register access" + * + * This page lists the macros to access UDP CSR register. + * + * \comment + * In a preemptive environment, set or clear the flag and wait for a time of + * 1 UDPCK clock cycle and 1 peripheral clock cycle. However, RX_DATA_BK0, + * TXPKTRDY, RX_DATA_BK1 require wait times of 3 UDPCK clock cycles and + * 5 peripheral clock cycles before accessing DPR. + * See datasheet + * + * !Macros + * - CLEAR_CSR + * - SET_CSR + */ + +#if defined ( __CC_ARM ) + #define nop() {volatile int h; for(h=0;h<10;h++){}} +#elif defined ( __ICCARM__ ) + #include + #define nop() (__no_operation()) +#elif defined ( __GNUC__ ) + #define nop() __asm__ __volatile__ ( "nop" ) +#endif + + +/** Bitmap for all status bits in CSR. */ +#define REG_NO_EFFECT_1_ALL UDP_CSR_RX_DATA_BK0 | UDP_CSR_RX_DATA_BK1 \ + |UDP_CSR_STALLSENTISOERROR | UDP_CSR_RXSETUP \ + |UDP_CSR_TXCOMP + +/** + * Sets the specified bit(s) in the UDP_CSR register. + * + * \param endpoint The endpoint number of the CSR to process. + * \param flags The bitmap to set to 1. + */ +#define SET_CSR(endpoint, flags) \ + { \ + volatile uint32_t reg; \ + int32_t nop_count ; \ + reg = UDP->UDP_CSR[endpoint] ; \ + reg |= REG_NO_EFFECT_1_ALL; \ + reg |= (flags); \ + UDP->UDP_CSR[endpoint] = reg; \ + for( nop_count=0; nop_count<15; nop_count++ ) {\ + nop();\ + }\ + } + +/** + * Clears the specified bit(s) in the UDP_CSR register. + * + * \param endpoint The endpoint number of the CSR to process. + * \param flags The bitmap to clear to 0. + */ +#define CLEAR_CSR(endpoint, flags) \ +{ \ + volatile uint32_t reg; \ + int32_t nop_count ; \ + reg = UDP->UDP_CSR[endpoint]; \ + reg |= REG_NO_EFFECT_1_ALL; \ + reg &= ~((uint32_t)(flags)); \ + UDP->UDP_CSR[endpoint] = reg; \ + for( nop_count=0; nop_count<15; nop_count++ ) {\ + nop();\ + }\ +} + + +/** Get Number of buffer in Multi-Buffer-List + * \param i input index + * \param o output index + * \param size list size + */ +#define MBL_NbBuffer(i, o, size) (((i)>(o))?((i)-(o)):((i)+(size)-(o))) + +/** Buffer list is full */ +#define MBL_FULL 1 +/** Buffer list is null */ +#define MBL_NULL 2 + +/*--------------------------------------------------------------------------- + * Types + *---------------------------------------------------------------------------*/ + +/** Describes header for UDP endpoint transfer. */ +typedef struct { + /** Optional callback to invoke when the transfer completes. */ + void* fCallback; + /** Optional argument to the callback function. */ + void* pArgument; + /** Transfer type */ + uint8_t transType; +} TransferHeader; + +/** Describes a transfer on a UDP endpoint. */ +typedef struct { + + /** Optional callback to invoke when the transfer completes. */ + TransferCallback fCallback; + /** Optional argument to the callback function. */ + void *pArgument; + /** Transfer type */ + uint16_t transType; + /** Number of bytes which have been written into the UDP internal FIFO + * buffers. */ + int16_t buffered; + /** Pointer to a data buffer used for emission/reception. */ + uint8_t *pData; + /** Number of bytes which have been sent/received. */ + int32_t transferred; + /** Number of bytes which have not been buffered/transferred yet. */ + int32_t remaining; +} Transfer; + +/** Describes Multi Buffer List transfer on a UDP endpoint. */ +typedef struct { + /** Optional callback to invoke when the transfer completes. */ + MblTransferCallback fCallback; + /** Optional argument to the callback function. */ + void *pArgument; + /** Transfer type */ + volatile uint8_t transType; + /** List state (OK, FULL, NULL) (run time) */ + uint8_t listState; + /** Multi-Buffer List size */ + uint16_t listSize; + /** Pointer to multi-buffer list */ + USBDTransferBuffer *pMbl; + /** Offset number of buffers to start transfer */ + uint16_t offsetSize; + /** Current processing buffer index (run time) */ + uint16_t outCurr; + /** Loast loaded buffer index (run time) */ + uint16_t outLast; + /** Current buffer for input (run time) */ + uint16_t inCurr; +} MblTransfer; + +/** + * Describes the state of an endpoint of the UDP controller. + */ +typedef struct { + + /* CSR */ + //uint32_t CSR; + /** Current endpoint state. */ + volatile uint8_t state; + /** Current reception bank (0 or 1). */ + volatile uint8_t bank; + /** Maximum packet size for the endpoint. */ + volatile uint16_t size; + /** Describes an ongoing transfer (if current state is either + * UDP_ENDPOINT_SENDING or UDP_ENDPOINT_RECEIVING) */ + union { + TransferHeader transHdr; + Transfer singleTransfer; + MblTransfer mblTransfer; + } transfer; +} Endpoint; + +/*--------------------------------------------------------------------------- + * Internal variables + *---------------------------------------------------------------------------*/ + +/** Holds the internal state for each endpoint of the UDP. */ +static Endpoint endpoints[CHIP_USB_NUMENDPOINTS]; + +/*--------------------------------------------------------------------------- + * Internal Functions + *---------------------------------------------------------------------------*/ + +/** + * Enables the clock of the UDP peripheral. + * \return 1 if peripheral status changed. + */ +static uint8_t UDP_EnablePeripheralClock(void) +{ + if (!PMC_IsPeriphEnabled(ID_UDP)) { + PMC_EnablePeripheral(ID_UDP); + return 1; + } + return 0; +} + +/** + * Disables the UDP peripheral clock. + */ +static inline void UDP_DisablePeripheralClock(void) +{ + PMC_DisablePeripheral(ID_UDP); +} + +/** + * Enables the 48MHz USB clock. + */ +static inline void UDP_EnableUsbClock(void) +{ + REG_PMC_SCER = PMC_SCER_UDP; +} + +/** + * Disables the 48MHz USB clock. + */ +static inline void UDP_DisableUsbClock(void) +{ + REG_PMC_SCDR = PMC_SCER_UDP; +} + +/** + * Enables the UDP transceiver. + */ +static inline void UDP_EnableTransceiver(void) +{ + UDP->UDP_TXVC &= ~(uint32_t)UDP_TXVC_TXVDIS; +} + +/** + * Disables the UDP transceiver. + */ +static inline void UDP_DisableTransceiver(void) +{ + UDP->UDP_TXVC |= UDP_TXVC_TXVDIS; +} + +/** + * Handles a completed transfer on the given endpoint, invoking the + * configured callback if any. + * \param bEndpoint Number of the endpoint for which the transfer has completed. + * \param bStatus Status code returned by the transfer operation + */ +static void UDP_EndOfTransfer(uint8_t bEndpoint, uint8_t bStatus) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + + // Check that endpoint was sending or receiving data + if( (pEndpoint->state == UDP_ENDPOINT_RECEIVING) + || (pEndpoint->state == UDP_ENDPOINT_SENDING)) { + + Transfer *pTransfer = (Transfer *)&(pEndpoint->transfer); + uint32_t transferred = pTransfer->transferred; + uint32_t remaining = pTransfer->remaining + pTransfer->buffered; + + TRACE_DEBUG_WP("EoT "); + + /* Endpoint returns in Idle state */ + pEndpoint->state = UDP_ENDPOINT_IDLE; + /* Reset descriptor values */ + pTransfer->pData = 0; + pTransfer->transferred = -1; + pTransfer->buffered = -1; + pTransfer->remaining = -1; + + // Invoke callback is present + if (pTransfer->fCallback != 0) { + + ((TransferCallback) pTransfer->fCallback) + (pTransfer->pArgument, + bStatus, + transferred, + remaining); + } + else { + TRACE_DEBUG_WP("NoCB "); + } + } + else if ( (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM) + || (pEndpoint->state == UDP_ENDPOINT_SENDINGM) ) { + + MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer); + + TRACE_DEBUG_WP("EoMT "); + + /* Endpoint returns in Idle state */ + pEndpoint->state = UDP_ENDPOINT_IDLE; + /* Reset transfer descriptor */ + if (pTransfer->transType) { + MblTransfer *pMblt = (MblTransfer*)&(pEndpoint->transfer); + pMblt->listState = 0; + pMblt->outCurr = pMblt->inCurr = pMblt->outLast = 0; + } + /* Invoke callback */ + if (pTransfer->fCallback != 0) { + + ((MblTransferCallback) pTransfer->fCallback) + (pTransfer->pArgument, + bStatus); + } + else { + TRACE_DEBUG_WP("NoCB "); + } + } +} + +/** + * Clears the correct reception flag (bank 0 or bank 1) of an endpoint + * \param bEndpoint Index of endpoint + */ +static void UDP_ClearRxFlag(uint8_t bEndpoint) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + + // Clear flag and change banks + if (pEndpoint->bank == 0) { + + CLEAR_CSR(bEndpoint, UDP_CSR_RX_DATA_BK0); + // Swap bank if in dual-fifo mode + if (CHIP_USB_ENDPOINTS_BANKS(bEndpoint) > 1) { + + pEndpoint->bank = 1; + } + } + else { + + CLEAR_CSR(bEndpoint, UDP_CSR_RX_DATA_BK1); + pEndpoint->bank = 0; + } +} + +/** + * Update multi-buffer-transfer descriptors. + * \param pTransfer Pointer to instance MblTransfer. + * \param size Size of bytes that processed. + * \param forceEnd Force the buffer END. + * \return 1 if current buffer ended. + */ +static uint8_t UDP_MblUpdate(MblTransfer *pTransfer, + USBDTransferBuffer * pBi, + uint16_t size, + uint8_t forceEnd) +{ + /* Update transfer descriptor */ + pBi->remaining -= size; + /* Check if list NULL */ + if (pTransfer->listState == MBL_NULL) { + return 1; + } + /* Check if current buffer ended */ + if (pBi->remaining == 0 || forceEnd || size == 0) { + + /* Process to next buffer */ + if ((++ pTransfer->outCurr) == pTransfer->listSize) + pTransfer->outCurr = 0; + /* Check buffer NULL case */ + if (pTransfer->outCurr == pTransfer->inCurr) + pTransfer->listState = MBL_NULL; + else { + pTransfer->listState = 0; + /* Continue transfer, prepare for next operation */ + pBi = &pTransfer->pMbl[pTransfer->outCurr]; + pBi->buffered = 0; + pBi->transferred = 0; + pBi->remaining = pBi->size; + } + return 1; + } + return 0; +} + +/** + * Transfers a data payload from the current tranfer buffer to the endpoint + * FIFO + * \param bEndpoint Number of the endpoint which is sending data. + */ +static uint8_t UDP_MblWriteFifo(uint8_t bEndpoint) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + MblTransfer *pTransfer = (MblTransfer*)&(pEndpoint->transfer); + USBDTransferBuffer *pBi = &(pTransfer->pMbl[pTransfer->outCurr]); + int32_t size; + + volatile uint8_t * pBytes; + volatile uint8_t bufferEnd = 1; + + /* Get the number of bytes to send */ + size = pEndpoint->size; + if (size > pBi->remaining) size = pBi->remaining; + + TRACE_DEBUG_WP("w%d.%d ", pTransfer->outCurr, size); + + /* Record last accessed buffer */ + pTransfer->outLast = pTransfer->outCurr; + + pBytes = &(pBi->pBuffer[pBi->transferred + pBi->buffered]); + pBi->buffered += size; + bufferEnd = UDP_MblUpdate(pTransfer, pBi, size, 0); + + /* Write packet in the FIFO buffer */ + if (size) { + int32_t c8 = size >> 3; + int32_t c1 = size & 0x7; + for (; c8; c8 --) { + UDP->UDP_FDR[bEndpoint] = *(pBytes ++); + UDP->UDP_FDR[bEndpoint] = *(pBytes ++); + UDP->UDP_FDR[bEndpoint] = *(pBytes ++); + UDP->UDP_FDR[bEndpoint] = *(pBytes ++); + + UDP->UDP_FDR[bEndpoint] = *(pBytes ++); + UDP->UDP_FDR[bEndpoint] = *(pBytes ++); + UDP->UDP_FDR[bEndpoint] = *(pBytes ++); + UDP->UDP_FDR[bEndpoint] = *(pBytes ++); + } + for (; c1; c1 --) { + UDP->UDP_FDR[bEndpoint] = *(pBytes ++); + } + } + return bufferEnd; +} + +/** + * Transfers a data payload from the current tranfer buffer to the endpoint + * FIFO + * \param bEndpoint Number of the endpoint which is sending data. + */ +static void UDP_WritePayload(uint8_t bEndpoint) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer); + int32_t size; + + // Get the number of bytes to send + size = pEndpoint->size; + if (size > pTransfer->remaining) { + + size = pTransfer->remaining; + } + + // Update transfer descriptor information + pTransfer->buffered += size; + pTransfer->remaining -= size; + + // Write packet in the FIFO buffer + while (size > 0) { + + UDP->UDP_FDR[bEndpoint] = *(pTransfer->pData); + pTransfer->pData++; + size--; + } +} + + +/** + * Transfers a data payload from an endpoint FIFO to the current transfer buffer + * \param bEndpoint Endpoint number. + * \param wPacketSize Size of received data packet + */ +static void UDP_ReadPayload(uint8_t bEndpoint, int32_t wPacketSize) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer); + + // Check that the requested size is not bigger than the remaining transfer + if (wPacketSize > pTransfer->remaining) { + + pTransfer->buffered += wPacketSize - pTransfer->remaining; + wPacketSize = pTransfer->remaining; + } + + // Update transfer descriptor information + pTransfer->remaining -= wPacketSize; + pTransfer->transferred += wPacketSize; + + // Retrieve packet + while (wPacketSize > 0) { + + *(pTransfer->pData) = (uint8_t) UDP->UDP_FDR[bEndpoint]; + pTransfer->pData++; + wPacketSize--; + } +} + +/** + * Received SETUP packet from endpoint 0 FIFO + * \param pRequest Generic USB SETUP request sent over Control endpoints + */ +static void UDP_ReadRequest(USBGenericRequest *pRequest) +{ + uint8_t *pData = (uint8_t *)pRequest; + uint32_t i; + + // Copy packet + for (i = 0; i < 8; i++) { + + *pData = (uint8_t) UDP->UDP_FDR[0]; + pData++; + } +} + +/** + * Checks if an ongoing transfer on an endpoint has been completed. + * \param bEndpoint Endpoint number. + * \return 1 if the current transfer on the given endpoint is complete; + * otherwise 0. + */ +static uint8_t UDP_IsTransferFinished(uint8_t bEndpoint) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer); + + // Check if it is a Control endpoint + // -> Control endpoint must always finish their transfer with a zero-length + // packet + if ((UDP->UDP_CSR[bEndpoint] & UDP_CSR_EPTYPE_Msk) == UDP_CSR_EPTYPE_CTRL) { + + return (pTransfer->buffered < pEndpoint->size); + } + // Other endpoints only need to transfer all the data + else { + + return (pTransfer->buffered <= pEndpoint->size) + && (pTransfer->remaining == 0); + } +} + +/** + * Endpoint interrupt handler. + * Handle IN/OUT transfers, received SETUP packets and STALLing + * \param bEndpoint Index of endpoint + */ +static void UDP_EndpointHandler(uint8_t bEndpoint) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer); + MblTransfer *pMblt = (MblTransfer*)&(pEndpoint->transfer); + uint32_t status = UDP->UDP_CSR[bEndpoint]; + uint16_t wPacketSize; + USBGenericRequest request; + + TRACE_DEBUG_WP("E%d ", bEndpoint); + TRACE_DEBUG_WP("st:0x%X ", status); + + // Handle interrupts + // IN packet sent + if ((status & UDP_CSR_TXCOMP) != 0) { + + TRACE_DEBUG_WP("Wr "); + + // Check that endpoint was in MBL Sending state + if (pEndpoint->state == UDP_ENDPOINT_SENDINGM) { + + USBDTransferBuffer * pMbli = &(pMblt->pMbl[pMblt->outLast]); + uint8_t bufferEnd = 0; + + TRACE_DEBUG_WP("TxM%d.%d ", pMblt->listState, pMbli->buffered); + + // End of transfer ? + if (pMblt->listState == MBL_NULL && pMbli->buffered == 0) { + + pMbli->transferred += pMbli->buffered; + pMbli->buffered = 0; + + // Disable interrupt + UDP->UDP_IDR = 1 << bEndpoint; + UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS); + CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP); + } + else { + + // Transfer remaining data + TRACE_DEBUG_WP("%d ", pEndpoint->size); + + if (pMbli->buffered > pEndpoint->size) { + pMbli->transferred += pEndpoint->size; + pMbli->buffered -= pEndpoint->size; + } + else { + pMbli->transferred += pMbli->buffered; + pMbli->buffered = 0; + } + + // Send next packet + if (CHIP_USB_ENDPOINTS_BANKS(bEndpoint) == 1) { + + // No double buffering + bufferEnd = UDP_MblWriteFifo(bEndpoint); + SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY); + CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP); + } + else { + // Double buffering + SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY); + CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP); + bufferEnd = UDP_MblWriteFifo(bEndpoint); + } + + if (bufferEnd && pMblt->fCallback) { + ((MblTransferCallback) pTransfer->fCallback) + (pTransfer->pArgument, + USBD_STATUS_PARTIAL_DONE); + } + } + } + // Check that endpoint was in Sending state + else if (pEndpoint->state == UDP_ENDPOINT_SENDING) { + + // End of transfer ? + if (UDP_IsTransferFinished(bEndpoint)) { + + pTransfer->transferred += pTransfer->buffered; + pTransfer->buffered = 0; + + // Disable interrupt if this is not a control endpoint + if ((status & UDP_CSR_EPTYPE_Msk) != UDP_CSR_EPTYPE_CTRL) { + + UDP->UDP_IDR = 1 << bEndpoint; + } + + UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS); + CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP); + } + else { + + // Transfer remaining data + TRACE_DEBUG_WP(" %d ", pEndpoint->size); + + pTransfer->transferred += pEndpoint->size; + pTransfer->buffered -= pEndpoint->size; + + // Send next packet + if (CHIP_USB_ENDPOINTS_BANKS(bEndpoint) == 1) { + + // No double buffering + UDP_WritePayload(bEndpoint); + SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY); + CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP); + } + else { + // Double buffering + SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY); + CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP); + UDP_WritePayload(bEndpoint); + } + } + } + else { + // Acknowledge interrupt + TRACE_ERROR("Error Wr%d, %x\n\r", bEndpoint, pEndpoint->state); + CLEAR_CSR(bEndpoint, UDP_CSR_TXCOMP); + } + } + + // OUT packet received + if ((status & UDP_CSR_RXDATA_BK) != 0) { + + TRACE_DEBUG_WP("Rd "); + + // Check that the endpoint is in Receiving state + if (pEndpoint->state != UDP_ENDPOINT_RECEIVING) { + + // Check if an ACK has been received on a Control endpoint + if (((status & UDP_CSR_EPTYPE_Msk) == UDP_CSR_EPTYPE_CTRL) + && ((status & UDP_CSR_RXBYTECNT_Msk) == 0)) { + + // Acknowledge the data and finish the current transfer + UDP_ClearRxFlag(bEndpoint); + UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS); + } + // Check if the data has been STALLed + else if ((status & UDP_CSR_FORCESTALL) != 0) { + + // Discard STALLed data + TRACE_DEBUG_WP("Discard "); + UDP_ClearRxFlag(bEndpoint); + } + // NAK the data + else { + + TRACE_DEBUG_WP("Nak "); + UDP->UDP_IDR = 1 << bEndpoint; + } + } + // Endpoint is in Read state + else { + + // Retrieve data and store it into the current transfer buffer + wPacketSize = (uint16_t) (status >> 16); + TRACE_DEBUG_WP("%d ", wPacketSize); + UDP_ReadPayload(bEndpoint, wPacketSize); + UDP_ClearRxFlag(bEndpoint); + + // Check if the transfer is finished + if ((pTransfer->remaining == 0) || (wPacketSize < pEndpoint->size)) { + + // Disable interrupt if this is not a control endpoint + if ((status & UDP_CSR_EPTYPE_Msk) != UDP_CSR_EPTYPE_CTRL) { + + UDP->UDP_IDR = 1 << bEndpoint; + } + UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS); + } + } + } + + // STALL sent + if ((status & UDP_CSR_STALLSENTISOERROR) != 0) { + + CLEAR_CSR(bEndpoint, UDP_CSR_STALLSENTISOERROR); + + if ( (status & UDP_CSR_EPTYPE_Msk) == UDP_CSR_EPTYPE_ISO_IN + || (status & UDP_CSR_EPTYPE_Msk) == UDP_CSR_EPTYPE_ISO_OUT ) { + + TRACE_WARNING("Isoe [%d] ", bEndpoint); + UDP_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED); + } + else { + + TRACE_WARNING("Sta 0x%X [%d] ", (int)status, bEndpoint); + + if (pEndpoint->state != UDP_ENDPOINT_HALTED) { + + TRACE_WARNING( "_ " ); + // If the endpoint is not halted, clear the STALL condition + CLEAR_CSR(bEndpoint, UDP_CSR_FORCESTALL); + } + } + } + + // SETUP packet received + if ((status & UDP_CSR_RXSETUP) != 0) { + + TRACE_DEBUG_WP("Stp "); + + // If a transfer was pending, complete it + // Handles the case where during the status phase of a control write + // transfer, the host receives the device ZLP and ack it, but the ack + // is not received by the device + if ((pEndpoint->state == UDP_ENDPOINT_RECEIVING) + || (pEndpoint->state == UDP_ENDPOINT_SENDING)) { + + UDP_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS); + } + // Copy the setup packet + UDP_ReadRequest(&request); + + // Set the DIR bit before clearing RXSETUP in Control IN sequence + if (USBGenericRequest_GetDirection(&request) == USBGenericRequest_IN) { + + SET_CSR(bEndpoint, UDP_CSR_DIR); + } + // Acknowledge setup packet + CLEAR_CSR(bEndpoint, UDP_CSR_RXSETUP); + + // Forward the request to the upper layer + USBD_RequestHandler(0, &request); + } + +} + +/** + * Sends data through a USB endpoint. Sets up the transfer descriptor, + * writes one or two data payloads (depending on the number of FIFO bank + * for the endpoint) and then starts the actual transfer. The operation is + * complete when all the data has been sent. + * + * *If the size of the buffer is greater than the size of the endpoint + * (or twice the size if the endpoint has two FIFO banks), then the buffer + * must be kept allocated until the transfer is finished*. This means that + * it is not possible to declare it on the stack (i.e. as a local variable + * of a function which returns after starting a transfer). + * + * \param pEndpoint Pointer to Endpoint struct. + * \param pData Pointer to a buffer with the data to send. + * \param dLength Size of the data buffer. + * \return USBD_STATUS_SUCCESS if the transfer has been started; + * otherwise, the corresponding error status code. + */ +static inline uint8_t UDP_Write(uint8_t bEndpoint, + const void *pData, + uint32_t dLength) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer); + + /* Check that the endpoint is in Idle state */ + if (pEndpoint->state != UDP_ENDPOINT_IDLE) { + + return USBD_STATUS_LOCKED; + } + TRACE_DEBUG_WP("Write%d(%d) ", bEndpoint, dLength); + + /* Setup the transfer descriptor */ + pTransfer->pData = (void *) pData; + pTransfer->remaining = dLength; + pTransfer->buffered = 0; + pTransfer->transferred = 0; + + /* Send the first packet */ + pEndpoint->state = UDP_ENDPOINT_SENDING; + while((UDP->UDP_CSR[bEndpoint]&UDP_CSR_TXPKTRDY)==UDP_CSR_TXPKTRDY); + UDP_WritePayload(bEndpoint); + SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY); + + /* If double buffering is enabled and there is data remaining, + prepare another packet */ + if ((CHIP_USB_ENDPOINTS_BANKS(bEndpoint) > 1) && (pTransfer->remaining > 0)) { + + UDP_WritePayload(bEndpoint); + } + + /* Enable interrupt on endpoint */ + UDP->UDP_IER = 1 << bEndpoint; + + return USBD_STATUS_SUCCESS; +} + +/** + * Sends data through a USB endpoint. Sets up the transfer descriptor list, + * writes one or two data payloads (depending on the number of FIFO bank + * for the endpoint) and then starts the actual transfer. The operation is + * complete when all the transfer buffer in the list has been sent. + * + * *If the size of the buffer is greater than the size of the endpoint + * (or twice the size if the endpoint has two FIFO banks), then the buffer + * must be kept allocated until the transfer is finished*. This means that + * it is not possible to declare it on the stack (i.e. as a local variable + * of a function which returns after starting a transfer). + * + * \param pEndpoint Pointer to Endpoint struct. + * \param pData Pointer to a buffer with the data to send. + * \param dLength Size of the data buffer. + * \return USBD_STATUS_SUCCESS if the transfer has been started; + * otherwise, the corresponding error status code. + */ +static inline uint8_t UDP_AddWr(uint8_t bEndpoint, + const void *pData, + uint32_t dLength) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + MblTransfer *pMbl = (MblTransfer*)&(pEndpoint->transfer); + USBDTransferBuffer *pTx; + + /* Check parameter */ + if (dLength >= 0x10000) + return USBD_STATUS_INVALID_PARAMETER; + + /* Data in progressing */ + if (pEndpoint->state > UDP_ENDPOINT_IDLE) { + /* If list full */ + if (pMbl->listState == MBL_FULL) { + return USBD_STATUS_LOCKED; + } + } + + TRACE_DEBUG_WP("AddW%d(%d) ", bEndpoint, dLength); + + /* Add buffer to buffer list and update index */ + pTx = &(pMbl->pMbl[pMbl->inCurr]); + pTx->pBuffer = (uint8_t*)pData; + pTx->size = pTx->remaining = dLength; + pTx->transferred = pTx->buffered = 0; + /* Update input index */ + if (pMbl->inCurr >= (pMbl->listSize-1)) pMbl->inCurr = 0; + else pMbl->inCurr ++; + if (pMbl->inCurr == pMbl->outCurr) pMbl->listState = MBL_FULL; + else pMbl->listState = 0; + /* Start sending when offset achieved */ + if (MBL_NbBuffer(pMbl->inCurr, pMbl->outCurr, pMbl->listSize) + >= pMbl->offsetSize + && pEndpoint->state == UDP_ENDPOINT_IDLE) { + TRACE_DEBUG_WP("StartT "); + /* Change state */ + pEndpoint->state = UDP_ENDPOINT_SENDINGM; + while((UDP->UDP_CSR[bEndpoint]&UDP_CSR_TXPKTRDY)==UDP_CSR_TXPKTRDY); + /* Send first packet */ + UDP_MblWriteFifo(bEndpoint); + SET_CSR(bEndpoint, UDP_CSR_TXPKTRDY); + /* If double buffering is enabled and there is remaining, continue */ + if ((CHIP_USB_ENDPOINTS_BANKS(bEndpoint) > 1) + && pMbl->pMbl[pMbl->outCurr].remaining) { + UDP_MblWriteFifo(bEndpoint); + } + /* Enable interrupt on endpoint */ + UDP->UDP_IER = 1 << bEndpoint; + } + + return USBD_STATUS_SUCCESS; +} + +/** + * Reads incoming data on an USB endpoint This methods sets the transfer + * descriptor and activate the endpoint interrupt. The actual transfer is + * then carried out by the endpoint interrupt handler. The Read operation + * finishes either when the buffer is full, or a short packet (inferior to + * endpoint maximum size) is received. + * + * *The buffer must be kept allocated until the transfer is finished*. + * \param bEndpoint Endpoint number. + * \param pData Pointer to a data buffer. + * \param dLength Size of the data buffer in bytes. + * \return USBD_STATUS_SUCCESS if the read operation has been started; + * otherwise, the corresponding error code. + */ +static inline uint8_t UDP_Read(uint8_t bEndpoint, + void *pData, + uint32_t dLength) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + Transfer *pTransfer = (Transfer*)&(pEndpoint->transfer); + + /* Return if the endpoint is not in IDLE state */ + if (pEndpoint->state != UDP_ENDPOINT_IDLE) { + + return USBD_STATUS_LOCKED; + } + + /* Endpoint enters Receiving state */ + pEndpoint->state = UDP_ENDPOINT_RECEIVING; + TRACE_DEBUG_WP("Read%d(%d) ", bEndpoint, dLength); + + /* Set the transfer descriptor */ + pTransfer->pData = pData; + pTransfer->remaining = dLength; + pTransfer->buffered = 0; + pTransfer->transferred = 0; + + /* Enable interrupt on endpoint */ + UDP->UDP_IER = 1 << bEndpoint; + + return USBD_STATUS_SUCCESS; +} + + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/** + * USBD (UDP) interrupt handler + * Manages device resume, suspend, end of bus reset. + * Forwards endpoint events to the appropriate handler. + */ +void USBD_IrqHandler(void) +{ + uint32_t status; + int32_t eptnum = 0; + + /* Enable peripheral ? */ + //UDP_EnablePeripheralClock(); + + /* Get interrupt status + Some interrupts may get masked depending on the device state */ + status = UDP->UDP_ISR; + status &= UDP->UDP_IMR; + + if (USBD_GetState() < USBD_STATE_POWERED) { + + status &= UDP_ICR_WAKEUP | UDP_ICR_RXRSM; + UDP->UDP_ICR = ~status; + } + + /* Return immediately if there is no interrupt to service */ + if (status == 0) { + + TRACE_DEBUG_WP(".\n\r"); + return; + } + + /* Toggle USB LED if the device is active */ + if (USBD_GetState() >= USBD_STATE_POWERED) { + + //LED_Set(USBD_LEDUSB); + } + + /* Service interrupts */ + + /** / Start Of Frame (SOF) */ + //if (ISSET(dStatus, UDP_ISR_SOFINT)) { + // + // TRACE_DEBUG("SOF"); + // + // // Invoke the SOF callback + // USB_StartOfFrameCallback(pUsb); + // + // // Acknowledge interrupt + // UDP->UDP_ICR = UDP_ICR_SOFINT; + // dStatus &= ~UDP_ISR_SOFINT; + //} + /* Resume (Wakeup) */ + if ((status & (UDP_ISR_WAKEUP | UDP_ISR_RXRSM)) != 0) { + + TRACE_INFO_WP("Res "); + /* Clear and disable resume interrupts */ + UDP->UDP_ICR = UDP_ICR_WAKEUP | UDP_ICR_RXRSM | UDP_ICR_RXSUSP; + UDP->UDP_IDR = UDP_IDR_WAKEUP | UDP_IDR_RXRSM; + /* Do resome operations */ + USBD_ResumeHandler(); + } + + /* Suspend + This interrupt is always treated last (hence the '==') */ + if (status == UDP_ISR_RXSUSP) { + + TRACE_INFO_WP("Susp "); + /* Enable wakeup */ + UDP->UDP_IER = UDP_IER_WAKEUP | UDP_IER_RXRSM; + /* Acknowledge interrupt */ + UDP->UDP_ICR = UDP_ICR_RXSUSP; + /* Do suspend operations */ + USBD_SuspendHandler(); + } + /* End of bus reset */ + else if ((status & UDP_ISR_ENDBUSRES) != 0) { + + TRACE_INFO_WP("EoBRes "); + /* Flush and enable the Suspend interrupt */ + UDP->UDP_ICR = UDP_ICR_WAKEUP | UDP_ICR_RXRSM | UDP_ICR_RXSUSP; + UDP->UDP_IER = UDP_IER_RXSUSP; + + /* Do RESET operations */ + USBD_ResetHandler(); + + /* Acknowledge end of bus reset interrupt */ + UDP->UDP_ICR = UDP_ICR_ENDBUSRES; + } + /* Endpoint interrupts */ + else { + + status &= ((1 << CHIP_USB_NUMENDPOINTS) - 1); + while (status != 0) { + + /* Check if endpoint has a pending interrupt */ + if ((status & (1 << eptnum)) != 0) { + + UDP_EndpointHandler(eptnum); + status &= ~(1 << eptnum); + + if (status != 0) { + + TRACE_INFO_WP("\n\r - "); + } + } + eptnum++; + } + } + + /* Toggle LED back to its previous state */ + TRACE_DEBUG_WP("!"); + TRACE_INFO_WP("\n\r"); + if (USBD_GetState() >= USBD_STATE_POWERED) { + + //LED_Clear(USBD_LEDUSB); + } +} + +/** + * \brief Reset endpoints and disable them. + * -# Terminate transfer if there is any, with given status; + * -# Reset the endpoint & disable it. + * \param bmEPs Bitmap for endpoints to reset. + * \param bStatus Status passed to terminate transfer on endpoint. + * \param bKeepCfg 1 to keep old endpoint configuration. + * \note Use USBD_HAL_ConfigureEP() to configure and enable endpoint + if not keeping old configuration. + * \sa USBD_HAL_ConfigureEP(). + */ +void USBD_HAL_ResetEPs(uint32_t bmEPs, uint8_t bStatus, uint8_t bKeepCfg) +{ + Endpoint *pEndpoint; + uint32_t tmp = bmEPs & ((1<UDP_IDR = epBit; + /* Kill pending TXPKTREADY */ + CLEAR_CSR(ep, UDP_CSR_TXPKTRDY); + + /* Reset transfer information */ + pEndpoint = &(endpoints[ep]); + /* Reset endpoint state */ + pEndpoint->bank = 0; + /* Endpoint configure */ + epCfg = UDP->UDP_CSR[ep]; + /* Reset endpoint */ + UDP->UDP_RST_EP |= epBit; + UDP->UDP_RST_EP &= ~epBit; + /* Restore configure */ + if (bKeepCfg) { + //SET_CSR(ep, pEndpoint->CSR); + SET_CSR(ep, epCfg); + } + else { + //pEndpoint->CSR = 0; + pEndpoint->state = UDP_ENDPOINT_DISABLED; + } + + /* Terminate transfer on this EP */ + UDP_EndOfTransfer(ep, bStatus); + } + epBit <<= 1; + } + /* Reset EPs */ + // UDP->UDP_RST_EP |= bmEPs; + // UDP->UDP_RST_EP &= ~bmEPs; +} + +/** + * Cancel pending READ/WRITE + * \param bmEPs Bitmap for endpoints to reset. + * \note EP callback is invoked with USBD_STATUS_CANCELED. + */ +void USBD_HAL_CancelIo(uint32_t bmEPs) +{ + uint32_t tmp = bmEPs & ((1<UDP_IDR = epBit; + /* Kill pending TXPKTREADY */ + CLEAR_CSR(ep, UDP_CSR_TXPKTRDY); + + /* Terminate transfer on this EP */ + UDP_EndOfTransfer(ep, USBD_STATUS_CANCELED); + } + epBit <<= 1; + } +} + +/** + * Configures an endpoint according to its endpoint Descriptor. + * \param pDescriptor Pointer to an endpoint descriptor. + */ +uint8_t USBD_HAL_ConfigureEP(const USBEndpointDescriptor *pDescriptor) +{ + Endpoint *pEndpoint; + uint8_t bEndpoint; + uint8_t bType; + uint8_t bEndpointDir; + + /* NULL descriptor -> Control endpoint 0 in default */ + if (pDescriptor == 0) { + bEndpoint = 0; + pEndpoint = &(endpoints[bEndpoint]); + bType= USBEndpointDescriptor_CONTROL; + bEndpointDir = 0; + pEndpoint->size = CHIP_USB_ENDPOINTS_MAXPACKETSIZE(0); + } + /* Device descriptor -> Specific Control EP */ + else if (pDescriptor->bDescriptorType == USBGenericDescriptor_DEVICE) { + bEndpoint = 0; + pEndpoint = &(endpoints[bEndpoint]); + bType = USBEndpointDescriptor_CONTROL; + bEndpointDir = 0; + pEndpoint->size = ((USBDeviceDescriptor *)pDescriptor)->bMaxPacketSize0; + } + /* Not endpoint descriptor, ERROR! */ + else if (pDescriptor->bDescriptorType != USBGenericDescriptor_ENDPOINT) { + return 0xFF; + } + else { + bEndpoint = USBEndpointDescriptor_GetNumber(pDescriptor); + pEndpoint = &(endpoints[bEndpoint]); + bType = USBEndpointDescriptor_GetType(pDescriptor); + bEndpointDir = USBEndpointDescriptor_GetDirection(pDescriptor); + pEndpoint->size = USBEndpointDescriptor_GetMaxPacketSize(pDescriptor); + } + + /* Abort the current transfer is the endpoint was configured and in + Write or Read state */ + if ((pEndpoint->state == UDP_ENDPOINT_RECEIVING) + || (pEndpoint->state == UDP_ENDPOINT_SENDING) + || (pEndpoint->state == UDP_ENDPOINT_RECEIVINGM) + || (pEndpoint->state == UDP_ENDPOINT_SENDINGM)) { + UDP_EndOfTransfer(bEndpoint, USBD_STATUS_RESET); + } + pEndpoint->state = UDP_ENDPOINT_IDLE; + + /* Reset Endpoint Fifos */ + UDP->UDP_RST_EP |= (1 << bEndpoint); + UDP->UDP_RST_EP &= ~(1 << bEndpoint); + + /* Configure endpoint */ + SET_CSR(bEndpoint, (uint32_t)UDP_CSR_EPEDS + | (bType << 8) | (bEndpointDir << 10)); + if (bType != USBEndpointDescriptor_CONTROL) { + + } + else { + + UDP->UDP_IER = (1 << bEndpoint); + } + + TRACE_INFO_WP("CfgEp%d ", bEndpoint); + return bEndpoint; +} + +/** + * Set callback for a USB endpoint for transfer (read/write). + * + * \param bEP Endpoint number. + * \param fCallback Optional callback function to invoke when the transfer is + * complete. + * \param pCbData Optional pointer to data to the callback function. + * \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED if endpoint is busy. + */ +uint8_t USBD_HAL_SetTransferCallback(uint8_t bEP, + TransferCallback fCallback, + void *pCbData) +{ + Endpoint *pEndpoint = &(endpoints[bEP]); + TransferHeader *pTransfer = (TransferHeader*)&(pEndpoint->transfer); + /* Check that the endpoint is not transferring */ + if (pEndpoint->state > UDP_ENDPOINT_IDLE) { + return USBD_STATUS_LOCKED; + } + TRACE_DEBUG_WP("sXfrCb "); + /* Setup the transfer callback and extension data */ + pTransfer->fCallback = (void*)fCallback; + pTransfer->pArgument = pCbData; + return USBD_STATUS_SUCCESS; +} + +/** + * Configure an endpoint to use multi-buffer-list transfer mode. + * The buffers can be added by _Read/_Write function. + * \param pMbList Pointer to a multi-buffer list used, NULL to disable MBL. + * \param mblSize Multi-buffer list size (number of buffers can be queued) + * \param startOffset When number of buffer achieve this offset transfer start + */ +uint8_t USBD_HAL_SetupMblTransfer( uint8_t bEndpoint, + USBDTransferBuffer* pMbList, + uint16_t mblSize, + uint16_t startOffset) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + MblTransfer *pXfr = (MblTransfer*)&(pEndpoint->transfer); + uint16_t i; + /* Check that the endpoint is not transferring */ + if (pEndpoint->state > UDP_ENDPOINT_IDLE) { + return USBD_STATUS_LOCKED; + } + TRACE_DEBUG_WP("sMblXfr "); + /* Enable Multi-Buffer Transfer List */ + if (pMbList) { + /* Reset list items */ + for (i = 0; i < mblSize; i --) { + pMbList[i].pBuffer = NULL; + pMbList[i].size = 0; + pMbList[i].transferred = 0; + pMbList[i].buffered = 0; + pMbList[i].remaining = 0; + } + /* Setup transfer */ + pXfr->transType = 1; + pXfr->listState = 0; /* OK */ + pXfr->listSize = mblSize; + pXfr->pMbl = pMbList; + pXfr->outCurr = pXfr->outLast = 0; + pXfr->inCurr = 0; + pXfr->offsetSize = startOffset; + } + /* Disable Multi-Buffer Transfer */ + else { + pXfr->transType = 0; + pXfr->pMbl = NULL; + pXfr->listSize = 0; + pXfr->offsetSize = 1; + } + return USBD_STATUS_SUCCESS; +} + +/** + * Sends data through a USB endpoint. Sets up the transfer descriptor, + * writes one or two data payloads (depending on the number of FIFO bank + * for the endpoint) and then starts the actual transfer. The operation is + * complete when all the data has been sent. + * + * *If the size of the buffer is greater than the size of the endpoint + * (or twice the size if the endpoint has two FIFO banks), then the buffer + * must be kept allocated until the transfer is finished*. This means that + * it is not possible to declare it on the stack (i.e. as a local variable + * of a function which returns after starting a transfer). + * + * \param bEndpoint Endpoint number. + * \param pData Pointer to a buffer with the data to send. + * \param dLength Size of the data buffer. + * \return USBD_STATUS_SUCCESS if the transfer has been started; + * otherwise, the corresponding error status code. + */ +uint8_t USBD_HAL_Write( uint8_t bEndpoint, + const void *pData, + uint32_t dLength) +{ + if (endpoints[bEndpoint].transfer.transHdr.transType) + return UDP_AddWr(bEndpoint, pData, dLength); + else + return UDP_Write(bEndpoint, pData, dLength); +} + +/** + * Reads incoming data on an USB endpoint This methods sets the transfer + * descriptor and activate the endpoint interrupt. The actual transfer is + * then carried out by the endpoint interrupt handler. The Read operation + * finishes either when the buffer is full, or a short packet (inferior to + * endpoint maximum size) is received. + * + * *The buffer must be kept allocated until the transfer is finished*. + * \param bEndpoint Endpoint number. + * \param pData Pointer to a data buffer. + * \param dLength Size of the data buffer in bytes. + * \return USBD_STATUS_SUCCESS if the read operation has been started; + * otherwise, the corresponding error code. + */ +uint8_t USBD_HAL_Read(uint8_t bEndpoint, + void *pData, + uint32_t dLength) +{ + if (endpoints[bEndpoint].transfer.transHdr.transType) + return USBD_STATUS_SW_NOT_SUPPORTED; + else + return UDP_Read(bEndpoint, pData, dLength); +} + +/** + * \brief Enable Pull-up, connect. + * + * -# Enable HW access if needed + * -# Enable Pull-Up + * -# Disable HW access if needed + */ +void USBD_HAL_Connect(void) +{ + uint8_t dis = UDP_EnablePeripheralClock(); + UDP->UDP_TXVC |= UDP_TXVC_PUON; + if (dis) UDP_DisablePeripheralClock(); +} + +/** + * \brief Disable Pull-up, disconnect. + * + * -# Enable HW access if needed + * -# Disable PULL-Up + * -# Disable HW access if needed + */ +void USBD_HAL_Disconnect(void) +{ + uint8_t dis = UDP_EnablePeripheralClock(); + UDP->UDP_TXVC &= ~(uint32_t)UDP_TXVC_PUON; + if (dis) UDP_DisablePeripheralClock(); +} + +/** + * Starts a remote wake-up procedure. + */ +void USBD_HAL_RemoteWakeUp(void) +{ + UDP_EnablePeripheralClock(); + UDP_EnableUsbClock(); + UDP_EnableTransceiver(); + + TRACE_INFO_WP("RWUp "); + + // Activates a remote wakeup (edge on ESR), then clear ESR + UDP->UDP_GLB_STAT |= UDP_GLB_STAT_ESR; + UDP->UDP_GLB_STAT &= ~(uint32_t)UDP_GLB_STAT_ESR; +} + +/** + * Sets the device address to the given value. + * \param address New device address. + */ +void USBD_HAL_SetAddress(uint8_t address) +{ + /* Set address */ + UDP->UDP_FADDR = UDP_FADDR_FEN | (address & UDP_FADDR_FADD_Msk); + /* If the address is 0, the device returns to the Default state */ + if (address == 0) UDP->UDP_GLB_STAT = 0; + /* If the address is non-zero, the device enters the Address state */ + else UDP->UDP_GLB_STAT = UDP_GLB_STAT_FADDEN; +} + +/** + * Sets the current device configuration. + * \param cfgnum - Configuration number to set. + */ +void USBD_HAL_SetConfiguration(uint8_t cfgnum) +{ + /* If the configuration number if non-zero, the device enters the + Configured state */ + if (cfgnum != 0) UDP->UDP_GLB_STAT |= UDP_GLB_STAT_CONFG; + /* If the configuration number is zero, the device goes back to the Address + state */ + else { + UDP->UDP_GLB_STAT = UDP_FADDR_FEN; + } +} + +/** + * Initializes the USB HW Access driver. + */ +void USBD_HAL_Init(void) +{ + /* Must before USB & TXVC access! */ + UDP_EnablePeripheralClock(); + + /* Reset & disable endpoints */ + USBD_HAL_ResetEPs(0xFFFFFFFF, USBD_STATUS_RESET, 0); + + /* Configure the pull-up on D+ and disconnect it */ + UDP->UDP_TXVC &= ~(uint32_t)UDP_TXVC_PUON; + + UDP_EnableUsbClock(); + + UDP->UDP_IDR = 0xFE; + UDP->UDP_IER = UDP_IER_WAKEUP; +} + +/** + * Causes the given endpoint to acknowledge the next packet it receives + * with a STALL handshake except setup request. + * \param bEP Endpoint number. + * \return USBD_STATUS_SUCCESS or USBD_STATUS_LOCKED. + */ +uint8_t USBD_HAL_Stall(uint8_t bEP) +{ + Endpoint *pEndpoint = &(endpoints[bEP]); + + /* Check that endpoint is in Idle state */ + if (pEndpoint->state != UDP_ENDPOINT_IDLE) { + TRACE_WARNING("UDP_Stall: EP%d locked\n\r", bEP); + return USBD_STATUS_LOCKED; + } + /* STALL endpoint */ + SET_CSR(bEP, UDP_CSR_FORCESTALL); + TRACE_DEBUG_WP("Stall%d ", bEP); + return USBD_STATUS_SUCCESS; +} + +/** + * Sets/Clear/Get the HALT state on the endpoint. + * In HALT state, the endpoint should keep stalling any packet. + * \param bEndpoint Endpoint number. + * \param ctl Control code CLR/HALT/READ. + * 0: Clear HALT state; + * 1: Set HALT state; + * .: Return HALT status. + * \return USBD_STATUS_INVALID_PARAMETER if endpoint not exist, + * otherwise endpoint halt status. + */ +uint8_t USBD_HAL_Halt(uint8_t bEndpoint, uint8_t ctl) +{ + Endpoint *pEndpoint = &(endpoints[bEndpoint]); + uint8_t status = 0; + + /* SET Halt */ + if (ctl == 1) { + /* Check that endpoint is enabled and not already in Halt state */ + if ((pEndpoint->state != UDP_ENDPOINT_DISABLED) + && (pEndpoint->state != UDP_ENDPOINT_HALTED)) { + + TRACE_DEBUG_WP("Halt%d ", bEndpoint); + + /* Abort the current transfer if necessary */ + UDP_EndOfTransfer(bEndpoint, USBD_STATUS_ABORTED); + + /* Put endpoint into Halt state */ + SET_CSR(bEndpoint, UDP_CSR_FORCESTALL); + pEndpoint->state = UDP_ENDPOINT_HALTED; + + /* Enable the endpoint interrupt */ + UDP->UDP_IER = 1 << bEndpoint; + } + } + /* CLEAR Halt */ + else if (ctl == 0) { + /* Check if the endpoint is halted */ + //if (pEndpoint->state != UDP_ENDPOINT_DISABLED) { + if (pEndpoint->state == UDP_ENDPOINT_HALTED) { + + TRACE_DEBUG_WP("Unhalt%d ", bEndpoint); + + /* Return endpoint to Idle state */ + pEndpoint->state = UDP_ENDPOINT_IDLE; + + /* Clear FORCESTALL flag */ + CLEAR_CSR(bEndpoint, UDP_CSR_FORCESTALL); + + /* Reset Endpoint Fifos, beware this is a 2 steps operation */ + UDP->UDP_RST_EP |= 1 << bEndpoint; + UDP->UDP_RST_EP &= ~(1 << bEndpoint); + } + } + + /* Return Halt status */ + if (pEndpoint->state == UDP_ENDPOINT_HALTED) { + status = 1; + } + return( status ); +} + +/** + * Indicates if the device is running in high or full-speed. Always returns 0 + * since UDP does not support high-speed mode. + */ +uint8_t USBD_HAL_IsHighSpeed(void) +{ + return 0; +} + +/** + * Suspend USB Device HW Interface + * + * -# Disable transceiver + * -# Disable USB Clock + * -# Disable USB Peripheral + */ +void USBD_HAL_Suspend(void) +{ + /* The device enters the Suspended state */ + UDP_DisableTransceiver(); + UDP_DisableUsbClock(); + UDP_DisablePeripheralClock(); +} + +/** + * Activate USB Device HW Interface + * -# Enable USB Peripheral + * -# Enable USB Clock + * -# Enable transceiver + */ +void USBD_HAL_Activate(void) +{ + UDP_EnablePeripheralClock(); + UDP_EnableUsbClock(); + UDP_EnableTransceiver(); +} + +/**@}*/ + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/acc.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/acc.c new file mode 100644 index 00000000..76f4e47d --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/acc.c @@ -0,0 +1,162 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup acc_module Working with ACC + * The ACC driver provides the interface to configure and use the ACC peripheral.\n + * + * It applies comparison on two inputs and gives a compare output. + * + * To Enable a ACC Comparison,the user has to follow these few steps: + *
    + *
  • Enable ACC peripheral clock by setting the corresponding bit in PMC_PCER1 + * (PMC Peripheral Clock Enable Register 1) + *
  • + *
  • Reset the controller by asserting ACC_CR_SWRST in ACC_CR(ACC Control Register) +
  • + *
  • Configure the mode as following steps:
  • + * -# Select inputs for SELMINUS and SELPLUS in ACC_MR (ACC Mode Register). + * -# Enable Analog Comparator by setting ACEN in ACC_MR. + * -# Configure Edge Type to detect different compare output. + * + *
  • Wait until the automatic mask period expires by polling MASK bit in + * ACC_ISR. + *
+ * + * For more accurate information, please look at the ACC section of the + * Datasheet. + * + * Related files :\n + * \ref acc.c\n + * \ref acc.h\n + */ +/*@{*/ +/*@}*/ +/** + * \file + * + * Implementation of Analog Comparator Controller (ACC). + * + */ +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "chip.h" + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Initialize the ACC controller + * + * \param pAcc Pointer to an Acc instance. + * \param idAcc ACC identifier + * \param ucSelplus input connected to inp, 0~7 + * \param ucSelminus input connected to inm,0~7 + * \param wAc_en Analog comprator enabled/disabled + * \param wEdge CF flag triggering mode + * \param wInvert INVert comparator output,use pattern defined in the device header file + */ +extern void ACC_Configure( Acc *pAcc, uint8_t idAcc, uint8_t ucSelplus, uint8_t ucSelminus, + uint16_t wAc_en, uint16_t wEdge, uint16_t wInvert ) +{ + /* Enable peripheral clock*/ + PMC->PMC_PCER1 = 1 << (idAcc - 32) ; + + /* Reset the controller */ + pAcc->ACC_CR |= ACC_CR_SWRST ; + + /* Write to the MR register */ + ACC_CfgModeReg( pAcc, + ( (ucSelplus<ACC_ACR = (ACC_ACR_ISEL_HISP | ((0x01 << ACC_ACR_HYST_Pos) & ACC_ACR_HYST_Msk)); + + /* Automatic Output Masking Period*/ + while ( pAcc->ACC_ISR & (uint32_t)ACC_ISR_MASK ) ; +} + +/** + * Return the Channel Converted Data + * \param pAcc Pointer to an Acc instance. + * \param selplus input applied on ACC SELPLUS + * \param selminus input applied on ACC SELMINUS + */ +extern void ACC_SetComparisionPair( Acc *pAcc, uint8_t ucSelplus, uint8_t ucSelminus ) +{ + uint32_t dwTemp ; + + assert( ucSelplus < 8 && ucSelminus < 8 ) ; + + dwTemp = pAcc->ACC_MR ; + + pAcc->ACC_MR = dwTemp & (uint32_t) ((~ACC_MR_SELMINUS_Msk) & (~ACC_MR_SELPLUS_Msk)); + + pAcc->ACC_MR |= ( ((ucSelplus << ACC_MR_SELPLUS_Pos) & ACC_MR_SELPLUS_Msk) | + ((ucSelminus << ACC_MR_SELMINUS_Pos) & ACC_MR_SELMINUS_Msk) ) ; + +} +/** + * Return Comparison Result + * \param pAcc Pointer to an Acc instance. + * \param status value of ACC_ISR + */ +extern uint32_t ACC_GetComparisionResult( Acc *pAcc, uint32_t dwStatus ) +{ + uint32_t dwTemp = pAcc->ACC_MR ; + + if ( (dwTemp & ACC_MR_INV) == ACC_MR_INV ) + { + if ( dwStatus & ACC_ISR_SCO ) + { + return 0 ; /* inn>inp*/ + } + else + { + return 1 ;/* inp>inn*/ + } + } + else + { + if ( dwStatus & ACC_ISR_SCO ) + { + return 1 ; /* inp>inn*/ + } + else + { + return 0 ;/* inn>inp*/ + } + } +} + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/adc.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/adc.c new file mode 100644 index 00000000..95c9d5b2 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/adc.c @@ -0,0 +1,417 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup adc_module Working with ADC + * The ADC driver provides the interface to configure and use the ADC peripheral. + * \n + * + * It converts the analog input to digital format. The converted result could be + * 12bit or 10bit. The ADC supports up to 16 analog lines. + * + * To Enable a ADC conversion,the user has to follow these few steps: + *
    + *
  • Select an appropriate reference voltage on ADVREF
  • + *
  • Configure the ADC according to its requirements and special needs,which + * could be broken down into several parts: + * -# Select the resolution by setting or clearing ADC_MR_LOWRES bit in + * ADC_MR (Mode Register) + * -# Set ADC clock by setting ADC_MR_PRESCAL bits in ADC_MR, the clock is + * calculated with ADCClock = MCK / ( (PRESCAL+1) * 2 ) + * -# Set Startup Time,Tracking Clock cycles and Transfer Clock respectively + * in ADC_MR. +
  • + *
  • Start conversion by setting ADC_CR_START in ADC_CR.
  • + *
+ * + * For more accurate information, please look at the ADC section of the + * Datasheet. + * + * Related files :\n + * \ref adc.c\n + * \ref adc.h\n + */ +/*@{*/ +/*@}*/ +/** + * \file + * + * Implementation of Analog-to-Digital Converter (ADC). + * + */ +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "chip.h" + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Initialize the ADC controller + * + * \param pAdc Pointer to an Adc instance. + * \param idAdc ADC Index + * \param trgEn trigger mode, software or Hardware + * \param trgSel hardware trigger selection + * \param sleepMode sleep mode selection + * \param resolution resolution selection 10 bits or 12 bits + * \param mckClock value of MCK in Hz + * \param adcClock value of the ADC clock in Hz + * \param startup value of the start up time (in ADCClock) (see datasheet) + * \param tracking Tracking Time (in ADCClock cycle) + */ +extern void ADC_Initialize( Adc* pAdc, uint32_t idAdc ) +{ + /* Enable peripheral clock*/ + PMC->PMC_PCER0 = 1 << idAdc; + + /* Reset the controller */ + pAdc->ADC_CR = ADC_CR_SWRST; + + /* Reset Mode Register set to default */ + /* TrackTime set to 0 */ + /* Transfer set to 1 */ + /* settling set to 3 */ + pAdc->ADC_MR = ADC_MR_TRANSFER(1) | ADC_MR_TRACKTIM(0) | ADC_MR_SETTLING(3); +} + +/** + * \brief Initialize the ADC Timing + */ +extern void ADC_CfgTiming( Adc* pAdc, uint32_t tracking, uint32_t settling, uint32_t transfer ) +{ + pAdc->ADC_MR = ADC_MR_TRANSFER( transfer ) + | ADC_MR_SETTLING( settling ) + | ADC_MR_TRACKTIM( tracking ) ; +} + +/** + * \brief Initialize the ADC Timing + */ +extern void ADC_cfgFrequency( Adc* pAdc, uint32_t startup, uint32_t prescal ) +{ + pAdc->ADC_MR |= ADC_MR_PRESCAL( prescal ) + | ( (startup<ADC_MR |= ((trgEn<<0) & ADC_MR_TRGEN) + | ((trgSel<ADC_MR |= (resolution<<4) & ADC_MR_LOWRES; +} + +/** + * \brief Initialize the ADC PowerSave + */ +extern void ADC_CfgPowerSave( Adc* pAdc, uint32_t sleep, uint32_t fwup ) +{ + pAdc->ADC_MR |= ( ((sleep<<5) & ADC_MR_SLEEP) + | ((fwup<<6) & ADC_MR_FWUP) ); +} + +/** + * \brief Initialize the ADC Channel Mode + */ +extern void ADC_CfgChannelMode( Adc* pAdc, uint32_t useq, uint32_t anach ) +{ + pAdc->ADC_MR |= ( ((anach<<23) & ADC_MR_ANACH) + | ((useq <<31) & (uint32_t)ADC_MR_USEQ) ); +} + + +/** + * \brief calcul_startup + */ +static uint32_t calcul_startup( uint32_t startup ) +{ + uint32_t startup_value=0; + + if( startup == 0 ) + startup_value = 0; + else if( startup == 1 ) + startup_value = 8; + else if( startup == 2 ) + startup_value = 16; + else if( startup == 3 ) + startup_value = 24; + else if( startup == 4 ) + startup_value = 64; + else if( startup == 5 ) + startup_value = 80; + else if( startup == 6 ) + startup_value = 96; + else if( startup == 7 ) + startup_value = 112; + else if( startup == 8 ) + startup_value = 512; + else if( startup == 9 ) + startup_value = 576; + else if( startup == 10 ) + startup_value = 640; + else if( startup == 11 ) + startup_value = 704; + else if( startup == 12 ) + startup_value = 768; + else if( startup == 13 ) + startup_value = 832; + else if( startup == 14 ) + startup_value = 896; + else if( startup == 15 ) + startup_value = 960; + + return startup_value; +} + +/** + * \brief ADC check + */ +extern void ADC_check( Adc* pAdc, uint32_t mck_freq ) +{ + uint32_t adc_freq; + uint32_t prescal; + uint32_t startup; + + /* ADCClock = MCK / ( (PRESCAL+1) * 2 ) */ + prescal = (( pAdc->ADC_MR & ADC_MR_PRESCAL_Msk) >> ADC_MR_PRESCAL_Pos); + adc_freq = mck_freq / ((prescal+1)*2); + printf("ADC clock frequency = %d Hz\r\n", (int)adc_freq ); + + if( adc_freq < ADC_FREQ_MIN ) + { + printf("adc frequency too low (out of specification: %d Hz)\r\n", (int)ADC_FREQ_MIN); + } + if( adc_freq > ADC_FREQ_MAX ) + { + printf("adc frequency too high (out of specification: %d Hz)\r\n", (int)ADC_FREQ_MAX); + } + + startup = (( pAdc->ADC_MR & ADC_MR_STARTUP_Msk) >> ADC_MR_STARTUP_Pos); + if( !(pAdc->ADC_MR & ADC_MR_SLEEP_SLEEP) ) + { + /* 40µs */ + if( ADC_STARTUP_NORM * adc_freq / 1000000 > calcul_startup(startup) ) + { + printf("Startup time too small: %d, programmed: %d\r\n", (int)(ADC_STARTUP_NORM * adc_freq / 1000000), (int)calcul_startup(startup)); + } + } + else + { + if(pAdc->ADC_MR & ADC_MR_FREERUN_ON) + { + printf("FreeRun forbidden in sleep mode\n\r"); + } + if( !(pAdc->ADC_MR & ADC_MR_FWUP_ON) ) + { + /* Sleep 40µs */ + if( ADC_STARTUP_NORM * adc_freq / 1000000 > calcul_startup(startup) ) + { + printf("Startup time too small: %d, programmed: %d\r\n", (int)(ADC_STARTUP_NORM * adc_freq / 1000000), (int)(calcul_startup(startup))); + } + } + else + { + if( pAdc->ADC_MR & ADC_MR_FWUP_ON ) + { + /* Fast Wake Up Sleep Mode: 12µs */ + if( ADC_STARTUP_FAST * adc_freq / 1000000 > calcul_startup(startup) ) + { + printf("Startup time too small: %d, programmed: %d\r\n", (int)(ADC_STARTUP_NORM * adc_freq / 1000000), (int)(calcul_startup(startup))); + } + } + } + } + + + + +} + + + +/** + * Return the Channel Converted Data + * + * \param pAdc Pointer to an Adc instance. + * \param channel channel to get converted value + */ +extern uint32_t ADC_GetConvertedData( Adc* pAdc, uint32_t dwChannel ) +{ + uint32_t dwData = 0; + + assert( dwChannel < 16 ) ; + + if ( 15 >= dwChannel ) + { + dwData=*(pAdc->ADC_CDR+dwChannel) ; + } + + return dwData ; +} +/** + * Set compare channel + * + * \param pAdc Pointer to an Adc instance. + * \param channel channel number to be set,16 for all channels + */ +extern void ADC_SetCompareChannel( Adc* pAdc, uint32_t dwChannel ) +{ + assert( dwChannel <= 16 ) ; + + if ( dwChannel < 16 ) + { + pAdc->ADC_EMR &= (uint32_t)~(ADC_EMR_CMPALL); + pAdc->ADC_EMR &= (uint32_t)~(ADC_EMR_CMPSEL_Msk); + pAdc->ADC_EMR |= (dwChannel << ADC_EMR_CMPSEL_Pos); + } + else + { + pAdc->ADC_EMR |= ADC_EMR_CMPALL; + } +} +/** + * Set compare mode + * + * \param pAdc Pointer to an Adc instance. + * \param mode compare mode + */ +extern void ADC_SetCompareMode( Adc* pAdc, uint32_t dwMode ) +{ + pAdc->ADC_EMR &= (uint32_t)~(ADC_EMR_CMPMODE_Msk); + pAdc->ADC_EMR |= (dwMode & ADC_EMR_CMPMODE_Msk) ; +} +/** + * Set comparsion window,one thereshold each time + * + * \param pAdc Pointer to an Adc instance. + * \param hi_lo Comparison Window + */ +extern void ADC_SetComparisonWindow( Adc* pAdc, uint32_t dwHi_Lo ) +{ + pAdc->ADC_CWR = dwHi_Lo ; +} + +/**---------------------------------------------------------------------------- + * Test if ADC Interrupt is Masked + * + * \param pAdc Pointer to an Adc instance. + * \param flag flag to be tested + * + * \return 1 if interrupt is masked, otherwise 0 + */ +uint32_t ADC_IsInterruptMasked( Adc* pAdc, uint32_t dwFlag ) +{ + return (ADC_GetInterruptMaskStatus( pAdc ) & dwFlag) ; +} + +/**---------------------------------------------------------------------------- + * Test if ADC Status is Set + * + * \param pAdc Pointer to an Adc instance. + * \param flag flag to be tested + * + * \return 1 if the staus is set; 0 otherwise + */ +extern uint32_t ADC_IsStatusSet( Adc* pAdc, uint32_t dwFlag ) +{ + return (ADC_GetStatus( pAdc ) & dwFlag) ; +} + +/**---------------------------------------------------------------------------- + * Test if ADC channel interrupt Status is Set + * + * \param adc_sr Value of SR register + * \param channel Channel to be tested + * + * \return 1 if interrupt status is set, otherwise 0 + */ +extern uint32_t ADC_IsChannelInterruptStatusSet( uint32_t dwAdc_sr, uint32_t dwChannel ) +{ + uint32_t dwStatus ; + + if ( (dwAdc_sr & ((uint32_t)1 << dwChannel)) == ((uint32_t)1 << dwChannel) ) + { + dwStatus = 1 ; + } + else + { + dwStatus = 0 ; + } + + return dwStatus ; +} + +/** + * \brief Read converted data through PDC channel + * + * \param pADC the pointer of adc peripheral + * \param pBuffer the destination buffer + * \param dwSize the size of the buffer + */ +extern uint32_t ADC_ReadBuffer( Adc* pADC, int16_t *pwBuffer, uint32_t dwSize ) +{ + /* Check if the first PDC bank is free*/ + if ( (pADC->ADC_RCR == 0) && (pADC->ADC_RNCR == 0) ) + { + pADC->ADC_RPR = (uint32_t)pwBuffer ; + pADC->ADC_RCR = dwSize ; + pADC->ADC_PTCR = ADC_PTCR_RXTEN; + + return 1; + } + /* Check if the second PDC bank is free*/ + else + { + if ( pADC->ADC_RNCR == 0 ) + { + pADC->ADC_RNPR = (uint32_t)pwBuffer ; + pADC->ADC_RNCR = dwSize ; + + return 1 ; + } + else + { + return 0 ; + } + } +} + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/async.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/async.c new file mode 100644 index 00000000..b202be22 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/async.c @@ -0,0 +1,53 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Provide a routine for asynchronos transfer. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ +#include "chip.h" + +/*---------------------------------------------------------------------------- + * Global functions + *----------------------------------------------------------------------------*/ + /** + * \brief Returns 1 if the given transfer has ended; otherwise returns 0. + * \param pAsync Pointer to an Async instance. + */ +uint32_t ASYNC_IsFinished( Async* pAsync ) +{ + return (pAsync->status != ASYNC_STATUS_PENDING) ; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/crccu.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/crccu.c new file mode 100644 index 00000000..d356cf17 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/crccu.c @@ -0,0 +1,112 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup crccu_module Working with CRCCU + * The CRCCU driver provides the interface to configure and use the CRCCU + * peripheral. + * + * It performs a CRC computation on a Memory Area. CRC computation is performed + * from the LSB to MSB bit. Three different polynomials are available: + * CCIT802.3, CASTAGNOLI and CCIT16. + * + * To computes CRC of a buffer, the user has to follow these few steps: + *
    + *
  • Reset initial CRC by setting RESET bit in CRCCU_CRC_CR,
  • + *
  • Configure CRC descriptor and working mode,
  • + *
  • Start to compute CRC by setting DMAEN in CRCCU_DMA_EN,
  • + *
  • Get CRC value in CRCCU_CRC_SR.
  • + *
+ * + * For more accurate information, please look at the CRCCU section of the + * Datasheet. + * + * Related files :\n + * \ref crccu.c\n + * \ref crccu.h.\n +*/ +/*@{*/ +/*@}*/ + +/** + * \file + * + * Implementation of Cyclic Redundancy Check Calculation Unit (CRCCU). + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ +#include "chip.h" + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ +#define CRCCU_TIMEOUT 0xFFFFFFFF + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ +/** + * \brief Reset initial CRC to 0xFFFFFFFF. + */ +extern void CRCCU_ResetCrcValue( Crccu* pCrccu ) +{ + pCrccu->CRCCU_CR = CRCCU_CR_RESET; +} + +/** + * \brief Configure the CRCCU. + * + * \param dscrAddr CRC decscriptor address. + * \param mode CRC work mode + */ +extern void CRCCU_Configure( Crccu* pCrccu, uint32_t dwDscrAddr, uint32_t dwMode ) +{ + pCrccu->CRCCU_DSCR = dwDscrAddr ; + pCrccu->CRCCU_MR = dwMode ; +} + +/** + * \brief Start to compute the CRC of a buffer. + * + * \return The CRC of the buffer. + */ +extern uint32_t CRCCU_ComputeCrc( Crccu* pCrccu ) +{ + uint32_t dwTimeout = 0 ; + + pCrccu->CRCCU_DMA_EN = CRCCU_DMA_EN_DMAEN ; + + while ( ((pCrccu->CRCCU_DMA_SR & CRCCU_DMA_SR_DMASR) == CRCCU_DMA_SR_DMASR) && + (dwTimeout++ < CRCCU_TIMEOUT) ) ; + + return (pCrccu->CRCCU_SR) ; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/dacc.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/dacc.c new file mode 100644 index 00000000..ae460dfc --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/dacc.c @@ -0,0 +1,183 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup dacc_module Working with DACC + * The DACC driver provides the interface to configure and use the DACC peripheral.\n + * + * The DACC(Digital-to-Analog Converter Controller) converts digital code to analog output. + * The data to be converted are sent in a common register for all channels. It offers up to 2 + * analog outputs.The output voltage ranges from (1/6)ADVREF to (5/6)ADVREF. + * + * To Enable a DACC conversion,the user has to follow these few steps: + *
    + *
  • Select an appropriate reference voltage on ADVREF
  • + *
  • Configure the DACC according to its requirements and special needs,which could be + broken down into several parts: + * -# Enable DACC in free running mode by clearing TRGEN in DACC_MR; + * -# Configure Startup Time and Refresh Period through setting STARTUP and REFRESH fields + * in DACC_MR; The refresh mechanism is used to protect the output analog value from + * decreasing. + * -# Enable channels and write digital code to DACC_CDR,in free running mode, the conversion + * is started right after at least one channel is enabled and data is written . +
  • + *
+ * + * For more accurate information, please look at the DACC section of the + * Datasheet. + * + * Related files :\n + * \ref DACC.c\n + * \ref DACC.h\n +*/ +/*@{*/ +/*@}*/ +/** + * \file + * + * Implementation of Digital-to-Analog Converter Controller (DACC). + * + */ +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "chip.h" + +#include +#include + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Initialize the DACC controller + * \param pDACC Pointer to an DACC instance. + * \param idDACC identifier of DAC peripheral + * \param trgEn trigger mode, free running mode or external Hardware trigger + * \param word transfer size,word or half word + * \param trgSel hardware trigger selection + * \param sleepMode sleep mode selection + * \param mck value of MCK in Hz + * \param refresh refresh period + * \param user_sel user channel selection ,0 or 1 + * \param tag_mode tag for channel number + * \param startup value of the start up time (in DACCClock) (see datasheet) +*/ +extern void DACC_Initialize( Dacc* pDACC, + uint8_t idDACC, + uint8_t trgEn, + uint8_t trgSel, + uint8_t word, + uint8_t sleepMode, + uint32_t mck, + uint8_t refresh, /* refresh period */ + uint8_t user_sel, /* user channel selection */ + uint32_t tag_mode, /* using tag for channel number */ + uint32_t startup + ) +{ + assert( 1024*refresh*1000/(mck>>1) < 20 ) ; + + /* Enable peripheral clock*/ + PMC->PMC_PCER0 = 1 << idDACC; + + /* Reset the controller */ + DACC_SoftReset(pDACC); + + /* Write to the MR register */ + DACC_CfgModeReg( pDACC, + ( (trgEn<<0) & DACC_MR_TRGEN) + | DACC_MR_TRGSEL(trgSel) + | ( (word<<4) & DACC_MR_WORD) + | ( (sleepMode<<5) & DACC_MR_SLEEP) + | DACC_MR_REFRESH(refresh) + | ( (user_sel<DACC_MR ; + + if ( dwMR & DACC_MR_WORD ) + { + pDACC->DACC_CDR = dwData ; + } + else + { + pDACC->DACC_CDR = (dwData&0xFFFF) ; + } +} + + +/** + * \brief Write converted data through PDC channel + * \param pDACC the pointer of DACC peripheral + * \param pBuffer the destination buffer + * \param size the size of the buffer +*/ +extern uint32_t DACC_WriteBuffer( Dacc* pDACC, uint16_t *pwBuffer, uint32_t dwSize ) +{ + + /* Check if the first PDC bank is free*/ + if ( (pDACC->DACC_TCR == 0) && (pDACC->DACC_TNCR == 0) ) + { + pDACC->DACC_TPR = (uint32_t)pwBuffer ; + pDACC->DACC_TCR = dwSize ; + pDACC->DACC_PTCR = DACC_PTCR_TXTEN ; + + return 1 ; + } + /* Check if the second PDC bank is free*/ + else + { + if (pDACC->DACC_TNCR == 0) + { + pDACC->DACC_TNPR = (uint32_t)pwBuffer ; + pDACC->DACC_TNCR = dwSize ; + + return 1 ; + } + else + { + return 0 ; + } + } + +} + + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/efc.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/efc.c new file mode 100644 index 00000000..97104d5e --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/efc.c @@ -0,0 +1,289 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup efc_module Working with EEFC + * The EEFC driver provides the interface to configure and use the EEFC + * peripheral. + * + * The user needs to set the number of wait states depending on the frequency used.\n + * Configure number of cycles for flash read/write operations in the FWS field of EEFC_FMR. + * + * It offers a function to send flash command to EEFC and waits for the + * flash to be ready. + * + * To send flash command, the user could do in either of following way: + *
    + *
  • Write a correct key, command and argument in EEFC_FCR.
  • + *
  • Or, Use IAP (In Application Programming) function which is executed from + * ROM directly, this allows flash programming to be done by code running in flash.
  • + *
  • Once the command is achieved, it can be detected even by polling EEFC_FSR or interrupt. + *
+ * + * The command argument could be a page number,GPNVM number or nothing, it depends on + * the command itself. Some useful functions in this driver could help user tranlate physical + * flash address into a page number and vice verse. + * + * For more accurate information, please look at the EEFC section of the + * Datasheet. + * + * Related files :\n + * \ref efc.c\n + * \ref efc.h.\n +*/ +/*@{*/ +/*@}*/ + + +/** + * \file + * + * Implementation of Enhanced Embedded Flash Controller (EEFC). + * + */ + + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ +#include "chip.h" + +#include + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Enables the flash ready interrupt source on the EEFC peripheral. + * + * \param efc Pointer to a Efc instance + */ +extern void EFC_EnableFrdyIt( Efc* efc ) +{ + efc->EEFC_FMR |= EEFC_FMR_FRDY ; +} + +/** + * \brief Disables the flash ready interrupt source on the EEFC peripheral. + * + * \param efc Pointer to a Efc instance + */ + +extern void EFC_DisableFrdyIt( Efc* efc ) +{ + efc->EEFC_FMR &= ~((uint32_t)EEFC_FMR_FRDY) ; +} + + +/** + * \brief Set read/write wait state on the EEFC perpherial. + * + * \param efc Pointer to a Efc instance + * \param cycles the number of wait states in cycle. + */ + +extern void EFC_SetWaitState( Efc* efc, uint8_t ucCycles ) +{ + uint32_t dwValue ; + + dwValue = efc->EEFC_FMR ; + dwValue &= ~((uint32_t)EEFC_FMR_FWS_Msk) ; + dwValue |= EEFC_FMR_FWS(ucCycles); + efc->EEFC_FMR = dwValue ; +} + +/** + * \brief Returns the current status of the EEFC. + * + * \note Keep in mind that this function clears the value of some status bits (LOCKE, PROGE). + * + * \param efc Pointer to a Efc instance + */ +extern uint32_t EFC_GetStatus( Efc* efc ) +{ + return efc->EEFC_FSR ; +} + +/** + * \brief Returns the result of the last executed command. + * + * \param efc Pointer to a Efc instance + */ +extern uint32_t EFC_GetResult( Efc* efc ) +{ + return efc->EEFC_FRR ; +} + +/** + * \brief Translates the given address page and offset values. + * \note The resulting values are stored in the provided variables if they are not null. + * + * \param efc Pointer to a Efc instance + * \param address Address to translate. + * \param pPage First page accessed. + * \param pOffset Byte offset in first page. + */ +extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwPage, uint16_t* pwOffset ) +{ + Efc *pEfc ; + uint16_t wPage ; + uint16_t wOffset ; + + assert( dwAddress >= IFLASH_ADDR ) ; + assert( dwAddress <= (IFLASH_ADDR + IFLASH_SIZE) ) ; + + pEfc = EFC ; + wPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE; + wOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE; + + TRACE_DEBUG( "Translated 0x%08X to page=%d and offset=%d\n\r", dwAddress, wPage, wOffset ) ; + /* Store values */ + if ( pEfc ) + { + *ppEfc = pEfc ; + } + + if ( pwPage ) + { + *pwPage = wPage ; + } + + if ( pwOffset ) + { + *pwOffset = wOffset ; + } +} + +/** + * \brief Computes the address of a flash access given the page and offset. + * + * \param efc Pointer to a Efc instance + * \param page Page number. + * \param offset Byte offset inside page. + * \param pAddress Computed address (optional). + */ +extern void EFC_ComputeAddress( Efc *efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress ) +{ + uint32_t dwAddress ; + + assert( efc ) ; + assert( wPage <= IFLASH_NB_OF_PAGES ) ; + assert( wOffset < IFLASH_PAGE_SIZE ) ; + + /* Compute address */ + dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset ; + + /* Store result */ + if ( pdwAddress != NULL ) + { + *pdwAddress = dwAddress ; + } +} + +/** + * \brief Starts the executing the given command on the EEFC and returns as soon as the command is started. + * + * \note It does NOT set the FMCN field automatically. + * \param efc Pointer to a Efc instance + * \param command Command to execute. + * \param argument Command argument (should be 0 if not used). + */ +extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument ) +{ + /* Check command & argument */ + switch ( dwCommand ) + { + case EFC_FCMD_WP: + case EFC_FCMD_WPL: + case EFC_FCMD_EWP: + case EFC_FCMD_EWPL: + case EFC_FCMD_SLB: + case EFC_FCMD_CLB: + assert( dwArgument < IFLASH_NB_OF_PAGES ) ; + break ; + + case EFC_FCMD_SFB: + case EFC_FCMD_CFB: + assert( dwArgument < 2 ) ; + break; + + case EFC_FCMD_GETD: + case EFC_FCMD_EA: + case EFC_FCMD_GLB: + case EFC_FCMD_GFB: + case EFC_FCMD_STUI: + assert( dwArgument == 0 ) ; + break; + + default: assert( 0 ) ; + } + + /* Start command Embedded flash */ + assert( (efc->EEFC_FSR & EEFC_FMR_FRDY) == EEFC_FMR_FRDY ) ; + efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ; +} + +/** + * \brief Performs the given command and wait until its completion (or an error). + * + * \param efc Pointer to a Efc instance + * \param command Command to perform. + * \param argument Optional command argument. + * + * \return 0 if successful, otherwise returns an error code. + */ + +extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP ) +{ + if ( dwUseIAP != 0 ) + { + /* Pointer on IAP function in ROM */ + static uint32_t (*IAP_PerformCommand)( uint32_t, uint32_t ) ; + + IAP_PerformCommand = (uint32_t (*)( uint32_t, uint32_t )) *((uint32_t*)CHIP_FLASH_IAP_ADDRESS ) ; + IAP_PerformCommand( 0, EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ) ; + + return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)) ; + } + else + { + uint32_t dwStatus ; + + efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ; + do + { + dwStatus = efc->EEFC_FSR ; + } + while ( (dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ; + + return ( dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE) ) ; + } +} + + diff --git a/sam3s_example/src/exceptions.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/exceptions.c similarity index 100% rename from sam3s_example/src/exceptions.c rename to sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/exceptions.c diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/flashd.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/flashd.c new file mode 100644 index 00000000..7dc7276c --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/flashd.c @@ -0,0 +1,512 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup flashd_module Flash Memory Interface + * The flash driver manages the programming, erasing, locking and unlocking sequences + * with dedicated commands. + * + * To implement flash programing operation, the user has to follow these few steps : + *
    + *
  • Configue flash wait states to initializes the flash.
  • + *
  • Checks whether a region to be programmed is locked.
  • + *
  • Unlocks the user region to be programmed if the region have locked before.
  • + *
  • Erases the user page before program (optional).
  • + *
  • Writes the user page from the page buffer.
  • + *
  • Locks the region of programmed area if any.
  • + *
+ * + * Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption. + * A check of this validity and padding for 32-bit alignment should be done in write algorithm. + + * Lock/unlock range associated with the user address range is automatically translated. + * + * This security bit can be enabled through the command "Set General Purpose NVM Bit 0". + * + * A 128-bit factory programmed unique ID could be read to serve several purposes. + * + * The driver accesses the flash memory by calling the lowlevel module provided in \ref efc_module. + * For more accurate information, please look at the EEFC section of the Datasheet. + * + * Related files :\n + * \ref flashd.c\n + * \ref flashd.h.\n + * \ref efc.c\n + * \ref efc.h.\n +*/ +/*@{*/ +/*@}*/ + + +/** + * \file + * + * The flash driver provides the unified interface for flash program operations. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ +#include "chip.h" + +#include +#include + +/*---------------------------------------------------------------------------- + * Local variables + *----------------------------------------------------------------------------*/ + +//static NO_INIT uint8_t _aucPageBuffer[IFLASH_PAGE_SIZE] ; +static NO_INIT uint32_t _adwPageBuffer[IFLASH_PAGE_SIZE/4] ; +static uint8_t* _aucPageBuffer = (uint8_t*)_adwPageBuffer; +static NO_INIT uint32_t _dwUseIAP ; + +/*---------------------------------------------------------------------------- + * Local macros + *----------------------------------------------------------------------------*/ + +#define min( a, b ) (((a) < (b)) ? (a) : (b)) + +/*---------------------------------------------------------------------------- + * Local functions + *----------------------------------------------------------------------------*/ + + +/** + * \brief Computes the lock range associated with the given address range. + * + * \param dwStart Start address of lock range. + * \param dwEnd End address of lock range. + * \param pdwActualStart Actual start address of lock range. + * \param pdwActualEnd Actual end address of lock range. + */ +static void ComputeLockRange( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd ) +{ + Efc* pStartEfc ; + Efc* pEndEfc ; + uint16_t wStartPage ; + uint16_t wEndPage ; + uint16_t wNumPagesInRegion ; + uint16_t wActualStartPage ; + uint16_t wActualEndPage ; + + // Convert start and end address in page numbers + EFC_TranslateAddress( &pStartEfc, dwStart, &wStartPage, 0 ) ; + EFC_TranslateAddress( &pEndEfc, dwEnd, &wEndPage, 0 ) ; + + // Find out the first page of the first region to lock + wNumPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE ; + wActualStartPage = wStartPage - (wStartPage % wNumPagesInRegion) ; + wActualEndPage = wEndPage ; + + if ( (wEndPage % wNumPagesInRegion) != 0 ) + { + wActualEndPage += wNumPagesInRegion - (wEndPage % wNumPagesInRegion) ; + } + // Store actual page numbers + EFC_ComputeAddress( pStartEfc, wActualStartPage, 0, pdwActualStart ) ; + EFC_ComputeAddress( pEndEfc, wActualEndPage, 0, pdwActualEnd ) ; + TRACE_DEBUG( "Actual lock range is 0x%06X - 0x%06X\n\r", *pdwActualStart, *pdwActualEnd ) ; +} + + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Initializes the flash driver. + * + * \param mck Master clock frequency in Hz. + */ + +extern void FLASHD_Initialize( uint32_t dwMCk, uint32_t dwUseIAP ) +{ + EFC_DisableFrdyIt( EFC ) ; + + if ( (dwMCk/1000000) >= 64 ) + { + EFC_SetWaitState( EFC, 2 ) ; + } + else + { + if ( (dwMCk/1000000) >= 50 ) + { + EFC_SetWaitState( EFC, 1 ) ; + } + else + { + EFC_SetWaitState( EFC, 0 ) ; + } + } + + _dwUseIAP=dwUseIAP ; +} + +/** + * \brief Erases the entire flash. + * + * \param address Flash start address. + * \return 0 if successful; otherwise returns an error code. + */ +extern uint32_t FLASHD_Erase( uint32_t dwAddress ) +{ + Efc* pEfc ; + uint16_t wPage ; + uint16_t wOffset ; + uint32_t dwError ; + + assert( (dwAddress >=IFLASH_ADDR) || (dwAddress <= (IFLASH_ADDR + IFLASH_SIZE)) ) ; + + // Translate write address + EFC_TranslateAddress( &pEfc, dwAddress, &wPage, &wOffset ) ; + dwError = EFC_PerformCommand( pEfc, EFC_FCMD_EA, 0, _dwUseIAP ) ; + + return dwError ; +} + +/** + * \brief Writes a data buffer in the internal flash + * + * \note This function works in polling mode, and thus only returns when the + * data has been effectively written. + * \param address Write address. + * \param pBuffer Data buffer. + * \param size Size of data buffer in bytes. + * \return 0 if successful, otherwise returns an error code. + */ +extern uint32_t FLASHD_Write( uint32_t dwAddress, const void *pvBuffer, uint32_t dwSize ) +{ + Efc* pEfc ; + uint16_t page ; + uint16_t offset ; + uint32_t writeSize ; + uint32_t pageAddress ; + uint16_t padding ; + uint32_t dwError ; + uint32_t sizeTmp ; + uint32_t *pAlignedDestination ; + uint32_t *pAlignedSource ; + + assert( pvBuffer ) ; + assert( dwAddress >=IFLASH_ADDR ) ; + assert( (dwAddress + dwSize) <= (IFLASH_ADDR + IFLASH_SIZE) ) ; + + /* Translate write address */ + EFC_TranslateAddress( &pEfc, dwAddress, &page, &offset ) ; + + /* Write all pages */ + while ( dwSize > 0 ) + { + /* Copy data in temporary buffer to avoid alignment problems */ + writeSize = min((uint32_t)IFLASH_PAGE_SIZE - offset, dwSize ) ; + EFC_ComputeAddress(pEfc, page, 0, &pageAddress ) ; + padding = IFLASH_PAGE_SIZE - offset - writeSize ; + + /* Pre-buffer data */ + memcpy( _aucPageBuffer, (void *) pageAddress, offset); + + /* Buffer data */ + memcpy( _aucPageBuffer + offset, pvBuffer, writeSize); + + /* Post-buffer data */ + memcpy( _aucPageBuffer + offset + writeSize, (void *) (pageAddress + offset + writeSize), padding); + + /* Write page + * Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption + */ + pAlignedDestination = (uint32_t*)pageAddress ; + pAlignedSource = (uint32_t*)_adwPageBuffer ; + sizeTmp = IFLASH_PAGE_SIZE ; + + while ( sizeTmp >= 4 ) + { + *pAlignedDestination++ = *pAlignedSource++; + sizeTmp -= 4; + } + + /* Send writing command */ + dwError = EFC_PerformCommand( pEfc, EFC_FCMD_EWP, page, _dwUseIAP ) ; + if ( dwError ) + { + return dwError ; + } + + /* Progression */ + dwAddress += IFLASH_PAGE_SIZE ; + pvBuffer = (void *)((uint32_t) pvBuffer + writeSize) ; + dwSize -= writeSize ; + page++; + offset = 0; + } + + return 0 ; +} +/** + * \brief Locks all the regions in the given address range. The actual lock range is + * reported through two output parameters. + * + * \param start Start address of lock range. + * \param end End address of lock range. + * \param pActualStart Start address of the actual lock range (optional). + * \param pActualEnd End address of the actual lock range (optional). + * \return 0 if successful, otherwise returns an error code. + */ +extern uint32_t FLASHD_Lock( uint32_t start, uint32_t end, uint32_t *pActualStart, uint32_t *pActualEnd ) +{ + Efc *pEfc ; + uint32_t actualStart, actualEnd ; + uint16_t startPage, endPage ; + uint32_t dwError ; + uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE; + + /* Compute actual lock range and store it */ + ComputeLockRange( start, end, &actualStart, &actualEnd ) ; + if ( pActualStart != NULL ) + { + *pActualStart = actualStart ; + } + if ( pActualEnd != NULL ) + { + *pActualEnd = actualEnd; + } + + /* Compute page numbers */ + EFC_TranslateAddress( &pEfc, actualStart, &startPage, 0 ) ; + EFC_TranslateAddress( 0, actualEnd, &endPage, 0 ) ; + + /* Lock all pages */ + while ( startPage < endPage ) + { + dwError = EFC_PerformCommand( pEfc, EFC_FCMD_SLB, startPage, _dwUseIAP ) ; + if ( dwError ) + { + return dwError ; + } + startPage += numPagesInRegion; + } + + return 0 ; +} + +/** + * \brief Unlocks all the regions in the given address range. The actual unlock range is + * reported through two output parameters. + * \param start Start address of unlock range. + * \param end End address of unlock range. + * \param pActualStart Start address of the actual unlock range (optional). + * \param pActualEnd End address of the actual unlock range (optional). + * \return 0 if successful, otherwise returns an error code. + */ +extern uint32_t FLASHD_Unlock( uint32_t start, uint32_t end, uint32_t *pActualStart, uint32_t *pActualEnd ) +{ + Efc* pEfc ; + uint32_t actualStart, actualEnd ; + uint16_t startPage, endPage ; + uint32_t dwError ; + uint16_t numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE; + + // Compute actual unlock range and store it + ComputeLockRange(start, end, &actualStart, &actualEnd); + if ( pActualStart != NULL ) + { + *pActualStart = actualStart ; + } + if ( pActualEnd != NULL ) + { + *pActualEnd = actualEnd ; + } + + // Compute page numbers + EFC_TranslateAddress( &pEfc, actualStart, &startPage, 0 ) ; + EFC_TranslateAddress( 0, actualEnd, &endPage, 0 ) ; + + // Unlock all pages + while ( startPage < endPage ) + { + dwError = EFC_PerformCommand( pEfc, EFC_FCMD_CLB, startPage, _dwUseIAP ) ; + if ( dwError ) + { + return dwError ; + } + startPage += numPagesInRegion ; + } + return 0 ; +} + +/** + * \brief Returns the number of locked regions inside the given address range. + * + * \param start Start address of range + * \param end End address of range. + */ +extern uint32_t FLASHD_IsLocked( uint32_t start, uint32_t end ) +{ + Efc *pEfc ; + uint16_t startPage, endPage ; + uint8_t startRegion, endRegion ; + uint32_t numPagesInRegion ; + uint32_t status ; + uint32_t dwError ; + uint32_t numLockedRegions = 0 ; + + assert( end >= start ) ; + assert( (start >=IFLASH_ADDR) && (end <= IFLASH_ADDR + IFLASH_SIZE) ) ; + + // Compute page numbers + EFC_TranslateAddress( &pEfc, start, &startPage, 0 ) ; + EFC_TranslateAddress( 0, end, &endPage, 0 ) ; + + // Compute region numbers + numPagesInRegion = IFLASH_LOCK_REGION_SIZE / IFLASH_PAGE_SIZE ; + startRegion = startPage / numPagesInRegion ; + endRegion = endPage / numPagesInRegion ; + if ((endPage % numPagesInRegion) != 0) + { + endRegion++ ; + } + + // Retrieve lock status + dwError = EFC_PerformCommand( pEfc, EFC_FCMD_GLB, 0, _dwUseIAP ) ; + assert( !dwError ) ; + status = EFC_GetResult( pEfc ) ; + + // Check status of each involved region + while ( startRegion < endRegion ) + { + if ( (status & (1 << startRegion)) != 0 ) + { + numLockedRegions++ ; + } + startRegion++ ; + } + + return numLockedRegions ; +} + +/** + * \brief Check if the given GPNVM bit is set or not. + * + * \param gpnvm GPNVM bit index. + * \returns 1 if the given GPNVM bit is currently set; otherwise returns 0. + */ +extern uint32_t FLASHD_IsGPNVMSet( uint8_t ucGPNVM ) +{ + uint32_t dwError ; + uint32_t dwStatus ; + + assert( ucGPNVM < 2 ) ; + + /* Get GPNVMs status */ + dwError = EFC_PerformCommand( EFC, EFC_FCMD_GFB, 0, _dwUseIAP ) ; + assert( !dwError ) ; + dwStatus = EFC_GetResult( EFC ) ; + + /* Check if GPNVM is set */ + if ( (dwStatus & (1 << ucGPNVM)) != 0 ) + { + return 1 ; + } + else + { + return 0 ; + } +} + +/** + * \brief Sets the selected GPNVM bit. + * + * \param gpnvm GPNVM bit index. + * \returns 0 if successful; otherwise returns an error code. + */ +extern uint32_t FLASHD_SetGPNVM( uint8_t ucGPNVM ) +{ + assert( ucGPNVM < 2 ) ; + + if ( !FLASHD_IsGPNVMSet( ucGPNVM ) ) + { + return EFC_PerformCommand( EFC, EFC_FCMD_SFB, ucGPNVM, _dwUseIAP ) ; + } + else + { + return 0 ; + } +} + +/** + * \brief Clears the selected GPNVM bit. + * + * \param gpnvm GPNVM bit index. + * \returns 0 if successful; otherwise returns an error code. + */ +extern uint32_t FLASHD_ClearGPNVM( uint8_t ucGPNVM ) +{ + assert( ucGPNVM < 2 ) ; + + if ( FLASHD_IsGPNVMSet( ucGPNVM ) ) + { + return EFC_PerformCommand( EFC, EFC_FCMD_CFB, ucGPNVM, _dwUseIAP ) ; + } + else + { + return 0 ; + } +} +/** + * \brief Read the unique ID. + * + * \param uniqueID pointer on a 4bytes char containing the unique ID value. + * \returns 0 if successful; otherwise returns an error code. + */ +extern uint32_t FLASHD_ReadUniqueID( uint32_t* pdwUniqueID ) +{ + uint32_t dwError ; + + assert( pdwUniqueID != NULL ) ; + + pdwUniqueID[0] = 0 ; + pdwUniqueID[1] = 0 ; + pdwUniqueID[2] = 0 ; + pdwUniqueID[3] = 0 ; + + EFC_StartCommand( EFC, EFC_FCMD_STUI, 0 ) ; + + pdwUniqueID[0] = *(uint32_t*) IFLASH_ADDR; + pdwUniqueID[1] = *(uint32_t*)(IFLASH_ADDR + 4) ; + pdwUniqueID[2] = *(uint32_t*)(IFLASH_ADDR + 8) ; + pdwUniqueID[3] = *(uint32_t*)(IFLASH_ADDR + 12) ; + + dwError = EFC_PerformCommand( EFC, EFC_FCMD_SPUI, 0, _dwUseIAP ) ; + if ( dwError ) + { + return dwError ; + } + + return 0 ; +} diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/hsmci.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/hsmci.c new file mode 100644 index 00000000..bcc811b9 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/hsmci.c @@ -0,0 +1,262 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implementation of High Speed MultiMedia Card Interface (HSMCI) controller, + * not using PDC nor DMA to transfer data. + * + */ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ +#include "chip.h" + +#include + + +/*--------------------------------------------------------------------------- + * Local macros + *---------------------------------------------------------------------------*/ + +/** Reset MCI */ +#define MCI_RESET(pMciHw) (pMciHw->HSMCI_CR = HSMCI_CR_SWRST) + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/** + * Enable MCI + * \param pMciHw Pointer to a MCI peripheral. + */ +void MCI_Enable(Hsmci *pMciHw) +{ + pMciHw->HSMCI_CR = HSMCI_CR_MCIEN; +} + +/** + * Disable MCI + * \param pMciHw Pointer to a MCI peripheral. + */ +void MCI_Disable(Hsmci *pMciHw) +{ + pMciHw->HSMCI_CR = HSMCI_CR_MCIDIS; +} + +/** + * Initializes a MCI driver instance and the underlying peripheral. + * \param pMci Pointer to a MCI driver instance. + * \param pMciHw Pointer to a MCI peripheral. + * \param mciId MCI peripheral identifier. + */ +void MCI_Init( Mcid *pMci, Hsmci *pMciHw, uint8_t mciId, uint32_t dwMCk ) +{ + unsigned short clkDiv; + + /* Initialize the MCI driver structure */ + pMci->pMciHw = pMciHw; + pMci->mciId = mciId; + pMci->semaphore = 1; + pMci->pCommand = NULL; + + /* Enable the MCI peripheral */ + PMC_EnablePeripheral( mciId ) ; + + /* Reset the MCI */ + pMciHw->HSMCI_CR = HSMCI_CR_SWRST; + + /* Disable the MCI */ + pMciHw->HSMCI_CR = HSMCI_CR_MCIDIS | HSMCI_CR_PWSDIS; + + /* Disable all the interrupts */ + pMciHw->HSMCI_IDR = 0xFFFFFFFF; + + /* Set the Data Timeout Register */ + pMciHw->HSMCI_DTOR = HSMCI_DTOR_DTOCYC_Msk | HSMCI_DTOR_DTOMUL_Msk ; + /* CSTOR ? */ + pMciHw->HSMCI_CSTOR = HSMCI_CSTOR_CSTOCYC_Msk | HSMCI_CSTOR_CSTOMUL_Msk ; + + /* Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58) */ + clkDiv = (dwMCk / (MCI_INITIAL_SPEED * 2)) - 1; + pMciHw->HSMCI_MR = (clkDiv | (HSMCI_MR_PWSDIV( 0x07 )) ) ; + + /* Set the SDCard Register 1-bit, slot A */ + pMciHw->HSMCI_SDCR = HSMCI_SDCR_SDCSEL_SLOTA | HSMCI_SDCR_SDCBUS_1 ; + + /* Enable the MCI and the Power Saving */ + pMciHw->HSMCI_CR = HSMCI_CR_MCIEN; + + /* Configure MCI */ + pMciHw->HSMCI_CFG = HSMCI_CFG_FIFOMODE + | ((1 << 4) & HSMCI_CFG_FERRCTRL); + + /* Disable the MCI peripheral clock. */ + PMC_DisablePeripheral(mciId); +} + +/** + * Configure the MCI CLKDIV in the MCI_MR register. The max. for MCI clock is + * MCK/2 and corresponds to CLKDIV = 0 + * \param pMci Pointer to the low level MCI driver. + * \param mciSpeed MCI clock speed in Hz, 0 will not change current speed. + * \param mck MCK to generate MCI Clock, in Hz + * \return The actual speed used, 0 for fail. + */ +uint32_t MCI_SetSpeed( Mcid* pMci, uint32_t mciSpeed, uint32_t mck ) +{ + Hsmci *pMciHw = pMci->pMciHw; + uint32_t mciMr; + uint32_t clkdiv; + uint8_t mciDis; + + assert(pMci); + assert(pMciHw); + + PMC_EnablePeripheral(pMci->mciId); + mciDis = PMC_IsPeriphEnabled(pMci->mciId); + + mciMr = pMciHw->HSMCI_MR & (~(uint32_t)HSMCI_MR_CLKDIV_Msk); + /* Multimedia Card Interface clock (MCCK or MCI_CK) is Master Clock (MCK) + * divided by (2*(CLKDIV+1)) + * mciSpeed = MCK / (2*(CLKDIV+1)) */ + if (mciSpeed > 0) + { + clkdiv = (mck / 2 / mciSpeed); + /* Speed should not bigger than expired one */ + if (mciSpeed < mck/2/clkdiv) + { + clkdiv ++; + } + + if ( clkdiv > 0 ) + { + clkdiv -= 1; + } + assert( (clkdiv & 0xFFFFFF00) == 0 ) ; /* "mciSpeed too small" */ + } + else + { + clkdiv = 0 ; + } + + /* Actual MCI speed */ + mciSpeed = mck / 2 / (clkdiv + 1); + /* Modify MR */ + pMciHw->HSMCI_MR = mciMr | clkdiv; + if ( mciDis ) + { + PMC_DisablePeripheral( pMci->mciId ) ; + } + + return (mciSpeed); +} + +/** + * Configure the MCI_CFG to enable the HS mode + * \param pMci Pointer to the low level MCI driver. + * \param hsEnable 1 to enable, 0 to disable HS mode. + */ +uint8_t MCI_EnableHsMode(Mcid* pMci, uint8_t hsEnable) +{ + Hsmci *pMciHw = pMci->pMciHw; + uint32_t cfgr; + uint8_t mciDis; + uint8_t rc = 0; + + assert(pMci); + assert(pMci->pMciHw); + + PMC_EnablePeripheral(pMci->mciId); + mciDis = PMC_IsPeriphEnabled(pMci->mciId); + + cfgr = pMciHw->HSMCI_CFG; + if (hsEnable == 1) + { + cfgr |= HSMCI_CFG_HSMODE; + } + else + { + if (hsEnable == 0) + { + cfgr &= ~(uint32_t)HSMCI_CFG_HSMODE; + } + else + { + rc = ((cfgr & HSMCI_CFG_HSMODE) != 0); + } + } + + pMciHw->HSMCI_CFG = cfgr; + if (mciDis) + { + PMC_DisablePeripheral(pMci->mciId); + } + + return rc; +} + +/** + * Configure the MCI SDCBUS in the MCI_SDCR register. Only two modes available + * + * \param pMci Pointer to the low level MCI driver. + * \param busWidth MCI bus width mode. 00: 1-bit, 10: 4-bit, 11: 8-bit. + */ +uint32_t MCI_SetBusWidth(Mcid*pMci, uint32_t busWidth) +{ + Hsmci *pMciHw = pMci->pMciHw; + uint32_t mciSdcr; + uint8_t mciDis; + + assert(pMci); + assert(pMci->pMciHw); + + if( (busWidth != HSMCI_SDCR_SDCBUS_1) && (busWidth != HSMCI_SDCR_SDCBUS_4) && (busWidth != HSMCI_SDCR_SDCBUS_8) ) + { + return (uint32_t)-1; + } + + busWidth &= HSMCI_SDCR_SDCBUS_Msk ; + + PMC_EnablePeripheral(pMci->mciId); + mciDis = PMC_IsPeriphEnabled(pMci->mciId); + + mciSdcr = (pMciHw->HSMCI_SDCR & ~(uint32_t)(HSMCI_SDCR_SDCBUS_Msk)); + pMciHw->HSMCI_SDCR = mciSdcr | busWidth; + + if (mciDis) + { + PMC_DisablePeripheral(pMci->mciId); + } + + return 0; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/hsmci_pdc.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/hsmci_pdc.c new file mode 100644 index 00000000..9f794cce --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/hsmci_pdc.c @@ -0,0 +1,305 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implementation of High Speed MultiMedia Card Interface (HSMCI) controller, + * using PDC to transfer data. + * + */ +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include "chip.h" + +#include + +/*--------------------------------------------------------------------------- + * Local macros + *---------------------------------------------------------------------------*/ + +/** Reset MCI */ +#define MCI_RESET(pMciHw) (pMciHw->HSMCI_CR = HSMCI_CR_SWRST) + + +/*--------------------------------------------------------------------------- + * Exported functions + *---------------------------------------------------------------------------*/ + +/** + * Enable MCI + * \param pMciHw Pointer to a MCI peripheral. + */ +void MCI_Enable(Hsmci *pMciHw) +{ + pMciHw->HSMCI_CR = HSMCI_CR_MCIEN; +} + +/** + * Disable MCI + * \param pMciHw Pointer to a MCI peripheral. + */ +void MCI_Disable(Hsmci *pMciHw) +{ + pMciHw->HSMCI_CR = HSMCI_CR_MCIDIS; +} + +/** + * Initializes a MCI driver instance and the underlying peripheral. + * \param pMci Pointer to a MCI driver instance. + * \param pMciHw Pointer to a MCI peripheral. + * \param mciId MCI peripheral identifier. + */ +void MCI_Init( Mcid *pMci, Hsmci *pMciHw, uint8_t mciId, uint32_t dwMCk ) +{ + unsigned short clkDiv; + + /* Initialize the MCI driver structure */ + pMci->pMciHw = pMciHw; + pMci->mciId = mciId; + pMci->semaphore = 1; + pMci->pCommand = NULL; + + /* Enable the MCI peripheral */ + PMC_EnablePeripheral( mciId ) ; + + /* Reset the MCI */ + pMciHw->HSMCI_CR = HSMCI_CR_SWRST; + + /* Disable the MCI */ + pMciHw->HSMCI_CR = HSMCI_CR_MCIDIS | HSMCI_CR_PWSDIS; + + /* Disable all the interrupts */ + pMciHw->HSMCI_IDR = 0xFFFFFFFF; + + /* Set the Data Timeout Register */ + pMciHw->HSMCI_DTOR = HSMCI_DTOR_DTOCYC_Msk | HSMCI_DTOR_DTOMUL_Msk ; + /* CSTOR ? */ + pMciHw->HSMCI_CSTOR = HSMCI_CSTOR_CSTOCYC_Msk | HSMCI_CSTOR_CSTOMUL_Msk ; + + /* Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58) */ + clkDiv = (dwMCk / (MCI_INITIAL_SPEED * 2)) - 1; + pMciHw->HSMCI_MR = (clkDiv | (HSMCI_MR_PWSDIV( 0x07 )) ) ; + + /* Set the SDCard Register 1-bit, slot A */ + pMciHw->HSMCI_SDCR = HSMCI_SDCR_SDCSEL_SLOTA | HSMCI_SDCR_SDCBUS_1 ; + + /* Enable the MCI and the Power Saving */ + pMciHw->HSMCI_CR = HSMCI_CR_MCIEN; + + /* Configure MCI */ + pMciHw->HSMCI_CFG = HSMCI_CFG_FIFOMODE + | ((1 << 4) & HSMCI_CFG_FERRCTRL); + + /* Disable the MCI peripheral clock. */ + PMC_DisablePeripheral(mciId); +} + +/** + * Reset MCI HW interface and disable it. + * \param keepSettings Keep old register settings, including + * _MR, _SDCR, _DTOR, _CSTOR, _DMA and _CFG. + */ +void MCI_Reset(Mcid *pMci, uint8_t keepSettings) +{ + Hsmci *pMciHw = pMci->pMciHw; + uint8_t mciDis; + + assert(pMci); + assert(pMci->pMciHw); + + PMC_EnablePeripheral(pMci->mciId); + mciDis = PMC_IsPeriphEnabled(pMci->mciId); + if (keepSettings) + { + uint32_t mr, sdcr, dtor, cstor; + uint32_t cfg; + mr = pMciHw->HSMCI_MR; + sdcr = pMciHw->HSMCI_SDCR; + dtor = pMciHw->HSMCI_DTOR; + cstor = pMciHw->HSMCI_CSTOR; + cfg = pMciHw->HSMCI_CFG; + MCI_RESET(pMciHw); + MCI_Disable(pMciHw); + pMciHw->HSMCI_MR = mr; + pMciHw->HSMCI_SDCR = sdcr; + pMciHw->HSMCI_DTOR = dtor; + pMciHw->HSMCI_CSTOR = cstor; + pMciHw->HSMCI_CFG = cfg; + } + else + { + MCI_RESET(pMciHw); + MCI_Disable(pMciHw); + } + if ( mciDis ) + { + PMC_DisablePeripheral( pMci->mciId ) ; + } +} + +/** + * Configure the MCI CLKDIV in the MCI_MR register. The max. for MCI clock is + * MCK/2 and corresponds to CLKDIV = 0 + * \param pMci Pointer to the low level MCI driver. + * \param mciSpeed MCI clock speed in Hz, 0 will not change current speed. + * \param mck MCK to generate MCI Clock, in Hz + * \return The actual speed used, 0 for fail. + */ +uint32_t MCI_SetSpeed( Mcid* pMci, uint32_t mciSpeed, uint32_t mck ) +{ + Hsmci *pMciHw = pMci->pMciHw; + uint32_t mciMr; + uint32_t clkdiv; + uint8_t mciDis; + + assert(pMci); + assert(pMciHw); + + PMC_EnablePeripheral(pMci->mciId); + mciDis = PMC_IsPeriphEnabled(pMci->mciId); + + mciMr = pMciHw->HSMCI_MR & (~(uint32_t)HSMCI_MR_CLKDIV_Msk); + /* Multimedia Card Interface clock (MCCK or MCI_CK) is Master Clock (MCK) + * divided by (2*(CLKDIV+1)) + * mciSpeed = MCK / (2*(CLKDIV+1)) */ + if (mciSpeed > 0) + { + clkdiv = (mck / 2 / mciSpeed); + /* Speed should not bigger than expired one */ + if (mciSpeed < mck/2/clkdiv) + { + clkdiv ++; + } + + if ( clkdiv > 0 ) + { + clkdiv -= 1; + } + assert( (clkdiv & 0xFFFFFF00) == 0 ) ; /* "mciSpeed too small" */ + } + else + { + clkdiv = 0 ; + } + + /* Actual MCI speed */ + mciSpeed = mck / 2 / (clkdiv + 1); + /* Modify MR */ + pMciHw->HSMCI_MR = mciMr | clkdiv; + if ( mciDis ) + { + PMC_DisablePeripheral( pMci->mciId ) ; + } + + return (mciSpeed); +} + +/** + * Configure the MCI_CFG to enable the HS mode + * \param pMci Pointer to the low level MCI driver. + * \param hsEnable 1 to enable, 0 to disable HS mode. + */ +uint8_t MCI_EnableHsMode(Mcid* pMci, uint8_t hsEnable) +{ + Hsmci *pMciHw = pMci->pMciHw; + uint32_t cfgr; + uint8_t mciDis; + uint8_t rc = 0; + + assert(pMci); + assert(pMci->pMciHw); + + PMC_EnablePeripheral(pMci->mciId); + mciDis = PMC_IsPeriphEnabled(pMci->mciId); + + cfgr = pMciHw->HSMCI_CFG; + if (hsEnable == 1) + { + cfgr |= HSMCI_CFG_HSMODE; + } + else + { + if (hsEnable == 0) + { + cfgr &= ~(uint32_t)HSMCI_CFG_HSMODE; + } + else + { + rc = ((cfgr & HSMCI_CFG_HSMODE) != 0); + } + } + + pMciHw->HSMCI_CFG = cfgr; + if (mciDis) + { + PMC_DisablePeripheral(pMci->mciId); + } + + return rc; +} + +/** + * Configure the MCI SDCBUS in the MCI_SDCR register. Only two modes available + * + * \param pMci Pointer to the low level MCI driver. + * \param busWidth MCI bus width mode. 00: 1-bit, 10: 4-bit, 11: 8-bit. + */ +uint32_t MCI_SetBusWidth(Mcid*pMci, uint32_t busWidth) +{ + Hsmci *pMciHw = pMci->pMciHw; + uint32_t mciSdcr; + uint8_t mciDis; + + assert(pMci); + assert(pMci->pMciHw); + + if( (busWidth != HSMCI_SDCR_SDCBUS_1) && (busWidth != HSMCI_SDCR_SDCBUS_4) && (busWidth != HSMCI_SDCR_SDCBUS_8) ) + { + return (uint32_t)-1; + } + + busWidth &= HSMCI_SDCR_SDCBUS_Msk ; + + PMC_EnablePeripheral(pMci->mciId); + mciDis = PMC_IsPeriphEnabled(pMci->mciId); + + mciSdcr = (pMciHw->HSMCI_SDCR & ~(uint32_t)(HSMCI_SDCR_SDCBUS_Msk)); + pMciHw->HSMCI_SDCR = mciSdcr | busWidth; + + if (mciDis) + { + PMC_DisablePeripheral(pMci->mciId); + } + + return 0; +} + diff --git a/sam3s_example/src/pio.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pio.c similarity index 96% rename from sam3s_example/src/pio.c rename to sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pio.c index 3bc258e7..49a6741c 100644 --- a/sam3s_example/src/pio.c +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pio.c @@ -36,7 +36,6 @@ #include "pio.h" #include "pmc.h" - /*---------------------------------------------------------------------------- * Local functions *----------------------------------------------------------------------------*/ diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pio_capture.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pio_capture.c new file mode 100644 index 00000000..407a5c05 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pio_capture.c @@ -0,0 +1,283 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2010, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup pio_capture_module Working with PIO Parallel Capture Mode + * The PIO Parallel Capture Mode driver provides the interface to configure and use the + * PIO Parallel Capture Mode peripheral.\n + * + * The PIO Controller integrates an interface able to read data from a CMOS digital + * image sensor, a high-speed parallel ADC, a DSP synchronous port in synchronous + * mode, etc.... For better understanding and to ease reading, the following + * description uses an example with a CMOS digital image sensor + * + * To use the PIO Parallel Capture, the user has to follow these few steps: + *
    + *
  • Enable PIOA peripheral clock
  • + *
  • Configure the PDC
  • + *
  • Configure the PIO Capture interrupt
  • + *
  • Enable the PDC
  • + *
  • Enable the PIO Capture
  • + *
  • Wait for interrupt
  • + *
  • Disable the interrupt
  • + *
  • Read the DATA
  • + *
+ * + * For more accurate information, please look at the PIO Parallel Capture Mode section of the + * Datasheet. + * + * Related files :\n + * \ref pio_capture.c\n + * \ref pio_capture.h\n + */ +/*@{*/ +/*@}*/ +/** + * \file + * + * Implementation of PIO Parallel Capture. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "chip.h" + +#include + +/*---------------------------------------------------------------------------- + * Local Functions + *----------------------------------------------------------------------------*/ +/** Copy the API structure for interrupt handler */ +static SpioCaptureInit* _PioCaptureCopy; + +/*---------------------------------------------------------------------------- + * Global Functions + *----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +/** + * \brief The PIO_CaptureHandler must be called by the PIO Capture Interrupt + * Service Routine with the corresponding PIO Capture instance. + */ +/*----------------------------------------------------------------------------*/ +extern void PIO_CaptureHandler( void ) +{ + volatile uint32_t pio_captureSr; + + /* Read the status register*/ + pio_captureSr = PIOA->PIO_PCISR ; + pio_captureSr &= PIOA->PIO_PCIMR ; + + if (pio_captureSr & PIO_PCISR_DRDY) + { + /* Parallel Capture Mode Data Ready */ + if ( _PioCaptureCopy->CbkDataReady != NULL ) + { + _PioCaptureCopy->CbkDataReady( _PioCaptureCopy ); + } + else + { + TRACE_DEBUG("IT PIO Capture Data Ready received (no callback)\n\r"); + } + } + + if (pio_captureSr & PIO_PCISR_OVRE) + { + /* Parallel Capture Mode Overrun Error */ + if ( _PioCaptureCopy->CbkOverrun != NULL ) + { + _PioCaptureCopy->CbkOverrun( _PioCaptureCopy ); + } + else + { + TRACE_DEBUG("IT PIO Capture Overrun Error received (no callback)\n\r"); + } + } + + if (pio_captureSr & PIO_PCISR_RXBUFF) + { + /* Reception Buffer Full */ + if ( _PioCaptureCopy->CbkBuffFull != NULL ) + { + _PioCaptureCopy->CbkBuffFull( _PioCaptureCopy ); + } + else + { + TRACE_DEBUG("IT PIO Capture Reception Buffer Full received (no callback)\n\r"); + } + } + + if (pio_captureSr & PIO_PCISR_ENDRX) + { + /* End of Reception Transfer */ + if ( _PioCaptureCopy->CbkEndReception != NULL ) + { + _PioCaptureCopy->CbkEndReception( _PioCaptureCopy ); + } + else + { + TRACE_DEBUG("IT PIO Capture End of Reception Transfer received (no callback)\n\r"); + } + } +} + +/*----------------------------------------------------------------------------*/ +/** + * \brief Disable Interupt of the PIO Capture + * \param itToDisable : Interrupt to disable + */ +/*----------------------------------------------------------------------------*/ +void PIO_CaptureDisableIt( uint32_t itToDisable ) +{ + /* Parallel capture mode is enabled */ + PIOA->PIO_PCIDR = itToDisable; +} + +/*----------------------------------------------------------------------------*/ +/** + * \brief Enable Interupt of the PIO Capture + * \param itToEnable : Interrupt to enable + */ +/*----------------------------------------------------------------------------*/ +void PIO_CaptureEnableIt( uint32_t itToEnable ) +{ + /* Parallel capture mode is enabled */ + PIOA->PIO_PCIER = itToEnable; +} + +/*----------------------------------------------------------------------------*/ +/** + * \brief Enable the PIO Capture + */ +/*----------------------------------------------------------------------------*/ +void PIO_CaptureEnable( void ) +{ + /* PDC: Receive Pointer Register */ + PIOA->PIO_RPR = (uint32_t)_PioCaptureCopy->pData ; + /* PDC: Receive Counter Register */ + /* Starts peripheral data transfer if corresponding channel is active */ + PIOA->PIO_RCR = PIO_RCR_RXCTR(_PioCaptureCopy->dPDCsize) ; + + /* Parallel capture mode is enabled */ + PIOA->PIO_PCMR |= PIO_PCMR_PCEN ; +} + +/*----------------------------------------------------------------------------*/ +/** + * \brief Disable the PIO Capture + */ +/*----------------------------------------------------------------------------*/ +void PIO_CaptureDisable( void ) +{ + /* Parallel capture mode is disabled */ + PIOA->PIO_PCMR &= (uint32_t)(~PIO_PCMR_PCEN) ; +} + +/*----------------------------------------------------------------------------*/ +/** + * \brief Initialize the PIO Capture + * Be careful to configure the PDC before enable interrupt on pio capture. + * Otherway, the pdc will go in interrupt handler continuously. + * \param dsize : + * 0 = The reception data in the PIO_PCRHR register is a BYTE (8-bit). + * 1 = The reception data in the PIO_PCRHR register is a HALF-WORD (16-bit). + * 2/3 = The reception data in the PIO_PCRHR register is a WORD (32-bit). + * \param alwaysSampling: ALWYS: Parallel Capture Mode Always Sampling + * 0 = The parallel capture mode samples the data when both data enables are active. + * 1 = The parallel capture mode samples the data whatever the data enables are. + * \param halfSampling: HALFS: Parallel Capture Mode Half Sampling + * 0 = The parallel capture mode samples all the data. + * 1 = The parallel capture mode samples the data only one time out of two. + * \param modeFirstSample: FRSTS: Parallel Capture Mode First Sample + * This bit is useful only if the HALFS bit is set to 1. If data are numbered + * in the order that they are received with an index from 0 to n: + * 0 = Only data with an even index are sampled. + * 1 = Only data with an odd index are sampled. + */ +/*----------------------------------------------------------------------------*/ +void PIO_CaptureInit( SpioCaptureInit *pInit ) +{ + PMC_EnablePeripheral( ID_PIOA ); + + assert( (pInit->dsize < 0x4) ) ; + assert( (pInit->dPDCsize <= PIO_RPR_RXPTR_Msk) ) ; + assert( (pInit->alwaysSampling < 2) ); + assert( (pInit->halfSampling < 2) ); + assert( (pInit->modeFirstSample < 2) ); + + /* PDC: Transfer Control Register */ + /* Disables the PDC transmitter channel requests */ + PIOA->PIO_PTCR = PIO_PTCR_RXTDIS; + /* PDC: Receive Pointer Register */ + PIOA->PIO_RPR = (uint32_t)pInit->pData; + /* PDC: Receive Counter Register */ + /* Starts peripheral data transfer if corresponding channel is active */ + PIOA->PIO_RCR = PIO_RCR_RXCTR(pInit->dPDCsize); + + /* PDC: Transfer Control Register */ + /* Enables PDC receiver channel requests if RXTDIS is not set */ + PIOA->PIO_PTCR = PIO_PTCR_RXTEN ; + + + /* Copy the API structure for interrupt handler */ + _PioCaptureCopy = pInit; + /* PIO Parallel Capture Mode */ + PIOA->PIO_PCMR = PIO_PCMR_DSIZE(pInit->dsize) + | ((pInit->alwaysSampling<<9) & PIO_PCMR_ALWYS) + | ((pInit->halfSampling<<10) & PIO_PCMR_HALFS) + | ((pInit->modeFirstSample<<11) & PIO_PCMR_FRSTS); + + if ( pInit->CbkDataReady != NULL ) + { + PIOA->PIO_PCIER = PIO_PCISR_DRDY; + } + + if ( pInit->CbkOverrun != NULL ) + { + PIOA->PIO_PCIER = PIO_PCISR_OVRE; + } + + if ( pInit->CbkEndReception != NULL ) + { + PIOA->PIO_PCIER = PIO_PCISR_ENDRX; + } + + if ( pInit->CbkBuffFull != NULL ) + { + PIOA->PIO_PCIER = PIO_PCISR_RXBUFF; + } +// else +// { +// TRACE_INFO("No interruption, no callback\n\r"); +// } + +} + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pio_it.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pio_it.c new file mode 100644 index 00000000..c5351e81 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pio_it.c @@ -0,0 +1,315 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/* + * \file + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "chip.h" + +#include + +/*---------------------------------------------------------------------------- + * Local definitions + *----------------------------------------------------------------------------*/ + +/* Maximum number of interrupt sources that can be defined. This + * constant can be increased, but the current value is the smallest possible + * that will be compatible with all existing projects. */ +#define MAX_INTERRUPT_SOURCES 7 + +/*---------------------------------------------------------------------------- + * Local types + *----------------------------------------------------------------------------*/ + +/** + * Describes a PIO interrupt source, including the PIO instance triggering the + * interrupt and the associated interrupt handler. + */ +typedef struct _InterruptSource +{ + /* Pointer to the source pin instance. */ + const Pin *pPin; + + /* Interrupt handler. */ + void (*handler)( const Pin* ) ; +} InterruptSource ; + +/*---------------------------------------------------------------------------- + * Local variables + *----------------------------------------------------------------------------*/ + +/* List of interrupt sources. */ +static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES] ; + +/* Number of currently defined interrupt sources. */ +static uint32_t _dwNumSources = 0; + +/*---------------------------------------------------------------------------- + * Local Functions + *----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/** + * \brief Stub, to handling all PIO Capture interrupts, if not defined. + */ +/*----------------------------------------------------------------------------*/ +//extern WEAK void PIO_CaptureHandler( void ) +//{ +//} + +/** + * \brief Handles all interrupts on the given PIO controller. + * \param id PIO controller ID. + * \param pPio PIO controller base address. + */ +extern void PioInterruptHandler( uint32_t id, Pio *pPio ) +{ + uint32_t status; + uint32_t i; + + /* Read PIO controller status */ + status = pPio->PIO_ISR; + status &= pPio->PIO_IMR; + + /* Check pending events */ + if ( status != 0 ) + { + TRACE_DEBUG( "PIO interrupt on PIO controller #%d\n\r", id ) ; + + /* Find triggering source */ + i = 0; + while ( status != 0 ) + { + /* There cannot be an unconfigured source enabled. */ + assert(i < _dwNumSources); + + /* Source is configured on the same controller */ + if (_aIntSources[i].pPin->id == id) + { + /* Source has PIOs whose statuses have changed */ + if ( (status & _aIntSources[i].pPin->mask) != 0 ) + { + TRACE_DEBUG( "Interrupt source #%d triggered\n\r", i ) ; + + _aIntSources[i].handler(_aIntSources[i].pPin); + status &= ~(_aIntSources[i].pPin->mask); + } + } + i++; + } + } +} + +/*---------------------------------------------------------------------------- + * Global Functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Parallel IO Controller A interrupt handler + * \Redefined PIOA interrupt handler for NVIC interrupt table. + */ +extern void PIOA_IrqHandler( void ) +{ + if ( PIOA->PIO_PCISR != 0 ) + { + PIO_CaptureHandler() ; + } + + PioInterruptHandler( ID_PIOA, PIOA ) ; +} + +/** + * \brief Parallel IO Controller B interrupt handler + * \Redefined PIOB interrupt handler for NVIC interrupt table. + */ +extern void PIOB_IrqHandler( void ) +{ + PioInterruptHandler( ID_PIOB, PIOB ) ; +} + +/** + * \brief Parallel IO Controller C interrupt handler + * \Redefined PIOC interrupt handler for NVIC interrupt table. + */ +extern void PIOC_IrqHandler( void ) +{ + PioInterruptHandler( ID_PIOC, PIOC ) ; +} + +/** + * \brief Initializes the PIO interrupt management logic + * + * The desired priority of PIO interrupts must be provided. + * Calling this function multiple times result in the reset of currently + * configured interrupts. + * + * \param priority PIO controller interrupts priority. + */ +extern void PIO_InitializeInterrupts( uint32_t dwPriority ) +{ + TRACE_DEBUG( "PIO_Initialize()\n\r" ) ; + + /* Reset sources */ + _dwNumSources = 0 ; + + /* Configure PIO interrupt sources */ + TRACE_DEBUG( "PIO_Initialize: Configuring PIOA\n\r" ) ; + PMC_EnablePeripheral( ID_PIOA ) ; + PIOA->PIO_ISR ; + PIOA->PIO_IDR = 0xFFFFFFFF ; + NVIC_DisableIRQ( PIOA_IRQn ) ; + NVIC_ClearPendingIRQ( PIOA_IRQn ) ; + NVIC_SetPriority( PIOA_IRQn, dwPriority ) ; + NVIC_EnableIRQ( PIOA_IRQn ) ; + + TRACE_DEBUG( "PIO_Initialize: Configuring PIOB\n\r" ) ; + PMC_EnablePeripheral( ID_PIOB ) ; + PIOB->PIO_ISR ; + PIOB->PIO_IDR = 0xFFFFFFFF ; + NVIC_DisableIRQ( PIOB_IRQn ) ; + NVIC_ClearPendingIRQ( PIOB_IRQn ) ; + NVIC_SetPriority( PIOB_IRQn, dwPriority ) ; + NVIC_EnableIRQ( PIOB_IRQn ) ; + + TRACE_DEBUG( "PIO_Initialize: Configuring PIOC\n\r" ) ; + PMC_EnablePeripheral( ID_PIOC ) ; + PIOC->PIO_ISR ; + PIOC->PIO_IDR = 0xFFFFFFFF ; + NVIC_DisableIRQ( PIOC_IRQn ) ; + NVIC_ClearPendingIRQ( PIOC_IRQn ) ; + NVIC_SetPriority( PIOC_IRQn, dwPriority ) ; + NVIC_EnableIRQ( PIOC_IRQn ) ; +} + +/** + * Configures a PIO or a group of PIO to generate an interrupt on status + * change. The provided interrupt handler will be called with the triggering + * pin as its parameter (enabling different pin instances to share the same + * handler). + * \param pPin Pointer to a Pin instance. + * \param handler Interrupt handler function pointer. + */ +extern void PIO_ConfigureIt( const Pin *pPin, void (*handler)( const Pin* ) ) +{ + Pio* pio ; + InterruptSource* pSource ; + + TRACE_DEBUG( "PIO_ConfigureIt()\n\r" ) ; + + assert( pPin ) ; + pio = pPin->pio ; + assert( _dwNumSources < MAX_INTERRUPT_SOURCES ) ; + + /* Define new source */ + TRACE_DEBUG( "PIO_ConfigureIt: Defining new source #%d.\n\r", _dwNumSources ) ; + + pSource = &(_aIntSources[_dwNumSources]) ; + pSource->pPin = pPin ; + pSource->handler = handler ; + _dwNumSources++ ; + + /* PIO3 with additional interrupt support + * Configure additional interrupt mode registers */ + if ( pPin->attribute & PIO_IT_AIME ) + { + // enable additional interrupt mode + pio->PIO_AIMER = pPin->mask ; + + // if bit field of selected pin is 1, set as Rising Edge/High level detection event + if ( pPin->attribute & PIO_IT_RE_OR_HL ) + { + pio->PIO_REHLSR = pPin->mask ; + } + else + { + pio->PIO_FELLSR = pPin->mask; + } + + /* if bit field of selected pin is 1, set as edge detection source */ + if (pPin->attribute & PIO_IT_EDGE) + pio->PIO_ESR = pPin->mask; + else + pio->PIO_LSR = pPin->mask; + } + else + { + /* disable additional interrupt mode */ + pio->PIO_AIMDR = pPin->mask; + } +} + +/** + * Enables the given interrupt source if it has been configured. The status + * register of the corresponding PIO controller is cleared prior to enabling + * the interrupt. + * \param pPin Interrupt source to enable. + */ +extern void PIO_EnableIt( const Pin *pPin ) +{ + TRACE_DEBUG( "PIO_EnableIt()\n\r" ) ; + + assert( pPin != NULL ) ; + +#ifndef NOASSERT + uint32_t i = 0; + uint32_t dwFound = 0; + + while ( (i < _dwNumSources) && !dwFound ) + { + if ( _aIntSources[i].pPin == pPin ) + { + dwFound = 1 ; + } + i++ ; + } + assert( dwFound != 0 ) ; +#endif + + pPin->pio->PIO_ISR; + pPin->pio->PIO_IER = pPin->mask ; +} + +/** + * Disables a given interrupt source, with no added side effects. + * + * \param pPin Interrupt source to disable. + */ +extern void PIO_DisableIt( const Pin *pPin ) +{ + assert( pPin != NULL ) ; + + TRACE_DEBUG( "PIO_DisableIt()\n\r" ) ; + + pPin->pio->PIO_IDR = pPin->mask; +} + diff --git a/sam3s_example/src/pmc.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pmc.c similarity index 86% rename from sam3s_example/src/pmc.c rename to sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pmc.c index 4efc8ba1..b71d7480 100644 --- a/sam3s_example/src/pmc.c +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pmc.c @@ -32,6 +32,7 @@ *----------------------------------------------------------------------------*/ #include "chip.h" +#include "trace.h" #include @@ -62,6 +63,7 @@ extern void PMC_EnablePeripheral( uint32_t dwId ) { if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId) ) { + TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %u is already enabled\n\r", dwId ) ; } else { @@ -73,6 +75,7 @@ extern void PMC_EnablePeripheral( uint32_t dwId ) dwId -= 32; if ((PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId)) { + TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %u is already enabled\n\r", dwId + 32 ) ; } else { @@ -97,6 +100,7 @@ extern void PMC_DisablePeripheral( uint32_t dwId ) { if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) ) { + TRACE_DEBUG("PMC_DisablePeripheral: clock of peripheral" " %u is not enabled\n\r", dwId ) ; } else { @@ -108,6 +112,7 @@ extern void PMC_DisablePeripheral( uint32_t dwId ) dwId -= 32 ; if ( (PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) ) { + TRACE_DEBUG( "PMC_DisablePeripheral: clock of peripheral" " %u is not enabled\n\r", dwId + 32 ) ; } else { @@ -127,6 +132,7 @@ extern void PMC_EnableAllPeripherals( void ) PMC->PMC_PCER1 = MASK_STATUS1 ; while ( (PMC->PMC_PCSR1 & MASK_STATUS1) != MASK_STATUS1 ) ; + TRACE_DEBUG( "Enable all periph clocks\n\r" ) ; } /** @@ -140,6 +146,7 @@ extern void PMC_DisableAllPeripherals( void ) PMC->PMC_PCDR1 = MASK_STATUS1 ; while ( (PMC->PMC_PCSR1 & MASK_STATUS1) != 0 ) ; + TRACE_DEBUG( "Disable all periph clocks\n\r" ) ; } /** diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pwmc.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pwmc.c new file mode 100644 index 00000000..6e367951 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/pwmc.c @@ -0,0 +1,608 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup pwm_module Working with PWM + * The PWM driver provides the interface to configure and use the PWM + * peripheral. + * + * The PWM macrocell controls square output waveforms of 4 channels. + * Characteristics of output waveforms such as period, duty-cycle, + * dead-time can be configured.\n + * Some of PWM channels can be linked together as synchronous channel and + * duty-cycle of synchronous channels can be updated by PDC automaticly. + * + * Before enabling the channels, they must have been configured first. + * The main settings include: + *
    + *
  • Configuration of the clock generator.
  • + *
  • Selection of the clock for each channel.
  • + *
  • Configuration of output waveform characteristics, such as period, duty-cycle etc.
  • + *
  • Configuration for synchronous channels if needed.
  • + * - Selection of the synchronous channels. + * - Selection of the moment when the WRDY flag and the corresponding PDC + * transfer request are set (PTRM and PTRCS in the PWM_SCM register). + * - Configuration of the update mode (UPDM in the PWM_SCM register). + * - Configuration of the update period (UPR in the PWM_SCUP register). + *
+ * + * After the channels is enabled, the user must use respective update registers + * to change the wave characteristics to prevent unexpected output waveform. + * i.e. PWM_CDTYUPDx register should be used if user want to change duty-cycle + * when the channel is enabled. + * + * For more accurate information, please look at the PWM section of the + * Datasheet. + * + * Related files :\n + * \ref pwmc.c\n + * \ref pwmc.h.\n + */ +/*@{*/ +/*@}*/ + +/** + * \file + * + * Implementation of the Pulse Width Modulation Controller (PWM) peripheral. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "chip.h" + +#include +#include + +/*---------------------------------------------------------------------------- + * Local functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Finds a prescaler/divisor couple to generate the desired frequency + * from MCK. + * + * Returns the value to enter in PWM_CLK or 0 if the configuration cannot be + * met. + * + * \param frequency Desired frequency in Hz. + * \param mck Master clock frequency in Hz. + */ +static uint16_t FindClockConfiguration( + uint32_t frequency, + uint32_t mck) +{ + uint32_t divisors[11] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024}; + uint8_t divisor = 0; + uint32_t prescaler; + + assert(frequency < mck); + + /* Find prescaler and divisor values */ + prescaler = (mck / divisors[divisor]) / frequency; + while ((prescaler > 255) && (divisor < 11)) { + + divisor++; + prescaler = (mck / divisors[divisor]) / frequency; + } + + /* Return result */ + if ( divisor < 11 ) + { + TRACE_DEBUG( "Found divisor=%u and prescaler=%u for freq=%uHz\n\r", divisors[divisor], prescaler, frequency ) ; + + return prescaler | (divisor << 8) ; + } + else + { + return 0 ; + } +} + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Configures PWM a channel with the given parameters, basic configure function. + * + * The PWM controller must have been clocked in the PMC prior to calling this + * function. + * Beware: this function disables the channel. It waits until disable is effective. + * + * \param channel Channel number. + * \param prescaler Channel prescaler. + * \param alignment Channel alignment. + * \param polarity Channel polarity. + */ +void PWMC_ConfigureChannel( + Pwm* pPwm, + uint8_t channel, + uint32_t prescaler, + uint32_t alignment, + uint32_t polarity) +{ + pPwm->PWM_CH_NUM[0].PWM_CMR = 1; + +// assert(prescaler < PWM_CMR0_CPRE_MCKB); + assert((alignment & (uint32_t)~PWM_CMR_CALG) == 0); + assert((polarity & (uint32_t)~PWM_CMR_CPOL) == 0); + + /* Disable channel (effective at the end of the current period) */ + if ((pPwm->PWM_SR & (1 << channel)) != 0) { + pPwm->PWM_DIS = 1 << channel; + while ((pPwm->PWM_SR & (1 << channel)) != 0); + } + + /* Configure channel */ + pPwm->PWM_CH_NUM[channel].PWM_CMR = prescaler | alignment | polarity; +} + +/** + * \brief Configures PWM a channel with the given parameters, extend configure function. + * + * The PWM controller must have been clocked in the PMC prior to calling this + * function. + * Beware: this function disables the channel. It waits until disable is effective. + * + * \param channel Channel number. + * \param prescaler Channel prescaler. + * \param alignment Channel alignment. + * \param polarity Channel polarity. + * \param countEventSelect Channel counter event selection. + * \param DTEnable Channel dead time generator enable. + * \param DTHInverte Channel Dead-Time PWMHx output Inverted. + * \param DTLInverte Channel Dead-Time PWMHx output Inverted. + */ +void PWMC_ConfigureChannelExt( + Pwm* pPwm, + uint8_t channel, + uint32_t prescaler, + uint32_t alignment, + uint32_t polarity, + uint32_t countEventSelect, + uint32_t DTEnable, + uint32_t DTHInverte, + uint32_t DTLInverte) +{ +// assert(prescaler < PWM_CMR0_CPRE_MCKB); + assert((alignment & (uint32_t)~PWM_CMR_CALG) == 0); + assert((polarity & (uint32_t)~PWM_CMR_CPOL) == 0); + assert((countEventSelect & (uint32_t)~PWM_CMR_CES) == 0); + assert((DTEnable & (uint32_t)~PWM_CMR_DTE) == 0); + assert((DTHInverte & (uint32_t)~PWM_CMR_DTHI) == 0); + assert((DTLInverte & (uint32_t)~PWM_CMR_DTLI) == 0); + + /* Disable channel (effective at the end of the current period) */ + if ((pPwm->PWM_SR & (1 << channel)) != 0) { + pPwm->PWM_DIS = 1 << channel; + while ((pPwm->PWM_SR & (1 << channel)) != 0); + } + + /* Configure channel */ + pPwm->PWM_CH_NUM[channel].PWM_CMR = prescaler | alignment | polarity | + countEventSelect | DTEnable | DTHInverte | DTLInverte; +} + +/** + * \brief Configures PWM clocks A & B to run at the given frequencies. + * + * This function finds the best MCK divisor and prescaler values automatically. + * + * \param clka Desired clock A frequency (0 if not used). + * \param clkb Desired clock B frequency (0 if not used). + * \param mck Master clock frequency. + */ +void PWMC_ConfigureClocks(uint32_t clka, uint32_t clkb, uint32_t mck) +{ + uint32_t mode = 0; + uint32_t result; + + /* Clock A */ + if (clka != 0) { + + result = FindClockConfiguration(clka, mck); + assert( result != 0 ) ; + mode |= result; + } + + /* Clock B */ + if (clkb != 0) { + + result = FindClockConfiguration(clkb, mck); + assert( result != 0 ) ; + mode |= (result << 16); + } + + /* Configure clocks */ + TRACE_DEBUG( "Setting PWM_CLK = 0x%08X\n\r", mode ) ; + PWM->PWM_CLK = mode; +} + +/** + * \brief Sets the period value used by a PWM channel. + * + * This function writes directly to the CPRD register if the channel is disabled; + * otherwise, it uses the update register CPRDUPD. + * + * \param channel Channel number. + * \param period Period value. + */ +void PWMC_SetPeriod( Pwm* pPwm, uint8_t channel, uint16_t period) +{ + /* If channel is disabled, write to CPRD */ + if ((pPwm->PWM_SR & (1 << channel)) == 0) { + + pPwm->PWM_CH_NUM[channel].PWM_CPRD = period; + } + /* Otherwise use update register */ + else { + + pPwm->PWM_CH_NUM[channel].PWM_CPRDUPD = period; + } +} + +/** + * \brief Sets the duty cycle used by a PWM channel. + * This function writes directly to the CDTY register if the channel is disabled; + * otherwise it uses the update register CDTYUPD. + * Note that the duty cycle must always be inferior or equal to the channel + * period. + * + * \param channel Channel number. + * \param duty Duty cycle value. + */ +void PWMC_SetDutyCycle( Pwm* pPwm, uint8_t channel, uint16_t duty) +{ + assert(duty <= pPwm->PWM_CH_NUM[channel].PWM_CPRD); + + /* If channel is disabled, write to CDTY */ + if ((pPwm->PWM_SR & (1 << channel)) == 0) { + + pPwm->PWM_CH_NUM[channel].PWM_CDTY = duty; + } + /* Otherwise use update register */ + else { + + pPwm->PWM_CH_NUM[channel].PWM_CDTYUPD = duty; + } +} + +/** + * \brief Sets the dead time used by a PWM channel. + * This function writes directly to the DT register if the channel is disabled; + * otherwise it uses the update register DTUPD. + * Note that the dead time must always be inferior or equal to the channel + * period. + * + * \param channel Channel number. + * \param timeH Dead time value for PWMHx output. + * \param timeL Dead time value for PWMLx output. + */ +void PWMC_SetDeadTime( Pwm* pPwm, uint8_t channel, uint16_t timeH, uint16_t timeL) +{ + assert(timeH <= pPwm->PWM_CH_NUM[channel].PWM_CPRD); + assert(timeL <= pPwm->PWM_CH_NUM[channel].PWM_CPRD); + + /* If channel is disabled, write to DT */ + if ((pPwm->PWM_SR & (1 << channel)) == 0) { + + pPwm->PWM_CH_NUM[channel].PWM_DT = timeH | (timeL << 16); + } + /* Otherwise use update register */ + else { + pPwm->PWM_CH_NUM[channel].PWM_DTUPD = timeH | (timeL << 16); + } +} + +/** + * \brief Configures Syncronous channel with the given parameters. + * Beware: At this time, the channels should be disabled. + * + * \param channels Bitwise OR of Syncronous channels. + * \param updateMode Syncronous channel update mode. + * \param requestMode PDC transfer request mode. + * \param requestComparisonSelect PDC transfer request comparison selection. + */ +void PWMC_ConfigureSyncChannel( Pwm* pPwm, + uint32_t channels, + uint32_t updateMode, + uint32_t requestMode, + uint32_t requestComparisonSelect) +{ + pPwm->PWM_SCM = channels | updateMode | requestMode | requestComparisonSelect; +} + +/** + * \brief Sets the update period of the synchronous channels. + * This function writes directly to the SCUP register if the channel #0 is disabled; + * otherwise it uses the update register SCUPUPD. + * + * \param period update period. + */ +void PWMC_SetSyncChannelUpdatePeriod( Pwm* pPwm, uint8_t period) +{ + /* If channel is disabled, write to SCUP */ + if ((pPwm->PWM_SR & (1 << 0)) == 0) { + + pPwm->PWM_SCUP = period; + } + /* Otherwise use update register */ + else { + + pPwm->PWM_SCUPUPD = period; + } +} + +/** + * \brief Sets synchronous channels update unlock. + * + * Note: If the UPDM field is set to 0, writing the UPDULOCK bit to 1 + * triggers the update of the period value, the duty-cycle and + * the dead-time values of synchronous channels at the beginning + * of the next PWM period. If the field UPDM is set to 1 or 2, + * writing the UPDULOCK bit to 1 triggers only the update of + * the period value and of the dead-time values of synchronous channels. + * This bit is automatically reset when the update is done. + */ +void PWMC_SetSyncChannelUpdateUnlock( Pwm* pPwm ) +{ + pPwm->PWM_SCUC = PWM_SCUC_UPDULOCK; +} + +/** + * \brief Enables the given PWM channel. + * + * This does NOT enable the corresponding pin;this must be done in the user code. + * + * \param channel Channel number. + */ +void PWMC_EnableChannel( Pwm* pPwm, uint8_t channel) +{ + pPwm->PWM_ENA = 1 << channel; +} + +/** + * \brief Disables the given PWM channel. + * + * Beware, channel will be effectively disabled at the end of the current period. + * Application can check channel is disabled using the following wait loop: + * while ((PWM->PWM_SR & (1 << channel)) != 0); + * + * \param channel Channel number. + */ +void PWMC_DisableChannel( Pwm* pPwm, uint8_t channel) +{ + pPwm->PWM_DIS = 1 << channel; +} + +/** + * \brief Enables the period interrupt for the given PWM channel. + * + * \param channel Channel number. + */ +void PWMC_EnableChannelIt( Pwm* pPwm, uint8_t channel) +{ + pPwm->PWM_IER1 = 1 << channel; +} + +/** + * \brief Disables the period interrupt for the given PWM channel. + * + * \param channel Channel number. + */ +void PWMC_DisableChannelIt( Pwm* pPwm, uint8_t channel) +{ + pPwm->PWM_IDR1 = 1 << channel; +} + +/** + * \brief Enables the selected interrupts sources on a PWMC peripheral. + * + * \param sources1 Bitwise OR of selected interrupt sources of PWM_IER1. + * \param sources2 Bitwise OR of selected interrupt sources of PWM_IER2. + */ +void PWMC_EnableIt( Pwm* pPwm, uint32_t sources1, uint32_t sources2) +{ + pPwm->PWM_IER1 = sources1; + pPwm->PWM_IER2 = sources2; +} + +/** + * \brief Disables the selected interrupts sources on a PWMC peripheral. + * + * \param sources1 Bitwise OR of selected interrupt sources of PWM_IDR1. + * \param sources2 Bitwise OR of selected interrupt sources of PWM_IDR2. + */ +void PWMC_DisableIt( Pwm* pPwm, uint32_t sources1, uint32_t sources2) +{ + pPwm->PWM_IDR1 = sources1; + pPwm->PWM_IDR2 = sources2; +} + +/** + * \brief Sends the contents of buffer through a PWMC peripheral, using the PDC to + * take care of the transfer. + * + * Note: Duty cycle of syncronous channels can update by PDC + * when the field UPDM (Update Mode) in the PWM_SCM register is set to 2. + * + * \param pwmc Pointer to an Pwm instance. + * \param buffer Data buffer to send. + * \param length Length of the data buffer. + */ +uint8_t PWMC_WriteBuffer(Pwm *pwmc, + void *buffer, + uint32_t length) +{ + /* Check if first bank is free */ + if (pwmc->PWM_TCR == 0) { + + pwmc->PWM_TPR = (uint32_t) buffer; + pwmc->PWM_TCR = length; + pwmc->PWM_PTCR = PERIPH_PTCR_TXTEN; + return 1; + } + /* Check if second bank is free */ + else if (pwmc->PWM_TNCR == 0) { + + pwmc->PWM_TNPR = (uint32_t) buffer; + pwmc->PWM_TNCR = length; + return 1; + } + + /* No free banks */ + return 0; +} + +/** + * \brief Set PWM output override value. + * + * \param value Bitwise OR of output override value. + */ +void PWMC_SetOverrideValue( Pwm* pPwm, uint32_t value) +{ + pPwm->PWM_OOV = value; +} + +/** + * \brief Enalbe override output. + * + * \param value Bitwise OR of output selection. + * \param sync 0: enable the output asyncronously, 1: enable it syncronously + */ +void PWMC_EnableOverrideOutput( Pwm* pPwm, uint32_t value, uint32_t sync) +{ + if (sync) { + + pPwm->PWM_OSSUPD = value; + } else { + + pPwm->PWM_OSS = value; + } +} + +/** + * \brief Disalbe override output. + * + * \param value Bitwise OR of output selection. + * \param sync 0: enable the output asyncronously, 1: enable it syncronously + */ +void PWMC_DisableOverrideOutput( Pwm* pPwm, uint32_t value, uint32_t sync) +{ + if (sync) { + + pPwm->PWM_OSCUPD = value; + } else { + + pPwm->PWM_OSC = value; + } +} + +/** + * \brief Set PWM fault mode. + * + * \param mode Bitwise OR of fault mode. + */ +void PWMC_SetFaultMode( Pwm* pPwm, uint32_t mode) +{ + pPwm->PWM_FMR = mode; +} + +/** + * \brief PWM fault clear. + * + * \param fault Bitwise OR of fault to clear. + */ +void PWMC_FaultClear( Pwm* pPwm, uint32_t fault) +{ + pPwm->PWM_FCR = fault; +} + +/** + * \brief Set PWM fault protection value. + * + * \param value Bitwise OR of fault protection value. + */ +void PWMC_SetFaultProtectionValue( Pwm* pPwm, uint32_t value) +{ + pPwm->PWM_FPV = value; +} + +/** + * \brief Enable PWM fault protection. + * + * \param value Bitwise OR of FPEx[y]. + */ +void PWMC_EnableFaultProtection( Pwm* pPwm, uint32_t value) +{ + pPwm->PWM_FPE = value; +} + +/** + * \brief Configure comparison unit. + * + * \param x comparison x index + * \param value comparison x value. + * \param mode comparison x mode + */ +void PWMC_ConfigureComparisonUnit( Pwm* pPwm, uint32_t x, uint32_t value, uint32_t mode) +{ + assert(x < 8); + + /* If channel is disabled, write to CMPxM & CMPxV */ + if ((pPwm->PWM_SR & (1 << 0)) == 0) { + pPwm->PWM_CMP[x].PWM_CMPxM = mode; + pPwm->PWM_CMP[x].PWM_CMPxV = value; + } + /* Otherwise use update register */ + else { + pPwm->PWM_CMP[x].PWM_CMPxMUPD = mode; + pPwm->PWM_CMP[x].PWM_CMPxVUPD = value; + } +} + +/** + * \brief Configure event line mode. + * + * \param x Line x + * \param mode Bitwise OR of line mode selection + */ +void PWMC_ConfigureEventLineMode( Pwm* pPwm, uint32_t x, uint32_t mode) +{ + assert(x < 2); + + if (x == 0) { + pPwm->PWM_ELxMR[0] = mode; + } else if (x == 1) { + pPwm->PWM_ELxMR[1] = mode; + } +} diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/rtc.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/rtc.c new file mode 100644 index 00000000..60ab3ef2 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/rtc.c @@ -0,0 +1,464 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup rtc_module Working with RTC + * The RTC driver provides the interface to configure and use the RTC + * peripheral. + * + * It manages date, time, and alarms.\n + * This timer is clocked by the 32kHz system clock, and is not impacted by + * power management settings (PMC). To be accurate, it is better to use an + * external 32kHz crystal instead of the internal 32kHz RC.\n + * + * It uses BCD format, and time can be set in AM/PM or 24h mode through a + * configuration bit in the mode register.\n + * + * To update date or time, the user has to follow these few steps : + *
    + *
  • Set UPDTIM and/or UPDCAL bit(s) in RTC_CR,
  • + *
  • Polling or IRQ on the ACKUPD bit of RTC_CR,
  • + *
  • Clear ACKUPD bit in RTC_SCCR,
  • + *
  • Update Time and/or Calendar values in RTC_TIMR/RTC_CALR (BCD format),
  • + *
  • Clear UPDTIM and/or UPDCAL bit in RTC_CR.
  • + *
+ * An alarm can be set to happen on month, date, hours, minutes or seconds, + * by setting the proper "Enable" bit of each of these fields in the Time and + * Calendar registers. + * This allows a large number of configurations to be available for the user. + * Alarm occurence can be detected even by polling or interrupt. + * + * A check of the validity of the date and time format and values written by the user is automatically done. + * Errors are reported through the Valid Entry Register. + * + * For more accurate information, please look at the RTC section of the + * Datasheet. + * + * Related files :\n + * \ref rtc.c\n + * \ref rtc.h.\n +*/ +/*@{*/ +/*@}*/ + + +/** + * \file + * + * Implementation of Real Time Clock (RTC) controller. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "chip.h" + +#include +#include + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Sets the RTC in either 12 or 24 hour mode. + * + * \param mode Hour mode. + */ +extern void RTC_SetHourMode( Rtc* pRtc, uint32_t dwMode ) +{ + assert((dwMode & 0xFFFFFFFE) == 0); + + pRtc->RTC_MR = dwMode ; +} + +/** + * \brief Gets the RTC mode. + * + * \return Hour mode. + */ +extern uint32_t RTC_GetHourMode( Rtc* pRtc ) +{ + uint32_t dwMode ; + + TRACE_DEBUG( "RTC_SetHourMode()\n\r" ) ; + + dwMode = pRtc->RTC_MR; + dwMode &= 0xFFFFFFFE; + + return dwMode ; +} + +/** + * \brief Enables the selected interrupt sources of the RTC. + * + * \param sources Interrupt sources to enable. + */ +extern void RTC_EnableIt( Rtc* pRtc, uint32_t dwSources ) +{ + assert((dwSources & (uint32_t)(~0x1F)) == 0); + + TRACE_DEBUG( "RTC_EnableIt()\n\r" ) ; + + pRtc->RTC_IER = dwSources ; +} + +/** +* \brief Disables the selected interrupt sources of the RTC. +* +* \param sources Interrupt sources to disable. +*/ +extern void RTC_DisableIt( Rtc* pRtc, uint32_t dwSources ) +{ + assert((dwSources & (uint32_t)(~0x1F)) == 0); + + TRACE_DEBUG( "RTC_DisableIt()\n\r" ) ; + + pRtc->RTC_IDR = dwSources ; +} + +/** + * \brief Sets the current time in the RTC. + * + * \note In successive update operations, the user must wait at least one second + * after resetting the UPDTIM/UPDCAL bit in the RTC_CR before setting these + * bits again. Please look at the RTC section of the datasheet for detail. + * + * \param ucHour Current hour in 12 or 24 hour mode. + * \param ucMinute Current minute. + * \param ucSecond Current second. + * + * \return 0 sucess, 1 fail to set + */ +extern int RTC_SetTime( Rtc* pRtc, uint8_t ucHour, uint8_t ucMinute, uint8_t ucSecond ) +{ + uint32_t dwTime=0 ; + uint8_t ucHour_bcd ; + uint8_t ucMin_bcd ; + uint8_t ucSec_bcd ; + + TRACE_DEBUG( "RTC_SetTime(%02d:%02d:%02d)\n\r", ucHour, ucMinute, ucSecond ) ; + + /* if 12-hour mode, set AMPM bit */ + if ( (pRtc->RTC_MR & RTC_MR_HRMOD) == RTC_MR_HRMOD ) + { + if ( ucHour > 12 ) + { + ucHour -= 12 ; + dwTime |= RTC_TIMR_AMPM ; + } + } + ucHour_bcd = (ucHour%10) | ((ucHour/10)<<4) ; + ucMin_bcd = (ucMinute%10) | ((ucMinute/10)<<4) ; + ucSec_bcd = (ucSecond%10) | ((ucSecond/10)<<4) ; + + /* value overflow */ + if ( (ucHour_bcd & (uint8_t)(~RTC_HOUR_BIT_LEN_MASK)) | + (ucMin_bcd & (uint8_t)(~RTC_MIN_BIT_LEN_MASK)) | + (ucSec_bcd & (uint8_t)(~RTC_SEC_BIT_LEN_MASK))) + { + return 1 ; + } + + dwTime = ucSec_bcd | (ucMin_bcd << 8) | (ucHour_bcd<<16) ; + + pRtc->RTC_CR |= RTC_CR_UPDTIM ; + while ((pRtc->RTC_SR & RTC_SR_ACKUPD) != RTC_SR_ACKUPD) ; + pRtc->RTC_SCCR = RTC_SCCR_ACKCLR ; + pRtc->RTC_TIMR = dwTime ; + pRtc->RTC_CR &= (uint32_t)(~RTC_CR_UPDTIM) ; + pRtc->RTC_SCCR |= RTC_SCCR_SECCLR ; + + return (int)(pRtc->RTC_VER & RTC_VER_NVTIM) ; +} + +/** + * \brief Retrieves the current time as stored in the RTC in several variables. + * + * \param pucHour If not null, current hour is stored in this variable. + * \param pucMinute If not null, current minute is stored in this variable. + * \param pucSecond If not null, current second is stored in this variable. + */ +extern void RTC_GetTime( Rtc* pRtc, uint8_t *pucHour, uint8_t *pucMinute, uint8_t *pucSecond ) +{ + uint32_t dwTime ; + + TRACE_DEBUG( "RTC_GetTime()\n\r" ) ; + + /* Get current RTC time */ + dwTime = pRtc->RTC_TIMR ; + while ( dwTime != pRtc->RTC_TIMR ) + { + dwTime = pRtc->RTC_TIMR ; + } + + /* Hour */ + if ( pucHour ) + { + *pucHour = ((dwTime & 0x00300000) >> 20) * 10 + + ((dwTime & 0x000F0000) >> 16); + + if ( (dwTime & RTC_TIMR_AMPM) == RTC_TIMR_AMPM ) + { + *pucHour += 12 ; + } + } + + /* Minute */ + if ( pucMinute ) + { + *pucMinute = ((dwTime & 0x00007000) >> 12) * 10 + + ((dwTime & 0x00000F00) >> 8); + } + + /* Second */ + if ( pucSecond ) + { + *pucSecond = ((dwTime & 0x00000070) >> 4) * 10 + + (dwTime & 0x0000000F); + } +} + +/** + * \brief Sets a time alarm on the RTC. + * The match is performed only on the provided variables; + * Setting all pointers to 0 disables the time alarm. + * + * \note In AM/PM mode, the hour value must have bit #7 set for PM, cleared for + * AM (as expected in the time registers). + * + * \param pucHour If not null, the time alarm will hour-match this value. + * \param pucMinute If not null, the time alarm will minute-match this value. + * \param pucSecond If not null, the time alarm will second-match this value. + * + * \return 0 success, 1 fail to set + */ +extern int RTC_SetTimeAlarm( Rtc* pRtc, uint8_t *pucHour, uint8_t *pucMinute, uint8_t *pucSecond ) +{ + uint32_t dwAlarm=0 ; + + TRACE_DEBUG( "RTC_SetTimeAlarm()\n\r" ) ; + + /* Hour */ + if ( pucHour ) + { + dwAlarm |= RTC_TIMALR_HOUREN | ((*pucHour / 10) << 20) | ((*pucHour % 10) << 16); + } + + /* Minute */ + if ( pucMinute ) + { + dwAlarm |= RTC_TIMALR_MINEN | ((*pucMinute / 10) << 12) | ((*pucMinute % 10) << 8); + } + + /* Second */ + if ( pucSecond ) + { + dwAlarm |= RTC_TIMALR_SECEN | ((*pucSecond / 10) << 4) | (*pucSecond % 10); + } + + pRtc->RTC_TIMALR = dwAlarm ; + + return (int)(pRtc->RTC_VER & RTC_VER_NVTIMALR) ; +} + +/** + * \brief Retrieves the current year, month and day from the RTC. + * Month, day and week values are numbered starting at 1. + * + * \param pYwear Current year (optional). + * \param pucMonth Current month (optional). + * \param pucDay Current day (optional). + * \param pucWeek Current day in current week (optional). + */ +extern void RTC_GetDate( Rtc* pRtc, uint16_t *pwYear, uint8_t *pucMonth, uint8_t *pucDay, uint8_t *pucWeek ) +{ + uint32_t dwDate ; + + /* Get current date (multiple reads are necessary to insure a stable value) */ + do + { + dwDate = pRtc->RTC_CALR ; + } + while ( dwDate != pRtc->RTC_CALR ) ; + + /* Retrieve year */ + if ( pwYear ) + { + *pwYear = (((dwDate >> 4) & 0x7) * 1000) + + ((dwDate & 0xF) * 100) + + (((dwDate >> 12) & 0xF) * 10) + + ((dwDate >> 8) & 0xF); + } + + /* Retrieve month */ + if ( pucMonth ) + { + *pucMonth = (((dwDate >> 20) & 1) * 10) + ((dwDate >> 16) & 0xF); + } + + /* Retrieve day */ + if ( pucDay ) + { + *pucDay = (((dwDate >> 28) & 0x3) * 10) + ((dwDate >> 24) & 0xF); + } + + /* Retrieve week */ + if ( pucWeek ) + { + *pucWeek = ((dwDate >> 21) & 0x7); + } +} + +/** + * \brief Sets the current year, month and day in the RTC. + * Month, day and week values must be numbered starting from 1. + * + * \note In successive update operations, the user must wait at least one second + * after resetting the UPDTIM/UPDCAL bit in the RTC_CR before setting these + * bits again. Please look at the RTC section of the datasheet for detail. + * + * \param wYear Current year. + * \param ucMonth Current month. + * \param ucDay Current day. + * \param ucWeek Day number in current week. + * + * \return 0 success, 1 fail to set + */ +extern int RTC_SetDate( Rtc* pRtc, uint16_t wYear, uint8_t ucMonth, uint8_t ucDay, uint8_t ucWeek ) +{ + uint32_t wDate ; + uint8_t ucCent_bcd ; + uint8_t ucYear_bcd ; + uint8_t ucMonth_bcd ; + uint8_t ucDay_bcd ; + uint8_t ucWeek_bcd ; + + ucCent_bcd = ((wYear/100)%10) | ((wYear/1000)<<4); + ucYear_bcd = (wYear%10) | (((wYear/10)%10)<<4); + ucMonth_bcd = ((ucMonth%10) | (ucMonth/10)<<4); + ucDay_bcd = ((ucDay%10) | (ucDay/10)<<4); + ucWeek_bcd = ((ucWeek%10) | (ucWeek/10)<<4); + + /* value over flow */ + if ( (ucCent_bcd & (uint8_t)(~RTC_CENT_BIT_LEN_MASK)) | + (ucYear_bcd & (uint8_t)(~RTC_YEAR_BIT_LEN_MASK)) | + (ucMonth_bcd & (uint8_t)(~RTC_MONTH_BIT_LEN_MASK)) | + (ucWeek_bcd & (uint8_t)(~RTC_WEEK_BIT_LEN_MASK)) | + (ucDay_bcd & (uint8_t)(~RTC_DATE_BIT_LEN_MASK)) + ) + { + return 1 ; + } + + + /* Convert values to date register value */ + wDate = ucCent_bcd | + (ucYear_bcd << 8) | + (ucMonth_bcd << 16) | + (ucWeek_bcd << 21) | + (ucDay_bcd << 24); + + /* Update calendar register */ + pRtc->RTC_CR |= RTC_CR_UPDCAL ; + while ((pRtc->RTC_SR & RTC_SR_ACKUPD) != RTC_SR_ACKUPD) ; + + pRtc->RTC_SCCR = RTC_SCCR_ACKCLR; + pRtc->RTC_CALR = wDate ; + pRtc->RTC_CR &= (uint32_t)(~RTC_CR_UPDCAL) ; + pRtc->RTC_SCCR |= RTC_SCCR_SECCLR; /* clear SECENV in SCCR */ + + return (int)(pRtc->RTC_VER & RTC_VER_NVCAL) ; +} + +/** + * \brief Sets a date alarm in the RTC. + * The alarm will match only the provided values; + * Passing a null-pointer disables the corresponding field match. + * + * \param pucMonth If not null, the RTC alarm will month-match this value. + * \param pucDay If not null, the RTC alarm will day-match this value. + * + * \return 0 success, 1 fail to set + */ +extern int RTC_SetDateAlarm( Rtc* pRtc, uint8_t *pucMonth, uint8_t *pucDay ) +{ + uint32_t dwAlarm ; + + dwAlarm = ((pucMonth) || (pucDay)) ? (0) : (0x01010000); + + TRACE_DEBUG( "RTC_SetDateAlarm()\n\r" ) ; + + /* Compute alarm field value */ + if ( pucMonth ) + { + dwAlarm |= RTC_CALALR_MTHEN | ((*pucMonth / 10) << 20) | ((*pucMonth % 10) << 16); + } + + if ( pucDay ) + { + dwAlarm |= RTC_CALALR_DATEEN | ((*pucDay / 10) << 28) | ((*pucDay % 10) << 24); + } + + /* Set alarm */ + pRtc->RTC_CALALR = dwAlarm ; + + return (int)(pRtc->RTC_VER & RTC_VER_NVCALALR) ; +} + +/** + * \brief Clear flag bits of status clear command register in the RTC. + * + * \param mask Bits mask of cleared events + */ +extern void RTC_ClearSCCR( Rtc* pRtc, uint32_t dwMask ) +{ + /* Clear all flag bits in status clear command register */ + dwMask &= RTC_SCCR_ACKCLR | RTC_SCCR_ALRCLR | RTC_SCCR_SECCLR | RTC_SCCR_TIMCLR | RTC_SCCR_CALCLR ; + + pRtc->RTC_SCCR = dwMask ; +} + +/** + * \brief Get flag bits of status register in the RTC. + * + * \param mask Bits mask of Status Register + * + * \return Status register & mask + */ +extern uint32_t RTC_GetSR( Rtc* pRtc, uint32_t dwMask ) +{ + uint32_t dwEvent ; + + dwEvent = pRtc->RTC_SR ; + + return (dwEvent & dwMask) ; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/rtt.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/rtt.c new file mode 100644 index 00000000..516a196c --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/rtt.c @@ -0,0 +1,132 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup rtt_module Working with RTT + * The RTT driver provides the interface to configure and use the RTT + * peripheral. + * + * The Real-time Timer is used to count elapsed seconds.\n + * This timer is clocked by the 32kHz system clock divided by a programmable + * 16-bit balue. To be accurate, it is better to use an + * external 32kHz crystal instead of the internal 32kHz RC.\n + * + * To count elapsed seconds, the user could follow these few steps: + *
    + *
  • Programming PTPRES in RTT_MR to feeding the timer with a 1Hz signal.
  • + *
  • Writing the bit RTTRST in RTT_MR to restart the timer with new settings.
  • + *
+ * + * An alarm can be set to happen on second by setting alarm value in RTT_AR. + * Alarm occurence can be detected by polling or interrupt. + * + * For more accurate information, please look at the RTT section of the + * Datasheet. + * + * Related files :\n + * \ref rtt.c\n + * \ref rtt.h.\n + */ +/*@{*/ +/*@}*/ + +/** + * \file + * + * Implementation of Real Time Timer (RTT) controller. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ +#include "chip.h" + +#include + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Changes the prescaler value of the given RTT and restarts it. + * + * \note This function disables RTT interrupt sources. + * + * \param rtt Pointer to a Rtt instance. + * \param prescaler Prescaler value for the RTT. + */ +void RTT_SetPrescaler(Rtt *rtt, uint16_t prescaler) +{ + rtt->RTT_MR = (prescaler | RTT_MR_RTTRST); +} + +/** + * \brief Returns the current value of the RTT timer value. + * + * \param rtt Pointer to a Rtt instance. + */ +uint32_t RTT_GetTime(Rtt *rtt) +{ + return rtt->RTT_VR; +} + +/** + * \brief Enables the specified RTT interrupt sources. + * + * \param rtt Pointer to a Rtt instance. + * \param sources Bitmask of interrupts to enable. + */ +void RTT_EnableIT(Rtt *rtt, uint32_t sources) +{ + assert( (sources & 0x0004FFFF) == 0 ) ; + rtt->RTT_MR |= sources; +} + +/** + * \brief Returns the status register value of the given RTT. + * + * \param rtt Pointer to an Rtt instance. + */ +uint32_t RTT_GetStatus(Rtt *rtt) +{ + return rtt->RTT_SR; +} + +/** + * \brief Configures the RTT to generate an alarm at the given time. + * + * \param pRtt Pointer to an Rtt instance. + * \param time Alarm time. + */ +void RTT_SetAlarm(Rtt *pRtt, uint32_t time) +{ + assert(time > 0); + + pRtt->RTT_AR = time - 1; +} diff --git a/sam3s_example/src/spi.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/spi.c similarity index 100% rename from sam3s_example/src/spi.c rename to sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/spi.c diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/spi_pdc.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/spi_pdc.c new file mode 100644 index 00000000..eea16ba8 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/spi_pdc.c @@ -0,0 +1,251 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup spi_pdc_module SPI PDC driver + * \ingroup spi_at45_module + * The Spi driver is a low level spi driver which performs SPI device Initializes, + * spi transfer and receive. It can be used by upper SPI driver such as AT45 + * driver and AT26 driver. + * + * \section Usage + *
    + *
  • Initializes a SPI instance and the corresponding SPI hardware, + * Configure SPI in Master Mode using SPID_Configure().
  • + *
  • Configures the SPI characteristics (such as Clock Polarity, Phase, + * transfers delay and Baud Rate) for the device corresponding to the + * chip select using SPID_ConfigureCS().
  • + *
  • Starts a SPI master transfer using SPID_SendCommand(). + * The transfer is performed using the PDC channels.
  • + *
  • It enable the SPI clock.
  • + *
  • Set the corresponding peripheral chip select.
  • + *
  • Initialize the two SPI PDC buffers.
  • + *
  • Initialize SPI_TPR and SPI_TCR with SPI command data and size + * to send command data first.
  • + *
  • Initialize SPI_RPR and SPI_RCR with SPI command data and size + * as dummy value.
  • + *
  • Initialize SPI_TNPR and SPI_TNCR with rest of the data to be + * transfered.(if the data specified in cmd structure)
  • + *
  • Initialize SPI_RNPR and SPI_RNCR with rest of the data to be + * received.(if the data specified in cmd structure)
  • + *
  • Initialize the callback function if specified.
  • + *
  • Enable transmitter and receiver.
  • + *
  • Example for sending a command to the dataflash through the SPI.
  • + * \code + * /// Build command to be sent. + * ... + * // Send Command and data through the SPI + * if (SPID_SendCommand(pAt45->pSpid, pCommand)) { + * return AT45_ERROR_SPI; + * } + * \endcode + *
  • The SPI_Handler() must be called by the SPI Interrupt Service Routine + * with the corresponding Spi instance. It is invokes to check for pending + * interrupts.
  • + *
  • Example for initializing SPI interrupt handler in upper application.
  • + * \code + * AIC_ConfigureIT(AT91C_ID_SPI, 0, SPI_Handler); + * \endcode + *
+ * Related files :\n + * \ref spi_pdc.c\n + * \ref spi_pdc.h.\n +*/ +/*@{*/ +/*@}*/ + + +/** + * \file + * + * Implementation of SPI PDC driver. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ +#include "chip.h" + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Initializes the Spid structure and the corresponding SPI hardware. + * + * \param pSpid Pointer to a Spid instance. + * \param pSpiHw Associated SPI peripheral. + * \param spiId SPI peripheral identifier. + * \return 0. + */ +extern uint32_t SPID_Configure( Spid* pSpid, Spi* pSpiHw, uint8_t spiId ) +{ + /* Initialize the SPI structure*/ + pSpid->pSpiHw = pSpiHw ; + pSpid->spiId = spiId ; + pSpid->semaphore = 1 ; + pSpid->pCurrentCommand = 0 ; + + /* Enable the SPI clock*/ + PMC_EnablePeripheral( pSpid->spiId ) ; + + /* Configure SPI in Master Mode with No CS selected !!! */ + SPI_Configure( pSpiHw, pSpid->spiId, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PCS_Msk ) ; + + /* Enable the SPI */ + SPI_Enable( pSpiHw ) ; + + /* Disable the SPI clock */ + PMC_DisablePeripheral( pSpid->spiId ) ; + + return 0 ; +} + +/** + * \brief Configures the parameters for the device corresponding to the cs. + * + * \param pSpid Pointer to a Spid instance. + * \param cs number corresponding to the SPI chip select. + * \param csr SPI_CSR value to setup. + */ +extern void SPID_ConfigureCS( Spid* pSpid, uint32_t dwCS, uint32_t dwCSR ) +{ + SPI_ConfigureNPCS( pSpid->pSpiHw, dwCS, dwCSR ) ; +} + +/** + * \brief Starts a SPI master transfer. This is a non blocking function. It will + * return as soon as the transfer is started. + * + * \param pSpid Pointer to a Spid instance. + * \param pCommand Pointer to the SPI command to execute. + * \return 0 if the transfer has been started successfully; otherwise returns + * SPID_ERROR_LOCK is the driver is in use, or SPID_ERROR if the command is not + * valid. + */ +extern uint32_t SPID_SendCommand( Spid* pSpid, SpidCmd* pCommand ) +{ + Spi* pSpiHw = pSpid->pSpiHw ; + uint32_t dwSpiMr ; + + /* Try to get the dataflash semaphore */ + if ( pSpid->semaphore == 0 ) + { + return SPID_ERROR_LOCK ; + } + pSpid->semaphore-- ; + + /* Enable the SPI clock */ + PMC_EnablePeripheral( pSpid->spiId ) ; + + /* Disable transmitter and receiver*/ + SPI_PdcDisableRx( pSpiHw ) ; + SPI_PdcDisableTx( pSpiHw ) ; + + /* Write to the MR register*/ + dwSpiMr = pSpiHw->SPI_MR ; + dwSpiMr |= SPI_MR_PCS_Msk ; + dwSpiMr &= ~((1 << pCommand->spiCs) << 16 ) ; + pSpiHw->SPI_MR=dwSpiMr ; + + /* Initialize the two SPI PDC buffer*/ + SPI_PdcSetRx( pSpiHw, pCommand->pCmd, pCommand->cmdSize, pCommand->pData, pCommand->dataSize ) ; + SPI_PdcSetTx( pSpiHw, pCommand->pCmd, pCommand->cmdSize, pCommand->pData, pCommand->dataSize ) ; + + /* Initialize the callback*/ + pSpid->pCurrentCommand = pCommand ; + + /* Enable transmitter and receiver*/ + SPI_PdcEnableRx( pSpiHw ) ; + SPI_PdcEnableTx( pSpiHw ) ; + + /* Enable buffer complete interrupt*/ + SPI_EnableIt( pSpiHw, SPI_IER_RXBUFF ) ; + + return 0 ; +} + +/** + * \brief The SPI_Handler must be called by the SPI Interrupt Service Routine with the + * corresponding Spi instance. + * + * \note The SPI_Handler will unlock the Spi semaphore and invoke the upper application + * callback. + * \param pSpid Pointer to a Spid instance. + */ +extern void SPID_Handler( Spid* pSpid ) +{ + SpidCmd *pSpidCmd = pSpid->pCurrentCommand ; + Spi *pSpiHw = pSpid->pSpiHw ; + volatile uint32_t spiSr ; + + /* Read the status register*/ + spiSr = pSpiHw->SPI_SR ; + if ( spiSr & SPI_SR_RXBUFF ) + { + /* Disable transmitter and receiver */ + SPI_PdcDisableRx( pSpiHw ) ; + SPI_PdcDisableTx( pSpiHw ) ; + + /* Disable the SPI clock*/ + PMC_DisablePeripheral( pSpid->spiId ) ; + + /* Disable buffer complete interrupt */ + SPI_DisableIt( pSpiHw, SPI_IDR_RXBUFF ) ; + + /* Release the dataflash semaphore*/ + pSpid->semaphore++ ; + + /* Invoke the callback associated with the current command*/ + if ( pSpidCmd && pSpidCmd->callback ) + { + pSpidCmd->callback( 0, pSpidCmd->pArgument ) ; + } + + /* Nothing must be done after. A new DF operation may have been started + in the callback function.*/ + } +} + +/** + * \brief Returns 1 if the SPI driver is currently busy executing a command; otherwise + * returns 0. + * \param pSpid Pointer to a Spid instance. + */ +extern uint32_t SPID_IsBusy( const Spid* pSpid ) +{ + if ( pSpid->semaphore == 0 ) + { + return 1 ; + } + else + { + return 0 ; + } +} diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/ssc.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/ssc.c new file mode 100644 index 00000000..44c7256a --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/ssc.c @@ -0,0 +1,247 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup ssc_module Working with SSC + * The SSC driver provides the interface to configure and use the SSC + * peripheral. + * + * !Usage + * + * -# Enable the SSC interface pins. + * -# Configure the SSC to operate at a specific frequency by calling + * SSC_Configure(). This function enables the peripheral clock of the SSC, + * but not its PIOs. + * -# Configure the transmitter and/or the receiver using the + * SSC_ConfigureTransmitter() and SSC_ConfigureEmitter() functions. + * -# Enable the PIOs or the transmitter and/or the received. + * -# Enable the transmitter and/or the receiver using SSC_EnableTransmitter() + * and SSC_EnableReceiver() + * -# Send data through the transmitter using SSC_Write() and SSC_WriteBuffer() + * -# Receive data from the receiver using SSC_Read() and SSC_ReadBuffer() + * -# Disable the transmitter and/or the receiver using SSC_DisableTransmitter() + * and SSC_DisableReceiver() + * + * For more accurate information, please look at the RTC section of the + * Datasheet. + * + * Related files :\n + * \ref ssc.c\n + * \ref ssc.h.\n +*/ +/*@{*/ +/*@}*/ + + +/** + * \file + * + * Implementation of Synchronous Serial (SSC) controller. + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "chip.h" + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Configures a SSC peripheral.If the divided clock is not used, the master + * clock frequency can be set to 0. + * \note The emitter and transmitter are disabled by this function. + * \param bitRate bit rate. + * \param masterClock master clock. + */ +void SSC_Configure(uint32_t bitRate, uint32_t masterClock) +{ + /* Enable SSC peripheral clock */ + PMC->PMC_PCER0 = 1 << ID_SSC; + + /* Reset, disable receiver & transmitter */ + SSC->SSC_CR = SSC_CR_RXDIS | SSC_CR_TXDIS | SSC_CR_SWRST; + + SSC->SSC_PTCR = SSC_PTCR_RXTDIS | SSC_PTCR_TXTDIS; + /* Configure clock frequency */ + if (bitRate != 0) { + + SSC->SSC_CMR = masterClock / (2 * bitRate); + } + else { + + SSC->SSC_CMR = 0; + } +} + +/** + * \brief Configures the transmitter of a SSC peripheral. + * \param tcmr Transmit Clock Mode Register value. + * \param tfmr Transmit Frame Mode Register value. + */ +void SSC_ConfigureTransmitter(uint32_t tcmr, uint32_t tfmr) +{ + SSC->SSC_TCMR = tcmr; + SSC->SSC_TFMR = tfmr; +} + +/** + * \brief Configures the receiver of a SSC peripheral. + * \param rcmr Receive Clock Mode Register value. + * \param rfmr Receive Frame Mode Register value. + */ +void SSC_ConfigureReceiver(uint32_t rcmr, uint32_t rfmr) +{ + SSC->SSC_RCMR = rcmr; + SSC->SSC_RFMR = rfmr; +} + +/** + * \brief Enables the transmitter of a SSC peripheral. + */ +void SSC_EnableTransmitter(void) +{ + SSC->SSC_CR = SSC_CR_TXEN; +} + +/** + * \brief Disables the transmitter of a SSC peripheral. + */ +void SSC_DisableTransmitter(void) +{ + SSC->SSC_CR = SSC_CR_TXDIS; +} + +/** + * \brief Enables the receiver of a SSC peripheral. + */ +void SSC_EnableReceiver(void) +{ + SSC->SSC_CR = SSC_CR_RXEN; +} + +/** + * \brief Disables the receiver of a SSC peripheral. + */ +void SSC_DisableReceiver(void) +{ + SSC->SSC_CR = SSC_CR_RXDIS; +} + +/** + * \brief Enables one or more interrupt sources of a SSC peripheral. + * \param sources Bitwise OR of selected interrupt sources. + */ +void SSC_EnableInterrupts(uint32_t sources) +{ + SSC->SSC_IER = sources; +} + +/** + * \brief Disables one or more interrupt sources of a SSC peripheral. + * \param sources Bitwise OR of selected interrupt sources. + */ +void SSC_DisableInterrupts(uint32_t sources) +{ + SSC->SSC_IDR = sources; +} + +/** + * \brief Sends one data frame through a SSC peripheral. If another frame is currently + * being sent, this function waits for the previous transfer to complete. + * \param frame Data frame to send. + */ +void SSC_Write(uint32_t frame) +{ + while ((SSC->SSC_SR & SSC_SR_TXRDY) == 0); + SSC->SSC_THR = frame; +} + +/** + * \brief Waits until one frame is received on a SSC peripheral, and returns it. + */ +uint32_t SSC_Read(void) +{ + while ((SSC->SSC_SR & SSC_SR_RXRDY) == 0); + return SSC->SSC_RHR; +} + +/** + * \brief Sends the contents of a data buffer a SSC peripheral, using the PDC. + * \param buffer Data buffer to send. + * \param length Size of the data buffer. + * \return 1 if the buffer has been queued for transmission; otherwise returns 0. + */ +uint8_t SSC_WriteBuffer(void *buffer, uint32_t length) +{ + /* Check if first bank is free*/ + if (SSC->SSC_TCR == 0) { + + SSC->SSC_TPR = (uint32_t) buffer; + SSC->SSC_TCR = length; + SSC->SSC_PTCR = SSC_PTCR_TXTEN; + return 1; + } + /* Check if second bank is free*/ + else if (SSC->SSC_TNCR == 0) { + + SSC->SSC_TNPR = (uint32_t) buffer; + SSC->SSC_TNCR = length; + return 1; + } + return 0; +} + +/** + * \brief Reads data coming from a SSC peripheral receiver and stores it into the + * giving buffer with PDC. + * \param buffer ata buffer used for reception. + * \param length Size of the data buffer. + * \return 1 if the buffer has been queued for reception; otherwise returns 0. + */ +uint8_t SSC_ReadBuffer(void *buffer, uint32_t length) +{ + /* Check if the first bank is free*/ + if (SSC->SSC_RCR == 0) { + + SSC->SSC_RPR = (uint32_t) buffer; + SSC->SSC_RCR = length; + SSC->SSC_PTCR = SSC_PTCR_RXTEN; + return 1; + } + /* Check if second bank is free*/ + else if (SSC->SSC_RNCR == 0) { + SSC->SSC_RNPR = (uint32_t) buffer; + SSC->SSC_RNCR = length; + return 1; + } + return 0; +} diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/supc.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/supc.c new file mode 100644 index 00000000..340bbd60 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/supc.c @@ -0,0 +1,196 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, 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 disclaimer below. + * + * 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 "chip.h" + +#include + +//------------------------------------------------------------------------------ +// Local definitions +//------------------------------------------------------------------------------ + +/// Key value for the SUPC_MR register. +#define SUPC_KEY ((uint32_t) (0xA5 << 24)) + +//------------------------------------------------------------------------------ +// Global functions +//------------------------------------------------------------------------------ + +#if !defined(__ICCARM__) +__attribute__ ((section (".ramfunc"))) // GCC +#endif +//------------------------------------------------------------------------------ +/// Enables the flash power supply with the given wake-up setting. +/// \param time Wake-up time. +//------------------------------------------------------------------------------ +void SUPC_EnableFlash( Supc* pSupc, uint32_t dwTime ) +{ + pSupc->SUPC_FWUTR = dwTime ; + pSupc->SUPC_MR = SUPC_KEY | pSupc->SUPC_MR | AT91C_SUPC_FLASHON ; + + while ((pSupc->SUPC_SR & AT91C_SUPC_FLASHS) != AT91C_SUPC_FLASHS) ; +} + +#if !defined(__ICCARM__) +__attribute__ ((section (".ramfunc"))) // GCC +#endif +//------------------------------------------------------------------------------ +/// Disables the flash power supply. +//------------------------------------------------------------------------------ +void SUPC_DisableFlash( Supc* pSupc ) +{ + pSupc->SUPC_MR = SUPC_KEY | (pSupc->SUPC_MR & ~AT91C_SUPC_FLASHON) ; + + while ((pSupc->SUPC_SR & AT91C_SUPC_FLASHS) == AT91C_SUPC_FLASHS) ; +} + +//------------------------------------------------------------------------------ +/// Sets the voltage regulator output voltage. +/// \param voltage Voltage to set. +//------------------------------------------------------------------------------ +void SUPC_SetVoltageOutput( Supc* pSupc, uint32_t dwVoltage ) +{ + assert( (voltage & ~AT91C_SUPC_VRVDD) == 0 ) ; + + pSupc->SUPC_MR = SUPC_KEY | (pSupc->SUPC_MR & ~AT91C_SUPC_VRVDD) | dwVoltage ; +} + +//------------------------------------------------------------------------------ +/// Puts the voltage regulator in deep mode. +//------------------------------------------------------------------------------ +void SUPC_EnableDeepMode( Supc* pSupc ) +{ + pSupc->SUPC_MR = SUPC_KEY | pSupc->SUPC_MR | AT91C_SUPC_VRDEEP ; +} + +//------------------------------------------------------------------------------ +/// Puts the voltage regulator in normal mode. +//------------------------------------------------------------------------------ +void SUPC_DisableDeepMode( Supc* pSupc ) +{ + pSupc->SUPC_MR = SUPC_KEY | (pSupc->SUPC_MR & ~AT91C_SUPC_VRDEEP) ; +} + +//----------------------------------------------------------------------------- +/// Enables the backup SRAM power supply, so its data is saved while the device +/// is in backup mode. +//----------------------------------------------------------------------------- +void SUPC_EnableSram( Supc* pSupc ) +{ + pSupc->SUPC_MR = SUPC_KEY | pSupc->SUPC_MR | AT91C_SUPC_SRAMON ; +} + +//----------------------------------------------------------------------------- +/// Disables the backup SRAM power supply. +//----------------------------------------------------------------------------- +void SUPC_DisableSram( Supc* pSupc ) +{ + pSupc->SUPC_MR = SUPC_KEY | (pSupc->SUPC_MR & ~AT91C_SUPC_SRAMON) ; +} + +//----------------------------------------------------------------------------- +/// Enables the RTC power supply. +//----------------------------------------------------------------------------- +void SUPC_EnableRtc( Supc* pSupc ) +{ + pSupc->SUPC_MR = SUPC_KEY | pSupc->SUPC_MR | AT91C_SUPC_RTCON ; + + while ((pSupc->SUPC_SR & AT91C_SUPC_RTS) != AT91C_SUPC_RTS) ; +} + +//----------------------------------------------------------------------------- +/// Disables the RTC power supply. +//----------------------------------------------------------------------------- +void SUPC_DisableRtc( Supc* pSupc ) +{ + pSupc->SUPC_MR = SUPC_KEY | (pSupc->SUPC_MR & ~AT91C_SUPC_RTCON) ; + + while ((pSupc->SUPC_SR & AT91C_SUPC_RTS) == AT91C_SUPC_RTS); +} + +//----------------------------------------------------------------------------- +/// Sets the BOD sampling mode (or disables it). +/// \param mode BOD sampling mode. +//----------------------------------------------------------------------------- +void SUPC_SetBodSampling( Supc* pSupc, uint32_t dwMode ) +{ + assert( (dwMode & ~AT91C_SUPC_BODSMPL) == 0 ) ; + + pSupc->SUPC_BOMR &= ~AT91C_SUPC_BODSMPL; + pSupc->SUPC_BOMR |= dwMode ; +} + +//------------------------------------------------------------------------------ +/// Disables the voltage regulator, which makes the device enter backup mode. +//------------------------------------------------------------------------------ +void SUPC_DisableVoltageRegulator( Supc* pSupc ) +{ + pSupc->SUPC_CR = SUPC_KEY | AT91C_SUPC_VROFF ; + + while ( 1 ) ; +} + +//------------------------------------------------------------------------------ +/// Shuts the device down so it enters Off mode. +//------------------------------------------------------------------------------ +void SUPC_Shutdown( Supc* pSupc ) +{ + pSupc->SUPC_CR = SUPC_KEY | AT91C_SUPC_SHDW ; + + while (1); +} + +//------------------------------------------------------------------------------ +/// Sets the wake-up sources when in backup mode. +/// \param sources Wake-up sources to enable. +//------------------------------------------------------------------------------ +void SUPC_SetWakeUpSources( Supc* pSupc, uint32_t dwSources ) +{ + assert( (dwSources & ~0x0000000B) == 0 ) ; + + pSupc->SUPC_WUMR &= ~0x0000000B; + pSupc->SUPC_WUMR |= dwSources ; +} + +//------------------------------------------------------------------------------ +/// Sets the wake-up inputs when in backup mode. +/// \param inputs Wake up inputs to enable. +//------------------------------------------------------------------------------ +void SUPC_SetWakeUpInputs( Supc* pSupc, uint32_t dwInputs ) +{ + assert( (dwInputs & ~0xFFFF) == 0 ) ; + + pSupc->SUPC_WUIR &= ~0xFFFF ; + pSupc->SUPC_WUIR |= dwInputs ; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/tc.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/tc.c new file mode 100644 index 00000000..9cad5467 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/tc.c @@ -0,0 +1,175 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implementation of Timer Counter (TC). + * + */ + +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ + +#include "chip.h" + +#include + +/*------------------------------------------------------------------------------ + * Global functions + *------------------------------------------------------------------------------*/ + +/** + * \brief Configures a Timer Counter Channel + * + * Configures a Timer Counter to operate in the given mode. Timer is stopped + * after configuration and must be restarted with TC_Start(). All the + * interrupts of the timer are also disabled. + * + * \param pTc Pointer to a Tc instance. + * \param channel Channel number. + * \param mode Operating mode (TC_CMR value). + */ +extern void TC_Configure( Tc *pTc, uint32_t dwChannel, uint32_t dwMode ) +{ + TcChannel* pTcCh ; + + assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ; + pTcCh = pTc->TC_CHANNEL+dwChannel ; + + /* Disable TC clock */ + pTcCh->TC_CCR = TC_CCR_CLKDIS ; + + /* Disable interrupts */ + pTcCh->TC_IDR = 0xFFFFFFFF ; + + /* Clear status register */ + pTcCh->TC_SR ; + + /* Set mode */ + pTcCh->TC_CMR = dwMode ; +} + +/** + * \brief Reset and Start the TC Channel + * + * Enables the timer clock and performs a software reset to start the counting. + * + * \param pTc Pointer to a Tc instance. + * \param dwChannel Channel number. + */ +extern void TC_Start( Tc *pTc, uint32_t dwChannel ) +{ + TcChannel* pTcCh ; + + assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ; + + pTcCh = pTc->TC_CHANNEL+dwChannel ; + pTcCh->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ; +} + +/** + * \brief Stop TC Channel + * + * Disables the timer clock, stopping the counting. + * + * \param pTc Pointer to a Tc instance. + * \param dwChannel Channel number. + */ +extern void TC_Stop(Tc *pTc, uint32_t dwChannel ) +{ + TcChannel* pTcCh ; + + assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ; + + pTcCh = pTc->TC_CHANNEL+dwChannel ; + pTcCh->TC_CCR = TC_CCR_CLKDIS ; +} + +/** + * \brief Find best MCK divisor + * + * Finds the best MCK divisor given the timer frequency and MCK. The result + * is guaranteed to satisfy the following equation: + * \code + * (MCK / (DIV * 65536)) <= freq <= (MCK / DIV) + * \endcode + * with DIV being the highest possible value. + * + * \param dwFreq Desired timer frequency. + * \param dwMCk Master clock frequency. + * \param dwDiv Divisor value. + * \param dwTcClks TCCLKS field value for divisor. + * \param dwBoardMCK Board clock frequency. + * + * \return 1 if a proper divisor has been found, otherwise 0. + */ +extern uint32_t TC_FindMckDivisor( uint32_t dwFreq, uint32_t dwMCk, uint32_t *dwDiv, uint32_t *dwTcClks, uint32_t dwBoardMCK ) +{ + const uint32_t adwDivisors[5] = { 2, 8, 32, 128, dwBoardMCK / 32768 } ; + + uint32_t dwIndex = 0 ; + + /* Satisfy lower bound */ + while ( dwFreq < ((dwMCk / adwDivisors[dwIndex]) / 65536) ) + { + dwIndex++ ; + + /* If no divisor can be found, return 0 */ + if ( dwIndex == (sizeof( adwDivisors )/sizeof( adwDivisors[0] )) ) + { + return 0 ; + } + } + + /* Try to maximize DIV while satisfying upper bound */ + while ( dwIndex < 4 ) + { + + if ( dwFreq > (dwMCk / adwDivisors[dwIndex + 1]) ) + { + break ; + } + dwIndex++ ; + } + + /* Store results */ + if ( dwDiv ) + { + *dwDiv = adwDivisors[dwIndex] ; + } + if ( dwTcClks ) + { + *dwTcClks = dwIndex ; + } + + return 1 ; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/twi.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/twi.c new file mode 100644 index 00000000..c2fec947 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/twi.c @@ -0,0 +1,380 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** \addtogroup twi_module Working with TWI + * The TWI driver provides the interface to configure and use the TWI + * peripheral. + * + * \section Usage + *
    + *
  • Configures a TWI peripheral to operate in master mode, at the given + * frequency (in Hz) using TWI_Configure().
  • + *
  • Sends a STOP condition on the TWI using TWI_Stop().
  • + *
  • Starts a read operation on the TWI bus with the specified slave using + * TWI_StartRead(). Data must then be read using TWI_ReadByte() whenever + * a byte is available (poll using TWI_ByteReceived()).
  • + *
  • Starts a write operation on the TWI to access the selected slave using + * TWI_StartWrite(). A byte of data must be provided to start the write; + * other bytes are written next.
  • + *
  • Sends a byte of data to one of the TWI slaves on the bus using TWI_WriteByte(). + * This function must be called once before TWI_StartWrite() with the first byte of data + * to send, then it shall be called repeatedly after that to send the remaining bytes.
  • + *
  • Check if a byte has been received and can be read on the given TWI + * peripheral using TWI_ByteReceived().< + * Check if a byte has been sent using TWI_ByteSent().
  • + *
  • Check if the current transmission is complete (the STOP has been sent) + * using TWI_TransferComplete().
  • + *
  • Enables & disable the selected interrupts sources on a TWI peripheral + * using TWI_EnableIt() and TWI_DisableIt().
  • + *
  • Get current status register of the given TWI peripheral using + * TWI_GetStatus(). Get current status register of the given TWI peripheral, but + * masking interrupt sources which are not currently enabled using + * TWI_GetMaskedStatus().
  • + *
+ * For more accurate information, please look at the TWI section of the + * Datasheet. + * + * Related files :\n + * \ref twi.c\n + * \ref twi.h.\n +*/ +/*@{*/ +/*@}*/ + +/** + * \file + * + * Implementation of Two Wire Interface (TWI). + * + */ + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "chip.h" + +#include + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Configures a TWI peripheral to operate in master mode, at the given + * frequency (in Hz). The duty cycle of the TWI clock is set to 50%. + * \param pTwi Pointer to an Twi instance. + * \param twck Desired TWI clock frequency. + * \param mck Master clock frequency. + */ +void TWI_ConfigureMaster( Twi* pTwi, uint32_t dwTwCk, uint32_t dwMCk ) +{ + uint32_t dwCkDiv = 0 ; + uint32_t dwClDiv ; + uint32_t dwOk = 0 ; + + TRACE_DEBUG( "TWI_ConfigureMaster()\n\r" ) ; + assert( pTwi ) ; + + /* SVEN: TWI Slave Mode Enabled */ + pTwi->TWI_CR = TWI_CR_SVEN ; + /* Reset the TWI */ + pTwi->TWI_CR = TWI_CR_SWRST ; + pTwi->TWI_RHR ; + + /* TWI Slave Mode Disabled, TWI Master Mode Disabled. */ + pTwi->TWI_CR = TWI_CR_SVDIS ; + pTwi->TWI_CR = TWI_CR_MSDIS ; + + /* Set master mode */ + pTwi->TWI_CR = TWI_CR_MSEN ; + + /* Configure clock */ + while ( !dwOk ) + { + dwClDiv = ((dwMCk / (2 * dwTwCk)) - 4) / (1<TWI_CWGR = 0 ; + pTwi->TWI_CWGR = (dwCkDiv << 16) | (dwClDiv << 8) | dwClDiv ; +} + +/** + * \brief Configures a TWI peripheral to operate in slave mode. + * \param pTwi Pointer to an Twi instance. + * \param slaveAddress Slave address. + */ +void TWI_ConfigureSlave(Twi *pTwi, uint8_t slaveAddress) +{ + uint32_t i; + + /* TWI software reset */ + pTwi->TWI_CR = TWI_CR_SWRST; + pTwi->TWI_RHR; + + /* Wait at least 10 ms */ + for (i=0; i < 1000000; i++); + + /* TWI Slave Mode Disabled, TWI Master Mode Disabled*/ + pTwi->TWI_CR = TWI_CR_SVDIS | TWI_CR_MSDIS; + + /* Configure slave address. */ + pTwi->TWI_SMR = 0; + pTwi->TWI_SMR = TWI_SMR_SADR(slaveAddress); + + /* SVEN: TWI Slave Mode Enabled */ + pTwi->TWI_CR = TWI_CR_SVEN; + + /* Wait at least 10 ms */ + for (i=0; i < 1000000; i++); + assert( (pTwi->TWI_CR & TWI_CR_SVDIS)!= TWI_CR_SVDIS ) ; +} + +/** + * \brief Sends a STOP condition on the TWI. + * \param pTwi Pointer to an Twi instance. + */ +void TWI_Stop( Twi *pTwi ) +{ + assert( pTwi != NULL ) ; + + pTwi->TWI_CR = TWI_CR_STOP; +} + +/** + * \brief Starts a read operation on the TWI bus with the specified slave, it returns + * immediately. Data must then be read using TWI_ReadByte() whenever a byte is + * available (poll using TWI_ByteReceived()). + * \param pTwi Pointer to an Twi instance. + * \param address Slave address on the bus. + * \param iaddress Optional internal address bytes. + * \param isize Number of internal address bytes. + */ +void TWI_StartRead( + Twi *pTwi, + uint8_t address, + uint32_t iaddress, + uint8_t isize) +{ + assert( pTwi != NULL ) ; + assert( (address & 0x80) == 0 ) ; + assert( (iaddress & 0xFF000000) == 0 ) ; + assert( isize < 4 ) ; + + /* Set slave address and number of internal address bytes. */ + pTwi->TWI_MMR = 0; + pTwi->TWI_MMR = (isize << 8) | TWI_MMR_MREAD | (address << 16); + + /* Set internal address bytes */ + pTwi->TWI_IADR = 0; + pTwi->TWI_IADR = iaddress; + + /* Send START condition */ + pTwi->TWI_CR = TWI_CR_START; +} + +/** + * \brief Reads a byte from the TWI bus. The read operation must have been started + * using TWI_StartRead() and a byte must be available (check with TWI_ByteReceived()). + * \param pTwi Pointer to an Twi instance. + * \return byte read. + */ +uint8_t TWI_ReadByte(Twi *pTwi) +{ + assert( pTwi != NULL ) ; + + return pTwi->TWI_RHR; +} + +/** + * \brief Sends a byte of data to one of the TWI slaves on the bus. + * \note This function must be called once before TWI_StartWrite() with + * the first byte of data to send, then it shall be called repeatedly + * after that to send the remaining bytes. + * \param pTwi Pointer to an Twi instance. + * \param byte Byte to send. + */ +void TWI_WriteByte(Twi *pTwi, uint8_t byte) +{ + assert( pTwi != NULL ) ; + + pTwi->TWI_THR = byte; +} + +/** + * \brief Starts a write operation on the TWI to access the selected slave, then + * returns immediately. A byte of data must be provided to start the write; + * other bytes are written next. + * after that to send the remaining bytes. + * \param pTwi Pointer to an Twi instance. + * \param address Address of slave to acccess on the bus. + * \param iaddress Optional slave internal address. + * \param isize Number of internal address bytes. + * \param byte First byte to send. + */ +void TWI_StartWrite( + Twi *pTwi, + uint8_t address, + uint32_t iaddress, + uint8_t isize, + uint8_t byte) +{ + assert( pTwi != NULL ) ; + assert( (address & 0x80) == 0 ) ; + assert( (iaddress & 0xFF000000) == 0 ) ; + assert( isize < 4 ) ; + + /* Set slave address and number of internal address bytes. */ + pTwi->TWI_MMR = 0; + pTwi->TWI_MMR = (isize << 8) | (address << 16); + + /* Set internal address bytes. */ + pTwi->TWI_IADR = 0; + pTwi->TWI_IADR = iaddress; + + /* Write first byte to send.*/ + TWI_WriteByte(pTwi, byte); +} + +/** + * \brief Check if a byte have been receiced from TWI. + * \param pTwi Pointer to an Twi instance. + * \return 1 if a byte has been received and can be read on the given TWI + * peripheral; otherwise, returns 0. This function resets the status register. + */ +uint8_t TWI_ByteReceived(Twi *pTwi) +{ + return ((pTwi->TWI_SR & TWI_SR_RXRDY) == TWI_SR_RXRDY); +} + +/** + * \brief Check if a byte have been sent to TWI. + * \param pTwi Pointer to an Twi instance. + * \return 1 if a byte has been sent so another one can be stored for + * transmission; otherwise returns 0. This function clears the status register. + */ +uint8_t TWI_ByteSent(Twi *pTwi) +{ + return ((pTwi->TWI_SR & TWI_SR_TXRDY) == TWI_SR_TXRDY); +} + +/** + * \brief Check if current transmission is complet. + * \param pTwi Pointer to an Twi instance. + * \return 1 if the current transmission is complete (the STOP has been sent); + * otherwise returns 0. + */ +uint8_t TWI_TransferComplete(Twi *pTwi) +{ + return ((pTwi->TWI_SR & TWI_SR_TXCOMP) == TWI_SR_TXCOMP); +} + +/** + * \brief Enables the selected interrupts sources on a TWI peripheral. + * \param pTwi Pointer to an Twi instance. + * \param sources Bitwise OR of selected interrupt sources. + */ +void TWI_EnableIt(Twi *pTwi, uint32_t sources) +{ + assert( pTwi != NULL ) ; + assert( (sources & 0xFFFFF088) == 0 ) ; + + pTwi->TWI_IER = sources; +} + +/** + * \brief Disables the selected interrupts sources on a TWI peripheral. + * \param pTwi Pointer to an Twi instance. + * \param sources Bitwise OR of selected interrupt sources. + */ +void TWI_DisableIt(Twi *pTwi, uint32_t sources) +{ + assert( pTwi != NULL ) ; + assert( (sources & 0xFFFFF088) == 0 ) ; + + pTwi->TWI_IDR = sources; +} + +/** + * \brief Get the current status register of the given TWI peripheral. + * \note This resets the internal value of the status register, so further + * read may yield different values. + * \param pTwi Pointer to an Twi instance. + * \return TWI status register. + */ +uint32_t TWI_GetStatus(Twi *pTwi) +{ + assert( pTwi != NULL ) ; + + return pTwi->TWI_SR; +} + +/** + * \brief Returns the current status register of the given TWI peripheral, but + * masking interrupt sources which are not currently enabled. + * \note This resets the internal value of the status register, so further + * read may yield different values. + * \param pTwi Pointer to an Twi instance. + */ +uint32_t TWI_GetMaskedStatus(Twi *pTwi) +{ + uint32_t status; + + assert( pTwi != NULL ) ; + + status = pTwi->TWI_SR; + status &= pTwi->TWI_IMR; + + return status; +} + +/** + * \brief Sends a STOP condition. STOP Condition is sent just after completing + * the current byte transmission in master read mode. + * \param pTwi Pointer to an Twi instance. + */ +void TWI_SendSTOPCondition(Twi *pTwi) +{ + assert( pTwi != NULL ) ; + + pTwi->TWI_CR |= TWI_CR_STOP; +} + diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/twid.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/twid.c new file mode 100644 index 00000000..a7dcdfdd --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/twid.c @@ -0,0 +1,342 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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 "chip.h" + +#include + +/*---------------------------------------------------------------------------- + * Definition + *----------------------------------------------------------------------------*/ +#define TWITIMEOUTMAX 50000 + +/*---------------------------------------------------------------------------- + * Types + *----------------------------------------------------------------------------*/ + +/** TWI driver callback function.*/ +typedef void (*TwiCallback)(Async *); + +/** \brief TWI asynchronous transfer descriptor.*/ +typedef struct _AsyncTwi { + + /** Asynchronous transfer status. */ + volatile uint8_t status; + // Callback function to invoke when transfer completes or fails.*/ + TwiCallback callback; + /** Pointer to the data buffer.*/ + uint8_t *pData; + /** Total number of bytes to transfer.*/ + uint32_t num; + /** Number of already transferred bytes.*/ + uint32_t transferred; + +} AsyncTwi; + +/*---------------------------------------------------------------------------- + * Global functions + *----------------------------------------------------------------------------*/ +/** + * \brief Initializes a TWI driver instance, using the given TWI peripheral. + * \note The peripheral must have been initialized properly before calling this function. + * \param pTwid Pointer to the Twid instance to initialize. + * \param pTwi Pointer to the TWI peripheral to use. + */ +void TWID_Initialize(Twid *pTwid, Twi *pTwi) +{ + TRACE_DEBUG( "TWID_Initialize()\n\r" ) ; + assert( pTwid != NULL ) ; + assert( pTwi != NULL ) ; + + /* Initialize driver. */ + pTwid->pTwi = pTwi; + pTwid->pTransfer = 0; +} + + +/** + * \brief Interrupt handler for a TWI peripheral. Manages asynchronous transfer + * occuring on the bus. This function MUST be called by the interrupt service + * routine of the TWI peripheral if asynchronous read/write are needed. + * \param pTwid Pointer to a Twid instance. + */ +void TWID_Handler( Twid *pTwid ) +{ + uint8_t status; + AsyncTwi *pTransfer ; + Twi *pTwi ; + + assert( pTwid != NULL ) ; + + pTransfer = (AsyncTwi*)pTwid->pTransfer ; + assert( pTransfer != NULL ) ; + pTwi = pTwid->pTwi ; + assert( pTwi != NULL ) ; + + /* Retrieve interrupt status */ + status = TWI_GetMaskedStatus(pTwi); + + /* Byte received */ + if (TWI_STATUS_RXRDY(status)) { + + pTransfer->pData[pTransfer->transferred] = TWI_ReadByte(pTwi); + pTransfer->transferred++; + + /* check for transfer finish */ + if (pTransfer->transferred == pTransfer->num) { + + TWI_DisableIt(pTwi, TWI_IDR_RXRDY); + TWI_EnableIt(pTwi, TWI_IER_TXCOMP); + } + /* Last byte? */ + else if (pTransfer->transferred == (pTransfer->num - 1)) { + + TWI_Stop(pTwi); + } + } + /* Byte sent*/ + else if (TWI_STATUS_TXRDY(status)) { + + /* Transfer finished ? */ + if (pTransfer->transferred == pTransfer->num) { + + TWI_DisableIt(pTwi, TWI_IDR_TXRDY); + TWI_EnableIt(pTwi, TWI_IER_TXCOMP); + TWI_SendSTOPCondition(pTwi); + } + /* Bytes remaining */ + else { + + TWI_WriteByte(pTwi, pTransfer->pData[pTransfer->transferred]); + pTransfer->transferred++; + } + } + /* Transfer complete*/ + else if (TWI_STATUS_TXCOMP(status)) { + + TWI_DisableIt(pTwi, TWI_IDR_TXCOMP); + pTransfer->status = 0; + if (pTransfer->callback) { + + pTransfer->callback((Async *) pTransfer); + } + pTwid->pTransfer = 0; + } +} + +/** + * \brief Asynchronously reads data from a slave on the TWI bus. An optional + * callback function is triggered when the transfer is complete. + * \param pTwid Pointer to a Twid instance. + * \param address TWI slave address. + * \param iaddress Optional slave internal address. + * \param isize Internal address size in bytes. + * \param pData Data buffer for storing received bytes. + * \param num Number of bytes to read. + * \param pAsync Asynchronous transfer descriptor. + * \return 0 if the transfer has been started; otherwise returns a TWI error code. + */ +uint8_t TWID_Read( + Twid *pTwid, + uint8_t address, + uint32_t iaddress, + uint8_t isize, + uint8_t *pData, + uint32_t num, + Async *pAsync) +{ + Twi *pTwi; + AsyncTwi *pTransfer; + uint32_t timeout; + + assert( pTwid != NULL ) ; + pTwi = pTwid->pTwi; + pTransfer = (AsyncTwi *) pTwid->pTransfer; + + assert( (address & 0x80) == 0 ) ; + assert( (iaddress & 0xFF000000) == 0 ) ; + assert( isize < 4 ) ; + + /* Check that no transfer is already pending*/ + if (pTransfer) { + + TRACE_ERROR("TWID_Read: A transfer is already pending\n\r"); + return TWID_ERROR_BUSY; + } + + /* Set STOP signal if only one byte is sent*/ + if (num == 1) { + + TWI_Stop(pTwi); + } + + /* Asynchronous transfer*/ + if (pAsync) { + + /* Update the transfer descriptor */ + pTwid->pTransfer = pAsync; + pTransfer = (AsyncTwi *) pAsync; + pTransfer->status = ASYNC_STATUS_PENDING; + pTransfer->pData = pData; + pTransfer->num = num; + pTransfer->transferred = 0; + + /* Enable read interrupt and start the transfer */ + TWI_EnableIt(pTwi, TWI_IER_RXRDY); + TWI_StartRead(pTwi, address, iaddress, isize); + } + /* Synchronous transfer*/ + else { + + /* Start read*/ + TWI_StartRead(pTwi, address, iaddress, isize); + + /* Read all bytes, setting STOP before the last byte*/ + while (num > 0) { + + /* Last byte ?*/ + if (num == 1) { + + TWI_Stop(pTwi); + } + + /* Wait for byte then read and store it*/ + timeout = 0; + while( !TWI_ByteReceived(pTwi) && (++timeoutpTwi; + AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer; + uint32_t timeout; + + assert( pTwi != NULL ) ; + assert( (address & 0x80) == 0 ) ; + assert( (iaddress & 0xFF000000) == 0 ) ; + assert( isize < 4 ) ; + + /* Check that no transfer is already pending */ + if (pTransfer) { + + TRACE_ERROR("TWI_Write: A transfer is already pending\n\r"); + return TWID_ERROR_BUSY; + } + + /* Asynchronous transfer */ + if (pAsync) { + + /* Update the transfer descriptor */ + pTwid->pTransfer = pAsync; + pTransfer = (AsyncTwi *) pAsync; + pTransfer->status = ASYNC_STATUS_PENDING; + pTransfer->pData = pData; + pTransfer->num = num; + pTransfer->transferred = 1; + + /* Enable write interrupt and start the transfer */ + TWI_StartWrite(pTwi, address, iaddress, isize, *pData); + TWI_EnableIt(pTwi, TWI_IER_TXRDY); + } + /* Synchronous transfer*/ + else { + + // Start write + TWI_StartWrite(pTwi, address, iaddress, isize, *pData++); + num--; + + /* Send all bytes */ + while (num > 0) { + + /* Wait before sending the next byte */ + timeout = 0; + while( !TWI_ByteSent(pTwi) && (++timeout + *
  • Configure USART with expected mode and baudrate(see \ref USART_Configure), which could be done by: + * -# Resetting and disabling transmitter and receiver by setting US_CR(Control Register).
  • + * -# Conifguring the USART in a specific mode by setting USART_MODE bits in US_MR(Mode Register) + * -# Setting baudrate which is different from mode to mode. + + *
  • Enable transmitter or receiver respectively by set US_CR_TXEN or US_CR_RXEN in US_CR.
  • + *
  • Read from or write to the peripheral with \ref USART_ReadBuffer or \ref USART_WriteBuffer. + These operations could be done by polling or interruption.
  • + *
  • For polling, check the status bit US_CSR_ENDRX/US_CSR_RXBUFF (READ) or US_CSR_ENDTX/ + US_CSR_TXBUFE (WRITE).
  • + *
  • For interruption,"enable" the status bit through US_IER and + realize the hanler with USARTx_IrqHandler according to IRQ vector + table which is defined in board_cstartup_.c + To enable the interruption of USART,it should be configured with priority and enabled first through + NVIC .
  • + * + * + * For more accurate information, please look at the USART section of the + * Datasheet. + * + * Related files :\n + * \ref usart.c\n + * \ref usart.h\n +*/ + + + +/** + * \file + * + * Implementation of USART (Universal Synchronous Asynchronous Receiver Transmitter) + * controller. + * + */ +/*------------------------------------------------------------------------------ + * Headers + *------------------------------------------------------------------------------*/ +#include "chip.h" +#include "trace.h" + +#include +#include + +/*---------------------------------------------------------------------------- + * Local definitions + *----------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------ + * Exported functions + *------------------------------------------------------------------------------*/ + +/** + * \brief Configures an USART peripheral with the specified parameters. + * + * + * \param usart Pointer to the USART peripheral to configure. + * \param mode Desired value for the USART mode register (see the datasheet). + * \param baudrate Baudrate at which the USART should operate (in Hz). + * \param masterClock Frequency of the system master clock (in Hz). + */ +void USART_Configure(Usart *usart, + uint32_t mode, + uint32_t baudrate, + uint32_t masterClock) +{ + /* Reset and disable receiver & transmitter*/ + usart->US_CR = US_CR_RSTRX | US_CR_RSTTX + | US_CR_RXDIS | US_CR_TXDIS; + + /* Configure mode*/ + usart->US_MR = mode; + + /* Configure baudrate*/ + /* Asynchronous, no oversampling*/ + if ( ((mode & US_MR_SYNC) == 0) && ((mode & US_MR_OVER) == 0) ) + { + usart->US_BRGR = (masterClock / baudrate) / 16; + } + + if( ((mode & US_MR_USART_MODE_SPI_MASTER) == US_MR_USART_MODE_SPI_MASTER) + || ((mode & US_MR_SYNC) == US_MR_SYNC)) + { + if( (mode & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK) + { + usart->US_BRGR = masterClock / baudrate; + } + else + { + if ( (mode & US_MR_USCLKS_DIV) == US_MR_USCLKS_DIV) + { + usart->US_BRGR = masterClock / baudrate / 8; + } + } + } + /* TODO other modes*/ +} +/** + * \brief Enables or disables the transmitter of an USART peripheral. + * + * + * \param usart Pointer to an USART peripheral + * \param enabled If true, the transmitter is enabled; otherwise it is + * disabled. + */ +void USART_SetTransmitterEnabled(Usart *usart, uint8_t enabled) +{ + if (enabled) { + + usart->US_CR = US_CR_TXEN; + } + else { + + usart->US_CR = US_CR_TXDIS; + } +} + +/** + * \brief Enables or disables the receiver of an USART peripheral + * + * + * \param usart Pointer to an USART peripheral + * \param enabled If true, the receiver is enabled; otherwise it is disabled. + */ +void USART_SetReceiverEnabled(Usart *usart, + uint8_t enabled) +{ + if (enabled) { + + usart->US_CR = US_CR_RXEN; + } + else { + + usart->US_CR = US_CR_RXDIS; + } +} + +/** + * \brief Sends one packet of data through the specified USART peripheral. This + * function operates synchronously, so it only returns when the data has been + * actually sent. + * + * + * \param usart Pointer to an USART peripheral. + * \param data Data to send including 9nth bit and sync field if necessary (in + * the same format as the US_THR register in the datasheet). + * \param timeOut Time out value (0 = no timeout). + */ +void USART_Write( + Usart *usart, + uint16_t data, + volatile uint32_t timeOut) +{ + if (timeOut == 0) { + + while ((usart->US_CSR & US_CSR_TXEMPTY) == 0); + } + else { + + while ((usart->US_CSR & US_CSR_TXEMPTY) == 0) { + + if (timeOut == 0) { + + TRACE_ERROR("USART_Write: Timed out.\n\r"); + return; + } + timeOut--; + } + } + + usart->US_THR = data; +} + +/** + * \brief Sends the contents of a data buffer through the specified USART peripheral. + * This function returns immediately (1 if the buffer has been queued, 0 + * otherwise); poll the ENDTX and TXBUFE bits of the USART status register + * to check for the transfer completion. + * + * \param usart Pointer to an USART peripheral. + * \param buffer Pointer to the data buffer to send. + * \param size Size of the data buffer (in bytes). + */ +uint8_t USART_WriteBuffer( + Usart *usart, + void *buffer, + uint32_t size) +{ + /* Check if the first PDC bank is free*/ + if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) { + + usart->US_TPR = (uint32_t) buffer; + usart->US_TCR = size; + usart->US_PTCR = US_PTCR_TXTEN; + + return 1; + } + /* Check if the second PDC bank is free*/ + else if (usart->US_TNCR == 0) { + + usart->US_TNPR = (uint32_t) buffer; + usart->US_TNCR = size; + + return 1; + } + else { + + return 0; + } +} + + +/** + * \brief Reads and return a packet of data on the specified USART peripheral. This + * function operates asynchronously, so it waits until some data has been + * received. + * + * \param usart Pointer to an USART peripheral. + * \param timeOut Time out value (0 -> no timeout). + */ +uint16_t USART_Read( + Usart *usart, + volatile uint32_t timeOut) +{ + if (timeOut == 0) { + + while ((usart->US_CSR & US_CSR_RXRDY) == 0); + } + else { + + while ((usart->US_CSR & US_CSR_RXRDY) == 0) { + + if (timeOut == 0) { + + TRACE_ERROR( "USART_Read: Timed out.\n\r" ) ; + return 0; + } + timeOut--; + } + } + + return usart->US_RHR; +} + +/** + * \brief Reads data from an USART peripheral, filling the provided buffer until it + * becomes full. This function returns immediately with 1 if the buffer has + * been queued for transmission; otherwise 0. + * + * \param usart Pointer to an USART peripheral. + * \param buffer Pointer to the buffer where the received data will be stored. + * \param size Size of the data buffer (in bytes). + */ +uint8_t USART_ReadBuffer(Usart *usart, + void *buffer, + uint32_t size) +{ + /* Check if the first PDC bank is free*/ + if ((usart->US_RCR == 0) && (usart->US_RNCR == 0)) { + + usart->US_RPR = (uint32_t) buffer; + usart->US_RCR = size; + usart->US_PTCR = US_PTCR_RXTEN; + + return 1; + } + /* Check if the second PDC bank is free*/ + else if (usart->US_RNCR == 0) { + + usart->US_RNPR = (uint32_t) buffer; + usart->US_RNCR = size; + + return 1; + } + else { + + return 0; + } +} + +/** + * \brief Returns 1 if some data has been received and can be read from an USART; + * otherwise returns 0. + * + * \param usart Pointer to an Usart instance. + */ +uint8_t USART_IsDataAvailable(Usart *usart) +{ + if ((usart->US_CSR & US_CSR_RXRDY) != 0) { + + return 1; + } + else { + + return 0; + } +} + +/** + * \brief Sets the filter value for the IRDA demodulator. + * + * \param pUsart Pointer to an Usart instance. + * \param filter Filter value. + */ +void USART_SetIrdaFilter(Usart *pUsart, uint8_t filter) +{ + assert( pUsart != NULL ) ; + + pUsart->US_IF = filter; +} + +/** + * \brief Sends one packet of data through the specified USART peripheral. This + * function operates synchronously, so it only returns when the data has been + * actually sent. + * + * \param usart Pointer to an USART peripheral. + * \param c Character to send + */ +void USART_PutChar( + Usart *usart, + uint8_t c) +{ + /* Wait for the transmitter to be ready*/ + while ((usart->US_CSR & US_CSR_TXEMPTY) == 0); + + /* Send character*/ + usart->US_THR = c; + + /* Wait for the transfer to complete*/ + while ((usart->US_CSR & US_CSR_TXEMPTY) == 0); +} + +/** + * \brief Return 1 if a character can be read in USART + */ +uint32_t USART_IsRxReady(Usart *usart) +{ + return (usart->US_CSR & US_CSR_RXRDY); +} +/** + * \brief Get present status + */ +uint32_t USART_GetStatus(Usart *usart) +{ + return usart->US_CSR; +} +/** + * \brief Enable interrupt + */ +void USART_EnableIt(Usart *usart,uint32_t mode) +{ + usart->US_IER = mode; +} +/** + * \brief Disable interrupt + */ +void USART_DisableIt(Usart *usart,uint32_t mode) +{ + usart->US_IDR = mode; +} +/** + * \brief Reads and returns a character from the USART. + * + * \note This function is synchronous (i.e. uses polling). + * \param usart Pointer to an USART peripheral. + * \return Character received. + */ +uint8_t USART_GetChar(Usart *usart) +{ + while ((usart->US_CSR & US_CSR_RXRDY) == 0); + return usart->US_RHR; +} diff --git a/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/wdt.c b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/wdt.c new file mode 100644 index 00000000..f8a493b5 --- /dev/null +++ b/sam3s_example/atmel_softpack_libraries/libchip_sam3s/source/wdt.c @@ -0,0 +1,132 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2009, 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 disclaimer below. + * + * 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. + * ---------------------------------------------------------------------------- + */ + +/** + * \file + * + * Implementation of Watchdog Timer (WDT) controller. + * + */ + +/** \addtogroup wdt_module Working with WDT + * The WDT driver provides the interface to configure and use the WDT + * peripheral. + * + * The WDT can be used to prevent system lock-up if the software becomes + * trapped in a deadlock. It can generate a general reset or a processor + * reset only. It is clocked by slow clock divided by 128. + * + * The WDT is running at reset with 16 seconds watchdog period (slow clock at 32.768 kHz) + * and external reset generation enabled. The user must either disable it or + * reprogram it to meet the application requires. + * + * To use the WDT, the user could follow these few steps: + *
      + *
    • Enable watchdog with given mode using \ref WDT_Enable(). + *
    • Restart the watchdog using \ref WDT_Restart() within the watchdog period. + *
    + * + * For more accurate information, please look at the WDT section of the + * Datasheet. + * + * \note + * The Watchdog Mode Register (WDT_MR) can be written only once.\n + * + * Related files :\n + * \ref wdt.c\n + * \ref wdt.h.\n + */ +/*@{*/ +/*@}*/ + +/*--------------------------------------------------------------------------- + * Headers + *---------------------------------------------------------------------------*/ + +#include "chip.h" + +#include + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + +/** + * \brief Enable watchdog with given mode. + * + * \note The Watchdog Mode Register (WDT_MR) can be written only once. + * Only a processor reset resets it. + * + * \param dwMode WDT mode to be set + */ +extern void WDT_Enable( Wdt* pWDT, uint32_t dwMode ) +{ + pWDT->WDT_MR = dwMode ; +} + +/** + * \brief Disable watchdog. + * + * \note The Watchdog Mode Register (WDT_MR) can be written only once. + * Only a processor reset resets it. + */ +extern void WDT_Disable( Wdt* pWDT ) +{ + pWDT->WDT_MR = WDT_MR_WDDIS; +} + +/** + * \brief Watchdog restart. + */ +extern void WDT_Restart( Wdt* pWDT ) +{ + pWDT->WDT_CR = 0xA5000001; +} + +/** + * \brief Watchdog get status. + */ +extern uint32_t WDT_GetStatus( Wdt* pWDT ) +{ + return (pWDT->WDT_SR & 0x3) ; +} + +/** + * \brief Watchdog get period. + * + * \param dwMs desired watchdog period in millisecond. + */ +extern uint32_t WDT_GetPeriod( uint32_t dwMs ) +{ + if ( (dwMs < 4) || (dwMs > 16000) ) + { + return 0 ; + } + return ((dwMs << 8) / 1000) ; +} diff --git a/sam3s_example/cmsis b/sam3s_example/cmsis new file mode 120000 index 00000000..895b6776 --- /dev/null +++ b/sam3s_example/cmsis @@ -0,0 +1 @@ +./atmel_softpack_libraries/libchip_sam3s/cmsis \ No newline at end of file diff --git a/sam3s_example/cmsis/core_cm3.c b/sam3s_example/cmsis/core_cm3.c deleted file mode 100644 index 46ca332b..00000000 --- a/sam3s_example/cmsis/core_cm3.c +++ /dev/null @@ -1,817 +0,0 @@ -/**************************************************************************//** - * @file core_cm3.c - * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Source File - * @version V1.30 - * @date 30. October 2009 - * - * @note - * Copyright (C) 2009 ARM Limited. All rights reserved. - * - * @par - * ARM Limited (ARM) is supplying this software for use with Cortex-M - * processor based microcontrollers. This file can be freely distributed - * within development tools that are supporting such ARM based processors. - * - * @par - * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED - * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. - * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR - * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. - * - ******************************************************************************/ - -/* - * Remo Giermann: - * 2012/01/09 - fixed __STREX[BHW] functions - * - * - */ - -#include - -/* define compiler specific symbols */ -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */ - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - -#endif - -uint32_t __get_PSP(void) ; -void __set_PSP(uint32_t topOfProcStack) ; -uint32_t __get_MSP(void) ; -void __set_MSP(uint32_t mainStackPointer) ; -uint32_t __REV16(uint16_t value) ; -int32_t __REVSH(int16_t value) ; -uint32_t __RBIT(uint32_t value) ; -uint8_t __LDREXB(uint8_t *addr) ; -uint16_t __LDREXH(uint16_t *addr) ; -uint32_t __LDREXW(uint32_t *addr) ; -uint32_t __STREXB(uint8_t value, uint8_t *addr) ; -uint32_t __STREXH(uint16_t value, uint16_t *addr) ; -uint32_t __STREXW(uint32_t value, uint32_t *addr) ; - -uint32_t __get_BASEPRI(void) ; -void __set_BASEPRI(uint32_t basePri) ; -uint32_t __get_PRIMASK(void) ; -void __set_PRIMASK(uint32_t priMask) ; -uint32_t __get_FAULTMASK(void) ; -void __set_FAULTMASK(uint32_t faultMask) ; -uint32_t __get_CONTROL(void) ; -void __set_CONTROL(uint32_t control) ; -uint32_t __REV(uint32_t value) ; - -/* ################### Compiler specific Intrinsics ########################### */ - -#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ -/* ARM armcc specific functions */ - -/** - * @brief Return the Process Stack Pointer - * - * @return ProcessStackPointer - * - * Return the actual process stack pointer - */ -__ASM uint32_t __get_PSP(void) -{ - mrs r0, psp - bx lr -} - -/** - * @brief Set the Process Stack Pointer - * - * @param topOfProcStack Process Stack Pointer - * - * Assign the value ProcessStackPointer to the MSP - * (process stack pointer) Cortex processor register - */ -__ASM void __set_PSP(uint32_t topOfProcStack) -{ - msr psp, r0 - bx lr -} - -/** - * @brief Return the Main Stack Pointer - * - * @return Main Stack Pointer - * - * Return the current value of the MSP (main stack pointer) - * Cortex processor register - */ -__ASM uint32_t __get_MSP(void) -{ - mrs r0, msp - bx lr -} - -/** - * @brief Set the Main Stack Pointer - * - * @param topOfMainStack Main Stack Pointer - * - * Assign the value mainStackPointer to the MSP - * (main stack pointer) Cortex processor register - */ -__ASM void __set_MSP(uint32_t mainStackPointer) -{ - msr msp, r0 - bx lr -} - -/** - * @brief Reverse byte order in unsigned short value - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in unsigned short value - */ -__ASM uint32_t __REV16(uint16_t value) -{ - rev16 r0, r0 - bx lr -} - -/** - * @brief Reverse byte order in signed short value with sign extension to integer - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in signed short value with sign extension to integer - */ -__ASM int32_t __REVSH(int16_t value) -{ - revsh r0, r0 - bx lr -} - - -#if (__ARMCC_VERSION < 400000) - -/** - * @brief Remove the exclusive lock created by ldrex - * - * Removes the exclusive lock which is created by ldrex. - */ -__ASM void __CLREX(void) -{ - clrex -} - -/** - * @brief Return the Base Priority value - * - * @return BasePriority - * - * Return the content of the base priority register - */ -__ASM uint32_t __get_BASEPRI(void) -{ - mrs r0, basepri - bx lr -} - -/** - * @brief Set the Base Priority value - * - * @param basePri BasePriority - * - * Set the base priority register - */ -__ASM void __set_BASEPRI(uint32_t basePri) -{ - msr basepri, r0 - bx lr -} - -/** - * @brief Return the Priority Mask value - * - * @return PriMask - * - * Return state of the priority mask bit from the priority mask register - */ -__ASM uint32_t __get_PRIMASK(void) -{ - mrs r0, primask - bx lr -} - -/** - * @brief Set the Priority Mask value - * - * @param priMask PriMask - * - * Set the priority mask bit in the priority mask register - */ -__ASM void __set_PRIMASK(uint32_t priMask) -{ - msr primask, r0 - bx lr -} - -/** - * @brief Return the Fault Mask value - * - * @return FaultMask - * - * Return the content of the fault mask register - */ -__ASM uint32_t __get_FAULTMASK(void) -{ - mrs r0, faultmask - bx lr -} - -/** - * @brief Set the Fault Mask value - * - * @param faultMask faultMask value - * - * Set the fault mask register - */ -__ASM void __set_FAULTMASK(uint32_t faultMask) -{ - msr faultmask, r0 - bx lr -} - -/** - * @brief Return the Control Register value - * - * @return Control value - * - * Return the content of the control register - */ -__ASM uint32_t __get_CONTROL(void) -{ - mrs r0, control - bx lr -} - -/** - * @brief Set the Control Register value - * - * @param control Control value - * - * Set the control register - */ -__ASM void __set_CONTROL(uint32_t control) -{ - msr control, r0 - bx lr -} - -#endif /* __ARMCC_VERSION */ - - - -#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/ -/* IAR iccarm specific functions */ -#pragma diag_suppress=Pe940 - -/** - * @brief Return the Process Stack Pointer - * - * @return ProcessStackPointer - * - * Return the actual process stack pointer - */ -uint32_t __get_PSP(void) -{ - __ASM("mrs r0, psp"); - __ASM("bx lr"); -} - -/** - * @brief Set the Process Stack Pointer - * - * @param topOfProcStack Process Stack Pointer - * - * Assign the value ProcessStackPointer to the MSP - * (process stack pointer) Cortex processor register - */ -void __set_PSP(uint32_t topOfProcStack) -{ - __ASM("msr psp, r0"); - __ASM("bx lr"); -} - -/** - * @brief Return the Main Stack Pointer - * - * @return Main Stack Pointer - * - * Return the current value of the MSP (main stack pointer) - * Cortex processor register - */ -uint32_t __get_MSP(void) -{ - __ASM("mrs r0, msp"); - __ASM("bx lr"); -} - -/** - * @brief Set the Main Stack Pointer - * - * @param topOfMainStack Main Stack Pointer - * - * Assign the value mainStackPointer to the MSP - * (main stack pointer) Cortex processor register - */ -void __set_MSP(uint32_t topOfMainStack) -{ - __ASM("msr msp, r0"); - __ASM("bx lr"); -} - -/** - * @brief Reverse byte order in unsigned short value - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in unsigned short value - */ -uint32_t __REV16(uint16_t value) -{ - __ASM("rev16 r0, r0"); - __ASM("bx lr"); -} - -/** - * @brief Reverse bit order of value - * - * @param value value to reverse - * @return reversed value - * - * Reverse bit order of value - */ -uint32_t __RBIT(uint32_t value) -{ - __ASM("rbit r0, r0"); - __ASM("bx lr"); -} - -/** - * @brief LDR Exclusive (8 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 8 bit values) - */ -uint8_t __LDREXB(uint8_t *addr) -{ - __ASM("ldrexb r0, [r0]"); - __ASM("bx lr"); -} - -/** - * @brief LDR Exclusive (16 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 16 bit values - */ -uint16_t __LDREXH(uint16_t *addr) -{ - __ASM("ldrexh r0, [r0]"); - __ASM("bx lr"); -} - -/** - * @brief LDR Exclusive (32 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 32 bit values - */ -uint32_t __LDREXW(uint32_t *addr) -{ - __ASM("ldrex r0, [r0]"); - __ASM("bx lr"); -} - -/** - * @brief STR Exclusive (8 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 8 bit values - */ -uint32_t __STREXB(uint8_t value, uint8_t *addr) -{ - __ASM("strexb r2, r0, [r1]"); - __ASM("mov r2, r0"); - __ASM("bx lr"); -} - -/** - * @brief STR Exclusive (16 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 16 bit values - */ -uint32_t __STREXH(uint16_t value, uint16_t *addr) -{ - __ASM("strexh r2, r0, [r1]"); - __ASM("mov r2, r0"); - __ASM("bx lr"); -} - -/** - * @brief STR Exclusive (32 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 32 bit values - */ -uint32_t __STREXW(uint32_t value, uint32_t *addr) -{ - __ASM("strex r2, r0, [r1]"); - __ASM("mov r2, r0"); - __ASM("bx lr"); -} - -#pragma diag_default=Pe940 - - -#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/ -/* GNU gcc specific functions */ - -/** - * @brief Return the Process Stack Pointer - * - * @return ProcessStackPointer - * - * Return the actual process stack pointer - */ -/*extern uint32_t __get_PSP(void) __attribute__( ( naked ) ); */ -uint32_t __get_PSP(void) -{ - uint32_t result=0; - - __ASM volatile ("MRS %0, psp\n\t" - "MOV r0, %0 \n\t" - "BX lr \n\t" : "=r" (result) ); - return(result); -} - -/** - * @brief Set the Process Stack Pointer - * - * @param topOfProcStack Process Stack Pointer - * - * Assign the value ProcessStackPointer to the MSP - * (process stack pointer) Cortex processor register - */ -/*void __set_PSP(uint32_t topOfProcStack) __attribute__( ( naked ) ); */ -void __set_PSP(uint32_t topOfProcStack) -{ - __ASM volatile ("MSR psp, %0\n\t" - "BX lr \n\t" : : "r" (topOfProcStack) ); -} - -/** - * @brief Return the Main Stack Pointer - * - * @return Main Stack Pointer - * - * Return the current value of the MSP (main stack pointer) - * Cortex processor register - */ -/*uint32_t __get_MSP(void) __attribute__( ( naked ) ); */ -uint32_t __get_MSP(void) -{ - uint32_t result=0; - - __ASM volatile ("MRS %0, msp\n\t" - "MOV r0, %0 \n\t" - "BX lr \n\t" : "=r" (result) ); - return(result); -} - -/** - * @brief Set the Main Stack Pointer - * - * @param topOfMainStack Main Stack Pointer - * - * Assign the value mainStackPointer to the MSP - * (main stack pointer) Cortex processor register - */ -/*void __set_MSP(uint32_t topOfMainStack) __attribute__( ( naked ) ); */ -void __set_MSP(uint32_t topOfMainStack) -{ - __ASM volatile ("MSR msp, %0\n\t" - "BX lr \n\t" : : "r" (topOfMainStack) ); -} - -/** - * @brief Return the Base Priority value - * - * @return BasePriority - * - * Return the content of the base priority register - */ -uint32_t __get_BASEPRI(void) -{ - uint32_t result=0; - - __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); - return(result); -} - -/** - * @brief Set the Base Priority value - * - * @param basePri BasePriority - * - * Set the base priority register - */ -void __set_BASEPRI(uint32_t value) -{ - __ASM volatile ("MSR basepri, %0" : : "r" (value) ); -} - -/** - * @brief Return the Priority Mask value - * - * @return PriMask - * - * Return state of the priority mask bit from the priority mask register - */ -uint32_t __get_PRIMASK(void) -{ - uint32_t result=0; - - __ASM volatile ("MRS %0, primask" : "=r" (result) ); - return(result); -} - -/** - * @brief Set the Priority Mask value - * - * @param priMask PriMask - * - * Set the priority mask bit in the priority mask register - */ -void __set_PRIMASK(uint32_t priMask) -{ - __ASM volatile ("MSR primask, %0" : : "r" (priMask) ); -} - -/** - * @brief Return the Fault Mask value - * - * @return FaultMask - * - * Return the content of the fault mask register - */ -uint32_t __get_FAULTMASK(void) -{ - uint32_t result=0; - - __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); - return(result); -} - -/** - * @brief Set the Fault Mask value - * - * @param faultMask faultMask value - * - * Set the fault mask register - */ -void __set_FAULTMASK(uint32_t faultMask) -{ - __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) ); -} - -/** - * @brief Return the Control Register value -* -* @return Control value - * - * Return the content of the control register - */ -uint32_t __get_CONTROL(void) -{ - uint32_t result=0; - - __ASM volatile ("MRS %0, control" : "=r" (result) ); - return(result); -} - -/** - * @brief Set the Control Register value - * - * @param control Control value - * - * Set the control register - */ -void __set_CONTROL(uint32_t control) -{ - __ASM volatile ("MSR control, %0" : : "r" (control) ); -} - - -/** - * @brief Reverse byte order in integer value - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in integer value - */ -uint32_t __REV(uint32_t value) -{ - uint32_t result=0; - - __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) ); - return(result); -} - -/** - * @brief Reverse byte order in unsigned short value - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in unsigned short value - */ -uint32_t __REV16(uint16_t value) -{ - uint32_t result=0; - - __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) ); - return(result); -} - -/** - * @brief Reverse byte order in signed short value with sign extension to integer - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in signed short value with sign extension to integer - */ -int32_t __REVSH(int16_t value) -{ - uint32_t result=0; - - __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) ); - return(result); -} - -/** - * @brief Reverse bit order of value - * - * @param value value to reverse - * @return reversed value - * - * Reverse bit order of value - */ -uint32_t __RBIT(uint32_t value) -{ - uint32_t result=0; - - __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); - return(result); -} - -/** - * @brief LDR Exclusive (8 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 8 bit value - */ -uint8_t __LDREXB(uint8_t *addr) -{ - uint8_t result=0; - - __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) ); - return(result); -} - -/** - * @brief LDR Exclusive (16 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 16 bit values - */ -uint16_t __LDREXH(uint16_t *addr) -{ - uint16_t result=0; - - __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) ); - return(result); -} - -/** - * @brief LDR Exclusive (32 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 32 bit values - */ -uint32_t __LDREXW(uint32_t *addr) -{ - uint32_t result=0; - - __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) ); - return(result); -} - -/** - * @brief STR Exclusive (8 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 8 bit values - */ -uint32_t __STREXB(uint8_t value, uint8_t *addr) -{ - uint32_t result=0; - - __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); - return(result); -} - -/** - * @brief STR Exclusive (16 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 16 bit values - */ -uint32_t __STREXH(uint16_t value, uint16_t *addr) -{ - uint32_t result=0; - - __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); - return(result); -} - -/** - * @brief STR Exclusive (32 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 32 bit values - */ -uint32_t __STREXW(uint32_t value, uint32_t *addr) -{ - uint32_t result=0; - - __ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); - return(result); -} - - -#elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/ -/* TASKING carm specific functions */ - -/* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all instrinsics, - * Including the CMSIS ones. - */ - -#endif diff --git a/sam3s_example/cmsis/core_cm3.h b/sam3s_example/cmsis/core_cm3.h deleted file mode 100644 index 1c07effa..00000000 --- a/sam3s_example/cmsis/core_cm3.h +++ /dev/null @@ -1,1818 +0,0 @@ -/**************************************************************************//** - * @file core_cm3.h - * @brief CMSIS Cortex-M3 Core Peripheral Access Layer Header File - * @version V1.30 - * @date 30. October 2009 - * - * @note - * Copyright (C) 2009 ARM Limited. All rights reserved. - * - * @par - * ARM Limited (ARM) is supplying this software for use with Cortex-M - * processor based microcontrollers. This file can be freely distributed - * within development tools that are supporting such ARM based processors. - * - * @par - * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED - * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. - * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR - * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. - * - ******************************************************************************/ - -#ifndef __CM3_CORE_H__ -#define __CM3_CORE_H__ - -/** @addtogroup CMSIS_CM3_core_LintCinfiguration CMSIS CM3 Core Lint Configuration - * - * List of Lint messages which will be suppressed and not shown: - * - Error 10: \n - * register uint32_t __regBasePri __asm("basepri"); \n - * Error 10: Expecting ';' - * . - * - Error 530: \n - * return(__regBasePri); \n - * Warning 530: Symbol '__regBasePri' (line 264) not initialized - * . - * - Error 550: \n - * __regBasePri = (basePri & 0x1ff); \n - * Warning 550: Symbol '__regBasePri' (line 271) not accessed - * . - * - Error 754: \n - * uint32_t RESERVED0[24]; \n - * Info 754: local structure member '' (line 109, file ./cm3_core.h) not referenced - * . - * - Error 750: \n - * #define __CM3_CORE_H__ \n - * Info 750: local macro '__CM3_CORE_H__' (line 43, file./cm3_core.h) not referenced - * . - * - Error 528: \n - * static __INLINE void NVIC_DisableIRQ(uint32_t IRQn) \n - * Warning 528: Symbol 'NVIC_DisableIRQ(unsigned int)' (line 419, file ./cm3_core.h) not referenced - * . - * - Error 751: \n - * } InterruptType_Type; \n - * Info 751: local typedef 'InterruptType_Type' (line 170, file ./cm3_core.h) not referenced - * . - * Note: To re-enable a Message, insert a space before 'lint' * - * - */ - -/*lint -save */ -/*lint -e10 */ -/*lint -e530 */ -/*lint -e550 */ -/*lint -e754 */ -/*lint -e750 */ -/*lint -e528 */ -/*lint -e751 */ - - -/** @addtogroup CMSIS_CM3_core_definitions CM3 Core Definitions - This file defines all structures and symbols for CMSIS core: - - CMSIS version number - - Cortex-M core registers and bitfields - - Cortex-M core peripheral base address - @{ - */ - -#ifdef __cplusplus - extern "C" { -#endif - -#define __CM3_CMSIS_VERSION_MAIN (0x01) /*!< [31:16] CMSIS HAL main version */ -#define __CM3_CMSIS_VERSION_SUB (0x30) /*!< [15:0] CMSIS HAL sub version */ -#define __CM3_CMSIS_VERSION ((__CM3_CMSIS_VERSION_MAIN << 16) | __CM3_CMSIS_VERSION_SUB) /*!< CMSIS HAL version number */ - -#define __CORTEX_M (0x03) /*!< Cortex core */ - -#include /* Include standard types */ - -#if defined (__ICCARM__) - #include /* IAR Intrinsics */ -#endif - - -#ifndef __NVIC_PRIO_BITS - #define __NVIC_PRIO_BITS 4 /*!< standard definition for NVIC Priority Bits */ -#endif - - - - -/** - * IO definitions - * - * define access restrictions to peripheral registers - */ - -#ifdef __cplusplus - #define __I volatile /*!< defines 'read only' permissions */ -#else - #define __I volatile const /*!< defines 'read only' permissions */ -#endif -#define __O volatile /*!< defines 'write only' permissions */ -#define __IO volatile /*!< defines 'read / write' permissions */ - - - -/******************************************************************************* - * Register Abstraction - ******************************************************************************/ -/** @addtogroup CMSIS_CM3_core_register CMSIS CM3 Core Register - @{ -*/ - - -/** @addtogroup CMSIS_CM3_NVIC CMSIS CM3 NVIC - memory mapped structure for Nested Vectored Interrupt Controller (NVIC) - @{ - */ -typedef struct -{ - __IO uint32_t ISER[8]; /*!< Offset: 0x000 Interrupt Set Enable Register */ - uint32_t RESERVED0[24]; - __IO uint32_t ICER[8]; /*!< Offset: 0x080 Interrupt Clear Enable Register */ - uint32_t RSERVED1[24]; - __IO uint32_t ISPR[8]; /*!< Offset: 0x100 Interrupt Set Pending Register */ - uint32_t RESERVED2[24]; - __IO uint32_t ICPR[8]; /*!< Offset: 0x180 Interrupt Clear Pending Register */ - uint32_t RESERVED3[24]; - __IO uint32_t IABR[8]; /*!< Offset: 0x200 Interrupt Active bit Register */ - uint32_t RESERVED4[56]; - __IO uint8_t IP[240]; /*!< Offset: 0x300 Interrupt Priority Register (8Bit wide) */ - uint32_t RESERVED5[644]; - __O uint32_t STIR; /*!< Offset: 0xE00 Software Trigger Interrupt Register */ -} NVIC_Type; -/*@}*/ /* end of group CMSIS_CM3_NVIC */ - - -/** @addtogroup CMSIS_CM3_SCB CMSIS CM3 SCB - memory mapped structure for System Control Block (SCB) - @{ - */ -typedef struct -{ - __I uint32_t CPUID; /*!< Offset: 0x00 CPU ID Base Register */ - __IO uint32_t ICSR; /*!< Offset: 0x04 Interrupt Control State Register */ - __IO uint32_t VTOR; /*!< Offset: 0x08 Vector Table Offset Register */ - __IO uint32_t AIRCR; /*!< Offset: 0x0C Application Interrupt / Reset Control Register */ - __IO uint32_t SCR; /*!< Offset: 0x10 System Control Register */ - __IO uint32_t CCR; /*!< Offset: 0x14 Configuration Control Register */ - __IO uint8_t SHP[12]; /*!< Offset: 0x18 System Handlers Priority Registers (4-7, 8-11, 12-15) */ - __IO uint32_t SHCSR; /*!< Offset: 0x24 System Handler Control and State Register */ - __IO uint32_t CFSR; /*!< Offset: 0x28 Configurable Fault Status Register */ - __IO uint32_t HFSR; /*!< Offset: 0x2C Hard Fault Status Register */ - __IO uint32_t DFSR; /*!< Offset: 0x30 Debug Fault Status Register */ - __IO uint32_t MMFAR; /*!< Offset: 0x34 Mem Manage Address Register */ - __IO uint32_t BFAR; /*!< Offset: 0x38 Bus Fault Address Register */ - __IO uint32_t AFSR; /*!< Offset: 0x3C Auxiliary Fault Status Register */ - __I uint32_t PFR[2]; /*!< Offset: 0x40 Processor Feature Register */ - __I uint32_t DFR; /*!< Offset: 0x48 Debug Feature Register */ - __I uint32_t ADR; /*!< Offset: 0x4C Auxiliary Feature Register */ - __I uint32_t MMFR[4]; /*!< Offset: 0x50 Memory Model Feature Register */ - __I uint32_t ISAR[5]; /*!< Offset: 0x60 ISA Feature Register */ -} SCB_Type; - -/* SCB CPUID Register Definitions */ -#define SCB_CPUID_IMPLEMENTER_Pos 24 /*!< SCB CPUID: IMPLEMENTER Position */ -#define SCB_CPUID_IMPLEMENTER_Msk (0xFFul << SCB_CPUID_IMPLEMENTER_Pos) /*!< SCB CPUID: IMPLEMENTER Mask */ - -#define SCB_CPUID_VARIANT_Pos 20 /*!< SCB CPUID: VARIANT Position */ -#define SCB_CPUID_VARIANT_Msk (0xFul << SCB_CPUID_VARIANT_Pos) /*!< SCB CPUID: VARIANT Mask */ - -#define SCB_CPUID_PARTNO_Pos 4 /*!< SCB CPUID: PARTNO Position */ -#define SCB_CPUID_PARTNO_Msk (0xFFFul << SCB_CPUID_PARTNO_Pos) /*!< SCB CPUID: PARTNO Mask */ - -#define SCB_CPUID_REVISION_Pos 0 /*!< SCB CPUID: REVISION Position */ -#define SCB_CPUID_REVISION_Msk (0xFul << SCB_CPUID_REVISION_Pos) /*!< SCB CPUID: REVISION Mask */ - -/* SCB Interrupt Control State Register Definitions */ -#define SCB_ICSR_NMIPENDSET_Pos 31 /*!< SCB ICSR: NMIPENDSET Position */ -#define SCB_ICSR_NMIPENDSET_Msk (1ul << SCB_ICSR_NMIPENDSET_Pos) /*!< SCB ICSR: NMIPENDSET Mask */ - -#define SCB_ICSR_PENDSVSET_Pos 28 /*!< SCB ICSR: PENDSVSET Position */ -#define SCB_ICSR_PENDSVSET_Msk (1ul << SCB_ICSR_PENDSVSET_Pos) /*!< SCB ICSR: PENDSVSET Mask */ - -#define SCB_ICSR_PENDSVCLR_Pos 27 /*!< SCB ICSR: PENDSVCLR Position */ -#define SCB_ICSR_PENDSVCLR_Msk (1ul << SCB_ICSR_PENDSVCLR_Pos) /*!< SCB ICSR: PENDSVCLR Mask */ - -#define SCB_ICSR_PENDSTSET_Pos 26 /*!< SCB ICSR: PENDSTSET Position */ -#define SCB_ICSR_PENDSTSET_Msk (1ul << SCB_ICSR_PENDSTSET_Pos) /*!< SCB ICSR: PENDSTSET Mask */ - -#define SCB_ICSR_PENDSTCLR_Pos 25 /*!< SCB ICSR: PENDSTCLR Position */ -#define SCB_ICSR_PENDSTCLR_Msk (1ul << SCB_ICSR_PENDSTCLR_Pos) /*!< SCB ICSR: PENDSTCLR Mask */ - -#define SCB_ICSR_ISRPREEMPT_Pos 23 /*!< SCB ICSR: ISRPREEMPT Position */ -#define SCB_ICSR_ISRPREEMPT_Msk (1ul << SCB_ICSR_ISRPREEMPT_Pos) /*!< SCB ICSR: ISRPREEMPT Mask */ - -#define SCB_ICSR_ISRPENDING_Pos 22 /*!< SCB ICSR: ISRPENDING Position */ -#define SCB_ICSR_ISRPENDING_Msk (1ul << SCB_ICSR_ISRPENDING_Pos) /*!< SCB ICSR: ISRPENDING Mask */ - -#define SCB_ICSR_VECTPENDING_Pos 12 /*!< SCB ICSR: VECTPENDING Position */ -#define SCB_ICSR_VECTPENDING_Msk (0x1FFul << SCB_ICSR_VECTPENDING_Pos) /*!< SCB ICSR: VECTPENDING Mask */ - -#define SCB_ICSR_RETTOBASE_Pos 11 /*!< SCB ICSR: RETTOBASE Position */ -#define SCB_ICSR_RETTOBASE_Msk (1ul << SCB_ICSR_RETTOBASE_Pos) /*!< SCB ICSR: RETTOBASE Mask */ - -#define SCB_ICSR_VECTACTIVE_Pos 0 /*!< SCB ICSR: VECTACTIVE Position */ -#define SCB_ICSR_VECTACTIVE_Msk (0x1FFul << SCB_ICSR_VECTACTIVE_Pos) /*!< SCB ICSR: VECTACTIVE Mask */ - -/* SCB Interrupt Control State Register Definitions */ -#define SCB_VTOR_TBLBASE_Pos 29 /*!< SCB VTOR: TBLBASE Position */ -#define SCB_VTOR_TBLBASE_Msk (0x1ul << SCB_VTOR_TBLBASE_Pos) /*!< SCB VTOR: TBLBASE Mask */ - -#define SCB_VTOR_TBLOFF_Pos 7 /*!< SCB VTOR: TBLOFF Position */ -#define SCB_VTOR_TBLOFF_Msk (0x3FFFFFul << SCB_VTOR_TBLOFF_Pos) /*!< SCB VTOR: TBLOFF Mask */ - -/* SCB Application Interrupt and Reset Control Register Definitions */ -#define SCB_AIRCR_VECTKEY_Pos 16 /*!< SCB AIRCR: VECTKEY Position */ -#define SCB_AIRCR_VECTKEY_Msk (0xFFFFul << SCB_AIRCR_VECTKEY_Pos) /*!< SCB AIRCR: VECTKEY Mask */ - -#define SCB_AIRCR_VECTKEYSTAT_Pos 16 /*!< SCB AIRCR: VECTKEYSTAT Position */ -#define SCB_AIRCR_VECTKEYSTAT_Msk (0xFFFFul << SCB_AIRCR_VECTKEYSTAT_Pos) /*!< SCB AIRCR: VECTKEYSTAT Mask */ - -#define SCB_AIRCR_ENDIANESS_Pos 15 /*!< SCB AIRCR: ENDIANESS Position */ -#define SCB_AIRCR_ENDIANESS_Msk (1ul << SCB_AIRCR_ENDIANESS_Pos) /*!< SCB AIRCR: ENDIANESS Mask */ - -#define SCB_AIRCR_PRIGROUP_Pos 8 /*!< SCB AIRCR: PRIGROUP Position */ -#define SCB_AIRCR_PRIGROUP_Msk (7ul << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ - -#define SCB_AIRCR_SYSRESETREQ_Pos 2 /*!< SCB AIRCR: SYSRESETREQ Position */ -#define SCB_AIRCR_SYSRESETREQ_Msk (1ul << SCB_AIRCR_SYSRESETREQ_Pos) /*!< SCB AIRCR: SYSRESETREQ Mask */ - -#define SCB_AIRCR_VECTCLRACTIVE_Pos 1 /*!< SCB AIRCR: VECTCLRACTIVE Position */ -#define SCB_AIRCR_VECTCLRACTIVE_Msk (1ul << SCB_AIRCR_VECTCLRACTIVE_Pos) /*!< SCB AIRCR: VECTCLRACTIVE Mask */ - -#define SCB_AIRCR_VECTRESET_Pos 0 /*!< SCB AIRCR: VECTRESET Position */ -#define SCB_AIRCR_VECTRESET_Msk (1ul << SCB_AIRCR_VECTRESET_Pos) /*!< SCB AIRCR: VECTRESET Mask */ - -/* SCB System Control Register Definitions */ -#define SCB_SCR_SEVONPEND_Pos 4 /*!< SCB SCR: SEVONPEND Position */ -#define SCB_SCR_SEVONPEND_Msk (1ul << SCB_SCR_SEVONPEND_Pos) /*!< SCB SCR: SEVONPEND Mask */ - -#define SCB_SCR_SLEEPDEEP_Pos 2 /*!< SCB SCR: SLEEPDEEP Position */ -#define SCB_SCR_SLEEPDEEP_Msk (1ul << SCB_SCR_SLEEPDEEP_Pos) /*!< SCB SCR: SLEEPDEEP Mask */ - -#define SCB_SCR_SLEEPONEXIT_Pos 1 /*!< SCB SCR: SLEEPONEXIT Position */ -#define SCB_SCR_SLEEPONEXIT_Msk (1ul << SCB_SCR_SLEEPONEXIT_Pos) /*!< SCB SCR: SLEEPONEXIT Mask */ - -/* SCB Configuration Control Register Definitions */ -#define SCB_CCR_STKALIGN_Pos 9 /*!< SCB CCR: STKALIGN Position */ -#define SCB_CCR_STKALIGN_Msk (1ul << SCB_CCR_STKALIGN_Pos) /*!< SCB CCR: STKALIGN Mask */ - -#define SCB_CCR_BFHFNMIGN_Pos 8 /*!< SCB CCR: BFHFNMIGN Position */ -#define SCB_CCR_BFHFNMIGN_Msk (1ul << SCB_CCR_BFHFNMIGN_Pos) /*!< SCB CCR: BFHFNMIGN Mask */ - -#define SCB_CCR_DIV_0_TRP_Pos 4 /*!< SCB CCR: DIV_0_TRP Position */ -#define SCB_CCR_DIV_0_TRP_Msk (1ul << SCB_CCR_DIV_0_TRP_Pos) /*!< SCB CCR: DIV_0_TRP Mask */ - -#define SCB_CCR_UNALIGN_TRP_Pos 3 /*!< SCB CCR: UNALIGN_TRP Position */ -#define SCB_CCR_UNALIGN_TRP_Msk (1ul << SCB_CCR_UNALIGN_TRP_Pos) /*!< SCB CCR: UNALIGN_TRP Mask */ - -#define SCB_CCR_USERSETMPEND_Pos 1 /*!< SCB CCR: USERSETMPEND Position */ -#define SCB_CCR_USERSETMPEND_Msk (1ul << SCB_CCR_USERSETMPEND_Pos) /*!< SCB CCR: USERSETMPEND Mask */ - -#define SCB_CCR_NONBASETHRDENA_Pos 0 /*!< SCB CCR: NONBASETHRDENA Position */ -#define SCB_CCR_NONBASETHRDENA_Msk (1ul << SCB_CCR_NONBASETHRDENA_Pos) /*!< SCB CCR: NONBASETHRDENA Mask */ - -/* SCB System Handler Control and State Register Definitions */ -#define SCB_SHCSR_USGFAULTENA_Pos 18 /*!< SCB SHCSR: USGFAULTENA Position */ -#define SCB_SHCSR_USGFAULTENA_Msk (1ul << SCB_SHCSR_USGFAULTENA_Pos) /*!< SCB SHCSR: USGFAULTENA Mask */ - -#define SCB_SHCSR_BUSFAULTENA_Pos 17 /*!< SCB SHCSR: BUSFAULTENA Position */ -#define SCB_SHCSR_BUSFAULTENA_Msk (1ul << SCB_SHCSR_BUSFAULTENA_Pos) /*!< SCB SHCSR: BUSFAULTENA Mask */ - -#define SCB_SHCSR_MEMFAULTENA_Pos 16 /*!< SCB SHCSR: MEMFAULTENA Position */ -#define SCB_SHCSR_MEMFAULTENA_Msk (1ul << SCB_SHCSR_MEMFAULTENA_Pos) /*!< SCB SHCSR: MEMFAULTENA Mask */ - -#define SCB_SHCSR_SVCALLPENDED_Pos 15 /*!< SCB SHCSR: SVCALLPENDED Position */ -#define SCB_SHCSR_SVCALLPENDED_Msk (1ul << SCB_SHCSR_SVCALLPENDED_Pos) /*!< SCB SHCSR: SVCALLPENDED Mask */ - -#define SCB_SHCSR_BUSFAULTPENDED_Pos 14 /*!< SCB SHCSR: BUSFAULTPENDED Position */ -#define SCB_SHCSR_BUSFAULTPENDED_Msk (1ul << SCB_SHCSR_BUSFAULTPENDED_Pos) /*!< SCB SHCSR: BUSFAULTPENDED Mask */ - -#define SCB_SHCSR_MEMFAULTPENDED_Pos 13 /*!< SCB SHCSR: MEMFAULTPENDED Position */ -#define SCB_SHCSR_MEMFAULTPENDED_Msk (1ul << SCB_SHCSR_MEMFAULTPENDED_Pos) /*!< SCB SHCSR: MEMFAULTPENDED Mask */ - -#define SCB_SHCSR_USGFAULTPENDED_Pos 12 /*!< SCB SHCSR: USGFAULTPENDED Position */ -#define SCB_SHCSR_USGFAULTPENDED_Msk (1ul << SCB_SHCSR_USGFAULTPENDED_Pos) /*!< SCB SHCSR: USGFAULTPENDED Mask */ - -#define SCB_SHCSR_SYSTICKACT_Pos 11 /*!< SCB SHCSR: SYSTICKACT Position */ -#define SCB_SHCSR_SYSTICKACT_Msk (1ul << SCB_SHCSR_SYSTICKACT_Pos) /*!< SCB SHCSR: SYSTICKACT Mask */ - -#define SCB_SHCSR_PENDSVACT_Pos 10 /*!< SCB SHCSR: PENDSVACT Position */ -#define SCB_SHCSR_PENDSVACT_Msk (1ul << SCB_SHCSR_PENDSVACT_Pos) /*!< SCB SHCSR: PENDSVACT Mask */ - -#define SCB_SHCSR_MONITORACT_Pos 8 /*!< SCB SHCSR: MONITORACT Position */ -#define SCB_SHCSR_MONITORACT_Msk (1ul << SCB_SHCSR_MONITORACT_Pos) /*!< SCB SHCSR: MONITORACT Mask */ - -#define SCB_SHCSR_SVCALLACT_Pos 7 /*!< SCB SHCSR: SVCALLACT Position */ -#define SCB_SHCSR_SVCALLACT_Msk (1ul << SCB_SHCSR_SVCALLACT_Pos) /*!< SCB SHCSR: SVCALLACT Mask */ - -#define SCB_SHCSR_USGFAULTACT_Pos 3 /*!< SCB SHCSR: USGFAULTACT Position */ -#define SCB_SHCSR_USGFAULTACT_Msk (1ul << SCB_SHCSR_USGFAULTACT_Pos) /*!< SCB SHCSR: USGFAULTACT Mask */ - -#define SCB_SHCSR_BUSFAULTACT_Pos 1 /*!< SCB SHCSR: BUSFAULTACT Position */ -#define SCB_SHCSR_BUSFAULTACT_Msk (1ul << SCB_SHCSR_BUSFAULTACT_Pos) /*!< SCB SHCSR: BUSFAULTACT Mask */ - -#define SCB_SHCSR_MEMFAULTACT_Pos 0 /*!< SCB SHCSR: MEMFAULTACT Position */ -#define SCB_SHCSR_MEMFAULTACT_Msk (1ul << SCB_SHCSR_MEMFAULTACT_Pos) /*!< SCB SHCSR: MEMFAULTACT Mask */ - -/* SCB Configurable Fault Status Registers Definitions */ -#define SCB_CFSR_USGFAULTSR_Pos 16 /*!< SCB CFSR: Usage Fault Status Register Position */ -#define SCB_CFSR_USGFAULTSR_Msk (0xFFFFul << SCB_CFSR_USGFAULTSR_Pos) /*!< SCB CFSR: Usage Fault Status Register Mask */ - -#define SCB_CFSR_BUSFAULTSR_Pos 8 /*!< SCB CFSR: Bus Fault Status Register Position */ -#define SCB_CFSR_BUSFAULTSR_Msk (0xFFul << SCB_CFSR_BUSFAULTSR_Pos) /*!< SCB CFSR: Bus Fault Status Register Mask */ - -#define SCB_CFSR_MEMFAULTSR_Pos 0 /*!< SCB CFSR: Memory Manage Fault Status Register Position */ -#define SCB_CFSR_MEMFAULTSR_Msk (0xFFul << SCB_CFSR_MEMFAULTSR_Pos) /*!< SCB CFSR: Memory Manage Fault Status Register Mask */ - -/* SCB Hard Fault Status Registers Definitions */ -#define SCB_HFSR_DEBUGEVT_Pos 31 /*!< SCB HFSR: DEBUGEVT Position */ -#define SCB_HFSR_DEBUGEVT_Msk (1ul << SCB_HFSR_DEBUGEVT_Pos) /*!< SCB HFSR: DEBUGEVT Mask */ - -#define SCB_HFSR_FORCED_Pos 30 /*!< SCB HFSR: FORCED Position */ -#define SCB_HFSR_FORCED_Msk (1ul << SCB_HFSR_FORCED_Pos) /*!< SCB HFSR: FORCED Mask */ - -#define SCB_HFSR_VECTTBL_Pos 1 /*!< SCB HFSR: VECTTBL Position */ -#define SCB_HFSR_VECTTBL_Msk (1ul << SCB_HFSR_VECTTBL_Pos) /*!< SCB HFSR: VECTTBL Mask */ - -/* SCB Debug Fault Status Register Definitions */ -#define SCB_DFSR_EXTERNAL_Pos 4 /*!< SCB DFSR: EXTERNAL Position */ -#define SCB_DFSR_EXTERNAL_Msk (1ul << SCB_DFSR_EXTERNAL_Pos) /*!< SCB DFSR: EXTERNAL Mask */ - -#define SCB_DFSR_VCATCH_Pos 3 /*!< SCB DFSR: VCATCH Position */ -#define SCB_DFSR_VCATCH_Msk (1ul << SCB_DFSR_VCATCH_Pos) /*!< SCB DFSR: VCATCH Mask */ - -#define SCB_DFSR_DWTTRAP_Pos 2 /*!< SCB DFSR: DWTTRAP Position */ -#define SCB_DFSR_DWTTRAP_Msk (1ul << SCB_DFSR_DWTTRAP_Pos) /*!< SCB DFSR: DWTTRAP Mask */ - -#define SCB_DFSR_BKPT_Pos 1 /*!< SCB DFSR: BKPT Position */ -#define SCB_DFSR_BKPT_Msk (1ul << SCB_DFSR_BKPT_Pos) /*!< SCB DFSR: BKPT Mask */ - -#define SCB_DFSR_HALTED_Pos 0 /*!< SCB DFSR: HALTED Position */ -#define SCB_DFSR_HALTED_Msk (1ul << SCB_DFSR_HALTED_Pos) /*!< SCB DFSR: HALTED Mask */ -/*@}*/ /* end of group CMSIS_CM3_SCB */ - - -/** @addtogroup CMSIS_CM3_SysTick CMSIS CM3 SysTick - memory mapped structure for SysTick - @{ - */ -typedef struct -{ - __IO uint32_t CTRL; /*!< Offset: 0x00 SysTick Control and Status Register */ - __IO uint32_t LOAD; /*!< Offset: 0x04 SysTick Reload Value Register */ - __IO uint32_t VAL; /*!< Offset: 0x08 SysTick Current Value Register */ - __I uint32_t CALIB; /*!< Offset: 0x0C SysTick Calibration Register */ -} SysTick_Type; - -/* SysTick Control / Status Register Definitions */ -#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */ -#define SysTick_CTRL_COUNTFLAG_Msk (1ul << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */ - -#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */ -#define SysTick_CTRL_CLKSOURCE_Msk (1ul << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */ - -#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */ -#define SysTick_CTRL_TICKINT_Msk (1ul << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */ - -#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */ -#define SysTick_CTRL_ENABLE_Msk (1ul << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */ - -/* SysTick Reload Register Definitions */ -#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */ -#define SysTick_LOAD_RELOAD_Msk (0xFFFFFFul << SysTick_LOAD_RELOAD_Pos) /*!< SysTick LOAD: RELOAD Mask */ - -/* SysTick Current Register Definitions */ -#define SysTick_VAL_CURRENT_Pos 0 /*!< SysTick VAL: CURRENT Position */ -#define SysTick_VAL_CURRENT_Msk (0xFFFFFFul << SysTick_VAL_CURRENT_Pos) /*!< SysTick VAL: CURRENT Mask */ - -/* SysTick Calibration Register Definitions */ -#define SysTick_CALIB_NOREF_Pos 31 /*!< SysTick CALIB: NOREF Position */ -#define SysTick_CALIB_NOREF_Msk (1ul << SysTick_CALIB_NOREF_Pos) /*!< SysTick CALIB: NOREF Mask */ - -#define SysTick_CALIB_SKEW_Pos 30 /*!< SysTick CALIB: SKEW Position */ -#define SysTick_CALIB_SKEW_Msk (1ul << SysTick_CALIB_SKEW_Pos) /*!< SysTick CALIB: SKEW Mask */ - -#define SysTick_CALIB_TENMS_Pos 0 /*!< SysTick CALIB: TENMS Position */ -#define SysTick_CALIB_TENMS_Msk (0xFFFFFFul << SysTick_VAL_CURRENT_Pos) /*!< SysTick CALIB: TENMS Mask */ -/*@}*/ /* end of group CMSIS_CM3_SysTick */ - - -/** @addtogroup CMSIS_CM3_ITM CMSIS CM3 ITM - memory mapped structure for Instrumentation Trace Macrocell (ITM) - @{ - */ -typedef struct -{ - __O union - { - __O uint8_t u8; /*!< Offset: ITM Stimulus Port 8-bit */ - __O uint16_t u16; /*!< Offset: ITM Stimulus Port 16-bit */ - __O uint32_t u32; /*!< Offset: ITM Stimulus Port 32-bit */ - } PORT [32]; /*!< Offset: 0x00 ITM Stimulus Port Registers */ - uint32_t RESERVED0[864]; - __IO uint32_t TER; /*!< Offset: ITM Trace Enable Register */ - uint32_t RESERVED1[15]; - __IO uint32_t TPR; /*!< Offset: ITM Trace Privilege Register */ - uint32_t RESERVED2[15]; - __IO uint32_t TCR; /*!< Offset: ITM Trace Control Register */ - uint32_t RESERVED3[29]; - __IO uint32_t IWR; /*!< Offset: ITM Integration Write Register */ - __IO uint32_t IRR; /*!< Offset: ITM Integration Read Register */ - __IO uint32_t IMCR; /*!< Offset: ITM Integration Mode Control Register */ - uint32_t RESERVED4[43]; - __IO uint32_t LAR; /*!< Offset: ITM Lock Access Register */ - __IO uint32_t LSR; /*!< Offset: ITM Lock Status Register */ - uint32_t RESERVED5[6]; - __I uint32_t PID4; /*!< Offset: ITM Peripheral Identification Register #4 */ - __I uint32_t PID5; /*!< Offset: ITM Peripheral Identification Register #5 */ - __I uint32_t PID6; /*!< Offset: ITM Peripheral Identification Register #6 */ - __I uint32_t PID7; /*!< Offset: ITM Peripheral Identification Register #7 */ - __I uint32_t PID0; /*!< Offset: ITM Peripheral Identification Register #0 */ - __I uint32_t PID1; /*!< Offset: ITM Peripheral Identification Register #1 */ - __I uint32_t PID2; /*!< Offset: ITM Peripheral Identification Register #2 */ - __I uint32_t PID3; /*!< Offset: ITM Peripheral Identification Register #3 */ - __I uint32_t CID0; /*!< Offset: ITM Component Identification Register #0 */ - __I uint32_t CID1; /*!< Offset: ITM Component Identification Register #1 */ - __I uint32_t CID2; /*!< Offset: ITM Component Identification Register #2 */ - __I uint32_t CID3; /*!< Offset: ITM Component Identification Register #3 */ -} ITM_Type; - -/* ITM Trace Privilege Register Definitions */ -#define ITM_TPR_PRIVMASK_Pos 0 /*!< ITM TPR: PRIVMASK Position */ -#define ITM_TPR_PRIVMASK_Msk (0xFul << ITM_TPR_PRIVMASK_Pos) /*!< ITM TPR: PRIVMASK Mask */ - -/* ITM Trace Control Register Definitions */ -#define ITM_TCR_BUSY_Pos 23 /*!< ITM TCR: BUSY Position */ -#define ITM_TCR_BUSY_Msk (1ul << ITM_TCR_BUSY_Pos) /*!< ITM TCR: BUSY Mask */ - -#define ITM_TCR_ATBID_Pos 16 /*!< ITM TCR: ATBID Position */ -#define ITM_TCR_ATBID_Msk (0x7Ful << ITM_TCR_ATBID_Pos) /*!< ITM TCR: ATBID Mask */ - -#define ITM_TCR_TSPrescale_Pos 8 /*!< ITM TCR: TSPrescale Position */ -#define ITM_TCR_TSPrescale_Msk (3ul << ITM_TCR_TSPrescale_Pos) /*!< ITM TCR: TSPrescale Mask */ - -#define ITM_TCR_SWOENA_Pos 4 /*!< ITM TCR: SWOENA Position */ -#define ITM_TCR_SWOENA_Msk (1ul << ITM_TCR_SWOENA_Pos) /*!< ITM TCR: SWOENA Mask */ - -#define ITM_TCR_DWTENA_Pos 3 /*!< ITM TCR: DWTENA Position */ -#define ITM_TCR_DWTENA_Msk (1ul << ITM_TCR_DWTENA_Pos) /*!< ITM TCR: DWTENA Mask */ - -#define ITM_TCR_SYNCENA_Pos 2 /*!< ITM TCR: SYNCENA Position */ -#define ITM_TCR_SYNCENA_Msk (1ul << ITM_TCR_SYNCENA_Pos) /*!< ITM TCR: SYNCENA Mask */ - -#define ITM_TCR_TSENA_Pos 1 /*!< ITM TCR: TSENA Position */ -#define ITM_TCR_TSENA_Msk (1ul << ITM_TCR_TSENA_Pos) /*!< ITM TCR: TSENA Mask */ - -#define ITM_TCR_ITMENA_Pos 0 /*!< ITM TCR: ITM Enable bit Position */ -#define ITM_TCR_ITMENA_Msk (1ul << ITM_TCR_ITMENA_Pos) /*!< ITM TCR: ITM Enable bit Mask */ - -/* ITM Integration Write Register Definitions */ -#define ITM_IWR_ATVALIDM_Pos 0 /*!< ITM IWR: ATVALIDM Position */ -#define ITM_IWR_ATVALIDM_Msk (1ul << ITM_IWR_ATVALIDM_Pos) /*!< ITM IWR: ATVALIDM Mask */ - -/* ITM Integration Read Register Definitions */ -#define ITM_IRR_ATREADYM_Pos 0 /*!< ITM IRR: ATREADYM Position */ -#define ITM_IRR_ATREADYM_Msk (1ul << ITM_IRR_ATREADYM_Pos) /*!< ITM IRR: ATREADYM Mask */ - -/* ITM Integration Mode Control Register Definitions */ -#define ITM_IMCR_INTEGRATION_Pos 0 /*!< ITM IMCR: INTEGRATION Position */ -#define ITM_IMCR_INTEGRATION_Msk (1ul << ITM_IMCR_INTEGRATION_Pos) /*!< ITM IMCR: INTEGRATION Mask */ - -/* ITM Lock Status Register Definitions */ -#define ITM_LSR_ByteAcc_Pos 2 /*!< ITM LSR: ByteAcc Position */ -#define ITM_LSR_ByteAcc_Msk (1ul << ITM_LSR_ByteAcc_Pos) /*!< ITM LSR: ByteAcc Mask */ - -#define ITM_LSR_Access_Pos 1 /*!< ITM LSR: Access Position */ -#define ITM_LSR_Access_Msk (1ul << ITM_LSR_Access_Pos) /*!< ITM LSR: Access Mask */ - -#define ITM_LSR_Present_Pos 0 /*!< ITM LSR: Present Position */ -#define ITM_LSR_Present_Msk (1ul << ITM_LSR_Present_Pos) /*!< ITM LSR: Present Mask */ -/*@}*/ /* end of group CMSIS_CM3_ITM */ - - -/** @addtogroup CMSIS_CM3_InterruptType CMSIS CM3 Interrupt Type - memory mapped structure for Interrupt Type - @{ - */ -typedef struct -{ - uint32_t RESERVED0; - __I uint32_t ICTR; /*!< Offset: 0x04 Interrupt Control Type Register */ -#if ((defined __CM3_REV) && (__CM3_REV >= 0x200)) - __IO uint32_t ACTLR; /*!< Offset: 0x08 Auxiliary Control Register */ -#else - uint32_t RESERVED1; -#endif -} InterruptType_Type; - -/* Interrupt Controller Type Register Definitions */ -#define InterruptType_ICTR_INTLINESNUM_Pos 0 /*!< InterruptType ICTR: INTLINESNUM Position */ -#define InterruptType_ICTR_INTLINESNUM_Msk (0x1Ful << InterruptType_ICTR_INTLINESNUM_Pos) /*!< InterruptType ICTR: INTLINESNUM Mask */ - -/* Auxiliary Control Register Definitions */ -#define InterruptType_ACTLR_DISFOLD_Pos 2 /*!< InterruptType ACTLR: DISFOLD Position */ -#define InterruptType_ACTLR_DISFOLD_Msk (1ul << InterruptType_ACTLR_DISFOLD_Pos) /*!< InterruptType ACTLR: DISFOLD Mask */ - -#define InterruptType_ACTLR_DISDEFWBUF_Pos 1 /*!< InterruptType ACTLR: DISDEFWBUF Position */ -#define InterruptType_ACTLR_DISDEFWBUF_Msk (1ul << InterruptType_ACTLR_DISDEFWBUF_Pos) /*!< InterruptType ACTLR: DISDEFWBUF Mask */ - -#define InterruptType_ACTLR_DISMCYCINT_Pos 0 /*!< InterruptType ACTLR: DISMCYCINT Position */ -#define InterruptType_ACTLR_DISMCYCINT_Msk (1ul << InterruptType_ACTLR_DISMCYCINT_Pos) /*!< InterruptType ACTLR: DISMCYCINT Mask */ -/*@}*/ /* end of group CMSIS_CM3_InterruptType */ - - -#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1) -/** @addtogroup CMSIS_CM3_MPU CMSIS CM3 MPU - memory mapped structure for Memory Protection Unit (MPU) - @{ - */ -typedef struct -{ - __I uint32_t TYPE; /*!< Offset: 0x00 MPU Type Register */ - __IO uint32_t CTRL; /*!< Offset: 0x04 MPU Control Register */ - __IO uint32_t RNR; /*!< Offset: 0x08 MPU Region RNRber Register */ - __IO uint32_t RBAR; /*!< Offset: 0x0C MPU Region Base Address Register */ - __IO uint32_t RASR; /*!< Offset: 0x10 MPU Region Attribute and Size Register */ - __IO uint32_t RBAR_A1; /*!< Offset: 0x14 MPU Alias 1 Region Base Address Register */ - __IO uint32_t RASR_A1; /*!< Offset: 0x18 MPU Alias 1 Region Attribute and Size Register */ - __IO uint32_t RBAR_A2; /*!< Offset: 0x1C MPU Alias 2 Region Base Address Register */ - __IO uint32_t RASR_A2; /*!< Offset: 0x20 MPU Alias 2 Region Attribute and Size Register */ - __IO uint32_t RBAR_A3; /*!< Offset: 0x24 MPU Alias 3 Region Base Address Register */ - __IO uint32_t RASR_A3; /*!< Offset: 0x28 MPU Alias 3 Region Attribute and Size Register */ -} MPU_Type; - -/* MPU Type Register */ -#define MPU_TYPE_IREGION_Pos 16 /*!< MPU TYPE: IREGION Position */ -#define MPU_TYPE_IREGION_Msk (0xFFul << MPU_TYPE_IREGION_Pos) /*!< MPU TYPE: IREGION Mask */ - -#define MPU_TYPE_DREGION_Pos 8 /*!< MPU TYPE: DREGION Position */ -#define MPU_TYPE_DREGION_Msk (0xFFul << MPU_TYPE_DREGION_Pos) /*!< MPU TYPE: DREGION Mask */ - -#define MPU_TYPE_SEPARATE_Pos 0 /*!< MPU TYPE: SEPARATE Position */ -#define MPU_TYPE_SEPARATE_Msk (1ul << MPU_TYPE_SEPARATE_Pos) /*!< MPU TYPE: SEPARATE Mask */ - -/* MPU Control Register */ -#define MPU_CTRL_PRIVDEFENA_Pos 2 /*!< MPU CTRL: PRIVDEFENA Position */ -#define MPU_CTRL_PRIVDEFENA_Msk (1ul << MPU_CTRL_PRIVDEFENA_Pos) /*!< MPU CTRL: PRIVDEFENA Mask */ - -#define MPU_CTRL_HFNMIENA_Pos 1 /*!< MPU CTRL: HFNMIENA Position */ -#define MPU_CTRL_HFNMIENA_Msk (1ul << MPU_CTRL_HFNMIENA_Pos) /*!< MPU CTRL: HFNMIENA Mask */ - -#define MPU_CTRL_ENABLE_Pos 0 /*!< MPU CTRL: ENABLE Position */ -#define MPU_CTRL_ENABLE_Msk (1ul << MPU_CTRL_ENABLE_Pos) /*!< MPU CTRL: ENABLE Mask */ - -/* MPU Region Number Register */ -#define MPU_RNR_REGION_Pos 0 /*!< MPU RNR: REGION Position */ -#define MPU_RNR_REGION_Msk (0xFFul << MPU_RNR_REGION_Pos) /*!< MPU RNR: REGION Mask */ - -/* MPU Region Base Address Register */ -#define MPU_RBAR_ADDR_Pos 5 /*!< MPU RBAR: ADDR Position */ -#define MPU_RBAR_ADDR_Msk (0x7FFFFFFul << MPU_RBAR_ADDR_Pos) /*!< MPU RBAR: ADDR Mask */ - -#define MPU_RBAR_VALID_Pos 4 /*!< MPU RBAR: VALID Position */ -#define MPU_RBAR_VALID_Msk (1ul << MPU_RBAR_VALID_Pos) /*!< MPU RBAR: VALID Mask */ - -#define MPU_RBAR_REGION_Pos 0 /*!< MPU RBAR: REGION Position */ -#define MPU_RBAR_REGION_Msk (0xFul << MPU_RBAR_REGION_Pos) /*!< MPU RBAR: REGION Mask */ - -/* MPU Region Attribute and Size Register */ -#define MPU_RASR_XN_Pos 28 /*!< MPU RASR: XN Position */ -#define MPU_RASR_XN_Msk (1ul << MPU_RASR_XN_Pos) /*!< MPU RASR: XN Mask */ - -#define MPU_RASR_AP_Pos 24 /*!< MPU RASR: AP Position */ -#define MPU_RASR_AP_Msk (7ul << MPU_RASR_AP_Pos) /*!< MPU RASR: AP Mask */ - -#define MPU_RASR_TEX_Pos 19 /*!< MPU RASR: TEX Position */ -#define MPU_RASR_TEX_Msk (7ul << MPU_RASR_TEX_Pos) /*!< MPU RASR: TEX Mask */ - -#define MPU_RASR_S_Pos 18 /*!< MPU RASR: Shareable bit Position */ -#define MPU_RASR_S_Msk (1ul << MPU_RASR_S_Pos) /*!< MPU RASR: Shareable bit Mask */ - -#define MPU_RASR_C_Pos 17 /*!< MPU RASR: Cacheable bit Position */ -#define MPU_RASR_C_Msk (1ul << MPU_RASR_C_Pos) /*!< MPU RASR: Cacheable bit Mask */ - -#define MPU_RASR_B_Pos 16 /*!< MPU RASR: Bufferable bit Position */ -#define MPU_RASR_B_Msk (1ul << MPU_RASR_B_Pos) /*!< MPU RASR: Bufferable bit Mask */ - -#define MPU_RASR_SRD_Pos 8 /*!< MPU RASR: Sub-Region Disable Position */ -#define MPU_RASR_SRD_Msk (0xFFul << MPU_RASR_SRD_Pos) /*!< MPU RASR: Sub-Region Disable Mask */ - -#define MPU_RASR_SIZE_Pos 1 /*!< MPU RASR: Region Size Field Position */ -#define MPU_RASR_SIZE_Msk (0x1Ful << MPU_RASR_SIZE_Pos) /*!< MPU RASR: Region Size Field Mask */ - -#define MPU_RASR_ENA_Pos 0 /*!< MPU RASR: Region enable bit Position */ -#define MPU_RASR_ENA_Msk (0x1Ful << MPU_RASR_ENA_Pos) /*!< MPU RASR: Region enable bit Disable Mask */ - -/*@}*/ /* end of group CMSIS_CM3_MPU */ -#endif - - -/** @addtogroup CMSIS_CM3_CoreDebug CMSIS CM3 Core Debug - memory mapped structure for Core Debug Register - @{ - */ -typedef struct -{ - __IO uint32_t DHCSR; /*!< Offset: 0x00 Debug Halting Control and Status Register */ - __O uint32_t DCRSR; /*!< Offset: 0x04 Debug Core Register Selector Register */ - __IO uint32_t DCRDR; /*!< Offset: 0x08 Debug Core Register Data Register */ - __IO uint32_t DEMCR; /*!< Offset: 0x0C Debug Exception and Monitor Control Register */ -} CoreDebug_Type; - -/* Debug Halting Control and Status Register */ -#define CoreDebug_DHCSR_DBGKEY_Pos 16 /*!< CoreDebug DHCSR: DBGKEY Position */ -#define CoreDebug_DHCSR_DBGKEY_Msk (0xFFFFul << CoreDebug_DHCSR_DBGKEY_Pos) /*!< CoreDebug DHCSR: DBGKEY Mask */ - -#define CoreDebug_DHCSR_S_RESET_ST_Pos 25 /*!< CoreDebug DHCSR: S_RESET_ST Position */ -#define CoreDebug_DHCSR_S_RESET_ST_Msk (1ul << CoreDebug_DHCSR_S_RESET_ST_Pos) /*!< CoreDebug DHCSR: S_RESET_ST Mask */ - -#define CoreDebug_DHCSR_S_RETIRE_ST_Pos 24 /*!< CoreDebug DHCSR: S_RETIRE_ST Position */ -#define CoreDebug_DHCSR_S_RETIRE_ST_Msk (1ul << CoreDebug_DHCSR_S_RETIRE_ST_Pos) /*!< CoreDebug DHCSR: S_RETIRE_ST Mask */ - -#define CoreDebug_DHCSR_S_LOCKUP_Pos 19 /*!< CoreDebug DHCSR: S_LOCKUP Position */ -#define CoreDebug_DHCSR_S_LOCKUP_Msk (1ul << CoreDebug_DHCSR_S_LOCKUP_Pos) /*!< CoreDebug DHCSR: S_LOCKUP Mask */ - -#define CoreDebug_DHCSR_S_SLEEP_Pos 18 /*!< CoreDebug DHCSR: S_SLEEP Position */ -#define CoreDebug_DHCSR_S_SLEEP_Msk (1ul << CoreDebug_DHCSR_S_SLEEP_Pos) /*!< CoreDebug DHCSR: S_SLEEP Mask */ - -#define CoreDebug_DHCSR_S_HALT_Pos 17 /*!< CoreDebug DHCSR: S_HALT Position */ -#define CoreDebug_DHCSR_S_HALT_Msk (1ul << CoreDebug_DHCSR_S_HALT_Pos) /*!< CoreDebug DHCSR: S_HALT Mask */ - -#define CoreDebug_DHCSR_S_REGRDY_Pos 16 /*!< CoreDebug DHCSR: S_REGRDY Position */ -#define CoreDebug_DHCSR_S_REGRDY_Msk (1ul << CoreDebug_DHCSR_S_REGRDY_Pos) /*!< CoreDebug DHCSR: S_REGRDY Mask */ - -#define CoreDebug_DHCSR_C_SNAPSTALL_Pos 5 /*!< CoreDebug DHCSR: C_SNAPSTALL Position */ -#define CoreDebug_DHCSR_C_SNAPSTALL_Msk (1ul << CoreDebug_DHCSR_C_SNAPSTALL_Pos) /*!< CoreDebug DHCSR: C_SNAPSTALL Mask */ - -#define CoreDebug_DHCSR_C_MASKINTS_Pos 3 /*!< CoreDebug DHCSR: C_MASKINTS Position */ -#define CoreDebug_DHCSR_C_MASKINTS_Msk (1ul << CoreDebug_DHCSR_C_MASKINTS_Pos) /*!< CoreDebug DHCSR: C_MASKINTS Mask */ - -#define CoreDebug_DHCSR_C_STEP_Pos 2 /*!< CoreDebug DHCSR: C_STEP Position */ -#define CoreDebug_DHCSR_C_STEP_Msk (1ul << CoreDebug_DHCSR_C_STEP_Pos) /*!< CoreDebug DHCSR: C_STEP Mask */ - -#define CoreDebug_DHCSR_C_HALT_Pos 1 /*!< CoreDebug DHCSR: C_HALT Position */ -#define CoreDebug_DHCSR_C_HALT_Msk (1ul << CoreDebug_DHCSR_C_HALT_Pos) /*!< CoreDebug DHCSR: C_HALT Mask */ - -#define CoreDebug_DHCSR_C_DEBUGEN_Pos 0 /*!< CoreDebug DHCSR: C_DEBUGEN Position */ -#define CoreDebug_DHCSR_C_DEBUGEN_Msk (1ul << CoreDebug_DHCSR_C_DEBUGEN_Pos) /*!< CoreDebug DHCSR: C_DEBUGEN Mask */ - -/* Debug Core Register Selector Register */ -#define CoreDebug_DCRSR_REGWnR_Pos 16 /*!< CoreDebug DCRSR: REGWnR Position */ -#define CoreDebug_DCRSR_REGWnR_Msk (1ul << CoreDebug_DCRSR_REGWnR_Pos) /*!< CoreDebug DCRSR: REGWnR Mask */ - -#define CoreDebug_DCRSR_REGSEL_Pos 0 /*!< CoreDebug DCRSR: REGSEL Position */ -#define CoreDebug_DCRSR_REGSEL_Msk (0x1Ful << CoreDebug_DCRSR_REGSEL_Pos) /*!< CoreDebug DCRSR: REGSEL Mask */ - -/* Debug Exception and Monitor Control Register */ -#define CoreDebug_DEMCR_TRCENA_Pos 24 /*!< CoreDebug DEMCR: TRCENA Position */ -#define CoreDebug_DEMCR_TRCENA_Msk (1ul << CoreDebug_DEMCR_TRCENA_Pos) /*!< CoreDebug DEMCR: TRCENA Mask */ - -#define CoreDebug_DEMCR_MON_REQ_Pos 19 /*!< CoreDebug DEMCR: MON_REQ Position */ -#define CoreDebug_DEMCR_MON_REQ_Msk (1ul << CoreDebug_DEMCR_MON_REQ_Pos) /*!< CoreDebug DEMCR: MON_REQ Mask */ - -#define CoreDebug_DEMCR_MON_STEP_Pos 18 /*!< CoreDebug DEMCR: MON_STEP Position */ -#define CoreDebug_DEMCR_MON_STEP_Msk (1ul << CoreDebug_DEMCR_MON_STEP_Pos) /*!< CoreDebug DEMCR: MON_STEP Mask */ - -#define CoreDebug_DEMCR_MON_PEND_Pos 17 /*!< CoreDebug DEMCR: MON_PEND Position */ -#define CoreDebug_DEMCR_MON_PEND_Msk (1ul << CoreDebug_DEMCR_MON_PEND_Pos) /*!< CoreDebug DEMCR: MON_PEND Mask */ - -#define CoreDebug_DEMCR_MON_EN_Pos 16 /*!< CoreDebug DEMCR: MON_EN Position */ -#define CoreDebug_DEMCR_MON_EN_Msk (1ul << CoreDebug_DEMCR_MON_EN_Pos) /*!< CoreDebug DEMCR: MON_EN Mask */ - -#define CoreDebug_DEMCR_VC_HARDERR_Pos 10 /*!< CoreDebug DEMCR: VC_HARDERR Position */ -#define CoreDebug_DEMCR_VC_HARDERR_Msk (1ul << CoreDebug_DEMCR_VC_HARDERR_Pos) /*!< CoreDebug DEMCR: VC_HARDERR Mask */ - -#define CoreDebug_DEMCR_VC_INTERR_Pos 9 /*!< CoreDebug DEMCR: VC_INTERR Position */ -#define CoreDebug_DEMCR_VC_INTERR_Msk (1ul << CoreDebug_DEMCR_VC_INTERR_Pos) /*!< CoreDebug DEMCR: VC_INTERR Mask */ - -#define CoreDebug_DEMCR_VC_BUSERR_Pos 8 /*!< CoreDebug DEMCR: VC_BUSERR Position */ -#define CoreDebug_DEMCR_VC_BUSERR_Msk (1ul << CoreDebug_DEMCR_VC_BUSERR_Pos) /*!< CoreDebug DEMCR: VC_BUSERR Mask */ - -#define CoreDebug_DEMCR_VC_STATERR_Pos 7 /*!< CoreDebug DEMCR: VC_STATERR Position */ -#define CoreDebug_DEMCR_VC_STATERR_Msk (1ul << CoreDebug_DEMCR_VC_STATERR_Pos) /*!< CoreDebug DEMCR: VC_STATERR Mask */ - -#define CoreDebug_DEMCR_VC_CHKERR_Pos 6 /*!< CoreDebug DEMCR: VC_CHKERR Position */ -#define CoreDebug_DEMCR_VC_CHKERR_Msk (1ul << CoreDebug_DEMCR_VC_CHKERR_Pos) /*!< CoreDebug DEMCR: VC_CHKERR Mask */ - -#define CoreDebug_DEMCR_VC_NOCPERR_Pos 5 /*!< CoreDebug DEMCR: VC_NOCPERR Position */ -#define CoreDebug_DEMCR_VC_NOCPERR_Msk (1ul << CoreDebug_DEMCR_VC_NOCPERR_Pos) /*!< CoreDebug DEMCR: VC_NOCPERR Mask */ - -#define CoreDebug_DEMCR_VC_MMERR_Pos 4 /*!< CoreDebug DEMCR: VC_MMERR Position */ -#define CoreDebug_DEMCR_VC_MMERR_Msk (1ul << CoreDebug_DEMCR_VC_MMERR_Pos) /*!< CoreDebug DEMCR: VC_MMERR Mask */ - -#define CoreDebug_DEMCR_VC_CORERESET_Pos 0 /*!< CoreDebug DEMCR: VC_CORERESET Position */ -#define CoreDebug_DEMCR_VC_CORERESET_Msk (1ul << CoreDebug_DEMCR_VC_CORERESET_Pos) /*!< CoreDebug DEMCR: VC_CORERESET Mask */ -/*@}*/ /* end of group CMSIS_CM3_CoreDebug */ - - -/* Memory mapping of Cortex-M3 Hardware */ -#define SCS_BASE (0xE000E000) /*!< System Control Space Base Address */ -#define ITM_BASE (0xE0000000) /*!< ITM Base Address */ -#define CoreDebug_BASE (0xE000EDF0) /*!< Core Debug Base Address */ -#define SysTick_BASE (SCS_BASE + 0x0010) /*!< SysTick Base Address */ -#define NVIC_BASE (SCS_BASE + 0x0100) /*!< NVIC Base Address */ -#define SCB_BASE (SCS_BASE + 0x0D00) /*!< System Control Block Base Address */ - -#define InterruptType ((InterruptType_Type *) SCS_BASE) /*!< Interrupt Type Register */ -#define SCB ((SCB_Type *) SCB_BASE) /*!< SCB configuration struct */ -#define SysTick ((SysTick_Type *) SysTick_BASE) /*!< SysTick configuration struct */ -#define NVIC ((NVIC_Type *) NVIC_BASE) /*!< NVIC configuration struct */ -#define ITM ((ITM_Type *) ITM_BASE) /*!< ITM configuration struct */ -#define CoreDebug ((CoreDebug_Type *) CoreDebug_BASE) /*!< Core Debug configuration struct */ - -#if defined (__MPU_PRESENT) && (__MPU_PRESENT == 1) - #define MPU_BASE (SCS_BASE + 0x0D90) /*!< Memory Protection Unit */ - #define MPU ((MPU_Type*) MPU_BASE) /*!< Memory Protection Unit */ -#endif - -/*@}*/ /* end of group CMSIS_CM3_core_register */ - - -/******************************************************************************* - * Hardware Abstraction Layer - ******************************************************************************/ - -#if defined ( __CC_ARM ) - #define __ASM __asm /*!< asm keyword for ARM Compiler */ - #define __INLINE __inline /*!< inline keyword for ARM Compiler */ - -#elif defined ( __ICCARM__ ) - #define __ASM __asm /*!< asm keyword for IAR Compiler */ - #define __INLINE inline /*!< inline keyword for IAR Compiler. Only avaiable in High optimization mode! */ - -#elif defined ( __GNUC__ ) - #define __ASM __asm /*!< asm keyword for GNU Compiler */ - #define __INLINE inline /*!< inline keyword for GNU Compiler */ - -#elif defined ( __TASKING__ ) - #define __ASM __asm /*!< asm keyword for TASKING Compiler */ - #define __INLINE inline /*!< inline keyword for TASKING Compiler */ - -#endif - - -/* ################### Compiler specific Intrinsics ########################### */ - -#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ -/* ARM armcc specific functions */ - -#define __enable_fault_irq __enable_fiq -#define __disable_fault_irq __disable_fiq - -#define __NOP __nop -#define __WFI __wfi -#define __WFE __wfe -#define __SEV __sev -#define __ISB() __isb(0) -#define __DSB() __dsb(0) -#define __DMB() __dmb(0) -#define __REV __rev -#define __RBIT __rbit -#define __LDREXB(ptr) ((unsigned char ) __ldrex(ptr)) -#define __LDREXH(ptr) ((unsigned short) __ldrex(ptr)) -#define __LDREXW(ptr) ((unsigned int ) __ldrex(ptr)) -#define __STREXB(value, ptr) __strex(value, ptr) -#define __STREXH(value, ptr) __strex(value, ptr) -#define __STREXW(value, ptr) __strex(value, ptr) - - -/* intrinsic unsigned long long __ldrexd(volatile void *ptr) */ -/* intrinsic int __strexd(unsigned long long val, volatile void *ptr) */ -/* intrinsic void __enable_irq(); */ -/* intrinsic void __disable_irq(); */ - - -/** - * @brief Return the Process Stack Pointer - * - * @return ProcessStackPointer - * - * Return the actual process stack pointer - */ -extern uint32_t __get_PSP(void); - -/** - * @brief Set the Process Stack Pointer - * - * @param topOfProcStack Process Stack Pointer - * - * Assign the value ProcessStackPointer to the MSP - * (process stack pointer) Cortex processor register - */ -extern void __set_PSP(uint32_t topOfProcStack); - -/** - * @brief Return the Main Stack Pointer - * - * @return Main Stack Pointer - * - * Return the current value of the MSP (main stack pointer) - * Cortex processor register - */ -extern uint32_t __get_MSP(void); - -/** - * @brief Set the Main Stack Pointer - * - * @param topOfMainStack Main Stack Pointer - * - * Assign the value mainStackPointer to the MSP - * (main stack pointer) Cortex processor register - */ -extern void __set_MSP(uint32_t topOfMainStack); - -/** - * @brief Reverse byte order in unsigned short value - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in unsigned short value - */ -extern uint32_t __REV16(uint16_t value); - -/** - * @brief Reverse byte order in signed short value with sign extension to integer - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in signed short value with sign extension to integer - */ -extern int32_t __REVSH(int16_t value); - - -#if (__ARMCC_VERSION < 400000) - -/** - * @brief Remove the exclusive lock created by ldrex - * - * Removes the exclusive lock which is created by ldrex. - */ -extern void __CLREX(void); - -/** - * @brief Return the Base Priority value - * - * @return BasePriority - * - * Return the content of the base priority register - */ -extern uint32_t __get_BASEPRI(void); - -/** - * @brief Set the Base Priority value - * - * @param basePri BasePriority - * - * Set the base priority register - */ -extern void __set_BASEPRI(uint32_t basePri); - -/** - * @brief Return the Priority Mask value - * - * @return PriMask - * - * Return state of the priority mask bit from the priority mask register - */ -extern uint32_t __get_PRIMASK(void); - -/** - * @brief Set the Priority Mask value - * - * @param priMask PriMask - * - * Set the priority mask bit in the priority mask register - */ -extern void __set_PRIMASK(uint32_t priMask); - -/** - * @brief Return the Fault Mask value - * - * @return FaultMask - * - * Return the content of the fault mask register - */ -extern uint32_t __get_FAULTMASK(void); - -/** - * @brief Set the Fault Mask value - * - * @param faultMask faultMask value - * - * Set the fault mask register - */ -extern void __set_FAULTMASK(uint32_t faultMask); - -/** - * @brief Return the Control Register value - * - * @return Control value - * - * Return the content of the control register - */ -extern uint32_t __get_CONTROL(void); - -/** - * @brief Set the Control Register value - * - * @param control Control value - * - * Set the control register - */ -extern void __set_CONTROL(uint32_t control); - -#else /* (__ARMCC_VERSION >= 400000) */ - -/** - * @brief Remove the exclusive lock created by ldrex - * - * Removes the exclusive lock which is created by ldrex. - */ -#define __CLREX __clrex - -/** - * @brief Return the Base Priority value - * - * @return BasePriority - * - * Return the content of the base priority register - */ -static __INLINE uint32_t __get_BASEPRI(void) -{ - register uint32_t __regBasePri __ASM("basepri"); - return(__regBasePri); -} - -/** - * @brief Set the Base Priority value - * - * @param basePri BasePriority - * - * Set the base priority register - */ -static __INLINE void __set_BASEPRI(uint32_t basePri) -{ - register uint32_t __regBasePri __ASM("basepri"); - __regBasePri = (basePri & 0xff); -} - -/** - * @brief Return the Priority Mask value - * - * @return PriMask - * - * Return state of the priority mask bit from the priority mask register - */ -static __INLINE uint32_t __get_PRIMASK(void) -{ - register uint32_t __regPriMask __ASM("primask"); - return(__regPriMask); -} - -/** - * @brief Set the Priority Mask value - * - * @param priMask PriMask - * - * Set the priority mask bit in the priority mask register - */ -static __INLINE void __set_PRIMASK(uint32_t priMask) -{ - register uint32_t __regPriMask __ASM("primask"); - __regPriMask = (priMask); -} - -/** - * @brief Return the Fault Mask value - * - * @return FaultMask - * - * Return the content of the fault mask register - */ -static __INLINE uint32_t __get_FAULTMASK(void) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - return(__regFaultMask); -} - -/** - * @brief Set the Fault Mask value - * - * @param faultMask faultMask value - * - * Set the fault mask register - */ -static __INLINE void __set_FAULTMASK(uint32_t faultMask) -{ - register uint32_t __regFaultMask __ASM("faultmask"); - __regFaultMask = (faultMask & 1); -} - -/** - * @brief Return the Control Register value - * - * @return Control value - * - * Return the content of the control register - */ -static __INLINE uint32_t __get_CONTROL(void) -{ - register uint32_t __regControl __ASM("control"); - return(__regControl); -} - -/** - * @brief Set the Control Register value - * - * @param control Control value - * - * Set the control register - */ -static __INLINE void __set_CONTROL(uint32_t control) -{ - register uint32_t __regControl __ASM("control"); - __regControl = control; -} - -#endif /* __ARMCC_VERSION */ - - - -#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/ -/* IAR iccarm specific functions */ - -#define __enable_irq __enable_interrupt /*!< global Interrupt enable */ -#define __disable_irq __disable_interrupt /*!< global Interrupt disable */ - -static __INLINE void __enable_fault_irq( void ) { __ASM ("cpsie f"); } -static __INLINE void __disable_fault_irq( void ) { __ASM ("cpsid f"); } - -#define __NOP __no_operation /*!< no operation intrinsic in IAR Compiler */ -static __INLINE void __WFI( void ) { __ASM ("wfi"); } -static __INLINE void __WFE( void ) { __ASM ("wfe"); } -static __INLINE void __SEV( void ) { __ASM ("sev"); } -static __INLINE void __CLREX( void ) { __ASM ("clrex"); } - -/* intrinsic void __ISB(void) */ -/* intrinsic void __DSB(void) */ -/* intrinsic void __DMB(void) */ -/* intrinsic void __set_PRIMASK(); */ -/* intrinsic void __get_PRIMASK(); */ -/* intrinsic void __set_FAULTMASK(); */ -/* intrinsic void __get_FAULTMASK(); */ -/* intrinsic uint32_t __REV(uint32_t value); */ -/* intrinsic uint32_t __REVSH(uint32_t value); */ -/* intrinsic unsigned long __STREX(unsigned long, unsigned long); */ -/* intrinsic unsigned long __LDREX(unsigned long *); */ - - -/** - * @brief Return the Process Stack Pointer - * - * @return ProcessStackPointer - * - * Return the actual process stack pointer - */ -extern uint32_t __get_PSP(void); - -/** - * @brief Set the Process Stack Pointer - * - * @param topOfProcStack Process Stack Pointer - * - * Assign the value ProcessStackPointer to the MSP - * (process stack pointer) Cortex processor register - */ -extern void __set_PSP(uint32_t topOfProcStack); - -/** - * @brief Return the Main Stack Pointer - * - * @return Main Stack Pointer - * - * Return the current value of the MSP (main stack pointer) - * Cortex processor register - */ -extern uint32_t __get_MSP(void); - -/** - * @brief Set the Main Stack Pointer - * - * @param topOfMainStack Main Stack Pointer - * - * Assign the value mainStackPointer to the MSP - * (main stack pointer) Cortex processor register - */ -extern void __set_MSP(uint32_t topOfMainStack); - -/** - * @brief Reverse byte order in unsigned short value - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in unsigned short value - */ -extern uint32_t __REV16(uint16_t value); - -/** - * @brief Reverse bit order of value - * - * @param value value to reverse - * @return reversed value - * - * Reverse bit order of value - */ -extern uint32_t __RBIT(uint32_t value); - -/** - * @brief LDR Exclusive (8 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 8 bit values) - */ -extern uint8_t __LDREXB(uint8_t *addr); - -/** - * @brief LDR Exclusive (16 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 16 bit values - */ -extern uint16_t __LDREXH(uint16_t *addr); - -/** - * @brief LDR Exclusive (32 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 32 bit values - */ -extern uint32_t __LDREXW(uint32_t *addr); - -/** - * @brief STR Exclusive (8 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 8 bit values - */ -extern uint32_t __STREXB(uint8_t value, uint8_t *addr); - -/** - * @brief STR Exclusive (16 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 16 bit values - */ -extern uint32_t __STREXH(uint16_t value, uint16_t *addr); - -/** - * @brief STR Exclusive (32 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 32 bit values - */ -extern uint32_t __STREXW(uint32_t value, uint32_t *addr); - - - -#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/ -/* GNU gcc specific functions */ - -static __INLINE void __enable_irq(void) { __ASM volatile ("cpsie i"); } -static __INLINE void __disable_irq(void) { __ASM volatile ("cpsid i"); } - -static __INLINE void __enable_fault_irq(void) { __ASM volatile ("cpsie f"); } -static __INLINE void __disable_fault_irq(void) { __ASM volatile ("cpsid f"); } - -static __INLINE void __NOP(void) { __ASM volatile ("nop"); } -static __INLINE void __WFI(void) { __ASM volatile ("wfi"); } -static __INLINE void __WFE(void) { __ASM volatile ("wfe"); } -static __INLINE void __SEV(void) { __ASM volatile ("sev"); } -static __INLINE void __ISB(void) { __ASM volatile ("isb"); } -static __INLINE void __DSB(void) { __ASM volatile ("dsb"); } -static __INLINE void __DMB(void) { __ASM volatile ("dmb"); } -static __INLINE void __CLREX(void) { __ASM volatile ("clrex"); } - - -/** - * @brief Return the Process Stack Pointer - * - * @return ProcessStackPointer - * - * Return the actual process stack pointer - */ -extern uint32_t __get_PSP(void); - -/** - * @brief Set the Process Stack Pointer - * - * @param topOfProcStack Process Stack Pointer - * - * Assign the value ProcessStackPointer to the MSP - * (process stack pointer) Cortex processor register - */ -extern void __set_PSP(uint32_t topOfProcStack); - -/** - * @brief Return the Main Stack Pointer - * - * @return Main Stack Pointer - * - * Return the current value of the MSP (main stack pointer) - * Cortex processor register - */ -extern uint32_t __get_MSP(void); - -/** - * @brief Set the Main Stack Pointer - * - * @param topOfMainStack Main Stack Pointer - * - * Assign the value mainStackPointer to the MSP - * (main stack pointer) Cortex processor register - */ -extern void __set_MSP(uint32_t topOfMainStack); - -/** - * @brief Return the Base Priority value - * - * @return BasePriority - * - * Return the content of the base priority register - */ -extern uint32_t __get_BASEPRI(void); - -/** - * @brief Set the Base Priority value - * - * @param basePri BasePriority - * - * Set the base priority register - */ -extern void __set_BASEPRI(uint32_t basePri); - -/** - * @brief Return the Priority Mask value - * - * @return PriMask - * - * Return state of the priority mask bit from the priority mask register - */ -extern uint32_t __get_PRIMASK(void); - -/** - * @brief Set the Priority Mask value - * - * @param priMask PriMask - * - * Set the priority mask bit in the priority mask register - */ -extern void __set_PRIMASK(uint32_t priMask); - -/** - * @brief Return the Fault Mask value - * - * @return FaultMask - * - * Return the content of the fault mask register - */ -extern uint32_t __get_FAULTMASK(void); - -/** - * @brief Set the Fault Mask value - * - * @param faultMask faultMask value - * - * Set the fault mask register - */ -extern void __set_FAULTMASK(uint32_t faultMask); - -/** - * @brief Return the Control Register value -* -* @return Control value - * - * Return the content of the control register - */ -extern uint32_t __get_CONTROL(void); - -/** - * @brief Set the Control Register value - * - * @param control Control value - * - * Set the control register - */ -extern void __set_CONTROL(uint32_t control); - -/** - * @brief Reverse byte order in integer value - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in integer value - */ -extern uint32_t __REV(uint32_t value); - -/** - * @brief Reverse byte order in unsigned short value - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in unsigned short value - */ -extern uint32_t __REV16(uint16_t value); - -/** - * @brief Reverse byte order in signed short value with sign extension to integer - * - * @param value value to reverse - * @return reversed value - * - * Reverse byte order in signed short value with sign extension to integer - */ -extern int32_t __REVSH(int16_t value); - -/** - * @brief Reverse bit order of value - * - * @param value value to reverse - * @return reversed value - * - * Reverse bit order of value - */ -extern uint32_t __RBIT(uint32_t value); - -/** - * @brief LDR Exclusive (8 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 8 bit value - */ -extern uint8_t __LDREXB(uint8_t *addr); - -/** - * @brief LDR Exclusive (16 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 16 bit values - */ -extern uint16_t __LDREXH(uint16_t *addr); - -/** - * @brief LDR Exclusive (32 bit) - * - * @param *addr address pointer - * @return value of (*address) - * - * Exclusive LDR command for 32 bit values - */ -extern uint32_t __LDREXW(uint32_t *addr); - -/** - * @brief STR Exclusive (8 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 8 bit values - */ -extern uint32_t __STREXB(uint8_t value, uint8_t *addr); - -/** - * @brief STR Exclusive (16 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 16 bit values - */ -extern uint32_t __STREXH(uint16_t value, uint16_t *addr); - -/** - * @brief STR Exclusive (32 bit) - * - * @param value value to store - * @param *addr address pointer - * @return successful / failed - * - * Exclusive STR command for 32 bit values - */ -extern uint32_t __STREXW(uint32_t value, uint32_t *addr); - - -#elif (defined (__TASKING__)) /*------------------ TASKING Compiler ---------------------*/ -/* TASKING carm specific functions */ - -/* - * The CMSIS functions have been implemented as intrinsics in the compiler. - * Please use "carm -?i" to get an up to date list of all instrinsics, - * Including the CMSIS ones. - */ - -#endif - - -/** @addtogroup CMSIS_CM3_Core_FunctionInterface CMSIS CM3 Core Function Interface - Core Function Interface containing: - - Core NVIC Functions - - Core SysTick Functions - - Core Reset Functions -*/ -/*@{*/ - -/* ########################## NVIC functions #################################### */ - -/** - * @brief Set the Priority Grouping in NVIC Interrupt Controller - * - * @param PriorityGroup is priority grouping field - * - * Set the priority grouping field using the required unlock sequence. - * The parameter priority_grouping is assigned to the field - * SCB->AIRCR [10:8] PRIGROUP field. Only values from 0..7 are used. - * In case of a conflict between priority grouping and available - * priority bits (__NVIC_PRIO_BITS) the smallest possible priority group is set. - */ -static __INLINE void NVIC_SetPriorityGrouping(uint32_t PriorityGroup) -{ - uint32_t reg_value; - uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ - - reg_value = SCB->AIRCR; /* read old register configuration */ - reg_value &= ~(SCB_AIRCR_VECTKEY_Msk | SCB_AIRCR_PRIGROUP_Msk); /* clear bits to change */ - reg_value = (reg_value | - (0x5FA << SCB_AIRCR_VECTKEY_Pos) | - (PriorityGroupTmp << 8)); /* Insert write key and priorty group */ - SCB->AIRCR = reg_value; -} - -/** - * @brief Get the Priority Grouping from NVIC Interrupt Controller - * - * @return priority grouping field - * - * Get the priority grouping from NVIC Interrupt Controller. - * priority grouping is SCB->AIRCR [10:8] PRIGROUP field. - */ -static __INLINE uint32_t NVIC_GetPriorityGrouping(void) -{ - return ((SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) >> SCB_AIRCR_PRIGROUP_Pos); /* read priority grouping field */ -} - -/** - * @brief Enable Interrupt in NVIC Interrupt Controller - * - * @param IRQn The positive number of the external interrupt to enable - * - * Enable a device specific interupt in the NVIC interrupt controller. - * The interrupt number cannot be a negative value. - */ -static __INLINE void NVIC_EnableIRQ(IRQn_Type IRQn) -{ - NVIC->ISER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* enable interrupt */ -} - -/** - * @brief Disable the interrupt line for external interrupt specified - * - * @param IRQn The positive number of the external interrupt to disable - * - * Disable a device specific interupt in the NVIC interrupt controller. - * The interrupt number cannot be a negative value. - */ -static __INLINE void NVIC_DisableIRQ(IRQn_Type IRQn) -{ - NVIC->ICER[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* disable interrupt */ -} - -/** - * @brief Read the interrupt pending bit for a device specific interrupt source - * - * @param IRQn The number of the device specifc interrupt - * @return 1 = interrupt pending, 0 = interrupt not pending - * - * Read the pending register in NVIC and return 1 if its status is pending, - * otherwise it returns 0 - */ -static __INLINE uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn) -{ - return((uint32_t) ((NVIC->ISPR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if pending else 0 */ -} - -/** - * @brief Set the pending bit for an external interrupt - * - * @param IRQn The number of the interrupt for set pending - * - * Set the pending bit for the specified interrupt. - * The interrupt number cannot be a negative value. - */ -static __INLINE void NVIC_SetPendingIRQ(IRQn_Type IRQn) -{ - NVIC->ISPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* set interrupt pending */ -} - -/** - * @brief Clear the pending bit for an external interrupt - * - * @param IRQn The number of the interrupt for clear pending - * - * Clear the pending bit for the specified interrupt. - * The interrupt number cannot be a negative value. - */ -static __INLINE void NVIC_ClearPendingIRQ(IRQn_Type IRQn) -{ - NVIC->ICPR[((uint32_t)(IRQn) >> 5)] = (1 << ((uint32_t)(IRQn) & 0x1F)); /* Clear pending interrupt */ -} - -/** - * @brief Read the active bit for an external interrupt - * - * @param IRQn The number of the interrupt for read active bit - * @return 1 = interrupt active, 0 = interrupt not active - * - * Read the active register in NVIC and returns 1 if its status is active, - * otherwise it returns 0. - */ -static __INLINE uint32_t NVIC_GetActive(IRQn_Type IRQn) -{ - return((uint32_t)((NVIC->IABR[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F)))?1:0)); /* Return 1 if active else 0 */ -} - -/** - * @brief Set the priority for an interrupt - * - * @param IRQn The number of the interrupt for set priority - * @param priority The priority to set - * - * Set the priority for the specified interrupt. The interrupt - * number can be positive to specify an external (device specific) - * interrupt, or negative to specify an internal (core) interrupt. - * - * Note: The priority cannot be set for every core interrupt. - */ -static __INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) -{ - if(IRQn < 0) { - SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M3 System Interrupts */ - else { - NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for device specific Interrupts */ -} - -/** - * @brief Read the priority for an interrupt - * - * @param IRQn The number of the interrupt for get priority - * @return The priority for the interrupt - * - * Read the priority for the specified interrupt. The interrupt - * number can be positive to specify an external (device specific) - * interrupt, or negative to specify an internal (core) interrupt. - * - * The returned priority value is automatically aligned to the implemented - * priority bits of the microcontroller. - * - * Note: The priority cannot be set for every core interrupt. - */ -static __INLINE uint32_t NVIC_GetPriority(IRQn_Type IRQn) -{ - - if(IRQn < 0) { - return((uint32_t)(SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for Cortex-M3 system interrupts */ - else { - return((uint32_t)(NVIC->IP[(uint32_t)(IRQn)] >> (8 - __NVIC_PRIO_BITS))); } /* get priority for device specific interrupts */ -} - - -/** - * @brief Encode the priority for an interrupt - * - * @param PriorityGroup The used priority group - * @param PreemptPriority The preemptive priority value (starting from 0) - * @param SubPriority The sub priority value (starting from 0) - * @return The encoded priority for the interrupt - * - * Encode the priority for an interrupt with the given priority group, - * preemptive priority value and sub priority value. - * In case of a conflict between priority grouping and available - * priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. - * - * The returned priority value can be used for NVIC_SetPriority(...) function - */ -static __INLINE uint32_t NVIC_EncodePriority (uint32_t PriorityGroup, uint32_t PreemptPriority, uint32_t SubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; - SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; - - return ( - ((PreemptPriority & ((1 << (PreemptPriorityBits)) - 1)) << SubPriorityBits) | - ((SubPriority & ((1 << (SubPriorityBits )) - 1))) - ); -} - - -/** - * @brief Decode the priority of an interrupt - * - * @param Priority The priority for the interrupt - * @param PriorityGroup The used priority group - * @param pPreemptPriority The preemptive priority value (starting from 0) - * @param pSubPriority The sub priority value (starting from 0) - * - * Decode an interrupt priority value with the given priority group to - * preemptive priority value and sub priority value. - * In case of a conflict between priority grouping and available - * priority bits (__NVIC_PRIO_BITS) the samllest possible priority group is set. - * - * The priority value can be retrieved with NVIC_GetPriority(...) function - */ -static __INLINE void NVIC_DecodePriority (uint32_t Priority, uint32_t PriorityGroup, uint32_t* pPreemptPriority, uint32_t* pSubPriority) -{ - uint32_t PriorityGroupTmp = (PriorityGroup & 0x07); /* only values 0..7 are used */ - uint32_t PreemptPriorityBits; - uint32_t SubPriorityBits; - - PreemptPriorityBits = ((7 - PriorityGroupTmp) > __NVIC_PRIO_BITS) ? __NVIC_PRIO_BITS : 7 - PriorityGroupTmp; - SubPriorityBits = ((PriorityGroupTmp + __NVIC_PRIO_BITS) < 7) ? 0 : PriorityGroupTmp - 7 + __NVIC_PRIO_BITS; - - *pPreemptPriority = (Priority >> SubPriorityBits) & ((1 << (PreemptPriorityBits)) - 1); - *pSubPriority = (Priority ) & ((1 << (SubPriorityBits )) - 1); -} - - - -/* ################################## SysTick function ############################################ */ - -#if (!defined (__Vendor_SysTickConfig)) || (__Vendor_SysTickConfig == 0) - -/** - * @brief Initialize and start the SysTick counter and its interrupt. - * - * @param ticks number of ticks between two interrupts - * @return 1 = failed, 0 = successful - * - * Initialise the system tick timer and its interrupt and start the - * system tick timer / counter in free running mode to generate - * periodical interrupts. - */ -static __INLINE uint32_t SysTick_Config(uint32_t ticks) -{ - if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */ - - SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */ - NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */ - SysTick->VAL = 0; /* Load the SysTick Counter Value */ - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_TICKINT_Msk | - SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */ - return (0); /* Function successful */ -} - -#endif - - - - -/* ################################## Reset function ############################################ */ - -/** - * @brief Initiate a system reset request. - * - * Initiate a system reset request to reset the MCU - */ -static __INLINE void NVIC_SystemReset(void) -{ - SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) | - (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) | - SCB_AIRCR_SYSRESETREQ_Msk); /* Keep priority group unchanged */ - __DSB(); /* Ensure completion of memory access */ - while(1); /* wait until reset */ -} - -/*@}*/ /* end of group CMSIS_CM3_Core_FunctionInterface */ - - - -/* ##################################### Debug In/Output function ########################################### */ - -/** @addtogroup CMSIS_CM3_CoreDebugInterface CMSIS CM3 Core Debug Interface - Core Debug Interface containing: - - Core Debug Receive / Transmit Functions - - Core Debug Defines - - Core Debug Variables -*/ -/*@{*/ - -extern volatile int ITM_RxBuffer; /*!< variable to receive characters */ -#define ITM_RXBUFFER_EMPTY 0x5AA55AA5 /*!< value identifying ITM_RxBuffer is ready for next character */ - - -/** - * @brief Outputs a character via the ITM channel 0 - * - * @param ch character to output - * @return character to output - * - * The function outputs a character via the ITM channel 0. - * The function returns when no debugger is connected that has booked the output. - * It is blocking when a debugger is connected, but the previous character send is not transmitted. - */ -static __INLINE uint32_t ITM_SendChar (uint32_t ch) -{ - if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk) && /* Trace enabled */ - (ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */ - (ITM->TER & (1ul << 0) ) ) /* ITM Port #0 enabled */ - { - while (ITM->PORT[0].u32 == 0); - ITM->PORT[0].u8 = (uint8_t) ch; - } - return (ch); -} - - -/** - * @brief Inputs a character via variable ITM_RxBuffer - * - * @return received character, -1 = no character received - * - * The function inputs a character via variable ITM_RxBuffer. - * The function returns when no debugger is connected that has booked the output. - * It is blocking when a debugger is connected, but the previous character send is not transmitted. - */ -static __INLINE int ITM_ReceiveChar (void) { - int ch = -1; /* no character available */ - - if (ITM_RxBuffer != ITM_RXBUFFER_EMPTY) { - ch = ITM_RxBuffer; - ITM_RxBuffer = ITM_RXBUFFER_EMPTY; /* ready for next character */ - } - - return (ch); -} - - -/** - * @brief Check if a character via variable ITM_RxBuffer is available - * - * @return 1 = character available, 0 = no character available - * - * The function checks variable ITM_RxBuffer whether a character is available or not. - * The function returns '1' if a character is available and '0' if no character is available. - */ -static __INLINE int ITM_CheckChar (void) { - - if (ITM_RxBuffer == ITM_RXBUFFER_EMPTY) { - return (0); /* no character available */ - } else { - return (1); /* character available */ - } -} - -/*@}*/ /* end of group CMSIS_CM3_core_DebugInterface */ - - -#ifdef __cplusplus -} -#endif - -/*@}*/ /* end of group CMSIS_CM3_core_definitions */ - -#endif /* __CM3_CORE_H__ */ - -/*lint -restore */ diff --git a/sam3s_example/blink.c b/sam3s_example/mains/blink.c similarity index 100% rename from sam3s_example/blink.c rename to sam3s_example/mains/blink.c diff --git a/sam3s_example/blink2.c b/sam3s_example/mains/blink2.c similarity index 100% rename from sam3s_example/blink2.c rename to sam3s_example/mains/blink2.c diff --git a/sam3s_example/src_board b/sam3s_example/src_board new file mode 120000 index 00000000..5ce1bf49 --- /dev/null +++ b/sam3s_example/src_board @@ -0,0 +1 @@ +./atmel_softpack_libraries/libboard_sam3s-ek/source \ No newline at end of file diff --git a/sam3s_example/src_sam3s b/sam3s_example/src_sam3s new file mode 120000 index 00000000..6355c88d --- /dev/null +++ b/sam3s_example/src_sam3s @@ -0,0 +1 @@ +./atmel_softpack_libraries/libchip_sam3s/source \ No newline at end of file