Stripped down version of microbuilder.eu lpc1343codebase
I hope I didn't break anything too hard.
This commit is contained in:
commit
0c23bf065d
|
@ -0,0 +1,108 @@
|
||||||
|
##########################################################################
|
||||||
|
# User configuration and firmware specific object files
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
# The target, flash and ram of the LPC1xxx microprocessor.
|
||||||
|
# Use for the target the value: LPC11xx, LPC13xx or LPC17xx
|
||||||
|
TARGET = LPC13xx
|
||||||
|
FLASH = 32K
|
||||||
|
SRAM = 8K
|
||||||
|
|
||||||
|
# For USB HID support the LPC134x reserves 384 bytes from the sram,
|
||||||
|
# if you don't want to use the USB features, just use 0 here.
|
||||||
|
SRAM_USB = 384
|
||||||
|
|
||||||
|
VPATH =
|
||||||
|
OBJS = main.o
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# Project-specific files
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
VPATH +=
|
||||||
|
OBJS +=
|
||||||
|
LIBS += core/libcore.a lcd/libfont.a
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# GNU GCC compiler prefix and location
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
CROSS_COMPILE = arm-none-eabi-
|
||||||
|
AS = $(CROSS_COMPILE)gcc
|
||||||
|
CC = $(CROSS_COMPILE)gcc
|
||||||
|
LD = $(CROSS_COMPILE)gcc
|
||||||
|
SIZE = $(CROSS_COMPILE)size
|
||||||
|
OBJCOPY = $(CROSS_COMPILE)objcopy
|
||||||
|
OBJDUMP = $(CROSS_COMPILE)objdump
|
||||||
|
OUTFILE = firmware
|
||||||
|
LPCRC = tools/lpcrc
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# GNU GCC compiler flags
|
||||||
|
##########################################################################
|
||||||
|
ROOT_PATH = .
|
||||||
|
INCLUDE_PATHS = -I$(ROOT_PATH) -I$(ROOT_PATH)/core
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# Startup files
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
LD_PATH = lpc1xxx
|
||||||
|
LD_SCRIPT = $(LD_PATH)/linkscript.ld
|
||||||
|
LD_TEMP = $(LD_PATH)/memory.ld
|
||||||
|
|
||||||
|
ifeq (LPC11xx,$(TARGET))
|
||||||
|
CORTEX_TYPE=m0
|
||||||
|
else
|
||||||
|
CORTEX_TYPE=m3
|
||||||
|
endif
|
||||||
|
|
||||||
|
CPU_TYPE = cortex-$(CORTEX_TYPE)
|
||||||
|
VPATH += lpc1xxx
|
||||||
|
OBJS += $(TARGET)_handlers.o LPC1xxx_startup.o
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# Compiler settings, parameters and flags
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
CFLAGS = -c -g -Os $(INCLUDE_PATHS) -Wall -mthumb -ffunction-sections -fdata-sections -fmessage-length=0 -mcpu=$(CPU_TYPE) -DTARGET=$(TARGET) -fno-builtin
|
||||||
|
LDFLAGS = -nostartfiles -mthumb -mcpu=$(CPU_TYPE) -Wl,--gc-sections
|
||||||
|
LDLIBS = -lm
|
||||||
|
LDLIBS += -Lcore -lcore
|
||||||
|
LDLIBS += -Llcd -lfont
|
||||||
|
OCFLAGS = --strip-unneeded
|
||||||
|
|
||||||
|
all: firmware
|
||||||
|
|
||||||
|
%.o : %.c
|
||||||
|
$(CC) $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
core/libcore.a: core/projectconfig.h
|
||||||
|
cd core && $(MAKE)
|
||||||
|
|
||||||
|
lcd/libfont.a:
|
||||||
|
cd lcd && $(MAKE)
|
||||||
|
|
||||||
|
tools/lpcrc:
|
||||||
|
cd tools && $(MAKE)
|
||||||
|
|
||||||
|
firmware: $(OBJS) $(SYS_OBJS) $(LIBS) $(LPCRC)
|
||||||
|
-@echo "MEMORY" > $(LD_TEMP)
|
||||||
|
-@echo "{" >> $(LD_TEMP)
|
||||||
|
-@echo " flash(rx): ORIGIN = 0x00000000, LENGTH = $(FLASH)" >> $(LD_TEMP)
|
||||||
|
-@echo " sram(rwx): ORIGIN = 0x10000000+$(SRAM_USB), LENGTH = $(SRAM)-$(SRAM_USB)" >> $(LD_TEMP)
|
||||||
|
-@echo "}" >> $(LD_TEMP)
|
||||||
|
-@echo "INCLUDE $(LD_SCRIPT)" >> $(LD_TEMP)
|
||||||
|
$(LD) $(LDFLAGS) -T $(LD_TEMP) -o $(OUTFILE).elf $(OBJS) $(LDLIBS)
|
||||||
|
-@echo ""
|
||||||
|
$(SIZE) $(OUTFILE).elf
|
||||||
|
-@echo ""
|
||||||
|
$(OBJCOPY) $(OCFLAGS) -O binary $(OUTFILE).elf $(OUTFILE).bin
|
||||||
|
-@echo ""
|
||||||
|
$(LPCRC) $(OUTFILE).bin
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJS) $(LD_TEMP) $(OUTFILE).elf $(OUTFILE).bin $(OUTFILE).hex
|
||||||
|
@cd core && $(MAKE) clean
|
||||||
|
@cd tools && $(MAKE) clean
|
||||||
|
@cd lcd && $(MAKE) clean
|
|
@ -0,0 +1,85 @@
|
||||||
|
##########################################################################
|
||||||
|
# User configuration and firmware specific object files
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
# The target, flash and ram of the LPC1xxx microprocessor.
|
||||||
|
# Use for the target the value: LPC11xx, LPC13xx or LPC17xx
|
||||||
|
TARGET = LPC13xx
|
||||||
|
|
||||||
|
OBJS = sysinit.o
|
||||||
|
OBJS += adc/adc.o
|
||||||
|
#OBJS += cmd/cmd.o
|
||||||
|
OBJS += cpu/cpu.o
|
||||||
|
OBJS += gpio/gpio.o
|
||||||
|
OBJS += i2c/i2c.o
|
||||||
|
OBJS += iap/iap.o
|
||||||
|
OBJS += libc/ctype.o
|
||||||
|
OBJS += libc/stdio.o
|
||||||
|
OBJS += libc/string.o
|
||||||
|
OBJS += pmu/pmu.o
|
||||||
|
#OBJS += pwm/pwm.o
|
||||||
|
OBJS += ssp/ssp.o
|
||||||
|
OBJS += systick/systick.o
|
||||||
|
OBJS += timer16/timer16.o
|
||||||
|
OBJS += timer32/timer32.o
|
||||||
|
#OBJS += uart/uart.o
|
||||||
|
#OBJS += uart/uart_buf.o
|
||||||
|
#OBJS += usbcdc/cdcuser.o
|
||||||
|
#OBJS += usbcdc/cdc_buf.o
|
||||||
|
#OBJS += usbcdc/usbcore.o
|
||||||
|
#OBJS += usbcdc/usbdesc.o
|
||||||
|
#OBJS += usbcdc/usbhw.o
|
||||||
|
#OBJS += usbcdc/usbuser.o
|
||||||
|
#OBJS += usbhid-rom/usbconfig.o
|
||||||
|
#OBJS += usbhid-rom/usbhid.o
|
||||||
|
OBJS += wdt/wdt.o
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# GNU GCC compiler prefix and location
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
CROSS_COMPILE = arm-none-eabi-
|
||||||
|
AS = $(CROSS_COMPILE)gcc
|
||||||
|
CC = $(CROSS_COMPILE)gcc
|
||||||
|
LD = $(CROSS_COMPILE)gcc
|
||||||
|
AR = $(CROSS_COMPILE)ar
|
||||||
|
SIZE = $(CROSS_COMPILE)size
|
||||||
|
OBJCOPY = $(CROSS_COMPILE)objcopy
|
||||||
|
OBJDUMP = $(CROSS_COMPILE)objdump
|
||||||
|
OUTFILE = firmware
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# GNU GCC compiler flags
|
||||||
|
##########################################################################
|
||||||
|
ROOT_PATH = .
|
||||||
|
INCLUDE_PATHS = -I$(ROOT_PATH) -I..
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# Startup files
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
ifeq (LPC11xx,$(TARGET))
|
||||||
|
CORTEX_TYPE=m0
|
||||||
|
else
|
||||||
|
CORTEX_TYPE=m3
|
||||||
|
endif
|
||||||
|
|
||||||
|
CPU_TYPE = cortex-$(CORTEX_TYPE)
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# Compiler settings, parameters and flags
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
CFLAGS = -c -g -Os $(INCLUDE_PATHS) -Wall -mthumb -ffunction-sections -fdata-sections -fmessage-length=0 -mcpu=$(CPU_TYPE) -DTARGET=$(TARGET) -fno-builtin
|
||||||
|
LDFLAGS = -nostartfiles -mthumb -mcpu=$(CPU_TYPE) -Wl,--gc-sections
|
||||||
|
|
||||||
|
all: libcore.a
|
||||||
|
|
||||||
|
libcore.a: $(OBJS)
|
||||||
|
$(AR) rcs libcore.a $(OBJS)
|
||||||
|
|
||||||
|
%.o : %.c projectconfig.h
|
||||||
|
$(CC) $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJS) libcore.a
|
|
@ -0,0 +1,228 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file adc.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section Description
|
||||||
|
|
||||||
|
SW-based single-channel A/D conversion. If you wish to convert
|
||||||
|
multiple ADC channels simultaneously, this code will need to be
|
||||||
|
modified to work in BURST mode.
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
#include "core/cpu/cpu.h"
|
||||||
|
#include "core/adc/adc.h"
|
||||||
|
|
||||||
|
void main (void)
|
||||||
|
{
|
||||||
|
cpuInit();
|
||||||
|
adcInit();
|
||||||
|
|
||||||
|
uint32_t results = 0;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Get A/D conversion results from A/D channel 0
|
||||||
|
results = adcRead(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "adc.h"
|
||||||
|
|
||||||
|
static bool _adcInitialised = false;
|
||||||
|
static uint8_t _adcLastChannel = 0;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Returns the conversion results on the specified ADC channel.
|
||||||
|
|
||||||
|
This function will manually start an A/D conversion on a single
|
||||||
|
channel and return the results.
|
||||||
|
|
||||||
|
@param[in] channelNum
|
||||||
|
The A/D channel [0..7] that will be used during the A/D
|
||||||
|
conversion. (Note that only A/D channel's 0..3 are
|
||||||
|
configured by default in adcInit.)
|
||||||
|
|
||||||
|
@return 0 if an overrun error occured, otherwise a 10-bit value
|
||||||
|
containing the A/D conversion results.
|
||||||
|
@warning Only AD channels 0..3 are configured for A/D in adcInit.
|
||||||
|
If you wish to use A/D pins 4..7 they will also need to
|
||||||
|
be added to the adcInit function.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
uint32_t adcRead (uint8_t channelNum)
|
||||||
|
{
|
||||||
|
if (!_adcInitialised) adcInit();
|
||||||
|
|
||||||
|
uint32_t regVal, adcData;
|
||||||
|
|
||||||
|
/* make sure that channel number is 0..7 */
|
||||||
|
if ( channelNum >= 8 )
|
||||||
|
{
|
||||||
|
// ToDo: Change this to throw an exception back
|
||||||
|
channelNum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Deselect all channels */
|
||||||
|
ADC_AD0CR &= ~ADC_AD0CR_SEL_MASK;
|
||||||
|
|
||||||
|
/* Start converting now on the appropriate channel */
|
||||||
|
ADC_AD0CR |= ADC_AD0CR_START_STARTNOW | (1 << channelNum);
|
||||||
|
|
||||||
|
/* wait until end of A/D convert */
|
||||||
|
while ( 1 )
|
||||||
|
{
|
||||||
|
// Get data register results for the requested channel
|
||||||
|
switch (channelNum)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
regVal = (*(pREG32(ADC_AD0DR0)));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
regVal = (*(pREG32(ADC_AD0DR1)));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
regVal = (*(pREG32(ADC_AD0DR2)));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
regVal = (*(pREG32(ADC_AD0DR3)));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
regVal = (*(pREG32(ADC_AD0DR4)));
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
regVal = (*(pREG32(ADC_AD0DR5)));
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
regVal = (*(pREG32(ADC_AD0DR6)));
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
regVal = (*(pREG32(ADC_AD0DR7)));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
regVal = (*(pREG32(ADC_AD0DR0)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read result of A/D conversion */
|
||||||
|
if (regVal & ADC_DR_DONE)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stop ADC */
|
||||||
|
ADC_AD0CR &= ~ADC_AD0CR_START_MASK;
|
||||||
|
|
||||||
|
/* return 0 if an overrun occurred */
|
||||||
|
if ( regVal & ADC_DR_OVERRUN )
|
||||||
|
{
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return conversion results */
|
||||||
|
adcData = (regVal >> 6) & 0x3FF;
|
||||||
|
return (adcData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Initialises the A/D converter and configures channels 0..3
|
||||||
|
for 10-bit, SW-controlled A/D conversion.
|
||||||
|
|
||||||
|
@return Nothing
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void adcInit (void)
|
||||||
|
{
|
||||||
|
/* Disable Power down bit to the ADC block. */
|
||||||
|
SCB_PDRUNCFG &= ~(SCB_PDRUNCFG_ADC);
|
||||||
|
|
||||||
|
/* Enable AHB clock to the ADC. */
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_ADC);
|
||||||
|
|
||||||
|
/* Digital pins need to have the 'analog' bit set in addition
|
||||||
|
to changing their pin function */
|
||||||
|
|
||||||
|
/* Set AD0 to analog input */
|
||||||
|
IOCON_JTAG_TDI_PIO0_11 &= ~(IOCON_JTAG_TDI_PIO0_11_ADMODE_MASK |
|
||||||
|
IOCON_JTAG_TDI_PIO0_11_FUNC_MASK |
|
||||||
|
IOCON_JTAG_TDI_PIO0_11_MODE_MASK);
|
||||||
|
IOCON_JTAG_TDI_PIO0_11 |= (IOCON_JTAG_TDI_PIO0_11_FUNC_AD0 &
|
||||||
|
IOCON_JTAG_TDI_PIO0_11_ADMODE_ANALOG);
|
||||||
|
|
||||||
|
/* Set AD1 to analog input */
|
||||||
|
IOCON_JTAG_TMS_PIO1_0 &= ~(IOCON_JTAG_TMS_PIO1_0_ADMODE_MASK |
|
||||||
|
IOCON_JTAG_TMS_PIO1_0_FUNC_MASK |
|
||||||
|
IOCON_JTAG_TMS_PIO1_0_MODE_MASK);
|
||||||
|
IOCON_JTAG_TMS_PIO1_0 |= (IOCON_JTAG_TMS_PIO1_0_FUNC_AD1 &
|
||||||
|
IOCON_JTAG_TMS_PIO1_0_ADMODE_ANALOG);
|
||||||
|
|
||||||
|
/* Set AD2 to analog input */
|
||||||
|
IOCON_JTAG_TDO_PIO1_1 &= ~(IOCON_JTAG_TDO_PIO1_1_ADMODE_MASK |
|
||||||
|
IOCON_JTAG_TDO_PIO1_1_FUNC_MASK |
|
||||||
|
IOCON_JTAG_TDO_PIO1_1_MODE_MASK);
|
||||||
|
IOCON_JTAG_TDO_PIO1_1 |= (IOCON_JTAG_TDO_PIO1_1_FUNC_AD2 &
|
||||||
|
IOCON_JTAG_TDO_PIO1_1_ADMODE_ANALOG);
|
||||||
|
|
||||||
|
/* Set AD3 to analog input */
|
||||||
|
IOCON_JTAG_nTRST_PIO1_2 &= ~(IOCON_JTAG_nTRST_PIO1_2_ADMODE_MASK |
|
||||||
|
IOCON_JTAG_nTRST_PIO1_2_FUNC_MASK |
|
||||||
|
IOCON_JTAG_nTRST_PIO1_2_MODE_MASK);
|
||||||
|
IOCON_JTAG_nTRST_PIO1_2 |= (IOCON_JTAG_nTRST_PIO1_2_FUNC_AD3 &
|
||||||
|
IOCON_JTAG_nTRST_PIO1_2_ADMODE_ANALOG);
|
||||||
|
|
||||||
|
/* Note that in SW mode only one channel can be selected at a time (AD0 in this case)
|
||||||
|
To select multiple channels, ADC_AD0CR_BURST_HWSCANMODE must be used */
|
||||||
|
ADC_AD0CR = (ADC_AD0CR_SEL_AD0 | /* SEL=1,select channel 0 on ADC0 */
|
||||||
|
(((CFG_CPU_CCLK / SCB_SYSAHBCLKDIV) / 1000000 - 1 ) << 8) | /* CLKDIV = Fpclk / 1000000 - 1 */
|
||||||
|
ADC_AD0CR_BURST_SWMODE | /* BURST = 0, no BURST, software controlled */
|
||||||
|
ADC_AD0CR_CLKS_10BITS | /* CLKS = 0, 11 clocks/10 bits */
|
||||||
|
ADC_AD0CR_START_NOSTART | /* START = 0 A/D conversion stops */
|
||||||
|
ADC_AD0CR_EDGE_RISING); /* EDGE = 0 (CAP/MAT signal falling, trigger A/D conversion) */
|
||||||
|
|
||||||
|
/* Set initialisation flag */
|
||||||
|
_adcInitialised = true;
|
||||||
|
|
||||||
|
/* Set last channel flag to 0 (initialised above) */
|
||||||
|
_adcLastChannel = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file adc.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _ADC_H_
|
||||||
|
#define _ADC_H_
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
uint32_t adcRead (uint8_t channelNum);
|
||||||
|
void adcInit (void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,296 @@
|
||||||
|
/*******************************************************************
|
||||||
|
Copyright (C) 2009 FreakLabs
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS 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.
|
||||||
|
|
||||||
|
Originally written by Christopher Wang aka Akiba.
|
||||||
|
Please post support questions to the FreakLabs forum.
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file cmd.c
|
||||||
|
@author Christopher Wang (Freaklabs)
|
||||||
|
Modified by: K. Townsend (microBuilder.eu)
|
||||||
|
@date 19 May 2010
|
||||||
|
|
||||||
|
Original code taken from the FreakUSB Open Source USB Device Stack
|
||||||
|
http://freaklabs.org/index.php/FreakUSB-Open-Source-USB-Device-Stack.html
|
||||||
|
|
||||||
|
If it works well, you can thank Akiba at Freaklabs. If it fails
|
||||||
|
miserably, you can blame me (since parts of it it were rather
|
||||||
|
ungraciously modified). :-)
|
||||||
|
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cmd.h"
|
||||||
|
#include "project/cmd_tbl.h"
|
||||||
|
|
||||||
|
#ifdef CFG_PRINTF_UART
|
||||||
|
#include "core/uart/uart.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CFG_PRINTF_USBCDC
|
||||||
|
#include "core/usbcdc/cdcuser.h"
|
||||||
|
static char usbcdcBuf [32];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_INTERFACE_ENABLEIRQ == 1
|
||||||
|
#include "core/gpio/gpio.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static uint8_t msg[CFG_INTERFACE_MAXMSGSIZE];
|
||||||
|
static uint8_t *msg_ptr;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Polls the relevant incoming message queue to see if anything
|
||||||
|
is waiting to be processed.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void cmdPoll()
|
||||||
|
{
|
||||||
|
#if defined CFG_PRINTF_UART
|
||||||
|
while (uartRxBufferDataPending())
|
||||||
|
{
|
||||||
|
uint8_t c = uartRxBufferRead();
|
||||||
|
cmdRx(c);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined CFG_PRINTF_USBCDC
|
||||||
|
int numBytesToRead, numBytesRead, numAvailByte;
|
||||||
|
|
||||||
|
CDC_OutBufAvailChar (&numAvailByte);
|
||||||
|
if (numAvailByte > 0)
|
||||||
|
{
|
||||||
|
numBytesToRead = numAvailByte > 32 ? 32 : numAvailByte;
|
||||||
|
numBytesRead = CDC_RdOutBuf (&usbcdcBuf[0], &numBytesToRead);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < numBytesRead; i++)
|
||||||
|
{
|
||||||
|
cmdRx(usbcdcBuf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Handles a single incoming character. If a new line is
|
||||||
|
detected, the entire command will be passed to the command
|
||||||
|
parser. If a text character is detected, it will be added to
|
||||||
|
the message buffer until a new line is detected (up to the
|
||||||
|
maximum queue size, CFG_INTERFACE_MAXMSGSIZE).
|
||||||
|
|
||||||
|
@param[in] c
|
||||||
|
The character to parse.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void cmdRx(uint8_t c)
|
||||||
|
{
|
||||||
|
// read out the data in the buffer and echo it back to the host.
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '\r':
|
||||||
|
case '\n':
|
||||||
|
// terminate the msg and reset the msg ptr. then send
|
||||||
|
// it to the handler for processing.
|
||||||
|
*msg_ptr = '\0';
|
||||||
|
#if CFG_INTERFACE_SILENTMODE == 0
|
||||||
|
printf("%s", CFG_PRINTF_NEWLINE);
|
||||||
|
#endif
|
||||||
|
cmdParse((char *)msg);
|
||||||
|
msg_ptr = msg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\b':
|
||||||
|
#if CFG_INTERFACE_SILENTMODE == 0
|
||||||
|
printf("%c",c);
|
||||||
|
#endif
|
||||||
|
if (msg_ptr > msg)
|
||||||
|
{
|
||||||
|
msg_ptr--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
#if CFG_INTERFACE_SILENTMODE == 0
|
||||||
|
printf("%c",c);
|
||||||
|
#endif
|
||||||
|
*msg_ptr++ = c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Displays the command prompt. The text that appears is defined
|
||||||
|
in projectconfig.h.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
static void cmdMenu()
|
||||||
|
{
|
||||||
|
#if CFG_INTERFACE_SILENTMODE == 0
|
||||||
|
printf(CFG_PRINTF_NEWLINE);
|
||||||
|
printf(CFG_INTERFACE_PROMPT);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Parse the command line. This function tokenizes the command
|
||||||
|
input, then searches for the command table entry associated
|
||||||
|
with the commmand. Once found, it will jump to the
|
||||||
|
corresponding function.
|
||||||
|
|
||||||
|
@param[in] cmd
|
||||||
|
The entire command string to be parsed
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void cmdParse(char *cmd)
|
||||||
|
{
|
||||||
|
size_t argc, i = 0;
|
||||||
|
char *argv[30];
|
||||||
|
|
||||||
|
argv[i] = strtok(cmd, " ");
|
||||||
|
do
|
||||||
|
{
|
||||||
|
argv[++i] = strtok(NULL, " ");
|
||||||
|
} while ((i < 30) && (argv[i] != NULL));
|
||||||
|
|
||||||
|
argc = i;
|
||||||
|
for (i=0; i < CMD_COUNT; i++)
|
||||||
|
{
|
||||||
|
if (!strcmp(argv[0], cmd_tbl[i].command))
|
||||||
|
{
|
||||||
|
if ((argc == 2) && !strcmp (argv [1], "?"))
|
||||||
|
{
|
||||||
|
// Display parameter help menu on 'command ?'
|
||||||
|
printf ("%s%s%s", cmd_tbl[i].description, CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE);
|
||||||
|
printf ("%s%s", cmd_tbl[i].parameters, CFG_PRINTF_NEWLINE);
|
||||||
|
}
|
||||||
|
else if ((argc - 1) < cmd_tbl[i].minArgs)
|
||||||
|
{
|
||||||
|
// Too few arguments supplied
|
||||||
|
printf ("Too few arguments (%d expected)%s", cmd_tbl[i].minArgs, CFG_PRINTF_NEWLINE);
|
||||||
|
printf ("%sType '%s ?' for more information%s%s", CFG_PRINTF_NEWLINE, cmd_tbl[i].command, CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE);
|
||||||
|
}
|
||||||
|
else if ((argc - 1) > cmd_tbl[i].maxArgs)
|
||||||
|
{
|
||||||
|
// Too many arguments supplied
|
||||||
|
printf ("Too many arguments (%d maximum)%s", cmd_tbl[i].maxArgs, CFG_PRINTF_NEWLINE);
|
||||||
|
printf ("%sType '%s ?' for more information%s%s", CFG_PRINTF_NEWLINE, cmd_tbl[i].command, CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if CFG_INTERFACE_ENABLEIRQ != 0
|
||||||
|
// Set the IRQ pin high at start of a command
|
||||||
|
gpioSetValue(CFG_INTERFACE_IRQPORT, CFG_INTERFACE_IRQPIN, 1);
|
||||||
|
#endif
|
||||||
|
// Dispatch command to the appropriate function
|
||||||
|
cmd_tbl[i].func(argc - 1, &argv [1]);
|
||||||
|
#if CFG_INTERFACE_ENABLEIRQ != 0
|
||||||
|
// Set the IRQ pin low to signal the end of a command
|
||||||
|
gpioSetValue(CFG_INTERFACE_IRQPORT, CFG_INTERFACE_IRQPIN, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh the command prompt
|
||||||
|
cmdMenu();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Command not recognized: '%s'%s%s", cmd, CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE);
|
||||||
|
#if CFG_INTERFACE_SILENTMODE == 0
|
||||||
|
printf("Type '?' for a list of all available commands%s", CFG_PRINTF_NEWLINE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cmdMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Initialises the command line using the appropriate interface
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void cmdInit()
|
||||||
|
{
|
||||||
|
#if defined CFG_INTERFACE && defined CFG_INTERFACE_UART
|
||||||
|
// Check if UART is already initialised
|
||||||
|
uart_pcb_t *pcb = uartGetPCB();
|
||||||
|
if (!pcb->initialised)
|
||||||
|
{
|
||||||
|
uartInit(CFG_UART_BAUDRATE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CFG_INTERFACE_ENABLEIRQ != 0
|
||||||
|
// Set IRQ pin as output
|
||||||
|
gpioSetDir(CFG_INTERFACE_IRQPORT, CFG_INTERFACE_IRQPIN, gpioDirection_Output);
|
||||||
|
gpioSetValue(CFG_INTERFACE_IRQPORT, CFG_INTERFACE_IRQPIN, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// init the msg ptr
|
||||||
|
msg_ptr = msg;
|
||||||
|
|
||||||
|
// Show the menu
|
||||||
|
cmdMenu();
|
||||||
|
|
||||||
|
// Set the IRQ pin low by default
|
||||||
|
#if CFG_INTERFACE_ENABLEIRQ != 0
|
||||||
|
gpioSetValue(CFG_INTERFACE_IRQPORT, CFG_INTERFACE_IRQPIN, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
'help' command handler
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void cmd_help(uint8_t argc, char **argv)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
printf("Command Description%s", CFG_PRINTF_NEWLINE);
|
||||||
|
printf("------- -----------%s", CFG_PRINTF_NEWLINE);
|
||||||
|
|
||||||
|
// Display full command list
|
||||||
|
for (i=0; i < CMD_COUNT; i++)
|
||||||
|
{
|
||||||
|
if (!cmd_tbl[i].hidden)
|
||||||
|
{
|
||||||
|
printf ("%-10s %s%s", cmd_tbl[i].command, cmd_tbl[i].description, CFG_PRINTF_NEWLINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%sCommand parameters can be seen by entering: <command-name> ?%s", CFG_PRINTF_NEWLINE, CFG_PRINTF_NEWLINE);
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file cmd.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __CMD_H__
|
||||||
|
#define __CMD_H__
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *command;
|
||||||
|
uint8_t minArgs;
|
||||||
|
uint8_t maxArgs;
|
||||||
|
uint8_t hidden;
|
||||||
|
void (*func)(uint8_t argc, char **argv);
|
||||||
|
const char *description;
|
||||||
|
const char *parameters;
|
||||||
|
} cmd_t;
|
||||||
|
|
||||||
|
void cmdPoll();
|
||||||
|
void cmdRx(uint8_t c);
|
||||||
|
void cmdParse(char *cmd);
|
||||||
|
void cmdInit();
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,169 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file cpu.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section DESCRIPTION
|
||||||
|
|
||||||
|
Initialises the CPU and any core clocks. By default, the core clock
|
||||||
|
is set to run at 72MHz. In order to reduce power consumption all pins
|
||||||
|
are set to GPIO and input by cpuInit.
|
||||||
|
|
||||||
|
@section EXAMPLE
|
||||||
|
@code
|
||||||
|
#include "lpc134x.h"
|
||||||
|
#include "core/cpu/cpu.h"
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
// Initialise the CPU and setup the PLL
|
||||||
|
cpuInit();
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "cpu.h"
|
||||||
|
#include "core/gpio/gpio.h"
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Configures the main clock/PLL
|
||||||
|
|
||||||
|
The speed at which the MCU operates is set here using the SCB_PLLCTRL
|
||||||
|
register, and the SCB_PLLCLKSEL register can be used to select which
|
||||||
|
oscillator to use to generate the system clocks (the internal 12MHz
|
||||||
|
oscillator or an external crystal).
|
||||||
|
|
||||||
|
@param[in] multiplier
|
||||||
|
The PLL multiplier
|
||||||
|
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void cpuPllSetup (cpuMultiplier_t multiplier)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
// Power up system oscillator
|
||||||
|
SCB_PDRUNCFG &= ~(SCB_PDRUNCFG_SYSOSC_MASK);
|
||||||
|
|
||||||
|
// Setup the crystal input (bypass disabled, 1-20MHz crystal)
|
||||||
|
SCB_SYSOSCCTRL = (SCB_SYSOSCCTRL_BYPASS_DISABLED | SCB_SYSOSCCTRL_FREQRANGE_1TO20MHZ);
|
||||||
|
|
||||||
|
for (i = 0; i < 200; i++)
|
||||||
|
{
|
||||||
|
__asm volatile ("NOP");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure PLL
|
||||||
|
SCB_PLLCLKSEL = SCB_CLKSEL_SOURCE_MAINOSC; // Select external crystal as PLL clock source
|
||||||
|
SCB_PLLCLKUEN = SCB_PLLCLKUEN_UPDATE; // Update clock source
|
||||||
|
SCB_PLLCLKUEN = SCB_PLLCLKUEN_DISABLE; // Toggle update register once
|
||||||
|
SCB_PLLCLKUEN = SCB_PLLCLKUEN_UPDATE; // Update clock source again
|
||||||
|
|
||||||
|
// Wait until the clock is updated
|
||||||
|
while (!(SCB_PLLCLKUEN & SCB_PLLCLKUEN_UPDATE));
|
||||||
|
|
||||||
|
// Set clock speed
|
||||||
|
switch (multiplier)
|
||||||
|
{
|
||||||
|
case CPU_MULTIPLIER_2:
|
||||||
|
SCB_PLLCTRL = (SCB_PLLCTRL_MULT_2 | (1 << SCB_PLLCTRL_DIV_BIT));
|
||||||
|
break;
|
||||||
|
case CPU_MULTIPLIER_3:
|
||||||
|
SCB_PLLCTRL = (SCB_PLLCTRL_MULT_3 | (1 << SCB_PLLCTRL_DIV_BIT));
|
||||||
|
break;
|
||||||
|
case CPU_MULTIPLIER_4:
|
||||||
|
SCB_PLLCTRL = (SCB_PLLCTRL_MULT_4 | (1 << SCB_PLLCTRL_DIV_BIT));
|
||||||
|
break;
|
||||||
|
case CPU_MULTIPLIER_5:
|
||||||
|
SCB_PLLCTRL = (SCB_PLLCTRL_MULT_5 | (1 << SCB_PLLCTRL_DIV_BIT));
|
||||||
|
break;
|
||||||
|
case CPU_MULTIPLIER_6:
|
||||||
|
SCB_PLLCTRL = (SCB_PLLCTRL_MULT_6 | (1 << SCB_PLLCTRL_DIV_BIT));
|
||||||
|
break;
|
||||||
|
case CPU_MULTIPLIER_1:
|
||||||
|
default:
|
||||||
|
SCB_PLLCTRL = (SCB_PLLCTRL_MULT_1 | (1 << SCB_PLLCTRL_DIV_BIT));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable system PLL
|
||||||
|
SCB_PDRUNCFG &= ~(SCB_PDRUNCFG_SYSPLL_MASK);
|
||||||
|
|
||||||
|
// Wait for PLL to lock
|
||||||
|
while (!(SCB_PLLSTAT & SCB_PLLSTAT_LOCK));
|
||||||
|
|
||||||
|
// Setup main clock (use PLL output)
|
||||||
|
SCB_MAINCLKSEL = SCB_MAINCLKSEL_SOURCE_SYSPLLCLKOUT;
|
||||||
|
SCB_MAINCLKUEN = SCB_MAINCLKUEN_UPDATE; // Update clock source
|
||||||
|
SCB_MAINCLKUEN = SCB_MAINCLKUEN_DISABLE; // Toggle update register once
|
||||||
|
SCB_MAINCLKUEN = SCB_MAINCLKUEN_UPDATE;
|
||||||
|
|
||||||
|
// Wait until the clock is updated
|
||||||
|
while (!(SCB_MAINCLKUEN & SCB_MAINCLKUEN_UPDATE));
|
||||||
|
|
||||||
|
// Disable USB clock by default (enabled in USB code)
|
||||||
|
SCB_PDRUNCFG |= (SCB_PDSLEEPCFG_USBPAD_PD); // Power-down USB PHY
|
||||||
|
SCB_PDRUNCFG |= (SCB_PDSLEEPCFG_USBPLL_PD); // Power-down USB PLL
|
||||||
|
|
||||||
|
// Set system AHB clock
|
||||||
|
SCB_SYSAHBCLKDIV = SCB_SYSAHBCLKDIV_DIV1;
|
||||||
|
|
||||||
|
// Enabled IOCON clock for I/O related peripherals
|
||||||
|
SCB_SYSAHBCLKCTRL |= SCB_SYSAHBCLKCTRL_IOCON;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Initialises the CPU, setting up the PLL, etc.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void cpuInit (void)
|
||||||
|
{
|
||||||
|
gpioInit();
|
||||||
|
|
||||||
|
// Set all GPIO pins to input by default
|
||||||
|
GPIO_GPIO0DIR &= ~(GPIO_IO_ALL);
|
||||||
|
GPIO_GPIO1DIR &= ~(GPIO_IO_ALL);
|
||||||
|
GPIO_GPIO2DIR &= ~(GPIO_IO_ALL);
|
||||||
|
GPIO_GPIO3DIR &= ~(GPIO_IO_ALL);
|
||||||
|
|
||||||
|
// Setup PLL (etc.)
|
||||||
|
cpuPllSetup(CPU_MULTIPLIER_6);
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file cpu.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _CPU_H_
|
||||||
|
#define _CPU_H_
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
// Macro to initialise, reset and enable the cycle counter.
|
||||||
|
// This can be used for rough timing and performance tests
|
||||||
|
// by resetting the cycle counter before a function, and
|
||||||
|
// then reading the value after with "int count = DWT_CYCCNT"
|
||||||
|
//
|
||||||
|
// CPU_RESET_CYCLECOUNTER;
|
||||||
|
// ... do something
|
||||||
|
// int count = DWT_CYCCNT;
|
||||||
|
//
|
||||||
|
#define CPU_RESET_CYCLECOUNTER do { SCB_DEMCR = SCB_DEMCR | 0x01000000; \
|
||||||
|
DWT_CYCCNT = 0; \
|
||||||
|
DWT_CTRL = DWT_CTRL | 1 ; } while(0)
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Indicates the value for the PLL multiplier
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CPU_MULTIPLIER_1 = 0,
|
||||||
|
CPU_MULTIPLIER_2,
|
||||||
|
CPU_MULTIPLIER_3,
|
||||||
|
CPU_MULTIPLIER_4,
|
||||||
|
CPU_MULTIPLIER_5,
|
||||||
|
CPU_MULTIPLIER_6
|
||||||
|
}
|
||||||
|
cpuMultiplier_t;
|
||||||
|
|
||||||
|
void cpuPllSetup (cpuMultiplier_t multiplier);
|
||||||
|
void cpuInit (void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,550 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file gpio.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section DESCRIPTION
|
||||||
|
|
||||||
|
Controls the general purpose digital IO.
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "gpio.h"
|
||||||
|
|
||||||
|
#ifdef CFG_CHIBI
|
||||||
|
#include "drivers/chibi/chb_drvr.h"
|
||||||
|
volatile uint32_t chibi_counter = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool _gpioInitialised = false;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief IRQ Handler for GPIO port 0 (currently checks pin 0.1)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void PIOINT0_IRQHandler(void)
|
||||||
|
{
|
||||||
|
uint32_t regVal;
|
||||||
|
|
||||||
|
regVal = gpioIntStatus(0, 1);
|
||||||
|
if (regVal)
|
||||||
|
{
|
||||||
|
gpioIntClear(0, 1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief IRQ Handler for GPIO port 1 (currently checks pin 1.1)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void PIOINT1_IRQHandler(void)
|
||||||
|
{
|
||||||
|
uint32_t regVal;
|
||||||
|
|
||||||
|
#ifdef CFG_CHIBI
|
||||||
|
// Check for interrupt on 1.8
|
||||||
|
regVal = gpioIntStatus(1, 8);
|
||||||
|
if (regVal)
|
||||||
|
{
|
||||||
|
chibi_counter++;
|
||||||
|
chb_ISR_Handler();
|
||||||
|
gpioIntClear(1, 8);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
regVal = gpioIntStatus(1, 1);
|
||||||
|
if ( regVal )
|
||||||
|
{
|
||||||
|
gpioIntClear(1, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief IRQ Handler for GPIO port 2 (currently checks pin 2.1)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void PIOINT2_IRQHandler(void)
|
||||||
|
{
|
||||||
|
uint32_t regVal;
|
||||||
|
|
||||||
|
regVal = gpioIntStatus(2, 1);
|
||||||
|
if ( regVal )
|
||||||
|
{
|
||||||
|
gpioIntClear(2, 1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief IRQ Handler for GPIO port 3 (currently checks pin 3.1)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void PIOINT3_IRQHandler(void)
|
||||||
|
{
|
||||||
|
uint32_t regVal;
|
||||||
|
|
||||||
|
regVal = gpioIntStatus(3, 1);
|
||||||
|
if ( regVal )
|
||||||
|
{
|
||||||
|
gpioIntClear(3, 1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Initialises GPIO and enables the GPIO interrupt
|
||||||
|
handler for all GPIO ports.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void gpioInit (void)
|
||||||
|
{
|
||||||
|
/* Enable AHB clock to the GPIO domain. */
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_GPIO);
|
||||||
|
|
||||||
|
/* Set up NVIC when I/O pins are configured as external interrupts. */
|
||||||
|
NVIC_EnableIRQ(EINT0_IRQn);
|
||||||
|
NVIC_EnableIRQ(EINT1_IRQn);
|
||||||
|
NVIC_EnableIRQ(EINT2_IRQn);
|
||||||
|
NVIC_EnableIRQ(EINT3_IRQn);
|
||||||
|
|
||||||
|
/* Set initialisation flag */
|
||||||
|
_gpioInitialised = true;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Sets the direction (input/output) for a specific port pin
|
||||||
|
|
||||||
|
@param[in] portNum
|
||||||
|
The port number (0..3)
|
||||||
|
@param[in] bitPos
|
||||||
|
The bit position (0..11)
|
||||||
|
@param[in] dir
|
||||||
|
The pin direction (gpioDirection_Input or
|
||||||
|
gpioDirection_Output)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void gpioSetDir (uint32_t portNum, uint32_t bitPos, gpioDirection_t dir)
|
||||||
|
{
|
||||||
|
if (!_gpioInitialised) gpioInit();
|
||||||
|
|
||||||
|
// Get the appropriate register (handled this way to optimise code size)
|
||||||
|
REG32 *gpiodir = &GPIO_GPIO0DIR;
|
||||||
|
switch (portNum)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
gpiodir = &GPIO_GPIO0DIR;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
gpiodir = &GPIO_GPIO1DIR;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
gpiodir = &GPIO_GPIO2DIR;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
gpiodir = &GPIO_GPIO3DIR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle dir
|
||||||
|
dir == gpioDirection_Output ? (*gpiodir |= (1 << bitPos)) : (*gpiodir &= ~(1 << bitPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Gets the value for a specific port pin
|
||||||
|
|
||||||
|
@param[in] portNum
|
||||||
|
The port number (0..3)
|
||||||
|
@param[in] bitPos
|
||||||
|
The bit position (0..31)
|
||||||
|
|
||||||
|
@return The current value for the specified port pin (0..1)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
uint32_t gpioGetValue (uint32_t portNum, uint32_t bitPos)
|
||||||
|
{
|
||||||
|
if (!_gpioInitialised) gpioInit();
|
||||||
|
|
||||||
|
uint32_t value = 0;
|
||||||
|
|
||||||
|
switch (portNum)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
value = (GPIO_GPIO0DATA & (1 << bitPos)) ? 1 : 0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
value = (GPIO_GPIO1DATA & (1 << bitPos)) ? 1 : 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value = (GPIO_GPIO2DATA & (1 << bitPos)) ? 1 : 0;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
value = (GPIO_GPIO3DATA & (1 << bitPos)) ? 1 : 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Sets the value for a specific port pin (only relevant when a
|
||||||
|
pin is configured as output).
|
||||||
|
|
||||||
|
@param[in] portNum
|
||||||
|
The port number (0..3)
|
||||||
|
@param[in] bitPos
|
||||||
|
The bit position (0..31)
|
||||||
|
@param[in] bitValue
|
||||||
|
The value to set for the specified bit (0..1). 0 will set
|
||||||
|
the pin low and 1 will set the pin high.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void gpioSetValue (uint32_t portNum, uint32_t bitPos, uint32_t bitVal)
|
||||||
|
{
|
||||||
|
if (!_gpioInitialised) gpioInit();
|
||||||
|
|
||||||
|
// Get the appropriate register (handled this way to optimise code size)
|
||||||
|
REG32 *gpiodata = &GPIO_GPIO0DATA;
|
||||||
|
switch (portNum)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
gpiodata = &GPIO_GPIO0DATA;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
gpiodata = &GPIO_GPIO1DATA;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
gpiodata = &GPIO_GPIO2DATA;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
gpiodata = &GPIO_GPIO3DATA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle value
|
||||||
|
bitVal == 1 ? (*gpiodata |= (1 << bitPos)) : (*gpiodata &= ~(1 << bitPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Sets the interrupt sense, event, etc.
|
||||||
|
|
||||||
|
@param[in] portNum
|
||||||
|
The port number (0..3)
|
||||||
|
@param[in] bitPos
|
||||||
|
The bit position (0..31)
|
||||||
|
@param[in] sense
|
||||||
|
Whether the interrupt should be configured as edge or level
|
||||||
|
sensitive.
|
||||||
|
@param[in] edge
|
||||||
|
Whether one edge or both trigger an interrupt.
|
||||||
|
@param[in] event
|
||||||
|
Whether the rising or the falling edge (high or low)
|
||||||
|
should be used to trigger the interrupt.
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
// Initialise gpio
|
||||||
|
gpioInit();
|
||||||
|
// Set GPIO1.8 to input
|
||||||
|
gpioSetDir(1, 8, gpioDirection_Input);
|
||||||
|
// Disable the internal pullup/down resistor on P1.8
|
||||||
|
gpioSetPullup (&IOCON_PIO1_8, gpioPullupMode_Inactive);
|
||||||
|
// Setup an interrupt on GPIO1.8
|
||||||
|
gpioSetInterrupt(1, // Port
|
||||||
|
8, // Pin
|
||||||
|
gpioInterruptSense_Edge, // Edge/Level Sensitive
|
||||||
|
gpioInterruptEdge_Single, // Single/Double Edge
|
||||||
|
gpioInterruptEvent_ActiveHigh); // Rising/Falling
|
||||||
|
// Enable the interrupt
|
||||||
|
gpioIntEnable(1, 8);
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void gpioSetInterrupt (uint32_t portNum, uint32_t bitPos, gpioInterruptSense_t sense, gpioInterruptEdge_t edge, gpioInterruptEvent_t event)
|
||||||
|
{
|
||||||
|
if (!_gpioInitialised) gpioInit();
|
||||||
|
|
||||||
|
// Get the appropriate register (handled this way to optimise code size)
|
||||||
|
REG32 *gpiois = &GPIO_GPIO0IS;
|
||||||
|
REG32 *gpioibe = &GPIO_GPIO0IBE;
|
||||||
|
REG32 *gpioiev = &GPIO_GPIO0IEV;
|
||||||
|
switch (portNum)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
gpiois = &GPIO_GPIO0IS;
|
||||||
|
gpioibe = &GPIO_GPIO0IBE;
|
||||||
|
gpioiev = &GPIO_GPIO0IEV;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
gpiois = &GPIO_GPIO1IS;
|
||||||
|
gpioibe = &GPIO_GPIO1IBE;
|
||||||
|
gpioiev = &GPIO_GPIO1IEV;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
gpiois = &GPIO_GPIO2IS;
|
||||||
|
gpioibe = &GPIO_GPIO2IBE;
|
||||||
|
gpioiev = &GPIO_GPIO2IEV;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
gpiois = &GPIO_GPIO3IS;
|
||||||
|
gpioibe = &GPIO_GPIO3IBE;
|
||||||
|
gpioiev = &GPIO_GPIO3IEV;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpioInterruptSense_Edge)
|
||||||
|
{
|
||||||
|
*gpiois &= ~(0x1<<bitPos);
|
||||||
|
/* single or double only applies when sense is 0(edge trigger). */
|
||||||
|
gpioInterruptEdge_Single ? (*gpioibe &= ~(0x1<<bitPos)) : (*gpioibe |= (0x1<<bitPos));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*gpiois |= (0x1<<bitPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpioInterruptEvent_ActiveHigh ? (*gpioiev &= ~(0x1<<bitPos)) : (*gpioiev |= (0x1<<bitPos));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Enables the interrupt mask for a specific port pin
|
||||||
|
|
||||||
|
@param[in] portNum
|
||||||
|
The port number (0..3)
|
||||||
|
@param[in] bitPos
|
||||||
|
The bit position (0..31)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void gpioIntEnable (uint32_t portNum, uint32_t bitPos)
|
||||||
|
{
|
||||||
|
if (!_gpioInitialised) gpioInit();
|
||||||
|
|
||||||
|
switch (portNum)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
GPIO_GPIO0IE |= (0x1<<bitPos);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
GPIO_GPIO1IE |= (0x1<<bitPos);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
GPIO_GPIO2IE |= (0x1<<bitPos);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
GPIO_GPIO3IE |= (0x1<<bitPos);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Disables the interrupt mask for a specific port pin
|
||||||
|
|
||||||
|
@param[in] portNum
|
||||||
|
The port number (0..3)
|
||||||
|
@param[in] bitPos
|
||||||
|
The bit position (0..31)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void gpioIntDisable (uint32_t portNum, uint32_t bitPos)
|
||||||
|
{
|
||||||
|
if (!_gpioInitialised) gpioInit();
|
||||||
|
|
||||||
|
switch (portNum)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
GPIO_GPIO0IE &= ~(0x1<<bitPos);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
GPIO_GPIO1IE &= ~(0x1<<bitPos);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
GPIO_GPIO2IE &= ~(0x1<<bitPos);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
GPIO_GPIO3IE &= ~(0x1<<bitPos);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Gets the interrupt status for a specific port pin
|
||||||
|
|
||||||
|
@param[in] portNum
|
||||||
|
The port number (0..3)
|
||||||
|
@param[in] bitPos
|
||||||
|
The bit position (0..31)
|
||||||
|
|
||||||
|
@return The interrupt status for the specified port pin (0..1)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
uint32_t gpioIntStatus (uint32_t portNum, uint32_t bitPos)
|
||||||
|
{
|
||||||
|
if (!_gpioInitialised) gpioInit();
|
||||||
|
|
||||||
|
uint32_t regVal = 0;
|
||||||
|
|
||||||
|
switch (portNum)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if (GPIO_GPIO0MIS & (0x1<<bitPos))
|
||||||
|
{
|
||||||
|
regVal = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (GPIO_GPIO1MIS & (0x1<<bitPos))
|
||||||
|
{
|
||||||
|
regVal = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (GPIO_GPIO2MIS & (0x1<<bitPos))
|
||||||
|
{
|
||||||
|
regVal = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (GPIO_GPIO3MIS & (0x1<<bitPos))
|
||||||
|
{
|
||||||
|
regVal = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ( regVal );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Clears the interrupt for a port pin
|
||||||
|
|
||||||
|
@param[in] portNum
|
||||||
|
The port number (0..3)
|
||||||
|
@param[in] bitPos
|
||||||
|
The bit position (0..31)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void gpioIntClear (uint32_t portNum, uint32_t bitPos)
|
||||||
|
{
|
||||||
|
if (!_gpioInitialised) gpioInit();
|
||||||
|
|
||||||
|
switch (portNum)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
GPIO_GPIO0IC |= (0x1<<bitPos);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
GPIO_GPIO1IC |= (0x1<<bitPos);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
GPIO_GPIO2IC |= (0x1<<bitPos);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
GPIO_GPIO3IC |= (0x1<<bitPos);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Configures the internal pullup/down resistor for GPIO pins
|
||||||
|
(only relevant for pins configured as inputs)
|
||||||
|
|
||||||
|
@param[in] ioconReg
|
||||||
|
A pointer to the IOCON registry value corresponding to
|
||||||
|
the pin you wish to change (for example: &IOCON_PIO2_0
|
||||||
|
for GPIO pin 2.0).
|
||||||
|
@param[in] mode
|
||||||
|
The 'mode' that the pin should be set to, which must be
|
||||||
|
correspond to a value defined in gpioPullupMode_t
|
||||||
|
|
||||||
|
@warning By default, all GPIO pins have the internal pull-up
|
||||||
|
resistor enabled. This may cause unusual behaviour if
|
||||||
|
care isn't taken to set the internal resistor to an
|
||||||
|
appropriate state.
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
// Initialise gpio
|
||||||
|
gpioInit();
|
||||||
|
// Set GPIO1.8 to input
|
||||||
|
gpioSetDir(1, 8, gpioDirection_Input);
|
||||||
|
// Disable the internal pullup/down resistor on P1.8
|
||||||
|
gpioSetPullup(&IOCON_PIO1_8, gpioPullupMode_Inactive);
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void gpioSetPullup (volatile uint32_t *ioconReg, gpioPullupMode_t mode)
|
||||||
|
{
|
||||||
|
if (!_gpioInitialised) gpioInit();
|
||||||
|
|
||||||
|
// ToDo: Disable interrupts while we are doing this?
|
||||||
|
|
||||||
|
*ioconReg &= ~(IOCON_COMMON_MODE_MASK);
|
||||||
|
*ioconReg |= mode;
|
||||||
|
|
||||||
|
// ToDo: Re-enable interrupts?
|
||||||
|
};
|
|
@ -0,0 +1,112 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file gpio.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _GPIO_H_
|
||||||
|
#define _GPIO_H_
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Indicates whether the interrupt should be configured as edge or
|
||||||
|
level sensitive.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
typedef enum gpioInterruptSense_e
|
||||||
|
{
|
||||||
|
gpioInterruptSense_Edge = 0,
|
||||||
|
gpioInterruptSense_Level
|
||||||
|
}
|
||||||
|
gpioInterruptSense_t;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Indicates whether one edge or both edges trigger an interrupt.
|
||||||
|
Setting this to Double will cause both edges to trigger an interrupt.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
typedef enum gpioInterruptEdge_e
|
||||||
|
{
|
||||||
|
gpioInterruptEdge_Single = 0,
|
||||||
|
gpioInterruptEdge_Double
|
||||||
|
}
|
||||||
|
gpioInterruptEdge_t;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Indicates whether the interrupt should be triggered in the rising
|
||||||
|
or falling edge. ActiveHigh means that a HIGH level on the pin will
|
||||||
|
trigger an interrupt, ActiveLow means that a LOW level on the pin
|
||||||
|
will trigger an interrupt.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
typedef enum gpioInterruptEvent_e
|
||||||
|
{
|
||||||
|
gpioInterruptEvent_ActiveHigh = 0,
|
||||||
|
gpioInterruptEvent_ActiveLow
|
||||||
|
}
|
||||||
|
gpioInterruptEvent_t;
|
||||||
|
|
||||||
|
typedef enum gpioDirection_e
|
||||||
|
{
|
||||||
|
gpioDirection_Input = 0,
|
||||||
|
gpioDirection_Output
|
||||||
|
}
|
||||||
|
gpioDirection_t;
|
||||||
|
|
||||||
|
typedef enum gpioPullupMode_e
|
||||||
|
{
|
||||||
|
gpioPullupMode_Inactive = IOCON_COMMON_MODE_INACTIVE,
|
||||||
|
gpioPullupMode_PullDown = IOCON_COMMON_MODE_PULLDOWN,
|
||||||
|
gpioPullupMode_PullUp = IOCON_COMMON_MODE_PULLUP,
|
||||||
|
gpioPullupMode_Repeater = IOCON_COMMON_MODE_REPEATER
|
||||||
|
}
|
||||||
|
gpioPullupMode_t;
|
||||||
|
|
||||||
|
void gpioInit (void);
|
||||||
|
void gpioSetDir (uint32_t portNum, uint32_t bitPos, gpioDirection_t dir);
|
||||||
|
uint32_t gpioGetValue (uint32_t portNum, uint32_t bitPos);
|
||||||
|
void gpioSetValue (uint32_t portNum, uint32_t bitPos, uint32_t bitVal);
|
||||||
|
void gpioSetInterrupt (uint32_t portNum, uint32_t bitPos, gpioInterruptSense_t sense, gpioInterruptEdge_t edge, gpioInterruptEvent_t event);
|
||||||
|
void gpioIntEnable (uint32_t portNum, uint32_t bitPos);
|
||||||
|
void gpioIntDisable (uint32_t portNum, uint32_t bitPos);
|
||||||
|
uint32_t gpioIntStatus (uint32_t portNum, uint32_t bitPos);
|
||||||
|
void gpioIntClear (uint32_t portNum, uint32_t bitPos);
|
||||||
|
void gpioSetPullup (volatile uint32_t *ioconRegister, gpioPullupMode_t mode);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,353 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* i2c.c: I2C C file for NXP LPC11xx/13xx Family Microprocessors
|
||||||
|
*
|
||||||
|
* Copyright(C) 2008, NXP Semiconductor
|
||||||
|
* Parts of this code are (C) 2010, MyVoice CAD/CAM Services
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* History
|
||||||
|
* 2009.12.07 ver 1.00 Preliminary version, first Release
|
||||||
|
* 2010.07.19 ver 1.10 Rob Jansen - MyVoice CAD/CAM Services:
|
||||||
|
* Major cleaning and a rewrite of some functions
|
||||||
|
* - adding ACK/NACK handling to the state machine
|
||||||
|
* - adding a return result to the I2CEngine()
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
#include "i2c.h"
|
||||||
|
|
||||||
|
volatile uint32_t I2CMasterState = I2CSTATE_IDLE;
|
||||||
|
volatile uint32_t I2CSlaveState = I2CSTATE_IDLE;
|
||||||
|
|
||||||
|
volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
|
||||||
|
volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
|
||||||
|
volatile uint32_t I2CReadLength;
|
||||||
|
volatile uint32_t I2CWriteLength;
|
||||||
|
|
||||||
|
volatile uint32_t RdIndex = 0;
|
||||||
|
volatile uint32_t WrIndex = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** Function name: I2C_IRQHandler
|
||||||
|
**
|
||||||
|
** Descriptions: I2C interrupt handler, deal with master mode only.
|
||||||
|
**
|
||||||
|
** parameters: None
|
||||||
|
** Returned value: None
|
||||||
|
**
|
||||||
|
*****************************************************************************/
|
||||||
|
void I2C_IRQHandler(void)
|
||||||
|
{
|
||||||
|
uint8_t StatValue;
|
||||||
|
|
||||||
|
/* this handler deals with master read and master write only */
|
||||||
|
StatValue = I2C_I2CSTAT;
|
||||||
|
switch ( StatValue )
|
||||||
|
{
|
||||||
|
case 0x08:
|
||||||
|
/*
|
||||||
|
* A START condition has been transmitted.
|
||||||
|
* We now send the slave address and initialize
|
||||||
|
* the write buffer
|
||||||
|
* (we always start with a write after START+SLA)
|
||||||
|
*/
|
||||||
|
WrIndex = 0;
|
||||||
|
I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
|
||||||
|
I2C_I2CCONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
|
||||||
|
I2CMasterState = I2CSTATE_PENDING;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x10:
|
||||||
|
/*
|
||||||
|
* A repeated START condition has been transmitted.
|
||||||
|
* Now a second, read, transaction follows so we
|
||||||
|
* initialize the read buffer.
|
||||||
|
*/
|
||||||
|
RdIndex = 0;
|
||||||
|
/* Send SLA with R bit set, */
|
||||||
|
I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
|
||||||
|
I2C_I2CCONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x18:
|
||||||
|
/*
|
||||||
|
* SLA+W has been transmitted; ACK has been received.
|
||||||
|
* We now start writing bytes.
|
||||||
|
*/
|
||||||
|
I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x20:
|
||||||
|
/*
|
||||||
|
* SLA+W has been transmitted; NOT ACK has been received.
|
||||||
|
* Send a stop condition to terminate the transaction
|
||||||
|
* and signal I2CEngine the transaction is aborted.
|
||||||
|
*/
|
||||||
|
I2C_I2CCONSET = I2CONSET_STO;
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||||
|
I2CMasterState = I2CSTATE_SLA_NACK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x28:
|
||||||
|
/*
|
||||||
|
* Data in I2DAT has been transmitted; ACK has been received.
|
||||||
|
* Continue sending more bytes as long as there are bytes to send
|
||||||
|
* and after this check if a read transaction should follow.
|
||||||
|
*/
|
||||||
|
if ( WrIndex < I2CWriteLength )
|
||||||
|
{
|
||||||
|
/* Keep writing as long as bytes avail */
|
||||||
|
I2C_I2CDAT = I2CMasterBuffer[WrIndex++];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( I2CReadLength != 0 )
|
||||||
|
{
|
||||||
|
/* Send a Repeated START to initialize a read transaction */
|
||||||
|
/* (handled in state 0x10) */
|
||||||
|
I2C_I2CCONSET = I2CONSET_STA; /* Set Repeated-start flag */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
I2CMasterState = I2CSTATE_ACK;
|
||||||
|
I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x30:
|
||||||
|
/*
|
||||||
|
* Data byte in I2DAT has been transmitted; NOT ACK has been received
|
||||||
|
* Send a STOP condition to terminate the transaction and inform the
|
||||||
|
* I2CEngine that the transaction failed.
|
||||||
|
*/
|
||||||
|
I2C_I2CCONSET = I2CONSET_STO;
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||||
|
I2CMasterState = I2CSTATE_NACK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x38:
|
||||||
|
/*
|
||||||
|
* Arbitration loss in SLA+R/W or Data bytes.
|
||||||
|
* This is a fatal condition, the transaction did not complete due
|
||||||
|
* to external reasons (e.g. hardware system failure).
|
||||||
|
* Inform the I2CEngine of this and cancel the transaction
|
||||||
|
* (this is automatically done by the I2C hardware)
|
||||||
|
*/
|
||||||
|
I2CMasterState = I2CSTATE_ARB_LOSS;
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x40:
|
||||||
|
/*
|
||||||
|
* SLA+R has been transmitted; ACK has been received.
|
||||||
|
* Initialize a read.
|
||||||
|
* Since a NOT ACK is sent after reading the last byte,
|
||||||
|
* we need to prepare a NOT ACK in case we only read 1 byte.
|
||||||
|
*/
|
||||||
|
if ( I2CReadLength == 1 )
|
||||||
|
{
|
||||||
|
/* last (and only) byte: send a NACK after data is received */
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_AAC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* more bytes to follow: send an ACK after data is received */
|
||||||
|
I2C_I2CCONSET = I2CONSET_AA;
|
||||||
|
}
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x48:
|
||||||
|
/*
|
||||||
|
* SLA+R has been transmitted; NOT ACK has been received.
|
||||||
|
* Send a stop condition to terminate the transaction
|
||||||
|
* and signal I2CEngine the transaction is aborted.
|
||||||
|
*/
|
||||||
|
I2C_I2CCONSET = I2CONSET_STO;
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||||
|
I2CMasterState = I2CSTATE_SLA_NACK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x50:
|
||||||
|
/*
|
||||||
|
* Data byte has been received; ACK has been returned.
|
||||||
|
* Read the byte and check for more bytes to read.
|
||||||
|
* Send a NOT ACK after the last byte is received
|
||||||
|
*/
|
||||||
|
I2CSlaveBuffer[RdIndex++] = I2C_I2CDAT;
|
||||||
|
if ( RdIndex < (I2CReadLength-1) )
|
||||||
|
{
|
||||||
|
/* lmore bytes to follow: send an ACK after data is received */
|
||||||
|
I2C_I2CCONSET = I2CONSET_AA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* last byte: send a NACK after data is received */
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_AAC;
|
||||||
|
}
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x58:
|
||||||
|
/*
|
||||||
|
* Data byte has been received; NOT ACK has been returned.
|
||||||
|
* This is the last byte to read.
|
||||||
|
* Generate a STOP condition and flag the I2CEngine that the
|
||||||
|
* transaction is finished.
|
||||||
|
*/
|
||||||
|
I2CSlaveBuffer[RdIndex++] = I2C_I2CDAT;
|
||||||
|
I2CMasterState = I2CSTATE_ACK;
|
||||||
|
I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_SIC; /* Clear SI flag */
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_SIC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** Function name: I2CStart
|
||||||
|
**
|
||||||
|
** Descriptions: Create I2C start condition, a timeout
|
||||||
|
** value is set if the I2C never gets started,
|
||||||
|
** and timed out. It's a fatal error.
|
||||||
|
**
|
||||||
|
** parameters: None
|
||||||
|
** Returned value: true or false, return false if timed out
|
||||||
|
**
|
||||||
|
*****************************************************************************/
|
||||||
|
static uint32_t I2CStart( void )
|
||||||
|
{
|
||||||
|
uint32_t timeout = 0;
|
||||||
|
|
||||||
|
/*--- Issue a start condition ---*/
|
||||||
|
I2C_I2CCONSET = I2CONSET_STA; /* Set Start flag */
|
||||||
|
|
||||||
|
while((I2CMasterState != I2CSTATE_PENDING) && (timeout < MAX_TIMEOUT))
|
||||||
|
{
|
||||||
|
timeout++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (timeout < MAX_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** Function name: I2CStop
|
||||||
|
**
|
||||||
|
** Descriptions: Set the I2C stop condition
|
||||||
|
**
|
||||||
|
** parameters: None
|
||||||
|
** Returned value: true or never return
|
||||||
|
**
|
||||||
|
*****************************************************************************/
|
||||||
|
static uint32_t I2CStop( void )
|
||||||
|
{
|
||||||
|
uint32_t timeout = 0;
|
||||||
|
|
||||||
|
I2C_I2CCONSET = I2CONSET_STO; /* Set Stop flag */
|
||||||
|
I2C_I2CCONCLR = I2CONCLR_SIC; /* Clear SI flag */
|
||||||
|
|
||||||
|
/*--- Wait for STOP detected ---*/
|
||||||
|
while((I2C_I2CCONSET & I2CONSET_STO) && (timeout < MAX_TIMEOUT))
|
||||||
|
{
|
||||||
|
timeout++;
|
||||||
|
}
|
||||||
|
return (timeout >= MAX_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** Function name: I2CInit
|
||||||
|
**
|
||||||
|
** Descriptions: Initialize I2C controller
|
||||||
|
**
|
||||||
|
** parameters: I2c mode is either MASTER or SLAVE
|
||||||
|
** Returned value: true or false, return false if the I2C
|
||||||
|
** interrupt handler was not installed correctly
|
||||||
|
**
|
||||||
|
*****************************************************************************/
|
||||||
|
uint32_t i2cInit( uint32_t I2cMode )
|
||||||
|
{
|
||||||
|
SCB_PRESETCTRL |= (0x1<<1);
|
||||||
|
|
||||||
|
// Enable I2C clock
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_I2C);
|
||||||
|
|
||||||
|
// Configure pin 0.4 for SCL
|
||||||
|
IOCON_PIO0_4 &= ~(IOCON_PIO0_4_FUNC_MASK | IOCON_PIO0_4_I2CMODE_MASK);
|
||||||
|
IOCON_PIO0_4 |= (IOCON_PIO0_4_FUNC_I2CSCL);
|
||||||
|
|
||||||
|
// Configure pin 0.5 for SDA
|
||||||
|
IOCON_PIO0_5 &= ~(IOCON_PIO0_5_FUNC_MASK | IOCON_PIO0_5_I2CMODE_MASK);
|
||||||
|
IOCON_PIO0_5 |= IOCON_PIO0_5_FUNC_I2CSDA;
|
||||||
|
|
||||||
|
// Clear flags
|
||||||
|
I2C_I2CCONCLR = I2C_I2CCONCLR_AAC |
|
||||||
|
I2C_I2CCONCLR_SIC |
|
||||||
|
I2C_I2CCONCLR_STAC |
|
||||||
|
I2C_I2CCONCLR_I2ENC;
|
||||||
|
|
||||||
|
// See p.128 for appropriate values for SCLL and SCLH
|
||||||
|
#if I2C_FAST_MODE_PLUS
|
||||||
|
IOCON_PIO0_4 |= (IOCON_PIO0_4_I2CMODE_FASTPLUSI2C);
|
||||||
|
IOCON_PIO0_5 |= (IOCON_PIO0_5_I2CMODE_FASTPLUSI2C);
|
||||||
|
I2C_I2CSCLL = I2C_SCLL_HS_SCLL;
|
||||||
|
I2C_I2CSCLH = I2C_SCLH_HS_SCLH;
|
||||||
|
#else
|
||||||
|
I2C_I2CSCLL = I2SCLL_SCLL;
|
||||||
|
I2C_I2CSCLH = I2SCLH_SCLH;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( I2cMode == I2CSLAVE )
|
||||||
|
{
|
||||||
|
I2C_I2CADR0 = SLAVE_ADDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable the I2C Interrupt */
|
||||||
|
NVIC_EnableIRQ(I2C_IRQn);
|
||||||
|
I2C_I2CCONSET = I2C_I2CCONSET_I2EN;
|
||||||
|
|
||||||
|
return( TRUE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
** Function name: I2CEngine
|
||||||
|
**
|
||||||
|
** Descriptions: The routine to complete a I2C transaction
|
||||||
|
** from start to stop. All the intermitten
|
||||||
|
** steps are handled in the interrupt handler.
|
||||||
|
** Before this routine is called, the read
|
||||||
|
** length, write length and I2C master buffer
|
||||||
|
** need to be filled.
|
||||||
|
**
|
||||||
|
** parameters: None
|
||||||
|
** Returned value: Any of the I2CSTATE_... values. See i2c.h
|
||||||
|
**
|
||||||
|
*****************************************************************************/
|
||||||
|
uint32_t i2cEngine( void )
|
||||||
|
{
|
||||||
|
I2CMasterState = I2CSTATE_IDLE;
|
||||||
|
RdIndex = 0;
|
||||||
|
WrIndex = 0;
|
||||||
|
if ( I2CStart() != TRUE )
|
||||||
|
{
|
||||||
|
I2CStop();
|
||||||
|
return ( FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait until the state is a terminal state */
|
||||||
|
while (I2CMasterState < 0x100);
|
||||||
|
|
||||||
|
return ( I2CMasterState );
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
** End Of File
|
||||||
|
******************************************************************************/
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* i2c.h: Header file for NXP LPC11xx Family Microprocessors
|
||||||
|
*
|
||||||
|
* Copyright(C) 2006, NXP Semiconductor
|
||||||
|
* Parts of this code are (C) 2010, MyVoice CAD/CAM Services
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* History
|
||||||
|
* 2006.07.19 ver 1.00 Preliminary version, first Release
|
||||||
|
* 2010.07.19 ver 1.10 Rob Jansen - MyVoice CAD/CAM Services
|
||||||
|
* Updated to reflect new code
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#ifndef __I2C_H
|
||||||
|
#define __I2C_H
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are states returned by the I2CEngine:
|
||||||
|
*
|
||||||
|
* IDLE - is never returned but only used internally
|
||||||
|
* PENDING - is never returned but only used internally in the I2C functions
|
||||||
|
* ACK - The transaction finished and the slave returned ACK (on all bytes)
|
||||||
|
* NACK - The transaction is aborted since the slave returned a NACK
|
||||||
|
* SLA_NACK - The transaction is aborted since the slave returned a NACK on the SLA
|
||||||
|
* this can be intentional (e.g. an 24LC08 EEPROM states it is busy)
|
||||||
|
* or the slave is not available/accessible at all.
|
||||||
|
* ARB_LOSS - Arbitration loss during any part of the transaction.
|
||||||
|
* This could only happen in a multi master system or could also
|
||||||
|
* identify a hardware problem in the system.
|
||||||
|
*/
|
||||||
|
#define I2CSTATE_IDLE 0x000
|
||||||
|
#define I2CSTATE_PENDING 0x001
|
||||||
|
#define I2CSTATE_ACK 0x101
|
||||||
|
#define I2CSTATE_NACK 0x102
|
||||||
|
#define I2CSTATE_SLA_NACK 0x103
|
||||||
|
#define I2CSTATE_ARB_LOSS 0x104
|
||||||
|
|
||||||
|
#define FAST_MODE_PLUS 0
|
||||||
|
|
||||||
|
#define I2C_BUFSIZE 6
|
||||||
|
#define MAX_TIMEOUT 0x00FFFFFF
|
||||||
|
|
||||||
|
#define I2CMASTER 0x01
|
||||||
|
#define I2CSLAVE 0x02
|
||||||
|
|
||||||
|
#define SLAVE_ADDR 0xA0
|
||||||
|
#define READ_WRITE 0x01
|
||||||
|
|
||||||
|
#define RD_BIT 0x01
|
||||||
|
|
||||||
|
#define I2CONSET_I2EN 0x00000040 /* I2C Control Set Register */
|
||||||
|
#define I2CONSET_AA 0x00000004
|
||||||
|
#define I2CONSET_SI 0x00000008
|
||||||
|
#define I2CONSET_STO 0x00000010
|
||||||
|
#define I2CONSET_STA 0x00000020
|
||||||
|
|
||||||
|
#define I2CONCLR_AAC 0x00000004 /* I2C Control clear Register */
|
||||||
|
#define I2CONCLR_SIC 0x00000008
|
||||||
|
#define I2CONCLR_STAC 0x00000020
|
||||||
|
#define I2CONCLR_I2ENC 0x00000040
|
||||||
|
|
||||||
|
#define I2DAT_I2C 0x00000000 /* I2C Data Reg */
|
||||||
|
#define I2ADR_I2C 0x00000000 /* I2C Slave Address Reg */
|
||||||
|
#define I2SCLH_SCLH 120 /* I2C SCL Duty Cycle High Reg */
|
||||||
|
#define I2SCLL_SCLL 120 /* I2C SCL Duty Cycle Low Reg */
|
||||||
|
#define I2SCLH_HS_SCLH 0x00000020 /* Fast Plus I2C SCL Duty Cycle High Reg */
|
||||||
|
#define I2SCLL_HS_SCLL 0x00000020 /* Fast Plus I2C SCL Duty Cycle Low Reg */
|
||||||
|
|
||||||
|
|
||||||
|
extern volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
|
||||||
|
extern volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
|
||||||
|
extern volatile uint32_t I2CReadLength, I2CWriteLength;
|
||||||
|
|
||||||
|
extern void I2C_IRQHandler( void );
|
||||||
|
extern uint32_t i2cInit( uint32_t I2cMode );
|
||||||
|
extern uint32_t i2cEngine( void );
|
||||||
|
|
||||||
|
#endif /* end __I2C_H */
|
||||||
|
/****************************************************************************
|
||||||
|
** End Of File
|
||||||
|
*****************************************************************************/
|
|
@ -0,0 +1,57 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file iap.c
|
||||||
|
Source: http://knowledgebase.nxp.com/showthread.php?t=1594
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
#include "iap.h"
|
||||||
|
|
||||||
|
IAP_return_t iap_return;
|
||||||
|
|
||||||
|
#define IAP_ADDRESS 0x1FFF1FF1
|
||||||
|
uint32_t param_table[5];
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Sends the IAP command and stores the result
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void iap_entry(uint32_t param_tab[], uint32_t result_tab[])
|
||||||
|
{
|
||||||
|
void (*iap)(uint32_t[], uint32_t[]);
|
||||||
|
iap = (void (*)(uint32_t[], uint32_t[]))IAP_ADDRESS;
|
||||||
|
iap(param_tab,result_tab);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Returns the CPU's unique 128-bit serial number (4 words long)
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
#include "core/iap/iap.h"
|
||||||
|
|
||||||
|
IAP_return_t iap_return;
|
||||||
|
iap_return = iapReadSerialNumber();
|
||||||
|
|
||||||
|
if (iap_return.ReturnCode == 0)
|
||||||
|
{
|
||||||
|
printf("Serial Number: %08X %08X %08X %08X %s",
|
||||||
|
iap_return.Result[0],
|
||||||
|
iap_return.Result[1],
|
||||||
|
iap_return.Result[2],
|
||||||
|
iap_return.Result[3],
|
||||||
|
CFG_PRINTF_NEWLINE);
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
IAP_return_t iapReadSerialNumber(void)
|
||||||
|
{
|
||||||
|
// ToDo: Why does IAP sometime cause the application to halt when read???
|
||||||
|
param_table[0] = IAP_CMD_READUID;
|
||||||
|
iap_entry(param_table,(uint32_t*)(&iap_return));
|
||||||
|
return iap_return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file iap.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _IAP_H_
|
||||||
|
#define _IAP_H_
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
#define IAP_CMD_PREPARESECTORFORWRITE (50)
|
||||||
|
#define IAP_CMD_COPYRAMTOFLASH (51)
|
||||||
|
#define CAP_CMD_ERASESECTORS (52)
|
||||||
|
#define IAP_CMD_BLANKCHECKSECTOR (53)
|
||||||
|
#define IAP_CMD_READPARTID (54)
|
||||||
|
#define IAP_CMD_READBOOTCODEVERSION (55)
|
||||||
|
#define IAP_CMD_COMPARE (56)
|
||||||
|
#define IAP_CMD_REINVOKEISP (57)
|
||||||
|
#define IAP_CMD_READUID (58)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned int ReturnCode;
|
||||||
|
unsigned int Result[4];
|
||||||
|
} IAP_return_t;
|
||||||
|
|
||||||
|
IAP_return_t iapReadSerialNumber(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the libpayload project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Uwe Hermann <uwe@hermann-uwe.de>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int isalpha(int c)
|
||||||
|
{
|
||||||
|
return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
|
||||||
|
}
|
||||||
|
|
||||||
|
int isascii(int c)
|
||||||
|
{
|
||||||
|
return (c >= 0 && c <= 127);
|
||||||
|
}
|
||||||
|
|
||||||
|
int isblank(int c)
|
||||||
|
{
|
||||||
|
return (c == ' ' || c == '\t');
|
||||||
|
}
|
||||||
|
|
||||||
|
int iscntrl(int c)
|
||||||
|
{
|
||||||
|
return (c <= 31 || c == 127);
|
||||||
|
}
|
||||||
|
|
||||||
|
int isdigit(int c)
|
||||||
|
{
|
||||||
|
return (c >= '0' && c <= '9');
|
||||||
|
}
|
||||||
|
|
||||||
|
int isalnum(int c)
|
||||||
|
{
|
||||||
|
return isalpha(c) || isdigit(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
int isgraph(int c)
|
||||||
|
{
|
||||||
|
return (c >= 33 && c <= 126);
|
||||||
|
}
|
||||||
|
|
||||||
|
int islower(int c)
|
||||||
|
{
|
||||||
|
return (c >= 'a' && c <= 'z');
|
||||||
|
}
|
||||||
|
|
||||||
|
int isprint(int c)
|
||||||
|
{
|
||||||
|
return (c >= 32 && c <= 126);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int isspace(int c)
|
||||||
|
{
|
||||||
|
return (c == ' ' || (c >= '\t' || c <= '\r'));
|
||||||
|
}
|
||||||
|
|
||||||
|
int isupper(int c)
|
||||||
|
{
|
||||||
|
return (c >= 'A' && c <= 'Z');
|
||||||
|
}
|
||||||
|
|
||||||
|
int tolower(int c)
|
||||||
|
{
|
||||||
|
return (c >= 'A' && c <= 'Z') ? (c + 32) : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int toupper(int c)
|
||||||
|
{
|
||||||
|
return (c >= 'a' && c <= 'z') ? (c - 32) : c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int isxdigit(int c)
|
||||||
|
{
|
||||||
|
return isdigit(c) || (tolower(c) >= 'a' && tolower(c) <= 'z');
|
||||||
|
}
|
||||||
|
|
||||||
|
int ispunct(int c)
|
||||||
|
{
|
||||||
|
return isprint(c) && !isspace(c) && !isalnum(c);
|
||||||
|
}
|
|
@ -0,0 +1,475 @@
|
||||||
|
/*
|
||||||
|
* Software License Agreement (BSD License)
|
||||||
|
*
|
||||||
|
* Based on original stdio.c released by Atmel
|
||||||
|
* Copyright (c) 2008, Atmel Corporation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Modified by Roel Verdult, Copyright (c) 2010
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local Definitions
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Maximum string size allowed (in bytes).
|
||||||
|
#define MAX_STRING_SIZE 255
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Global Variables
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Required for proper compilation.
|
||||||
|
//struct _reent r = {0, (FILE*) 0, (FILE*) 1, (FILE*) 0};
|
||||||
|
//struct _reent *_impure_ptr = &r;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Local Functions
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Writes a character inside the given string. Returns 1.
|
||||||
|
// \param pStr Storage string.
|
||||||
|
// \param c Character to write.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int append_char(char *pStr, char c)
|
||||||
|
{
|
||||||
|
*pStr = c;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Writes a string inside the given string.
|
||||||
|
// Returns the size of the written
|
||||||
|
// string.
|
||||||
|
// \param pStr Storage string.
|
||||||
|
// \param pSource Source string.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int PutString(char *pStr, char fill, signed int width, const char *pSource)
|
||||||
|
{
|
||||||
|
signed int num = 0;
|
||||||
|
|
||||||
|
while (*pSource != 0) {
|
||||||
|
|
||||||
|
*pStr++ = *pSource++;
|
||||||
|
num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
width -= num;
|
||||||
|
while (width > 0) {
|
||||||
|
|
||||||
|
*pStr++ = fill;
|
||||||
|
num++;
|
||||||
|
width--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Writes an unsigned int inside the given string, using the provided fill &
|
||||||
|
// width parameters.
|
||||||
|
// Returns the size in characters of the written integer.
|
||||||
|
// \param pStr Storage string.
|
||||||
|
// \param fill Fill character.
|
||||||
|
// \param width Minimum integer width.
|
||||||
|
// \param value Integer value.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int PutUnsignedInt(
|
||||||
|
char *pStr,
|
||||||
|
char fill,
|
||||||
|
signed int width,
|
||||||
|
unsigned int value)
|
||||||
|
{
|
||||||
|
signed int num = 0;
|
||||||
|
|
||||||
|
// Take current digit into account when calculating width
|
||||||
|
width--;
|
||||||
|
|
||||||
|
// Recursively write upper digits
|
||||||
|
if ((value / 10) > 0) {
|
||||||
|
|
||||||
|
num = PutUnsignedInt(pStr, fill, width, value / 10);
|
||||||
|
pStr += num;
|
||||||
|
}
|
||||||
|
// Write filler characters
|
||||||
|
else {
|
||||||
|
|
||||||
|
while (width > 0) {
|
||||||
|
|
||||||
|
append_char(pStr, fill);
|
||||||
|
pStr++;
|
||||||
|
num++;
|
||||||
|
width--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write lower digit
|
||||||
|
num += append_char(pStr, (value % 10) + '0');
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Writes a signed int inside the given string, using the provided fill & width
|
||||||
|
// parameters.
|
||||||
|
// Returns the size of the written integer.
|
||||||
|
// \param pStr Storage string.
|
||||||
|
// \param fill Fill character.
|
||||||
|
// \param width Minimum integer width.
|
||||||
|
// \param value Signed integer value.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int PutSignedInt(
|
||||||
|
char *pStr,
|
||||||
|
char fill,
|
||||||
|
signed int width,
|
||||||
|
signed int value)
|
||||||
|
{
|
||||||
|
signed int num = 0;
|
||||||
|
unsigned int absolute;
|
||||||
|
|
||||||
|
// Compute absolute value
|
||||||
|
if (value < 0) {
|
||||||
|
|
||||||
|
absolute = -value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
absolute = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take current digit into account when calculating width
|
||||||
|
width--;
|
||||||
|
|
||||||
|
// Recursively write upper digits
|
||||||
|
if ((absolute / 10) > 0) {
|
||||||
|
|
||||||
|
if (value < 0) {
|
||||||
|
|
||||||
|
num = PutSignedInt(pStr, fill, width, -(absolute / 10));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
num = PutSignedInt(pStr, fill, width, absolute / 10);
|
||||||
|
}
|
||||||
|
pStr += num;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
// Reserve space for sign
|
||||||
|
if (value < 0) {
|
||||||
|
|
||||||
|
width--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write filler characters
|
||||||
|
while (width > 0) {
|
||||||
|
|
||||||
|
append_char(pStr, fill);
|
||||||
|
pStr++;
|
||||||
|
num++;
|
||||||
|
width--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write sign
|
||||||
|
if (value < 0) {
|
||||||
|
|
||||||
|
num += append_char(pStr, '-');
|
||||||
|
pStr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write lower digit
|
||||||
|
num += append_char(pStr, (absolute % 10) + '0');
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Writes an hexadecimal value into a string, using the given fill, width &
|
||||||
|
// capital parameters.
|
||||||
|
// Returns the number of char written.
|
||||||
|
// \param pStr Storage string.
|
||||||
|
// \param fill Fill character.
|
||||||
|
// \param width Minimum integer width.
|
||||||
|
// \param maj Indicates if the letters must be printed in lower- or upper-case.
|
||||||
|
// \param value Hexadecimal value.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int PutHexa(
|
||||||
|
char *pStr,
|
||||||
|
char fill,
|
||||||
|
signed int width,
|
||||||
|
unsigned char maj,
|
||||||
|
unsigned int value)
|
||||||
|
{
|
||||||
|
signed int num = 0;
|
||||||
|
|
||||||
|
// Decrement width
|
||||||
|
width--;
|
||||||
|
|
||||||
|
// Recursively output upper digits
|
||||||
|
if ((value >> 4) > 0) {
|
||||||
|
|
||||||
|
num += PutHexa(pStr, fill, width, maj, value >> 4);
|
||||||
|
pStr += num;
|
||||||
|
}
|
||||||
|
// Write filler chars
|
||||||
|
else {
|
||||||
|
|
||||||
|
while (width > 0) {
|
||||||
|
|
||||||
|
append_char(pStr, fill);
|
||||||
|
pStr++;
|
||||||
|
num++;
|
||||||
|
width--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write current digit
|
||||||
|
if ((value & 0xF) < 10) {
|
||||||
|
|
||||||
|
append_char(pStr, (value & 0xF) + '0');
|
||||||
|
}
|
||||||
|
else if (maj) {
|
||||||
|
|
||||||
|
append_char(pStr, (value & 0xF) - 10 + 'A');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
append_char(pStr, (value & 0xF) - 10 + 'a');
|
||||||
|
}
|
||||||
|
num++;
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Stores the result of a formatted string into another string. Format
|
||||||
|
/// arguments are given in a va_list instance.
|
||||||
|
/// Return the number of characters written.
|
||||||
|
/// \param pStr Destination string.
|
||||||
|
/// \param length Length of Destination string.
|
||||||
|
/// \param pFormat Format string.
|
||||||
|
/// \param ap Argument list.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap)
|
||||||
|
{
|
||||||
|
char fill;
|
||||||
|
unsigned char width;
|
||||||
|
signed int num = 0;
|
||||||
|
signed int size = 0;
|
||||||
|
|
||||||
|
// Clear the string
|
||||||
|
if (pStr) {
|
||||||
|
|
||||||
|
*pStr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase string
|
||||||
|
while (*pFormat != 0 && size < length) {
|
||||||
|
|
||||||
|
// Normal character
|
||||||
|
if (*pFormat != '%') {
|
||||||
|
|
||||||
|
*pStr++ = *pFormat++;
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
// Escaped '%'
|
||||||
|
else if (*(pFormat+1) == '%') {
|
||||||
|
|
||||||
|
*pStr++ = '%';
|
||||||
|
pFormat += 2;
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
// Token delimiter
|
||||||
|
else {
|
||||||
|
|
||||||
|
fill = ' ';
|
||||||
|
width = 0;
|
||||||
|
pFormat++;
|
||||||
|
|
||||||
|
// Parse filler
|
||||||
|
if (*pFormat == '0') {
|
||||||
|
|
||||||
|
fill = '0';
|
||||||
|
pFormat++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore justifier
|
||||||
|
if (*pFormat == '-') {
|
||||||
|
pFormat++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse width
|
||||||
|
while ((*pFormat >= '0') && (*pFormat <= '9')) {
|
||||||
|
|
||||||
|
width = (width*10) + *pFormat-'0';
|
||||||
|
pFormat++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if there is enough space
|
||||||
|
if (size + width > length) {
|
||||||
|
|
||||||
|
width = length - size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse type
|
||||||
|
switch (*pFormat) {
|
||||||
|
case 'd':
|
||||||
|
case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break;
|
||||||
|
case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break;
|
||||||
|
case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned int)); break;
|
||||||
|
case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break;
|
||||||
|
case 's': num = PutString(pStr, fill, width, va_arg(ap, char *)); break;
|
||||||
|
case 'c': num = append_char(pStr, va_arg(ap, unsigned int)); break;
|
||||||
|
default:
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
|
||||||
|
pFormat++;
|
||||||
|
pStr += num;
|
||||||
|
size += num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NULL-terminated (final \0 is not counted)
|
||||||
|
if (size < length) {
|
||||||
|
|
||||||
|
*pStr = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
*(--pStr) = 0;
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Stores the result of a formatted string into another string. Format
|
||||||
|
/// arguments are given in a va_list instance.
|
||||||
|
/// Return the number of characters written.
|
||||||
|
/// \param pString Destination string.
|
||||||
|
/// \param length Length of Destination string.
|
||||||
|
/// \param pFormat Format string.
|
||||||
|
/// \param ... Other arguments
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int snprintf(char *pString, size_t length, const char *pFormat, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
signed int rc;
|
||||||
|
|
||||||
|
va_start(ap, pFormat);
|
||||||
|
rc = vsnprintf(pString, length, pFormat, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Stores the result of a formatted string into another string. Format
|
||||||
|
/// arguments are given in a va_list instance.
|
||||||
|
/// Return the number of characters written.
|
||||||
|
/// \param pString Destination string.
|
||||||
|
/// \param pFormat Format string.
|
||||||
|
/// \param ap Argument list.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int vsprintf(char *pString, const char *pFormat, va_list ap)
|
||||||
|
{
|
||||||
|
return vsnprintf(pString, MAX_STRING_SIZE, pFormat, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Outputs a formatted string on the DBGU stream. Format arguments are given
|
||||||
|
/// in a va_list instance.
|
||||||
|
/// \param pFormat Format string
|
||||||
|
/// \param ap Argument list.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int vprintf(const char *pFormat, va_list ap)
|
||||||
|
{
|
||||||
|
char pStr[MAX_STRING_SIZE];
|
||||||
|
char pError[] = "stdio.c: increase MAX_STRING_SIZE\r\n";
|
||||||
|
|
||||||
|
// Write formatted string in buffer
|
||||||
|
if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) {
|
||||||
|
|
||||||
|
puts(pError);
|
||||||
|
while (1); // Increase MAX_STRING_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display string
|
||||||
|
return puts(pStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Outputs a formatted string on the DBGU stream, using a variable number of
|
||||||
|
/// arguments.
|
||||||
|
/// \param pFormat Format string.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int printf(const char *pFormat, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
signed int result;
|
||||||
|
|
||||||
|
// Forward call to vprintf
|
||||||
|
va_start(ap, pFormat);
|
||||||
|
result = vprintf(pFormat, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Writes a formatted string inside another string.
|
||||||
|
/// \param pStr Storage string.
|
||||||
|
/// \param pFormat Format string.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
signed int sprintf(char *pStr, const char *pFormat, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
signed int result;
|
||||||
|
|
||||||
|
// Forward call to vsprintf
|
||||||
|
va_start(ap, pFormat);
|
||||||
|
result = vsprintf(pStr, pFormat, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -0,0 +1,328 @@
|
||||||
|
/*
|
||||||
|
* Software License Agreement (BSD License)
|
||||||
|
*
|
||||||
|
* Based on original stdio.c released by Atmel
|
||||||
|
* Copyright (c) 2008, Atmel Corporation
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Modified by Roel Verdult, Copyright (c) 2010
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 <string.h>
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Global Functions
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Copies data from a source buffer into a destination buffer. The two buffers
|
||||||
|
/// must NOT overlap. Returns the destination buffer.
|
||||||
|
/// \param pDestination Destination buffer.
|
||||||
|
/// \param pSource Source buffer.
|
||||||
|
/// \param num Number of bytes to copy.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void * memcpy(void *pDestination, const void *pSource, size_t num)
|
||||||
|
{
|
||||||
|
unsigned char *pByteDestination;
|
||||||
|
unsigned char *pByteSource;
|
||||||
|
unsigned int *pAlignedSource = (unsigned int *) pSource;
|
||||||
|
unsigned int *pAlignedDestination = (unsigned int *) pDestination;
|
||||||
|
|
||||||
|
// If num is more than 4 bytes, and both dest. and source are aligned,
|
||||||
|
// then copy dwords
|
||||||
|
if ((((unsigned int) pAlignedDestination & 0x3) == 0)
|
||||||
|
&& (((unsigned int) pAlignedSource & 0x3) == 0)
|
||||||
|
&& (num >= 4)) {
|
||||||
|
|
||||||
|
while (num >= 4) {
|
||||||
|
|
||||||
|
*pAlignedDestination++ = *pAlignedSource++;
|
||||||
|
num -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy remaining bytes
|
||||||
|
pByteDestination = (unsigned char *) pAlignedDestination;
|
||||||
|
pByteSource = (unsigned char *) pAlignedSource;
|
||||||
|
while (num--) {
|
||||||
|
|
||||||
|
*pByteDestination++ = *pByteSource++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pDestination;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/// Fills a memory region with the given value. Returns a pointer to the
|
||||||
|
/// memory region.
|
||||||
|
/// \param pBuffer Pointer to the start of the memory region to fill
|
||||||
|
/// \param value Value to fill the region with
|
||||||
|
/// \param num Size to fill in bytes
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
void * memset(void *pBuffer, int value, size_t num)
|
||||||
|
{
|
||||||
|
unsigned char *pByteDestination;
|
||||||
|
unsigned int *pAlignedDestination = (unsigned int *) pBuffer;
|
||||||
|
unsigned int alignedValue = (value << 24) | (value << 16) | (value << 8) | value;
|
||||||
|
|
||||||
|
// Set words if possible
|
||||||
|
if ((((unsigned int) pAlignedDestination & 0x3) == 0) && (num >= 4)) {
|
||||||
|
while (num >= 4) {
|
||||||
|
*pAlignedDestination++ = alignedValue;
|
||||||
|
num -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set remaining bytes
|
||||||
|
pByteDestination = (unsigned char *) pAlignedDestination;
|
||||||
|
while (num--) {
|
||||||
|
*pByteDestination++ = value;
|
||||||
|
}
|
||||||
|
return pBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* memmove(void *s1, const void *s2, size_t n)
|
||||||
|
{
|
||||||
|
char *s=(char*)s2, *d=(char*)s1;
|
||||||
|
|
||||||
|
if(d > s){
|
||||||
|
s+=n-1;
|
||||||
|
d+=n-1;
|
||||||
|
while(n){
|
||||||
|
*d--=*s--;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
}else if(d < s)
|
||||||
|
while(n){
|
||||||
|
*d++=*s++;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
return s1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int memcmp(const void *av, const void *bv, size_t len)
|
||||||
|
{
|
||||||
|
const unsigned char *a = av;
|
||||||
|
const unsigned char *b = bv;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i=0; i<len; i++)
|
||||||
|
{
|
||||||
|
if (a[i] != b[i])
|
||||||
|
{
|
||||||
|
return (int)(a[i] - b[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// Search a character in the given string.
|
||||||
|
/// Returns a pointer to the character location.
|
||||||
|
/// \param pString Pointer to the start of the string to search.
|
||||||
|
/// \param character The character to find.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
char * strchr(const char *pString, int character)
|
||||||
|
{
|
||||||
|
char * p = (char *)pString;
|
||||||
|
char c = character & 0xFF;
|
||||||
|
|
||||||
|
while(*p != c) {
|
||||||
|
if (*p == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// Return the length of a given string
|
||||||
|
/// \param pString Pointer to the start of the string.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
size_t strlen(const char *pString)
|
||||||
|
{
|
||||||
|
unsigned int length = 0;
|
||||||
|
|
||||||
|
while(*pString++ != 0) {
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// Search a character backword from the end of given string.
|
||||||
|
/// Returns a pointer to the character location.
|
||||||
|
/// \param pString Pointer to the start of the string to search.
|
||||||
|
/// \param character The character to find.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
char * strrchr(const char *pString, int character)
|
||||||
|
{
|
||||||
|
char *p = 0;
|
||||||
|
|
||||||
|
while(*pString != 0) {
|
||||||
|
if (*pString++ == character) {
|
||||||
|
p = (char*)pString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// Copy from source string to destination string
|
||||||
|
/// Return a pointer to the destination string
|
||||||
|
/// \param pDestination Pointer to the destination string.
|
||||||
|
/// \param pSource Pointer to the source string.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
char * strcpy(char *pDestination, const char *pSource)
|
||||||
|
{
|
||||||
|
char *pSaveDest = pDestination;
|
||||||
|
|
||||||
|
for(; (*pDestination = *pSource) != 0; ++pSource, ++pDestination);
|
||||||
|
return pSaveDest;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// Compare the first specified bytes of 2 given strings
|
||||||
|
/// Return 0 if equals
|
||||||
|
/// Return >0 if 1st string > 2nd string
|
||||||
|
/// Return <0 if 1st string < 2nd string
|
||||||
|
/// \param pString1 Pointer to the start of the 1st string.
|
||||||
|
/// \param pString2 Pointer to the start of the 2nd string.
|
||||||
|
/// \param count Number of bytes that should be compared.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
int strncmp(const char *pString1, const char *pString2, size_t count)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
while(count) {
|
||||||
|
r = *pString1 - *pString2;
|
||||||
|
if (r == 0) {
|
||||||
|
if (*pString1 == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pString1++;
|
||||||
|
pString2++;
|
||||||
|
count--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/// Copy the first number of bytes from source string to destination string
|
||||||
|
/// Return the pointer to the destination string.
|
||||||
|
/// \param pDestination Pointer to the start of destination string.
|
||||||
|
/// \param pSource Pointer to the start of the source string.
|
||||||
|
/// \param count Number of bytes that should be copied.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
char * strncpy(char *pDestination, const char *pSource, size_t count)
|
||||||
|
{
|
||||||
|
char *pSaveDest = pDestination;
|
||||||
|
|
||||||
|
while (count) {
|
||||||
|
*pDestination = *pSource;
|
||||||
|
if (*pSource == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pDestination++;
|
||||||
|
pSource++;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
return pSaveDest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Following code is based on the BSD licensed code released by UoC
|
||||||
|
// Copyright (c) 1988 Regents of the University of California
|
||||||
|
|
||||||
|
int strcmp(const char *s1, const char *s2)
|
||||||
|
{
|
||||||
|
while (*s1 == *s2++)
|
||||||
|
if (*s1++ == 0)
|
||||||
|
return (0);
|
||||||
|
return (*(unsigned char *)s1 - *(unsigned char *)--s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strtok(char *s, const char *delim)
|
||||||
|
{
|
||||||
|
static char *last;
|
||||||
|
return strtok_r(s, delim, &last);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strtok_r(char *s, const char *delim, char **last)
|
||||||
|
{
|
||||||
|
char *spanp;
|
||||||
|
int c, sc;
|
||||||
|
char *tok;
|
||||||
|
|
||||||
|
|
||||||
|
if (s == NULL && (s = *last) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip (span) leading delimiters (s += strspn(s, delim), sort of).
|
||||||
|
*/
|
||||||
|
cont:
|
||||||
|
c = *s++;
|
||||||
|
for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
|
||||||
|
if (c == sc)
|
||||||
|
goto cont;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == 0) { /* no non-delimiter characters */
|
||||||
|
*last = NULL;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
tok = s - 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
|
||||||
|
* Note that delim must have one NUL; we stop if we see that, too.
|
||||||
|
*/
|
||||||
|
for (;;) {
|
||||||
|
c = *s++;
|
||||||
|
spanp = (char *)delim;
|
||||||
|
do {
|
||||||
|
if ((sc = *spanp++) == c) {
|
||||||
|
if (c == 0)
|
||||||
|
s = NULL;
|
||||||
|
else
|
||||||
|
s[-1] = 0;
|
||||||
|
*last = s;
|
||||||
|
return (tok);
|
||||||
|
}
|
||||||
|
} while (sc != 0);
|
||||||
|
}
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,419 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file pmu.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section DESCRIPTION
|
||||||
|
|
||||||
|
Controls the power management features of the LPC1343, allowing you
|
||||||
|
to enter sleep/deep-sleep or deep power-down mode.
|
||||||
|
|
||||||
|
For examples of how to enter either mode, see the comments for the
|
||||||
|
functions pmuSleep(), pmuDeepSleep() and pmuPowerDown().
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "core/gpio/gpio.h"
|
||||||
|
#include "core/cpu/cpu.h"
|
||||||
|
#include "core/timer32/timer32.h"
|
||||||
|
#include "pmu.h"
|
||||||
|
|
||||||
|
#ifdef CFG_CHIBI
|
||||||
|
#include "drivers/chibi/chb_drvr.h"
|
||||||
|
#endif
|
||||||
|
#define PMU_WDTCLOCKSPEED_HZ 7812
|
||||||
|
|
||||||
|
void pmuSetupHW(void);
|
||||||
|
void pmuRestoreHW(void);
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Wakeup interrupt handler
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void WAKEUP_IRQHandler(void)
|
||||||
|
{
|
||||||
|
uint32_t regVal;
|
||||||
|
|
||||||
|
// Reconfigure system clock/PLL
|
||||||
|
cpuPllSetup(CPU_MULTIPLIER_6);
|
||||||
|
|
||||||
|
// Clear match bit on timer
|
||||||
|
TMR_TMR32B0EMR = 0;
|
||||||
|
|
||||||
|
// Clear pending bits
|
||||||
|
SCB_STARTRSRP0CLR = SCB_STARTRSRP0CLR_MASK;
|
||||||
|
|
||||||
|
// Clear SLEEPDEEP bit
|
||||||
|
SCB_SCR &= ~SCB_SCR_SLEEPDEEP;
|
||||||
|
|
||||||
|
// Disable the deep sleep timer
|
||||||
|
TMR_TMR32B0TCR = TMR_TMR32B0TCR_COUNTERENABLE_DISABLED;
|
||||||
|
|
||||||
|
/* This handler takes care of all the port pins if they
|
||||||
|
are configured as wakeup source. */
|
||||||
|
regVal = SCB_STARTSRP0;
|
||||||
|
if (regVal != 0)
|
||||||
|
{
|
||||||
|
SCB_STARTRSRP0CLR = regVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconfigure CT32B0
|
||||||
|
timer32Init(0, TIMER32_DEFAULTINTERVAL);
|
||||||
|
timer32Enable(0);
|
||||||
|
|
||||||
|
// Perform peripheral specific and custom wakeup tasks
|
||||||
|
pmuRestoreHW();
|
||||||
|
|
||||||
|
/* See tracker for bug report. */
|
||||||
|
__asm volatile ("NOP");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Setup the clock for the watchdog timer. The default is 7.8125kHz.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
static void pmuWDTClockInit (void)
|
||||||
|
{
|
||||||
|
/* Enable WDT clock */
|
||||||
|
SCB_PDRUNCFG &= ~(SCB_PDRUNCFG_WDTOSC);
|
||||||
|
|
||||||
|
/* Configure watchdog clock */
|
||||||
|
/* Freq. = 0.5MHz, div = 64: WDT_OSC = 7.8125kHz */
|
||||||
|
SCB_WDTOSCCTRL = SCB_WDTOSCCTRL_FREQSEL_0_5MHZ |
|
||||||
|
SCB_WDTOSCCTRL_DIVSEL_DIV64;
|
||||||
|
|
||||||
|
// Switch main clock to WDT output
|
||||||
|
SCB_MAINCLKSEL = SCB_MAINCLKSEL_SOURCE_WDTOSC;
|
||||||
|
SCB_MAINCLKUEN = SCB_MAINCLKUEN_UPDATE; // Update clock source
|
||||||
|
SCB_MAINCLKUEN = SCB_MAINCLKUEN_DISABLE; // Toggle update register once
|
||||||
|
SCB_MAINCLKUEN = SCB_MAINCLKUEN_UPDATE;
|
||||||
|
|
||||||
|
// Wait until the clock is updated
|
||||||
|
while (!(SCB_MAINCLKUEN & SCB_MAINCLKUEN_UPDATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Initialises the power management unit
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void pmuInit( void )
|
||||||
|
{
|
||||||
|
/* Enable all clocks, even those turned off at power up. */
|
||||||
|
SCB_PDRUNCFG &= ~(SCB_PDRUNCFG_WDTOSC_MASK |
|
||||||
|
SCB_PDRUNCFG_SYSOSC_MASK |
|
||||||
|
SCB_PDRUNCFG_ADC_MASK);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Puts select peripherals in sleep mode.
|
||||||
|
|
||||||
|
This function will put the device into sleep mode. Most gpio pins
|
||||||
|
can be used to wake the device up, but the pins must first be
|
||||||
|
configured for this in pmuInit.
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
// Configure wakeup sources before going into sleep/deep-sleep.
|
||||||
|
// By default, pin 0.1 is configured as wakeup source (falling edge)
|
||||||
|
pmuInit();
|
||||||
|
|
||||||
|
// Enter sleep mode
|
||||||
|
pmuSleep();
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void pmuSleep()
|
||||||
|
{
|
||||||
|
SCB_PDAWAKECFG = SCB_PDRUNCFG;
|
||||||
|
__asm volatile ("WFI");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Turns off select peripherals and puts the device in deep-sleep
|
||||||
|
mode.
|
||||||
|
|
||||||
|
The device can be configured to wakeup from deep-sleep mode after a
|
||||||
|
specified delay by supplying a non-zero value to the wakeupSeconds
|
||||||
|
parameter. This will configure CT32B0 to toggle pin 0.1 (CT32B0_MAT2)
|
||||||
|
after x seconds, waking the device up. The timer will be configured
|
||||||
|
to run off the WDT OSC while in deep-sleep mode, meaning that WDTOSC
|
||||||
|
should not be powered off (using the sleepCtrl parameter) when a
|
||||||
|
wakeup delay is specified.
|
||||||
|
|
||||||
|
The sleepCtrl parameter is used to indicate which peripherals should
|
||||||
|
be put in sleep mode (see the SCB_PDSLEEPCFG register for details).
|
||||||
|
|
||||||
|
@param[in] sleepCtrl
|
||||||
|
The bits to set in the SCB_PDSLEEPCFG register. This
|
||||||
|
controls which peripherals will be put in sleep mode.
|
||||||
|
@param[in] wakeupSeconds
|
||||||
|
The number of seconds to wait until the device will
|
||||||
|
wakeup. If you do not wish to wakeup after a specific
|
||||||
|
delay, enter a value of 0.
|
||||||
|
|
||||||
|
@code
|
||||||
|
uint32_t pmuRegVal;
|
||||||
|
|
||||||
|
// Initialise power management unit
|
||||||
|
pmuInit();
|
||||||
|
|
||||||
|
// Put peripherals into sleep mode
|
||||||
|
pmuRegVal = SCB_PDSLEEPCFG_IRCOUT_PD |
|
||||||
|
SCB_PDSLEEPCFG_IRC_PD |
|
||||||
|
SCB_PDSLEEPCFG_FLASH_PD |
|
||||||
|
SCB_PDSLEEPCFG_USBPLL_PD |
|
||||||
|
SCB_PDSLEEPCFG_SYSPLL_PD |
|
||||||
|
SCB_PDSLEEPCFG_SYSOSC_PD |
|
||||||
|
SCB_PDSLEEPCFG_ADC_PD |
|
||||||
|
SCB_PDSLEEPCFG_BOD_PD;
|
||||||
|
|
||||||
|
// Enter deep sleep mode (wakeup after 5 seconds)
|
||||||
|
// By default, pin 0.1 is configured as wakeup source
|
||||||
|
pmuDeepSleep(pmuRegVal, 5);
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void pmuDeepSleep(uint32_t sleepCtrl, uint32_t wakeupSeconds)
|
||||||
|
{
|
||||||
|
// Setup the board for deep sleep mode, shutting down certain
|
||||||
|
// peripherals and remapping pins for lower power
|
||||||
|
pmuSetupHW();
|
||||||
|
SCB_PDAWAKECFG = SCB_PDRUNCFG;
|
||||||
|
sleepCtrl |= (1 << 9) | (1 << 11);
|
||||||
|
SCB_PDSLEEPCFG = sleepCtrl;
|
||||||
|
SCB_SCR |= SCB_SCR_SLEEPDEEP;
|
||||||
|
|
||||||
|
/* Configure system to run from WDT and set TMR32B0 for wakeup */
|
||||||
|
if (wakeupSeconds > 0)
|
||||||
|
{
|
||||||
|
// Make sure WDTOSC isn't disabled in PDSLEEPCFG
|
||||||
|
SCB_PDSLEEPCFG &= ~(SCB_PDSLEEPCFG_WDTOSC_PD);
|
||||||
|
|
||||||
|
// Disable 32-bit timer 0 if currently in use
|
||||||
|
TMR_TMR32B0TCR = TMR_TMR32B0TCR_COUNTERENABLE_DISABLED;
|
||||||
|
|
||||||
|
// Disable internal pullup on 0.1
|
||||||
|
gpioSetPullup(&IOCON_PIO0_1, gpioPullupMode_Inactive);
|
||||||
|
|
||||||
|
/* Enable the clock for CT32B0 */
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT32B0);
|
||||||
|
|
||||||
|
/* Configure 0.1 as Timer0_32 MAT2 */
|
||||||
|
IOCON_PIO0_1 &= ~IOCON_PIO0_1_FUNC_MASK;
|
||||||
|
IOCON_PIO0_1 |= IOCON_PIO0_1_FUNC_CT32B0_MAT2;
|
||||||
|
|
||||||
|
/* Set appropriate timer delay */
|
||||||
|
TMR_TMR32B0MR0 = PMU_WDTCLOCKSPEED_HZ * wakeupSeconds;
|
||||||
|
|
||||||
|
/* Configure match control register to raise an interrupt and reset on MR0 */
|
||||||
|
TMR_TMR32B0MCR |= (TMR_TMR32B0MCR_MR0_INT_ENABLED | TMR_TMR32B0MCR_MR0_RESET_ENABLED);
|
||||||
|
|
||||||
|
/* Configure external match register to set 0.1 high on match */
|
||||||
|
TMR_TMR32B0EMR &= ~(0xFF<<4); // Clear EMR config bits
|
||||||
|
TMR_TMR32B0EMR |= TMR_TMR32B0EMR_EMC2_HIGH; // Set MAT2 (0.1) high on match
|
||||||
|
|
||||||
|
/* Enable wakeup interrupts (any I/O pin can be used as a wakeup source) */
|
||||||
|
//NVIC_EnableIRQ(WAKEUP0_IRQn); // P0.0
|
||||||
|
NVIC_EnableIRQ(WAKEUP1_IRQn); // P0.1 (CT32B0_MAT2)
|
||||||
|
//NVIC_EnableIRQ(WAKEUP2_IRQn); // P0.2
|
||||||
|
//NVIC_EnableIRQ(WAKEUP3_IRQn); // P0.3
|
||||||
|
//NVIC_EnableIRQ(WAKEUP4_IRQn); // P0.4
|
||||||
|
//NVIC_EnableIRQ(WAKEUP5_IRQn); // P0.5
|
||||||
|
//NVIC_EnableIRQ(WAKEUP6_IRQn); // P0.6
|
||||||
|
//NVIC_EnableIRQ(WAKEUP7_IRQn); // P0.7
|
||||||
|
//NVIC_EnableIRQ(WAKEUP8_IRQn); // P0.8
|
||||||
|
//NVIC_EnableIRQ(WAKEUP9_IRQn); // P0.9
|
||||||
|
//NVIC_EnableIRQ(WAKEUP10_IRQn); // P0.10
|
||||||
|
//NVIC_EnableIRQ(WAKEUP11_IRQn); // P0.11
|
||||||
|
//NVIC_EnableIRQ(WAKEUP12_IRQn); // P1.0
|
||||||
|
//NVIC_EnableIRQ(WAKEUP13_IRQn); // P1.1
|
||||||
|
//NVIC_EnableIRQ(WAKEUP14_IRQn); // P1.2
|
||||||
|
//NVIC_EnableIRQ(WAKEUP15_IRQn); // P1.3
|
||||||
|
//NVIC_EnableIRQ(WAKEUP16_IRQn); // P1.4
|
||||||
|
//NVIC_EnableIRQ(WAKEUP17_IRQn); // P1.5
|
||||||
|
//NVIC_EnableIRQ(WAKEUP18_IRQn); // P1.6
|
||||||
|
//NVIC_EnableIRQ(WAKEUP19_IRQn); // P1.7
|
||||||
|
//NVIC_EnableIRQ(WAKEUP20_IRQn); // P1.8
|
||||||
|
//NVIC_EnableIRQ(WAKEUP21_IRQn); // P1.9
|
||||||
|
//NVIC_EnableIRQ(WAKEUP22_IRQn); // P1.10
|
||||||
|
//NVIC_EnableIRQ(WAKEUP23_IRQn); // P1.11
|
||||||
|
//NVIC_EnableIRQ(WAKEUP24_IRQn); // P2.0
|
||||||
|
//NVIC_EnableIRQ(WAKEUP25_IRQn); // P2.1
|
||||||
|
//NVIC_EnableIRQ(WAKEUP26_IRQn); // P2.2
|
||||||
|
//NVIC_EnableIRQ(WAKEUP27_IRQn); // P2.3
|
||||||
|
//NVIC_EnableIRQ(WAKEUP28_IRQn); // P2.4
|
||||||
|
//NVIC_EnableIRQ(WAKEUP29_IRQn); // P2.5
|
||||||
|
//NVIC_EnableIRQ(WAKEUP30_IRQn); // P2.6
|
||||||
|
//NVIC_EnableIRQ(WAKEUP31_IRQn); // P2.7
|
||||||
|
//NVIC_EnableIRQ(WAKEUP32_IRQn); // P2.8
|
||||||
|
//NVIC_EnableIRQ(WAKEUP33_IRQn); // P2.9
|
||||||
|
//NVIC_EnableIRQ(WAKEUP34_IRQn); // P2.10
|
||||||
|
//NVIC_EnableIRQ(WAKEUP35_IRQn); // P2.11
|
||||||
|
//NVIC_EnableIRQ(WAKEUP36_IRQn); // P3.0
|
||||||
|
//NVIC_EnableIRQ(WAKEUP37_IRQn); // P3.1
|
||||||
|
//NVIC_EnableIRQ(WAKEUP38_IRQn); // P3.2
|
||||||
|
//NVIC_EnableIRQ(WAKEUP39_IRQn); // P3.3
|
||||||
|
|
||||||
|
/* Use RISING EDGE for wakeup detection. */
|
||||||
|
SCB_STARTAPRP0 |= SCB_STARTAPRP0_APRPIO0_1;
|
||||||
|
|
||||||
|
/* Clear all wakeup sources */
|
||||||
|
SCB_STARTRSRP0CLR = SCB_STARTRSRP0CLR_MASK;
|
||||||
|
|
||||||
|
/* Enable Port 0.1 as wakeup source. */
|
||||||
|
SCB_STARTERP0 |= SCB_STARTERP0_ERPIO0_1;
|
||||||
|
|
||||||
|
// Reconfigure clock to run from WDTOSC
|
||||||
|
pmuWDTClockInit();
|
||||||
|
|
||||||
|
/* Start the timer */
|
||||||
|
TMR_TMR32B0TCR = TMR_TMR32B0TCR_COUNTERENABLE_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
__asm volatile ("WFI");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Puts the device in deep power-down mode.
|
||||||
|
|
||||||
|
This function will configure the PMU control register and enter
|
||||||
|
deep power-down mode. Pre-determined values are stored in the four
|
||||||
|
general-purpose registers (PMU_GPREG0..3), which can be used to persist
|
||||||
|
any essential system settings while the device is in deep power-down
|
||||||
|
mode, so long as 3.3V is still available.
|
||||||
|
|
||||||
|
@warning The only way to wake a device up from deep power-down mode
|
||||||
|
is to set a low-level on P1.4. If 3.3V power is lost, the
|
||||||
|
values stored in the four general-purpose registers will
|
||||||
|
also be lost.
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
#include "core/cpu/cpu.h"
|
||||||
|
#include "core/pmu/pmu.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
cpuInit();
|
||||||
|
pmuInit();
|
||||||
|
|
||||||
|
// Enter power-down mode
|
||||||
|
pmuPowerDown();
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Device was woken up by WAKEUP pin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void pmuPowerDown( void )
|
||||||
|
{
|
||||||
|
uint32_t regVal;
|
||||||
|
|
||||||
|
// Make sure HW and external devices are in low power mode
|
||||||
|
pmuSetupHW();
|
||||||
|
|
||||||
|
if ( (PMU_PMUCTRL & ((0x1<<8) | (PMU_PMUCTRL_DPDFLAG))) != 0x0 )
|
||||||
|
{
|
||||||
|
/* Check sleep and deep power down bits. If sleep and/or
|
||||||
|
deep power down mode are entered, clear the PCON bits. */
|
||||||
|
regVal = PMU_PMUCTRL;
|
||||||
|
regVal |= ((0x1<<8) |
|
||||||
|
(PMU_PMUCTRL_DPDEN_SLEEP) |
|
||||||
|
(PMU_PMUCTRL_DPDFLAG));
|
||||||
|
PMU_PMUCTRL = regVal;
|
||||||
|
|
||||||
|
if ( (PMU_GPREG0 != 0x12345678)||(PMU_GPREG1 != 0x87654321)
|
||||||
|
||(PMU_GPREG2 != 0x56781234)||(PMU_GPREG3 != 0x43218765) )
|
||||||
|
{
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If in neither sleep nor deep-sleep mode, enter deep power down mode. */
|
||||||
|
PMU_GPREG0 = 0x12345678;
|
||||||
|
PMU_GPREG1 = 0x87654321;
|
||||||
|
PMU_GPREG2 = 0x56781234;
|
||||||
|
PMU_GPREG3 = 0x43218765;
|
||||||
|
SCB_SCR |= SCB_SCR_SLEEPDEEP;
|
||||||
|
PMU_PMUCTRL = PMU_PMUCTRL_DPDEN_DEEPPOWERDOWN;
|
||||||
|
__asm volatile ("WFI");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Configures parts and system peripherals to use lower power
|
||||||
|
before entering sleep mode
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void pmuSetupHW(void)
|
||||||
|
{
|
||||||
|
#ifdef CFG_CHIBI
|
||||||
|
chb_sleep(TRUE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Restores parts and system peripherals to an appropriate
|
||||||
|
state after waking up from deep-sleep mode
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void pmuRestoreHW(void)
|
||||||
|
{
|
||||||
|
#ifdef CFG_CHIBI
|
||||||
|
// Wakeup Chibi/Transceiver
|
||||||
|
chb_sleep(FALSE);
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file pmu.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __PMU_H__
|
||||||
|
#define __PMU_H__
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
void WAKEUP_IRQHandler( void );
|
||||||
|
void pmuInit( void );
|
||||||
|
void pmuSleep( void );
|
||||||
|
void pmuDeepSleep(uint32_t sleepCtrl, uint32_t wakeupSeconds);
|
||||||
|
void pmuPowerDown( void );
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,58 @@
|
||||||
|
#include "lpc134x.h"
|
||||||
|
#include "sysdefs.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*=========================================================================
|
||||||
|
CORE CPU SETTINGS
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
CFG_CPU_CCLK Value is for reference only. 'core/cpu/cpu.c' must
|
||||||
|
be modified to change the clock speed, but the value
|
||||||
|
should be indicated here since CFG_CPU_CCLK is used by
|
||||||
|
other peripherals to determine timing.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------*/
|
||||||
|
#define CFG_CPU_CCLK (72000000) // 1 tick = 13.88nS
|
||||||
|
/*=========================================================================*/
|
||||||
|
|
||||||
|
|
||||||
|
/*=========================================================================
|
||||||
|
SYSTICK TIMER
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
CFG_SYSTICK_DELAY_IN_MS The number of milliseconds between each tick
|
||||||
|
of the systick timer.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------*/
|
||||||
|
#define CFG_SYSTICK_DELAY_IN_MS (1)
|
||||||
|
/*=========================================================================*/
|
||||||
|
|
||||||
|
|
||||||
|
/*=========================================================================
|
||||||
|
SSP
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
CFG_SSP0_SCKPIN_2_11 Indicates which pin should be used for SCK0
|
||||||
|
CFG_SSP0_SCKPIN_0_6
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------*/
|
||||||
|
#define CFG_SSP0_SCKPIN_2_11
|
||||||
|
/*=========================================================================*/
|
||||||
|
|
||||||
|
/*=========================================================================
|
||||||
|
ON-BOARD LED
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
CFG_LED_PORT The port for the on board LED
|
||||||
|
CFG_LED_PIN The pin for the on board LED
|
||||||
|
CFG_LED_ON The pin state to turn the LED on (0 = low, 1 = high)
|
||||||
|
CFG_LED_OFF The pin state to turn the LED off (0 = low, 1 = high)
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------*/
|
||||||
|
#define CFG_LED_PORT (1)
|
||||||
|
#define CFG_LED_PIN (11)
|
||||||
|
#define CFG_LED_ON (1)
|
||||||
|
#define CFG_LED_OFF (0)
|
||||||
|
|
||||||
|
/*=========================================================================*/
|
|
@ -0,0 +1,254 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file pwm.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
|
||||||
|
@brief Simple PWM example that can be used to control a motor, dim
|
||||||
|
an LED, etc. Uses 16-bit Timer 1 and P1.9 for PWM output.
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
#include "core/pwm/pwm.h"
|
||||||
|
...
|
||||||
|
|
||||||
|
// Initialises PWM output on 16-bit Timer 1 and
|
||||||
|
// sets MAT0 (P1.9) as output
|
||||||
|
pwmInit();
|
||||||
|
|
||||||
|
// Setup the pulse-width and duty-cycle
|
||||||
|
pwmSetDutyCycle(50); // Set 50% duty cycle
|
||||||
|
pwmSetFrequencyInMicroseconds(100); // 100 millisecond pulse width
|
||||||
|
|
||||||
|
// Enable PWM output for exactly 50 pulses
|
||||||
|
pwmStartFixed(50);
|
||||||
|
|
||||||
|
// Alternatively, enable PWM output indefinately
|
||||||
|
pwmStart();
|
||||||
|
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "pwm.h"
|
||||||
|
|
||||||
|
uint32_t pwmPulseWidth = CFG_PWM_DEFAULT_PULSEWIDTH;
|
||||||
|
uint32_t pwmDutyCycle = CFG_PWM_DEFAULT_DUTYCYCLE;
|
||||||
|
|
||||||
|
// pwmMaxPulses is used by TIMER16_1_IRQHandler to turn PWM off after
|
||||||
|
// a specified number of pulses have been sent. This only relevant when
|
||||||
|
// pwmStartFixed() is used.
|
||||||
|
volatile uint32_t pwmMaxPulses = 0;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Initialises 16-bit Timer 1, and configures the MAT0 output (pin 1.9)
|
||||||
|
to send the PWM output signal.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void pwmInit(void)
|
||||||
|
{
|
||||||
|
/* Enable the clock for CT16B1 */
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT16B1);
|
||||||
|
|
||||||
|
/* Configure PIO1.9 as Timer1_16 MAT0 Output */
|
||||||
|
/* Alternatively, PIO1.10 (MAT1) can also be used though
|
||||||
|
the initialisation code will need to be modified */
|
||||||
|
IOCON_PIO1_9 &= ~IOCON_PIO1_9_FUNC_MASK;
|
||||||
|
IOCON_PIO1_9 |= IOCON_PIO1_9_FUNC_CT16B1_MAT0;
|
||||||
|
|
||||||
|
/* Set default pulse width (MR3)*/
|
||||||
|
TMR_TMR16B1MR3 = pwmPulseWidth;
|
||||||
|
|
||||||
|
/* Set default duty cycle (MR0) */
|
||||||
|
TMR_TMR16B1MR0 = (pwmPulseWidth * (100 - pwmDutyCycle)) / 100;
|
||||||
|
|
||||||
|
/* Configure match control register to reset on MR3 */
|
||||||
|
TMR_TMR16B1MCR = (TMR_TMR16B1MCR_MR3_RESET_ENABLED);
|
||||||
|
|
||||||
|
/* External Match Register Settings for PWM */
|
||||||
|
TMR_TMR16B1EMR = TMR_TMR16B1EMR_EMC0_TOGGLE | TMR_TMR16B1EMR_EM0;
|
||||||
|
|
||||||
|
/* Disable Timer1 by default (enabled by pwmStart of pwmStartFixed) */
|
||||||
|
TMR_TMR16B1TCR &= ~TMR_TMR16B1TCR_COUNTERENABLE_MASK;
|
||||||
|
|
||||||
|
/* Enable PWM0 and PWM3 */
|
||||||
|
TMR_TMR16B1PWMC = TMR_TMR16B1PWMC_PWM0_ENABLED | TMR_TMR16B1PWMC_PWM3_ENABLED;
|
||||||
|
|
||||||
|
/* Make sure that the timer interrupt is enabled */
|
||||||
|
NVIC_EnableIRQ(TIMER_16_1_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Starts the PWM output
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void pwmStart(void)
|
||||||
|
{
|
||||||
|
/* Disable interrupt on MR3 in case it was enabled by pwmStartFixed() */
|
||||||
|
TMR_TMR16B1MCR &= ~(TMR_TMR16B1MCR_MR3_INT_MASK);
|
||||||
|
|
||||||
|
/* Enable Timer1 */
|
||||||
|
TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERENABLE_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Stops the PWM output
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void pwmStop(void)
|
||||||
|
{
|
||||||
|
/* Disable Timer1 */
|
||||||
|
TMR_TMR16B1TCR &= ~(TMR_TMR16B1TCR_COUNTERENABLE_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Starts the PWM output, and stops after the specified number of
|
||||||
|
pulses.
|
||||||
|
|
||||||
|
@param[in] pulses
|
||||||
|
The number of pulses to generate before disabling the
|
||||||
|
PWM output. The output is actually disabled in the
|
||||||
|
timer ISR.
|
||||||
|
|
||||||
|
@warning The PWM output is actually stopped inside the 16-bit
|
||||||
|
timer ISR in "core/timer16/timer16.h".
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void pwmStartFixed(uint32_t pulses)
|
||||||
|
{
|
||||||
|
pwmMaxPulses = pulses;
|
||||||
|
|
||||||
|
/* Configure match control register to also raise an interrupt on MR3 */
|
||||||
|
TMR_TMR16B1MCR |= (TMR_TMR16B1MCR_MR3_INT_ENABLED);
|
||||||
|
|
||||||
|
/* Enable Timer1 (it will eventually be disabled in the ISR) */
|
||||||
|
TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERENABLE_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Sets the signal's duty cycle in percent (1-100).
|
||||||
|
|
||||||
|
@param[in] percentage
|
||||||
|
The duty-cycle in percentage (the amount of time that
|
||||||
|
the signal is 'high' relative to the time its 'low').
|
||||||
|
|
||||||
|
@returns -1 if an invalid percentage was supplied. Value must be
|
||||||
|
between 1 and 100.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
int pwmSetDutyCycle(uint32_t percentage)
|
||||||
|
{
|
||||||
|
if ((percentage < 1) || (percentage > 100))
|
||||||
|
{
|
||||||
|
/* Duty Cycle must be a value between 1 and 100 */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set Duty Cycle (MR0) */
|
||||||
|
TMR_TMR16B1MR0 = (pwmPulseWidth * (100 - (pwmDutyCycle = percentage))) / 100;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Sets the signal's frequency/pulse-width to the specified number
|
||||||
|
of ticks.
|
||||||
|
|
||||||
|
@param[in] ticks
|
||||||
|
The duration in clock ticks of each full pulse.
|
||||||
|
|
||||||
|
@returns -1 if a zero-value was provided for ticks.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
int pwmSetFrequencyInTicks(uint16_t ticks)
|
||||||
|
{
|
||||||
|
if (ticks < 1)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set Pulse Width (MR3)*/
|
||||||
|
TMR_TMR16B1MR3 = (pwmPulseWidth = ticks);
|
||||||
|
|
||||||
|
/* Adjust Duty Cycle (MR0) */
|
||||||
|
TMR_TMR16B1MR0 = (pwmPulseWidth * (100 - pwmDutyCycle)) / 100;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Sets the signal's frequency/pulse-width to the specified number
|
||||||
|
of microseconds.
|
||||||
|
|
||||||
|
@param[in] us
|
||||||
|
The duration in microseconds of each full pulse.
|
||||||
|
|
||||||
|
@returns -1 if the supplied value exceeds the limits of the 16-bit
|
||||||
|
timer, or if a zero-value was provided.
|
||||||
|
|
||||||
|
@Warning Because a 16-bit timer is used here by default, the
|
||||||
|
maximum frequency is quite small. Running at 36MHz, the
|
||||||
|
largest possible pulse-width/frequency is ~1,82mS or
|
||||||
|
1820 microSeconds. At 12MHz its 5461 uS, and at 48MHz
|
||||||
|
its 1365 uS.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
int pwmSetFrequencyInMicroseconds(uint16_t us)
|
||||||
|
{
|
||||||
|
if (us < 1)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ticks = (((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV) / 1000000) * us);
|
||||||
|
if (ticks > 0xFFFF)
|
||||||
|
{
|
||||||
|
/* Delay exceeds the upper limit for the 16-bit timer */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set Pulse Width (MR3)*/
|
||||||
|
TMR_TMR16B1MR3 = (pwmPulseWidth = ticks);
|
||||||
|
|
||||||
|
/* Adjust Duty Cycle (MR0) */
|
||||||
|
TMR_TMR16B1MR0 = (pwmPulseWidth * (100 - pwmDutyCycle)) / 100;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file pwm.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _PWM_H_
|
||||||
|
#define _PWM_H_
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
void pwmInit( void );
|
||||||
|
void pwmStart( void );
|
||||||
|
void pwmStop( void );
|
||||||
|
void pwmStartFixed( uint32_t pulses );
|
||||||
|
int pwmSetDutyCycle( uint32_t percentage );
|
||||||
|
int pwmSetFrequencyInTicks( uint16_t ticks );
|
||||||
|
int pwmSetFrequencyInMicroseconds(uint16_t us );
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,58 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file rom_drivers.h
|
||||||
|
@author NXP Semiconductor
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef ROM_DRIVERS_H_
|
||||||
|
#define ROM_DRIVERS_H_
|
||||||
|
|
||||||
|
#include "sysdefs.h"
|
||||||
|
|
||||||
|
typedef struct _USB_DEVICE_INFO
|
||||||
|
{
|
||||||
|
uint16_t DevType;
|
||||||
|
uint32_t DevDetailPtr;
|
||||||
|
} USB_DEV_INFO;
|
||||||
|
|
||||||
|
typedef struct _USBD
|
||||||
|
{
|
||||||
|
void (*init_clk_pins)(void);
|
||||||
|
void (*isr)(void);
|
||||||
|
void (*init)( USB_DEV_INFO * DevInfoPtr );
|
||||||
|
void (*connect)(uint32_t con);
|
||||||
|
} USBD;
|
||||||
|
|
||||||
|
typedef struct _ROM
|
||||||
|
{
|
||||||
|
const USBD * pUSBD;
|
||||||
|
} ROM;
|
||||||
|
|
||||||
|
typedef struct _MSC_DEVICE_INFO {
|
||||||
|
uint16_t idVendor;
|
||||||
|
uint16_t idProduct;
|
||||||
|
uint16_t bcdDevice;
|
||||||
|
uint32_t StrDescPtr;
|
||||||
|
uint32_t MSCInquiryStr;
|
||||||
|
uint32_t BlockCount;
|
||||||
|
uint32_t BlockSize;
|
||||||
|
uint32_t MemorySize;
|
||||||
|
void (*MSC_Write)( uint32_t offset, uint8_t src[], uint32_t length);
|
||||||
|
void (*MSC_Read)( uint32_t offset, uint8_t dst[], uint32_t length);
|
||||||
|
} MSC_DEVICE_INFO;
|
||||||
|
|
||||||
|
typedef struct _HID_DEVICE_INFO
|
||||||
|
{
|
||||||
|
uint16_t idVendor;
|
||||||
|
uint16_t idProduct;
|
||||||
|
uint16_t bcdDevice;
|
||||||
|
uint32_t StrDescPtr;
|
||||||
|
uint8_t InReportCount;
|
||||||
|
uint8_t OutReportCount;
|
||||||
|
uint8_t SampleInterval;
|
||||||
|
void (*InReport)(uint8_t src[], uint32_t length);
|
||||||
|
void (*OutReport)(uint8_t dst[], uint32_t length);
|
||||||
|
} HID_DEVICE_INFO;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,299 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file ssp.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section DESCRIPTION
|
||||||
|
|
||||||
|
Generic code for SSP/SPI communications. By default, the SSP block
|
||||||
|
is initialised in SPI master mode.
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
#include "core/cpu/cpu.h"
|
||||||
|
#include "core/ssp/ssp.h"
|
||||||
|
...
|
||||||
|
cpuInit();
|
||||||
|
sspInit(0, sspClockPolarity_High, sspClockPhase_RisingEdge);
|
||||||
|
...
|
||||||
|
uint8_t request[SSP_FIFOSIZE];
|
||||||
|
uint8_t response[SSP_FIFOSIZE];
|
||||||
|
|
||||||
|
// Send 0x9C to the slave device and wait for a response
|
||||||
|
request[0] = 0x80 | 0x1C;
|
||||||
|
// Toggle the select pin
|
||||||
|
ssp0Select();
|
||||||
|
// Send 1 byte from the request buffer
|
||||||
|
sspSend(0, (uint8_t *)&request, 1);
|
||||||
|
// Receive 1 byte into the response buffer
|
||||||
|
sspReceive(0, (uint8_t *)&response, 1);
|
||||||
|
// Reset the select pin
|
||||||
|
ssp0Deselect();
|
||||||
|
// Print the results
|
||||||
|
debug_printf("Ox%x ", response[0]);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "ssp.h"
|
||||||
|
#include "core/gpio/gpio.h"
|
||||||
|
|
||||||
|
/* Statistics for all interrupts */
|
||||||
|
volatile uint32_t interruptRxStat = 0;
|
||||||
|
volatile uint32_t interruptOverRunStat = 0;
|
||||||
|
volatile uint32_t interruptRxTimeoutStat = 0;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief SSP0 interrupt handler for SPI communication
|
||||||
|
|
||||||
|
The algorithm is, if RXFIFO is at least half full,
|
||||||
|
start receive until it's empty; if TXFIFO is at least
|
||||||
|
half empty, start transmit until it's full.
|
||||||
|
This will maximize the use of both FIFOs and performance.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void SSP_IRQHandler (void)
|
||||||
|
{
|
||||||
|
uint32_t regValue;
|
||||||
|
|
||||||
|
regValue = SSP_SSP0MIS;
|
||||||
|
|
||||||
|
/* Check for overrun interrupt */
|
||||||
|
if ( regValue & SSP_SSP0MIS_RORMIS_FRMRCVD )
|
||||||
|
{
|
||||||
|
interruptOverRunStat++;
|
||||||
|
SSP_SSP0ICR = SSP_SSP0ICR_RORIC_CLEAR; // Clear interrupt
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for timeout interrupt */
|
||||||
|
if ( regValue & SSP_SSP0MIS_RTMIS_NOTEMPTY )
|
||||||
|
{
|
||||||
|
interruptRxTimeoutStat++;
|
||||||
|
SSP_SSP0ICR = SSP_SSP0ICR_RTIC_CLEAR; // Clear interrupt
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if Rx buffer is at least half-full */
|
||||||
|
if ( regValue & SSP_SSP0MIS_RXMIS_HALFFULL )
|
||||||
|
{
|
||||||
|
// ToDo: Receive until it's empty
|
||||||
|
interruptRxStat++;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Initialises the SSP0 port
|
||||||
|
|
||||||
|
By default, SSP0 is set to SPI frame-format with 8-bit data. Pin 2.11
|
||||||
|
is routed to serve as serial clock (SCK), and SSEL (0.2) is set to
|
||||||
|
GPIO to allow manual control of when the SPI port is enabled or
|
||||||
|
disabled. Overrun and timeout interrupts are both enabled.
|
||||||
|
|
||||||
|
@param[in] portNum
|
||||||
|
The SPI port to use (0..1)
|
||||||
|
@param[in] polarity
|
||||||
|
Indicates whether the clock should be held high
|
||||||
|
(sspClockPolarity_High) or low (sspClockPolarity_Low)
|
||||||
|
when inactive.
|
||||||
|
@param[in] phase
|
||||||
|
Indicates whether new bits start on the leading
|
||||||
|
(sspClockPhase_RisingEdge) or falling
|
||||||
|
(sspClockPhase_FallingEdge) edge of clock transitions.
|
||||||
|
|
||||||
|
@note sspSelect() and sspDeselect() macros have been defined in
|
||||||
|
ssp.h to control the SSEL line without having to know the
|
||||||
|
specific pin being used.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void sspInit (uint8_t portNum, sspClockPolarity_t polarity, sspClockPhase_t phase)
|
||||||
|
{
|
||||||
|
gpioInit();
|
||||||
|
|
||||||
|
if (portNum == 0)
|
||||||
|
{
|
||||||
|
/* Reset SSP */
|
||||||
|
SCB_PRESETCTRL &= ~SCB_PRESETCTRL_SSP0_MASK;
|
||||||
|
SCB_PRESETCTRL |= SCB_PRESETCTRL_SSP0_RESETDISABLED;
|
||||||
|
|
||||||
|
/* Enable AHB clock to the SSP domain. */
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_SSP0);
|
||||||
|
|
||||||
|
/* Divide by 1 (SSPCLKDIV also enables to SSP CLK) */
|
||||||
|
SCB_SSP0CLKDIV = SCB_SSP0CLKDIV_DIV1;
|
||||||
|
|
||||||
|
/* Set P0.8 to SSP MISO */
|
||||||
|
IOCON_PIO0_8 &= ~IOCON_PIO0_8_FUNC_MASK;
|
||||||
|
IOCON_PIO0_8 |= IOCON_PIO0_8_FUNC_MISO0;
|
||||||
|
|
||||||
|
/* Set P0.9 to SSP MOSI */
|
||||||
|
IOCON_PIO0_9 &= ~IOCON_PIO0_9_FUNC_MASK;
|
||||||
|
IOCON_PIO0_9 |= IOCON_PIO0_9_FUNC_MOSI0;
|
||||||
|
|
||||||
|
/* Set 2.11 to SSP SCK (0.6 and 0.10 can also be used) */
|
||||||
|
#ifdef CFG_SSP0_SCKPIN_2_11
|
||||||
|
IOCON_SCKLOC = IOCON_SCKLOC_SCKPIN_PIO2_11;
|
||||||
|
IOCON_PIO2_11 = IOCON_PIO2_11_FUNC_SCK0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set 0.6 to SSP SCK (2.11 and 0.10 can also be used) */
|
||||||
|
#ifdef CFG_SSP0_SCKPIN_0_6
|
||||||
|
IOCON_SCKLOC = IOCON_SCKLOC_SCKPIN_PIO0_6;
|
||||||
|
IOCON_PIO0_6 = IOCON_PIO0_6_FUNC_SCK;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Set P0.2/SSEL to GPIO output and high */
|
||||||
|
IOCON_PIO0_2 &= ~IOCON_PIO0_2_FUNC_MASK;
|
||||||
|
IOCON_PIO0_2 |= IOCON_PIO0_2_FUNC_GPIO;
|
||||||
|
gpioSetDir(SSP0_CSPORT, SSP0_CSPIN, 1);
|
||||||
|
gpioSetValue(SSP0_CSPORT, SSP0_CSPIN, 1);
|
||||||
|
gpioSetPullup(&IOCON_PIO0_2, gpioPullupMode_Inactive); // Board has external pull-up
|
||||||
|
|
||||||
|
/* If SSP0CLKDIV = DIV1 -- (PCLK / (CPSDVSR × [SCR+1])) = (72,000,000 / (2 x [8 + 1])) = 4.0 MHz */
|
||||||
|
uint32_t configReg = ( SSP_SSP0CR0_DSS_8BIT // Data size = 8-bit
|
||||||
|
| SSP_SSP0CR0_FRF_SPI // Frame format = SPI
|
||||||
|
| SSP_SSP0CR0_SCR_8); // Serial clock rate = 8
|
||||||
|
|
||||||
|
// Set clock polarity
|
||||||
|
if (polarity == sspClockPolarity_High)
|
||||||
|
configReg |= SSP_SSP0CR0_CPOL_HIGH; // Clock polarity = High between frames
|
||||||
|
else
|
||||||
|
configReg &= ~SSP_SSP0CR0_CPOL_MASK; // Clock polarity = Low between frames
|
||||||
|
|
||||||
|
// Set edge transition
|
||||||
|
if (phase == sspClockPhase_FallingEdge)
|
||||||
|
configReg |= SSP_SSP0CR0_CPHA_SECOND; // Clock out phase = Trailing edge clock transition
|
||||||
|
else
|
||||||
|
configReg &= ~SSP_SSP0CR0_CPHA_MASK; // Clock out phase = Leading edge clock transition
|
||||||
|
|
||||||
|
// Assign config values to SSP0CR0
|
||||||
|
SSP_SSP0CR0 = configReg;
|
||||||
|
|
||||||
|
/* Clock prescale register must be even and at least 2 in master mode */
|
||||||
|
SSP_SSP0CPSR = SSP_SSP0CPSR_CPSDVSR_DIV2;
|
||||||
|
|
||||||
|
/* Clear the Rx FIFO */
|
||||||
|
uint8_t i, Dummy=Dummy;
|
||||||
|
for ( i = 0; i < SSP_FIFOSIZE; i++ )
|
||||||
|
{
|
||||||
|
Dummy = SSP_SSP0DR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enable the SSP Interrupt */
|
||||||
|
NVIC_EnableIRQ(SSP_IRQn);
|
||||||
|
|
||||||
|
/* Set SSPINMS registers to enable interrupts
|
||||||
|
* enable all error related interrupts */
|
||||||
|
SSP_SSP0IMSC = ( SSP_SSP0IMSC_RORIM_ENBL // Enable overrun interrupt
|
||||||
|
| SSP_SSP0IMSC_RTIM_ENBL); // Enable timeout interrupt
|
||||||
|
|
||||||
|
/* Enable device and set it to master mode, no loopback */
|
||||||
|
SSP_SSP0CR1 = SSP_SSP0CR1_SSE_ENABLED | SSP_SSP0CR1_MS_MASTER | SSP_SSP0CR1_LBM_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Sends a block of data to the SSP0 port
|
||||||
|
|
||||||
|
@param[in] portNum
|
||||||
|
The SPI port to use (0..1)
|
||||||
|
@param[in] buf
|
||||||
|
Pointer to the data buffer
|
||||||
|
@param[in] length
|
||||||
|
Block length of the data buffer
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void sspSend (uint8_t portNum, uint8_t *buf, uint32_t length)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
uint8_t Dummy = Dummy;
|
||||||
|
|
||||||
|
if (portNum == 0)
|
||||||
|
{
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
/* Move on only if NOT busy and TX FIFO not full. */
|
||||||
|
while ((SSP_SSP0SR & (SSP_SSP0SR_TNF_NOTFULL | SSP_SSP0SR_BSY_BUSY)) != SSP_SSP0SR_TNF_NOTFULL);
|
||||||
|
SSP_SSP0DR = *buf;
|
||||||
|
buf++;
|
||||||
|
|
||||||
|
while ( (SSP_SSP0SR & (SSP_SSP0SR_BSY_BUSY|SSP_SSP0SR_RNE_NOTEMPTY)) != SSP_SSP0SR_RNE_NOTEMPTY );
|
||||||
|
/* Whenever a byte is written, MISO FIFO counter increments, Clear FIFO
|
||||||
|
on MISO. Otherwise, when SSP0Receive() is called, previous data byte
|
||||||
|
is left in the FIFO. */
|
||||||
|
Dummy = SSP_SSP0DR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Receives a block of data from the SSP0 port
|
||||||
|
|
||||||
|
@param[in] portNum
|
||||||
|
The SPI port to use (0..1)
|
||||||
|
@param[in] buf
|
||||||
|
Pointer to the data buffer
|
||||||
|
@param[in] length
|
||||||
|
Block length of the data buffer
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void sspReceive(uint8_t portNum, uint8_t *buf, uint32_t length)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
if (portNum == 0)
|
||||||
|
{
|
||||||
|
for ( i = 0; i < length; i++ )
|
||||||
|
{
|
||||||
|
/* As long as the receive FIFO is not empty, data can be received. */
|
||||||
|
SSP_SSP0DR = 0xFF;
|
||||||
|
|
||||||
|
/* Wait until the Busy bit is cleared */
|
||||||
|
while ( (SSP_SSP0SR & (SSP_SSP0SR_BSY_BUSY|SSP_SSP0SR_RNE_NOTEMPTY)) != SSP_SSP0SR_RNE_NOTEMPTY );
|
||||||
|
|
||||||
|
*buf = SSP_SSP0DR;
|
||||||
|
buf++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file ssp.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _SSP_H_
|
||||||
|
#define _SSP_H_
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
#include "core/gpio/gpio.h"
|
||||||
|
|
||||||
|
#define SSP_FIFOSIZE 8 /* SPI read and write buffer size */
|
||||||
|
#define SSP_MAX_TIMEOUT 0xFF
|
||||||
|
|
||||||
|
#define SSP0_CSPORT 0
|
||||||
|
#define SSP0_CSPIN 2
|
||||||
|
|
||||||
|
/* Macro definitions to enable and disable SPI */
|
||||||
|
#define ssp0Select() do {gpioSetValue(SSP0_CSPORT, SSP0_CSPIN, 0);} while (0)
|
||||||
|
#define ssp0Deselect() do {gpioSetValue(SSP0_CSPORT, SSP0_CSPIN, 1);} while (0)
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Indicates whether the clock should be high or low between frames.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
typedef enum sspClockPolarity_e
|
||||||
|
{
|
||||||
|
sspClockPolarity_Low = 0,
|
||||||
|
sspClockPolarity_High
|
||||||
|
}
|
||||||
|
sspClockPolarity_t;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Indicates whether the bits start at the rising or falling edge of
|
||||||
|
the clock transition.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
typedef enum sspClockPhase_e
|
||||||
|
{
|
||||||
|
sspClockPhase_RisingEdge = 0,
|
||||||
|
sspClockPhase_FallingEdge
|
||||||
|
}
|
||||||
|
sspClockPhase_t;
|
||||||
|
|
||||||
|
extern void SSP_IRQHandler (void);
|
||||||
|
void sspInit (uint8_t portNum, sspClockPolarity_t polarity, sspClockPhase_t phase);
|
||||||
|
void sspSend (uint8_t portNum, uint8_t *buf, uint32_t length);
|
||||||
|
void sspReceive (uint8_t portNum, uint8_t *buf, uint32_t length);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,65 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file sysdefs.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _SYSDEFS_H_
|
||||||
|
#define _SYSDEFS_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
// Stay compatible with ugly "windows" style
|
||||||
|
#define BOOL bool
|
||||||
|
#define TRUE true
|
||||||
|
#define FALSE false
|
||||||
|
|
||||||
|
typedef volatile uint8_t REG8;
|
||||||
|
typedef volatile uint16_t REG16;
|
||||||
|
typedef volatile uint32_t REG32;
|
||||||
|
typedef unsigned char byte_t;
|
||||||
|
|
||||||
|
#define pREG8 (REG8 *)
|
||||||
|
#define pREG16 (REG16 *)
|
||||||
|
#define pREG32 (REG32 *)
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL ((void *) 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,280 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file sysinit.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "sysinit.h"
|
||||||
|
|
||||||
|
#include "core/cpu/cpu.h"
|
||||||
|
#include "core/pmu/pmu.h"
|
||||||
|
#include "core/adc/adc.h"
|
||||||
|
|
||||||
|
#ifdef CFG_PRINTF_UART
|
||||||
|
#include "core/uart/uart.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CFG_INTERFACE
|
||||||
|
#include "core/cmd/cmd.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CFG_CHIBI
|
||||||
|
#include "drivers/chibi/chb.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CFG_USBHID
|
||||||
|
#include "core/usbhid-rom/usbhid.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CFG_USBCDC
|
||||||
|
volatile unsigned int lastTick;
|
||||||
|
#include "core/usbcdc/usb.h"
|
||||||
|
#include "core/usbcdc/usbcore.h"
|
||||||
|
#include "core/usbcdc/usbhw.h"
|
||||||
|
#include "core/usbcdc/cdcuser.h"
|
||||||
|
#include "core/usbcdc/cdc_buf.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CFG_ST7565
|
||||||
|
#include "drivers/lcd/bitmap/st7565/st7565.h"
|
||||||
|
#include "drivers/lcd/smallfonts.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CFG_SSD1306
|
||||||
|
#include "drivers/lcd/bitmap/ssd1306/ssd1306.h"
|
||||||
|
#include "drivers/lcd/smallfonts.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CFG_TFTLCD
|
||||||
|
#include "drivers/lcd/tft/lcd.h"
|
||||||
|
#include "drivers/lcd/tft/touchscreen.h"
|
||||||
|
#include "drivers/lcd/tft/drawing.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CFG_I2CEEPROM
|
||||||
|
#include "drivers/eeprom/mcp24aa/mcp24aa.h"
|
||||||
|
#include "drivers/eeprom/eeprom.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CFG_PWM
|
||||||
|
#include "core/pwm/pwm.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CFG_SDCARD
|
||||||
|
#include "core/ssp/ssp.h"
|
||||||
|
#include "drivers/fatfs/diskio.h"
|
||||||
|
#include "drivers/fatfs/ff.h"
|
||||||
|
|
||||||
|
DWORD get_fattime ()
|
||||||
|
{
|
||||||
|
// ToDo!
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Configures the core system clock and sets up any mandatory
|
||||||
|
peripherals like the systick timer, UART for printf, etc.
|
||||||
|
|
||||||
|
This function should set the HW to the default state you wish to be
|
||||||
|
in coming out of reset/startup, such as disabling or enabling LEDs,
|
||||||
|
setting specific pin states, etc.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void systemInit()
|
||||||
|
{
|
||||||
|
cpuInit(); // Configure the CPU
|
||||||
|
systickInit(CFG_SYSTICK_DELAY_IN_MS); // Start systick timer
|
||||||
|
gpioInit(); // Enable GPIO
|
||||||
|
pmuInit(); // Configure power management
|
||||||
|
adcInit(); // Config adc pins to save power
|
||||||
|
|
||||||
|
// Set LED pin as output and turn LED off
|
||||||
|
gpioSetDir(CFG_LED_PORT, CFG_LED_PIN, 1);
|
||||||
|
gpioSetValue(CFG_LED_PORT, CFG_LED_PIN, CFG_LED_OFF);
|
||||||
|
|
||||||
|
// Initialise EEPROM
|
||||||
|
#ifdef CFG_I2CEEPROM
|
||||||
|
mcp24aaInit();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialise UART with the default baud rate
|
||||||
|
#ifdef CFG_PRINTF_UART
|
||||||
|
uint32_t uart = eepromReadU32(CFG_EEPROM_UART_SPEED);
|
||||||
|
if ((uart == 0xFFFFFFFF) || (uart > 115200))
|
||||||
|
{
|
||||||
|
uartInit(CFG_UART_BAUDRATE); // Use default baud rate
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uartInit(uart); // Use baud rate from EEPROM
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialise PWM (requires 16-bit Timer 1 and P1.9)
|
||||||
|
#ifdef CFG_PWM
|
||||||
|
pwmInit();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialise USB HID
|
||||||
|
#ifdef CFG_USBHID
|
||||||
|
usbHIDInit();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialise USB CDC
|
||||||
|
#ifdef CFG_USBCDC
|
||||||
|
lastTick = systickGetTicks(); // Used to control output/printf timing
|
||||||
|
CDC_Init(); // Initialise VCOM
|
||||||
|
USB_Init(); // USB Initialization
|
||||||
|
USB_Connect(TRUE); // USB Connect
|
||||||
|
// Wait until USB is configured or timeout occurs
|
||||||
|
uint32_t usbTimeout = 0;
|
||||||
|
while ( usbTimeout < CFG_USBCDC_INITTIMEOUT / 10 )
|
||||||
|
{
|
||||||
|
if (USB_Configuration) break;
|
||||||
|
systickDelay(10); // Wait 10ms
|
||||||
|
usbTimeout++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Printf can now be used with UART or USBCDC
|
||||||
|
|
||||||
|
// Initialise the ST7565 128x64 pixel display
|
||||||
|
#ifdef CFG_ST7565
|
||||||
|
st7565Init();
|
||||||
|
st7565ClearScreen(); // Clear the screen
|
||||||
|
st7565Backlight(1); // Enable the backlight
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialise the SSD1306 OLED display
|
||||||
|
#ifdef CFG_SSD1306
|
||||||
|
ssd1306Init(SSD1306_SWITCHCAPVCC);
|
||||||
|
ssd1306ClearScreen(); // Clear the screen
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialise TFT LCD Display
|
||||||
|
#ifdef CFG_TFTLCD
|
||||||
|
lcdInit();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Initialise Chibi
|
||||||
|
// Warning: CFG_CHIBI must be disabled if no antenna is connected,
|
||||||
|
// otherwise the SW will halt during initialisation
|
||||||
|
#ifdef CFG_CHIBI
|
||||||
|
// Write addresses to EEPROM for the first time if necessary
|
||||||
|
// uint16_t addr_short = 0x0025;
|
||||||
|
// uint64_t addr_ieee = 0x0000000000000025;
|
||||||
|
// mcp24aaWriteBuffer(CFG_EEPROM_CHIBI_SHORTADDR, (uint8_t *)&addr_short, 2);
|
||||||
|
// mcp24aaWriteBuffer(CFG_EEPROM_CHIBI_IEEEADDR, (uint8_t *)&addr_ieee, 8);
|
||||||
|
chb_init();
|
||||||
|
// chb_pcb_t *pcb = chb_get_pcb();
|
||||||
|
// printf("%-40s : 0x%04X%s", "Chibi Initialised", pcb->src_addr, CFG_PRINTF_NEWLINE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Start the command line interface
|
||||||
|
#ifdef CFG_INTERFACE
|
||||||
|
cmdInit();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Sends a single byte to a pre-determined peripheral (UART, etc.).
|
||||||
|
|
||||||
|
@param[in] byte
|
||||||
|
Byte value to send
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void __putchar(const char c)
|
||||||
|
{
|
||||||
|
#ifdef CFG_PRINTF_UART
|
||||||
|
// Send output to UART
|
||||||
|
uartSendByte(c);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CFG_USBCDC
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Sends a string to a pre-determined end point (UART, etc.).
|
||||||
|
|
||||||
|
@param[in] str
|
||||||
|
Text to send
|
||||||
|
|
||||||
|
@note This function is only called when using the GCC-compiler
|
||||||
|
in Codelite or running the Makefile manually. This function
|
||||||
|
will not be called when using the C library in Crossworks for
|
||||||
|
ARM.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
int puts(const char * str)
|
||||||
|
{
|
||||||
|
// There must be at least 1ms between USB frames (of up to 64 bytes)
|
||||||
|
// This buffers all data and writes it out from the buffer one frame
|
||||||
|
// and one millisecond at a time
|
||||||
|
#ifdef CFG_PRINTF_USBCDC
|
||||||
|
if (USB_Configuration)
|
||||||
|
{
|
||||||
|
while(*str)
|
||||||
|
cdcBufferWrite(*str++);
|
||||||
|
// Check if we can flush the buffer now or if we need to wait
|
||||||
|
unsigned int currentTick = systickGetTicks();
|
||||||
|
if (currentTick != lastTick)
|
||||||
|
{
|
||||||
|
uint8_t frame[64];
|
||||||
|
uint32_t bytesRead = 0;
|
||||||
|
while (cdcBufferDataPending())
|
||||||
|
{
|
||||||
|
// Read up to 64 bytes as long as possible
|
||||||
|
bytesRead = cdcBufferReadLen(frame, 64);
|
||||||
|
USB_WriteEP (CDC_DEP_IN, frame, bytesRead);
|
||||||
|
systickDelay(1);
|
||||||
|
}
|
||||||
|
lastTick = currentTick;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Handle output character by character in __putchar
|
||||||
|
while(*str) __putchar(*str++);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,50 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file sysinit.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __SYSINIT_H__
|
||||||
|
#define __SYSINIT_H__
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
#include "core/gpio/gpio.h"
|
||||||
|
#include "core/systick/systick.h"
|
||||||
|
|
||||||
|
// Function prototypes
|
||||||
|
void systemInit();
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,229 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file systick.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section DESCRIPTION
|
||||||
|
|
||||||
|
Controls the 24-bit 'system tick' clock, which can be used as a
|
||||||
|
generic timer or to control time sharing with an embedded real-time
|
||||||
|
operating system (such as FreeRTOS).
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
#include "core/cpu/cpu.h"
|
||||||
|
#include "core/systick/systick.h"
|
||||||
|
|
||||||
|
void main (void)
|
||||||
|
{
|
||||||
|
cpuInit();
|
||||||
|
|
||||||
|
// Start systick timer with one tick every 10ms
|
||||||
|
systickInit(10);
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "systick.h"
|
||||||
|
|
||||||
|
#ifdef CFG_SDCARD
|
||||||
|
#include "drivers/fatfs/diskio.h"
|
||||||
|
volatile uint32_t fatTicks = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
volatile uint32_t systickTicks = 0; // 1ms tick counter
|
||||||
|
volatile uint32_t systickRollovers = 0;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Systick interrupt handler
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void SysTick_Handler (void)
|
||||||
|
{
|
||||||
|
systickTicks++;
|
||||||
|
|
||||||
|
// Increment rollover counter
|
||||||
|
if (systickTicks == 0xFFFFFFFF) systickRollovers++;
|
||||||
|
|
||||||
|
#ifdef CFG_SDCARD
|
||||||
|
fatTicks++;
|
||||||
|
if (fatTicks == 10)
|
||||||
|
{
|
||||||
|
fatTicks = 0;
|
||||||
|
disk_timerproc();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Configures the systick timer
|
||||||
|
|
||||||
|
@param[in] ticks
|
||||||
|
The number of clock cycles between each tick of the
|
||||||
|
systick timer. for example, 'CFG_CPU_CCLK / 1000' =
|
||||||
|
1 millisecond. This value must not exceed 0x00FFFFFF.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
static uint32_t systickConfig(uint32_t ticks)
|
||||||
|
{
|
||||||
|
// Check if 'ticks' is greater than maximum value
|
||||||
|
if (ticks > SYSTICK_STRELOAD_MASK)
|
||||||
|
{
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset counter
|
||||||
|
systickTicks = 0;
|
||||||
|
|
||||||
|
// Set reload register
|
||||||
|
SYSTICK_STRELOAD = (ticks & SYSTICK_STRELOAD_MASK) - 1;
|
||||||
|
|
||||||
|
// Load the systick counter value
|
||||||
|
SYSTICK_STCURR = 0;
|
||||||
|
|
||||||
|
// Enable systick IRQ and timer
|
||||||
|
SYSTICK_STCTRL = SYSTICK_STCTRL_CLKSOURCE |
|
||||||
|
SYSTICK_STCTRL_TICKINT |
|
||||||
|
SYSTICK_STCTRL_ENABLE;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Initialises the systick timer
|
||||||
|
|
||||||
|
@param[in] delayMs
|
||||||
|
The number of milliseconds between each tick of the systick
|
||||||
|
timer.
|
||||||
|
|
||||||
|
@note The shortest possible delay is 1 millisecond, which will
|
||||||
|
allow fine grained delays, but will cause more load on the
|
||||||
|
system than a 10mS delay. The resolution of the systick
|
||||||
|
timer needs to be balanced with the amount of processing
|
||||||
|
time you can spare. The delay should really only be set
|
||||||
|
to 1 mS if you genuinely have a need for 1mS delays,
|
||||||
|
otherwise a higher value like 5 or 10 mS is probably
|
||||||
|
more appropriate.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void systickInit (uint32_t delayMs)
|
||||||
|
{
|
||||||
|
systickConfig ((CFG_CPU_CCLK / 1000) * delayMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Causes a blocking delay for 'delayTicks' ticks on the
|
||||||
|
systick timer. For example: systickDelay(100) would cause
|
||||||
|
a blocking delay for 100 ticks of the systick timer.
|
||||||
|
|
||||||
|
@param[in] delayTicks
|
||||||
|
The number of systick ticks to cause a blocking delay for
|
||||||
|
|
||||||
|
@Note This function takes into account the fact that the tick
|
||||||
|
counter may eventually roll over to 0 once it reaches
|
||||||
|
0xFFFFFFFF.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void systickDelay (uint32_t delayTicks)
|
||||||
|
{
|
||||||
|
uint32_t curTicks;
|
||||||
|
curTicks = systickTicks;
|
||||||
|
|
||||||
|
// Make sure delay is at least 1 tick in case of division, etc.
|
||||||
|
if (delayTicks == 0) delayTicks = 1;
|
||||||
|
|
||||||
|
if (curTicks > 0xFFFFFFFF - delayTicks)
|
||||||
|
{
|
||||||
|
// Rollover will occur during delay
|
||||||
|
while (systickTicks >= curTicks)
|
||||||
|
{
|
||||||
|
while (systickTicks < (delayTicks - (0xFFFFFFFF - curTicks)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while ((systickTicks - curTicks) < delayTicks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Returns the current value of the systick timer counter.
|
||||||
|
This value is incremented by one every time an interrupt
|
||||||
|
fires for the systick timer.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
uint32_t systickGetTicks(void)
|
||||||
|
{
|
||||||
|
return systickTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Returns the current value of the systick timer rollover
|
||||||
|
counter. This value is incremented by one every time the
|
||||||
|
tick counter rolls over from 0xFFFFFFFF to 0.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
uint32_t systickGetRollovers(void)
|
||||||
|
{
|
||||||
|
return systickRollovers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Returns the approximate number of seconds that the
|
||||||
|
systick timer has been running.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
uint32_t systickGetSecondsActive(void)
|
||||||
|
{
|
||||||
|
uint32_t currentTick = systickTicks;
|
||||||
|
uint32_t rollovers = systickRollovers;
|
||||||
|
uint32_t secsActive = currentTick / (1000 / CFG_SYSTICK_DELAY_IN_MS);
|
||||||
|
secsActive += rollovers * (0xFFFFFFFF / (1000 / CFG_SYSTICK_DELAY_IN_MS));
|
||||||
|
|
||||||
|
return secsActive;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file systick.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _SYSTICK_H_
|
||||||
|
#define _SYSTICK_H_
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
void systickInit (uint32_t delayMs);
|
||||||
|
void systickDelay (uint32_t delayTicks);
|
||||||
|
uint32_t systickGetTicks(void);
|
||||||
|
uint32_t systickGetRollovers(void);
|
||||||
|
uint32_t systickGetSecondsActive(void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,505 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file timer16.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
|
||||||
|
@section DESCRIPTION
|
||||||
|
|
||||||
|
Generic code for both 16-bit timers.
|
||||||
|
|
||||||
|
@warning 16-bit timers are limited to roughly ~0.91ms (or 910uS) on
|
||||||
|
a system running at 72MHz since:
|
||||||
|
@code
|
||||||
|
1 mS = CFG_CPU_CCLK / 1000
|
||||||
|
= 72000000 / 1000
|
||||||
|
= 72000 'ticks'
|
||||||
|
@endcode
|
||||||
|
Meaning that 0xFFFF (65535) 'ticks' = 0.910208 milliseconds
|
||||||
|
or 910 microseconds.
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
#include "/core/cpu/cpu.h"
|
||||||
|
#include "/core/timer16/timer16.h"
|
||||||
|
|
||||||
|
// Instantiated in timer16.h
|
||||||
|
extern volatile uint32_t timer16_0_counter;
|
||||||
|
...
|
||||||
|
cpuInit();
|
||||||
|
|
||||||
|
// Initialise timer0 with a delay of 0xFFFF, which will cause the
|
||||||
|
// timer interrupt to fire every 65535 ticks and increment
|
||||||
|
// timer16_0_counter by 1
|
||||||
|
timer16Init(0, 0xFFFF);
|
||||||
|
|
||||||
|
// Enable the timer
|
||||||
|
timer16Enable(0);
|
||||||
|
|
||||||
|
// At this point timer16_0_counter should start incrementing by 1
|
||||||
|
// every 65535 ticks
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "timer16.h"
|
||||||
|
|
||||||
|
volatile uint32_t timer16_0_counter = 0;
|
||||||
|
volatile uint32_t timer16_1_counter = 0;
|
||||||
|
|
||||||
|
#ifdef CFG_PWM
|
||||||
|
volatile uint32_t pwmCounter = 0;
|
||||||
|
extern volatile uint32_t pwmMaxPulses; // See drivers/pwm/pwm.c
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Causes a blocking delay for the specified number of
|
||||||
|
clock ticks.
|
||||||
|
|
||||||
|
@note The exact duration of this delay depends on the speed of the
|
||||||
|
system clock, but it will invariably be short because of the
|
||||||
|
16-bit limitation. For example, on a system with a 72MHz
|
||||||
|
clock, a 1mS delay would be equal to 72,000 ticks, which is
|
||||||
|
already above the maximum 16-bit value of 65,535. Thus, the
|
||||||
|
maximum delay measured in mS with a 72MHz clock is ~0.91mS.
|
||||||
|
|
||||||
|
@param[in] timerNum
|
||||||
|
The 16-bit timer to user (0..1)
|
||||||
|
@param[in] delayInTicks
|
||||||
|
The number of clock ticks to delay (0..65534)
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
#include "/core/cpu/cpu.h"
|
||||||
|
#include "/core/timer16/timer16.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
cpuInit();
|
||||||
|
|
||||||
|
// Initialise timer 0 ... delay is provided but not used here
|
||||||
|
timer16Init(0, 0xFFFF);
|
||||||
|
|
||||||
|
// Enable the timer
|
||||||
|
timer16Enable(0);
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Cause blocking delay for 36000 ticks (0.5mS @ 72MHz)
|
||||||
|
// Note: The delay must be 65534 or less (16-bit value)
|
||||||
|
timer16DelayTicks(0, 36000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void timer16DelayTicks(uint8_t timerNum, uint16_t delayInTicks)
|
||||||
|
{
|
||||||
|
// ToDo: Verify incoming value
|
||||||
|
|
||||||
|
if (timerNum == 0)
|
||||||
|
{
|
||||||
|
/* Reset the timer */
|
||||||
|
TMR_TMR16B0TCR = TMR_TMR16B0TCR_COUNTERRESET_ENABLED;
|
||||||
|
|
||||||
|
/* Set the prescaler to zero */
|
||||||
|
TMR_TMR16B0PR = 0x00;
|
||||||
|
|
||||||
|
TMR_TMR16B0MR0 = delayInTicks;
|
||||||
|
|
||||||
|
/* Reset all interrupts */
|
||||||
|
TMR_TMR16B0IR = TMR_TMR16B0IR_MASK_ALL;
|
||||||
|
|
||||||
|
/* Stop timer on match (MR0) */
|
||||||
|
TMR_TMR16B0MCR = TMR_TMR16B0MCR_MR0_STOP_ENABLED;
|
||||||
|
|
||||||
|
/* Start timer */
|
||||||
|
TMR_TMR16B0TCR = TMR_TMR16B0TCR_COUNTERENABLE_ENABLED;
|
||||||
|
|
||||||
|
/* Wait until the delay time has elapsed */
|
||||||
|
while (TMR_TMR16B0TCR & TMR_TMR16B0TCR_COUNTERENABLE_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (timerNum == 1)
|
||||||
|
{
|
||||||
|
/* Reset the timer */
|
||||||
|
TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERRESET_ENABLED;
|
||||||
|
|
||||||
|
/* Set the prescaler to zero */
|
||||||
|
TMR_TMR16B1PR = 0x00;
|
||||||
|
|
||||||
|
TMR_TMR16B1MR0 = delayInTicks;
|
||||||
|
|
||||||
|
/* Reset all interrupts */
|
||||||
|
TMR_TMR16B1IR = TMR_TMR16B1IR_MASK_ALL;
|
||||||
|
|
||||||
|
/* Stop timer on match (MR0) */
|
||||||
|
TMR_TMR16B1MCR = TMR_TMR16B1MCR_MR0_STOP_ENABLED;
|
||||||
|
|
||||||
|
/* Start timer */
|
||||||
|
TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERENABLE_ENABLED;
|
||||||
|
|
||||||
|
/* Wait until the delay time has elapsed */
|
||||||
|
while (TMR_TMR16B1TCR & TMR_TMR16B1TCR_COUNTERENABLE_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Causes a blocking delay for the specified number of
|
||||||
|
microseconds
|
||||||
|
|
||||||
|
@warning The maximum delay in uS will depend on the clock speed,
|
||||||
|
but running at 72MHz the maximum delay (MR = 0xFFFF)
|
||||||
|
would be 910uS (0xFFFF / 72 = 910), or 0.91 milliseconds.
|
||||||
|
|
||||||
|
@param[in] timerNum
|
||||||
|
The 16-bit timer to user (0..1)
|
||||||
|
@param[in] delayInUs
|
||||||
|
The number of microseconds to wait
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
#include "/core/cpu/cpu.h"
|
||||||
|
#include "/core/timer16/timer16.h"
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
cpuInit();
|
||||||
|
|
||||||
|
// Initialise timer 0 ... delay is provided but not used here
|
||||||
|
timer16Init(0, 0xFFFF);
|
||||||
|
|
||||||
|
// Enable the timer
|
||||||
|
timer16Enable(0);
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Cause blocking delay for 500 microseconds (0.5mS)
|
||||||
|
timer16DelayUS(0, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void timer16DelayUS(uint8_t timerNum, uint16_t delayInUS)
|
||||||
|
{
|
||||||
|
// ToDo: Check if the appropriate timer is enabled first?
|
||||||
|
|
||||||
|
if (timerNum == 0)
|
||||||
|
{
|
||||||
|
/* Reset the timer */
|
||||||
|
TMR_TMR16B0TCR = TMR_TMR16B0TCR_COUNTERRESET_ENABLED;
|
||||||
|
|
||||||
|
/* Set the prescaler to zero */
|
||||||
|
TMR_TMR16B0PR = 0x00;
|
||||||
|
|
||||||
|
TMR_TMR16B0MR0 = delayInUS * ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV)/1000000);
|
||||||
|
|
||||||
|
/* Reset all interrupts */
|
||||||
|
TMR_TMR16B0IR = TMR_TMR16B0IR_MASK_ALL;
|
||||||
|
|
||||||
|
/* Stop timer on match (MR0) */
|
||||||
|
TMR_TMR16B0MCR = TMR_TMR16B0MCR_MR0_STOP_ENABLED;
|
||||||
|
|
||||||
|
/* Start timer */
|
||||||
|
TMR_TMR16B0TCR = TMR_TMR16B0TCR_COUNTERENABLE_ENABLED;
|
||||||
|
|
||||||
|
/* Wait until the delay time has elapsed */
|
||||||
|
while (TMR_TMR16B0TCR & TMR_TMR16B0TCR_COUNTERENABLE_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (timerNum == 1)
|
||||||
|
{
|
||||||
|
/* Reset the timer */
|
||||||
|
TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERRESET_ENABLED;
|
||||||
|
|
||||||
|
/* Set the prescaler to zero */
|
||||||
|
TMR_TMR16B1PR = 0x00;
|
||||||
|
|
||||||
|
TMR_TMR16B1MR0 = delayInUS * ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV)/1000000);
|
||||||
|
|
||||||
|
/* Reset all interrupts */
|
||||||
|
TMR_TMR16B1IR = TMR_TMR16B1IR_MASK_ALL;
|
||||||
|
|
||||||
|
/* Stop timer on match (MR0) */
|
||||||
|
TMR_TMR16B1MCR = TMR_TMR16B1MCR_MR0_STOP_ENABLED;
|
||||||
|
|
||||||
|
/* Start timer */
|
||||||
|
TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERENABLE_ENABLED;
|
||||||
|
|
||||||
|
/* Wait until the delay time has elapsed */
|
||||||
|
while (TMR_TMR16B1TCR & TMR_TMR16B1TCR_COUNTERENABLE_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Interrupt handler for 16-bit timer 0
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void TIMER16_0_IRQHandler(void)
|
||||||
|
{
|
||||||
|
/* Clear the interrupt flag */
|
||||||
|
TMR_TMR16B0IR = TMR_TMR16B0IR_MR0;
|
||||||
|
|
||||||
|
/* Increment timer counter by 1 (it will automatically roll back to 0) */
|
||||||
|
timer16_0_counter++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Interrupt handler for 16-bit timer 1
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void TIMER16_1_IRQHandler(void)
|
||||||
|
{
|
||||||
|
/* Clear the interrupt flag */
|
||||||
|
TMR_TMR16B1IR = TMR_TMR16B1IR_MR0;
|
||||||
|
|
||||||
|
/* Increment timer counter by 1 (it will automatically roll back to 0) */
|
||||||
|
timer16_1_counter++;
|
||||||
|
|
||||||
|
#ifdef CFG_PWM
|
||||||
|
/* Check if the PWM output should be disabled after pwmMaxPulses pulses */
|
||||||
|
/* See "drivers/pwm/pwm.c" */
|
||||||
|
if (TMR_TMR16B1IR & TMR_TMR16B1IR_MR3)
|
||||||
|
{
|
||||||
|
/* Clear the interrupt flag */
|
||||||
|
TMR_TMR16B1IR = TMR_TMR16B1IR_MR3;
|
||||||
|
|
||||||
|
if (pwmMaxPulses > 0)
|
||||||
|
{
|
||||||
|
pwmCounter++;
|
||||||
|
if (pwmCounter == pwmMaxPulses)
|
||||||
|
{
|
||||||
|
/* Disable interrupt on MR3 */
|
||||||
|
TMR_TMR16B1MCR &= ~(TMR_TMR16B1MCR_MR3_INT_MASK);
|
||||||
|
/* Disable Timer */
|
||||||
|
TMR_TMR16B1TCR &= ~(TMR_TMR16B1TCR_COUNTERENABLE_MASK);
|
||||||
|
/* Reset the counter variables */
|
||||||
|
pwmCounter = 0;
|
||||||
|
pwmMaxPulses = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Enables the specified timer
|
||||||
|
|
||||||
|
@param[in] timerNum
|
||||||
|
The 16-bit timer to enable (0..1)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void timer16Enable(uint8_t timerNum)
|
||||||
|
{
|
||||||
|
if ( timerNum == 0 )
|
||||||
|
{
|
||||||
|
TMR_TMR16B0TCR = TMR_TMR16B0TCR_COUNTERENABLE_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (timerNum == 1)
|
||||||
|
{
|
||||||
|
TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERENABLE_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Disables the specified timer
|
||||||
|
|
||||||
|
@param[in] timerNum
|
||||||
|
The 16-bit timer to disable (0..1)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void timer16Disable(uint8_t timerNum)
|
||||||
|
{
|
||||||
|
if ( timerNum == 0 )
|
||||||
|
{
|
||||||
|
TMR_TMR16B0TCR = TMR_TMR16B0TCR_COUNTERENABLE_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (timerNum == 1)
|
||||||
|
{
|
||||||
|
TMR_TMR16B1TCR = TMR_TMR16B1TCR_COUNTERENABLE_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Resets the specified timer
|
||||||
|
|
||||||
|
@param[in] timerNum
|
||||||
|
The 16-bit timer to reset (0..1)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void timer16Reset(uint8_t timerNum)
|
||||||
|
{
|
||||||
|
uint32_t regVal;
|
||||||
|
|
||||||
|
if ( timerNum == 0 )
|
||||||
|
{
|
||||||
|
regVal = TMR_TMR16B0TCR;
|
||||||
|
regVal |= TMR_TMR16B0TCR_COUNTERRESET_ENABLED;
|
||||||
|
TMR_TMR16B0TCR = regVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (timerNum == 1)
|
||||||
|
{
|
||||||
|
regVal = TMR_TMR16B1TCR;
|
||||||
|
regVal |= TMR_TMR16B1TCR_COUNTERRESET_ENABLED;
|
||||||
|
TMR_TMR16B1TCR = regVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Initialises the specified 16-bit timer, sets the timer
|
||||||
|
interval, resets the timer, and configures the interrupt
|
||||||
|
handler.
|
||||||
|
|
||||||
|
Initialises a 16-bit timer with the supplied timer interval (the
|
||||||
|
amount of time that passes between each timer 'tick'). Every time that
|
||||||
|
this interval elapses, the timer's interrupt will be fired and the
|
||||||
|
appropriate counter variable will be incremented by one (For example,
|
||||||
|
with CT16B0, 'timer16_0_counter' would be incremented).
|
||||||
|
|
||||||
|
@param[in] timerNum
|
||||||
|
The 16-bit timer to initiliase (0..1)
|
||||||
|
@param[in] timerInterval
|
||||||
|
The number of clock 'ticks' between resets (0..65534)
|
||||||
|
|
||||||
|
@warning Care needs to be taken when configuring the timers since
|
||||||
|
the pins are all multiplexed with other peripherals. This
|
||||||
|
code is provided as a starting point, but it will need to
|
||||||
|
be adjusted according to your own situation and
|
||||||
|
pin/peripheral requirements
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void timer16Init(uint8_t timerNum, uint16_t timerInterval)
|
||||||
|
{
|
||||||
|
// If timerInterval is invalid, use the default value
|
||||||
|
if (timerInterval < 1)
|
||||||
|
{
|
||||||
|
timerInterval = TIMER16_DEFAULTINTERVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( timerNum == 0 )
|
||||||
|
{
|
||||||
|
/* Enable the clock for CT16B0 */
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT16B0);
|
||||||
|
|
||||||
|
/* The physical pins associated with CT16B0 are not enabled by
|
||||||
|
default in order to avoid conflicts with other peripherals.
|
||||||
|
Pin 0.10 (CT16B0_MAT2), for example, can not be used while
|
||||||
|
debugging with a hardware debugger. If you require one or
|
||||||
|
more of these pins, simply uncomment the code below */
|
||||||
|
|
||||||
|
/* Configure PIO0.2 as Timer0_16 CAP0 */
|
||||||
|
// IOCON_PIO0_2 &= ~IOCON_PIO0_2_FUNC_MASK;
|
||||||
|
// IOCON_PIO0_2 |= IOCON_PIO0_2_FUNC_CT16B0_CAP0;
|
||||||
|
|
||||||
|
/* Configure PIO0.8 as Timer0_16 MAT0 */
|
||||||
|
// IOCON_PIO0_8 &= ~IOCON_PIO0_8_FUNC_MASK;
|
||||||
|
// IOCON_PIO0_8 |= IOCON_PIO0_8_FUNC_CT16B0_MAT0;
|
||||||
|
|
||||||
|
/* Configure PIO0.9 as Timer0_16 MAT1 */
|
||||||
|
// IOCON_PIO0_9 &= ~IOCON_PIO0_9_FUNC_MASK;
|
||||||
|
// IOCON_PIO0_9 |= IOCON_PIO0_9_FUNC_CT16B0_MAT1;
|
||||||
|
|
||||||
|
/* Configure PIO0.10 as Timer0_16 MAT3 */
|
||||||
|
// IOCON_JTAG_TCK_PIO0_10 &= ~IOCON_JTAG_TCK_PIO0_10_FUNC_MASK;
|
||||||
|
// IOCON_JTAG_TCK_PIO0_10 |= IOCON_JTAG_TCK_PIO0_10_FUNC_CT16B0_MAT2;
|
||||||
|
|
||||||
|
timer16_0_counter = 0;
|
||||||
|
TMR_TMR16B0MR0 = timerInterval;
|
||||||
|
|
||||||
|
/* Configure match control register to raise an interrupt and reset on MR0 */
|
||||||
|
TMR_TMR16B0MCR = (TMR_TMR16B0MCR_MR0_INT_ENABLED | TMR_TMR16B0MCR_MR0_RESET_ENABLED);
|
||||||
|
|
||||||
|
/* Enable the TIMER0 interrupt */
|
||||||
|
NVIC_EnableIRQ(TIMER_16_0_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ( timerNum == 1 )
|
||||||
|
{
|
||||||
|
/* Enable the clock for CT16B1 */
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT16B1);
|
||||||
|
|
||||||
|
/* The physical pins associated with CT16B0 are not enabled by
|
||||||
|
default in order to avoid conflicts with other peripherals.
|
||||||
|
Pin 0.10 (CT16B0_MAT2), for example, can not be used while
|
||||||
|
debugging with a hardware debugger. If you require one or
|
||||||
|
more of these pins, simply uncomment the code below */
|
||||||
|
|
||||||
|
/* Configure PIO1.8 as Timer1_16 CAP0 */
|
||||||
|
// IOCON_PIO1_8 &= ~IOCON_PIO1_8_FUNC_MASK;
|
||||||
|
// IOCON_PIO1_8 |= IOCON_PIO1_8_FUNC_CT16B1_CAP0;
|
||||||
|
|
||||||
|
/* Configure PIO1.9 as Timer1_16 MAT0 */
|
||||||
|
// IOCON_PIO1_9 &= ~IOCON_PIO1_9_FUNC_MASK;
|
||||||
|
// IOCON_PIO1_9 |= IOCON_PIO1_9_FUNC_CT16B1_MAT0;
|
||||||
|
|
||||||
|
/* Configure PIO1.10 as Timer1_16 MAT1 */
|
||||||
|
// IOCON_PIO1_10 &= ~IOCON_PIO1_10_FUNC_MASK;
|
||||||
|
// IOCON_PIO1_10 |= IOCON_PIO1_10_FUNC_CT16B1_MAT1;
|
||||||
|
|
||||||
|
timer16_1_counter = 0;
|
||||||
|
TMR_TMR16B1MR0 = timerInterval;
|
||||||
|
|
||||||
|
/* Configure match control register to raise an interrupt and reset on MR0 */
|
||||||
|
TMR_TMR16B1MCR = (TMR_TMR16B1MCR_MR0_INT_ENABLED | TMR_TMR16B1MCR_MR0_RESET_ENABLED);
|
||||||
|
|
||||||
|
/* Enable the TIMER1 Interrupt */
|
||||||
|
NVIC_EnableIRQ(TIMER_16_1_IRQn);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file timer16.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __TIMER16_H__
|
||||||
|
#define __TIMER16_H__
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
#define TIMER16_DEFAULTINTERVAL (0xFFFF) // ~0.91mS @ 72MHz, ~1.37mS @ 48MHz
|
||||||
|
|
||||||
|
#define TIMER16_CCLK_100US ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV) / 10000)
|
||||||
|
#define TIMER16_CCLK_1MS ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV) / 1000)
|
||||||
|
|
||||||
|
void TIMER16_0_IRQHandler(void);
|
||||||
|
void TIMER16_1_IRQHandler(void);
|
||||||
|
|
||||||
|
void timer16DelayTicks(uint8_t timerNum, uint16_t delayInTicks);
|
||||||
|
void timer16DelayUS(uint8_t timerNum, uint16_t delayInUS);
|
||||||
|
void timer16Enable(uint8_t timerNum);
|
||||||
|
void timer16Disable(uint8_t timerNum);
|
||||||
|
void timer16Reset(uint8_t timerNum);
|
||||||
|
void timer16Init(uint8_t timerNum, uint16_t timerInterval);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,344 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file timer32.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section DESCRIPTION
|
||||||
|
|
||||||
|
Generic code for 32-bit timers. By default, the timers are configured
|
||||||
|
to generate an interrupt once every 100 microseconds, incrementing a
|
||||||
|
global variable once per tick.
|
||||||
|
|
||||||
|
@warning Please note that the ROM-based USB drivers on the LPC1343
|
||||||
|
require the use of 32-bit Timer 1. If you plan on using the
|
||||||
|
ROM-based USB functionality, you should restrict your timer
|
||||||
|
usage to 32-bit timer 0.
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
#include "/core/cpu/cpu.h"
|
||||||
|
#include "/core/timer32/timer32.h"
|
||||||
|
...
|
||||||
|
cpuInit();
|
||||||
|
|
||||||
|
// Initialise 32-bit timer 0 with 100uS ticks
|
||||||
|
timer32Init(0, TIMER32_DEFAULTINTERVAL);
|
||||||
|
|
||||||
|
// Enable timer 0
|
||||||
|
timer32Enable(0);
|
||||||
|
|
||||||
|
// Cause a blocking delay for 1 second (1000mS)
|
||||||
|
timer32Delay(0, TIMER32_DELAY_1MS * 1000);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "timer32.h"
|
||||||
|
|
||||||
|
volatile uint32_t timer32_0_counter = 0;
|
||||||
|
volatile uint32_t timer32_1_counter = 0;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Causes a blocking delay for the specified number of
|
||||||
|
timer ticks. The duration of each 'tick' is determined by
|
||||||
|
the 'timerInterval' property supplied to timer32Init.
|
||||||
|
|
||||||
|
@param[in] timerNum
|
||||||
|
The 32-bit timer to user (0..1)
|
||||||
|
@param[in] delay
|
||||||
|
The number of counter increments to wait
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void timer32Delay(uint8_t timerNum, uint32_t delay)
|
||||||
|
{
|
||||||
|
uint32_t curTicks;
|
||||||
|
|
||||||
|
if (timerNum == 0)
|
||||||
|
{
|
||||||
|
curTicks = timer32_0_counter;
|
||||||
|
if (curTicks > 0xFFFFFFFF - delay)
|
||||||
|
{
|
||||||
|
// Rollover will occur during delay
|
||||||
|
while (timer32_0_counter >= curTicks)
|
||||||
|
{
|
||||||
|
while (timer32_0_counter < (delay - (0xFFFFFFFF - curTicks)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while ((timer32_0_counter - curTicks) < delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (timerNum == 1)
|
||||||
|
{
|
||||||
|
curTicks = timer32_1_counter;
|
||||||
|
if (curTicks > 0xFFFFFFFF - delay)
|
||||||
|
{
|
||||||
|
// Rollover will occur during delay
|
||||||
|
while (timer32_1_counter >= curTicks)
|
||||||
|
{
|
||||||
|
while (timer32_1_counter < (delay - (0xFFFFFFFF - curTicks)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while ((timer32_1_counter - curTicks) < delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Interrupt handler for 32-bit timer 0
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void TIMER32_0_IRQHandler(void)
|
||||||
|
{
|
||||||
|
/* Clear the interrupt flag */
|
||||||
|
TMR_TMR32B0IR = TMR_TMR32B0IR_MR0;
|
||||||
|
|
||||||
|
/* If you wish to perform some action after each timer 'tick' (such as
|
||||||
|
incrementing a counter variable) you can do so here */
|
||||||
|
timer32_0_counter++;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Interrupt handler for 32-bit timer 1
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void TIMER32_1_IRQHandler(void)
|
||||||
|
{
|
||||||
|
/* Clear the interrupt flag */
|
||||||
|
TMR_TMR32B1IR = TMR_TMR32B1IR_MR0;
|
||||||
|
|
||||||
|
/* If you wish to perform some action after each timer 'tick' (such as
|
||||||
|
incrementing a counter variable) you can do so here */
|
||||||
|
timer32_1_counter++;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Enables the specified timer
|
||||||
|
|
||||||
|
@param[in] timerNum
|
||||||
|
The 32-bit timer to enable (0..1)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void timer32Enable(uint8_t timerNum)
|
||||||
|
{
|
||||||
|
if ( timerNum == 0 )
|
||||||
|
{
|
||||||
|
TMR_TMR32B0TCR = TMR_TMR32B0TCR_COUNTERENABLE_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (timerNum == 1)
|
||||||
|
{
|
||||||
|
TMR_TMR32B1TCR = TMR_TMR32B1TCR_COUNTERENABLE_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Disables the specified timer
|
||||||
|
|
||||||
|
@param[in] timerNum
|
||||||
|
The 32-bit timer to disable (0..1)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void timer32Disable(uint8_t timerNum)
|
||||||
|
{
|
||||||
|
if ( timerNum == 0 )
|
||||||
|
{
|
||||||
|
TMR_TMR32B0TCR = TMR_TMR32B0TCR_COUNTERENABLE_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (timerNum == 1)
|
||||||
|
{
|
||||||
|
TMR_TMR32B1TCR = TMR_TMR32B1TCR_COUNTERENABLE_DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Resets the specified timer
|
||||||
|
|
||||||
|
@param[in] timerNum
|
||||||
|
The 32-bit timer to reset (0..1)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void timer32Reset(uint8_t timerNum)
|
||||||
|
{
|
||||||
|
uint32_t regVal;
|
||||||
|
|
||||||
|
if ( timerNum == 0 )
|
||||||
|
{
|
||||||
|
regVal = TMR_TMR32B0TCR;
|
||||||
|
regVal |= TMR_TMR32B0TCR_COUNTERRESET_ENABLED;
|
||||||
|
TMR_TMR32B0TCR = regVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (timerNum == 1)
|
||||||
|
{
|
||||||
|
regVal = TMR_TMR32B1TCR;
|
||||||
|
regVal |= TMR_TMR32B1TCR_COUNTERRESET_ENABLED;
|
||||||
|
TMR_TMR32B1TCR = regVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Initialises the specified 32-bit timer, and configures the
|
||||||
|
timer to raise an interrupt and reset on match on MR0.
|
||||||
|
|
||||||
|
@param[in] timerNum
|
||||||
|
The 32-bit timer to initiliase (0..1)
|
||||||
|
@param[in] timerInterval
|
||||||
|
The number of clock 'ticks' between resets (0..0xFFFFFFFF)
|
||||||
|
|
||||||
|
@note Care needs to be taken when configuring the timers since the
|
||||||
|
pins are all multiplexed with other peripherals. This code is
|
||||||
|
provided as a starting point, but it will need to be adjusted
|
||||||
|
according to your own situation and pin/peripheral requirements
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void timer32Init(uint8_t timerNum, uint32_t timerInterval)
|
||||||
|
{
|
||||||
|
// If timerInterval is invalid, use the default value
|
||||||
|
if (timerInterval < 1)
|
||||||
|
{
|
||||||
|
timerInterval = TIMER32_DEFAULTINTERVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( timerNum == 0 )
|
||||||
|
{
|
||||||
|
/* Enable the clock for CT32B0 */
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT32B0);
|
||||||
|
|
||||||
|
/* The physical pins associated with CT32B0 are not enabled by
|
||||||
|
default in order to avoid conflicts with other peripherals. If
|
||||||
|
you wish to use any of the pin-dependant functionality, simply
|
||||||
|
uncomment the appropriate lines below. */
|
||||||
|
|
||||||
|
/* Configure PIO1.5 as Timer0_32 CAP0 */
|
||||||
|
// IOCON_PIO1_5 &= ~IOCON_PIO1_5_FUNC_MASK;
|
||||||
|
// IOCON_PIO1_5 |= IOCON_PIO1_5_FUNC_CT32B0_CAP0;
|
||||||
|
|
||||||
|
/* Configure PIO1.6 as Timer0_32 MAT0 */
|
||||||
|
// IOCON_PIO1_6 &= ~IOCON_PIO1_6_FUNC_MASK;
|
||||||
|
// IOCON_PIO1_6 |= IOCON_PIO1_6_FUNC_CT32B0_MAT0;
|
||||||
|
|
||||||
|
/* Configure PIO1.7 as Timer0_32 MAT1 */
|
||||||
|
// IOCON_PIO1_7 &= ~IOCON_PIO1_7_FUNC_MASK;
|
||||||
|
// IOCON_PIO1_7 |= IOCON_PIO1_7_FUNC_CT32B0_MAT1;
|
||||||
|
|
||||||
|
/* Configure PIO0.1 as Timer0_32 MAT2 */
|
||||||
|
// IOCON_PIO0_1 &= ~IOCON_PIO0_1_FUNC_MASK;
|
||||||
|
// IOCON_PIO0_1 |= IOCON_PIO0_1_FUNC_CT32B0_MAT2;
|
||||||
|
|
||||||
|
/* Configure PIO0.11 as Timer0_32 MAT3 */
|
||||||
|
/* Note: This pint can not be used with JTAG/SWD */
|
||||||
|
// IOCON_JTAG_TDI_PIO0_11 &= ~IOCON_JTAG_TDI_PIO0_11_FUNC_MASK;
|
||||||
|
// IOCON_JTAG_TDI_PIO0_11 |= IOCON_JTAG_TDI_PIO0_11_FUNC_CT32B0_MAT3;
|
||||||
|
|
||||||
|
timer32_0_counter = 0;
|
||||||
|
TMR_TMR32B0MR0 = timerInterval;
|
||||||
|
|
||||||
|
/* Configure match control register to raise an interrupt and reset on MR0 */
|
||||||
|
TMR_TMR32B0MCR = (TMR_TMR32B0MCR_MR0_INT_ENABLED | TMR_TMR32B0MCR_MR0_RESET_ENABLED);
|
||||||
|
|
||||||
|
/* Enable the TIMER0 interrupt */
|
||||||
|
NVIC_EnableIRQ(TIMER_32_0_IRQn);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if ( timerNum == 1 )
|
||||||
|
{
|
||||||
|
/* Enable the clock for CT32B1 */
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT32B1);
|
||||||
|
|
||||||
|
/* The physical pins associated with CT32B0 are not enabled by
|
||||||
|
default in order to avoid conflicts with other peripherals. */
|
||||||
|
|
||||||
|
/* Configure PIO1.0 as Timer1_32 CAP0 */
|
||||||
|
/* Note: This pint can not be used with JTAG/SWD */
|
||||||
|
// IOCON_JTAG_TMS_PIO1_0 &= ~IOCON_JTAG_TMS_PIO1_0_FUNC_MASK;
|
||||||
|
// IOCON_JTAG_TMS_PIO1_0 |= IOCON_JTAG_TMS_PIO1_0_FUNC_CT32B1_CAP0;
|
||||||
|
|
||||||
|
/* Configure PIO1.1 as Timer1_32 MAT0 */
|
||||||
|
/* Note: This pint can not be used with JTAG/SWD */
|
||||||
|
// IOCON_JTAG_TDO_PIO1_1 &= ~IOCON_JTAG_TDO_PIO1_1_FUNC_MASK;
|
||||||
|
// IOCON_JTAG_TDO_PIO1_1 |= IOCON_JTAG_TDO_PIO1_1_FUNC_CT32B1_MAT0;
|
||||||
|
|
||||||
|
/* Configure PIO1.2 as Timer1_32 MAT1 */
|
||||||
|
/* Note: This pint can not be used with JTAG/SWD */
|
||||||
|
// IOCON_JTAG_nTRST_PIO1_2 &= ~IOCON_JTAG_nTRST_PIO1_2_FUNC_MASK;
|
||||||
|
// IOCON_JTAG_nTRST_PIO1_2 |= IOCON_JTAG_nTRST_PIO1_2_FUNC_CT32B1_MAT1;
|
||||||
|
|
||||||
|
/* Configure PIO1.3 as Timer1_32 MAT2 */
|
||||||
|
/* Note: This pint can not be used with JTAG/SWD */
|
||||||
|
// IOCON_SWDIO_PIO1_3 &= ~IOCON_SWDIO_PIO1_3_FUNC_MASK;
|
||||||
|
// IOCON_SWDIO_PIO1_3 |= IOCON_SWDIO_PIO1_3_FUNC_CT32B1_MAT2;
|
||||||
|
|
||||||
|
/* Configure PIO1.4 as Timer1_32 MAT3 */
|
||||||
|
// IOCON_PIO1_4 &= ~IOCON_PIO1_4_FUNC_MASK;
|
||||||
|
// IOCON_PIO1_4 |= IOCON_PIO1_4_FUNC_CT32B1_MAT3;
|
||||||
|
|
||||||
|
timer32_1_counter = 0;
|
||||||
|
TMR_TMR32B1MR0 = timerInterval;
|
||||||
|
|
||||||
|
/* Configure match control register to raise an interrupt and reset on MR0 */
|
||||||
|
TMR_TMR32B1MCR = (TMR_TMR32B1MCR_MR0_INT_ENABLED | TMR_TMR32B1MCR_MR0_RESET_ENABLED);
|
||||||
|
|
||||||
|
/* Enable the TIMER1 Interrupt */
|
||||||
|
NVIC_EnableIRQ(TIMER_32_1_IRQn);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file timer32.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __TIMER32_H__
|
||||||
|
#define __TIMER32_H__
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
#define TIMER32_CCLK_1US ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV) / 1000000)
|
||||||
|
#define TIMER32_CCLK_10US ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV) / 100000)
|
||||||
|
#define TIMER32_CCLK_100US ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV) / 10000)
|
||||||
|
#define TIMER32_CCLK_1MS ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV) / 1000)
|
||||||
|
#define TIMER32_CCLK_10MS ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV) / 100)
|
||||||
|
#define TIMER32_CCLK_100MS ((CFG_CPU_CCLK/SCB_SYSAHBCLKDIV) / 10)
|
||||||
|
#define TIMER32_CCLK_1S (CFG_CPU_CCLK/SCB_SYSAHBCLKDIV)
|
||||||
|
#define TIMER32_DEFAULTINTERVAL (TIMER32_CCLK_100US)
|
||||||
|
|
||||||
|
#define TIMER32_DELAY_100US (1) // 100uS delay = 1 tick
|
||||||
|
#define TIMER32_DELAY_1MS (10) // 1mS delay = 10 ticks
|
||||||
|
#define TIMER32_DELAY_1S (10000) // 1S delay = 10000 ticks
|
||||||
|
|
||||||
|
void TIMER32_0_IRQHandler(void);
|
||||||
|
void TIMER32_1_IRQHandler(void);
|
||||||
|
|
||||||
|
void timer32Delay(uint8_t timerNum, uint32_t delay);
|
||||||
|
void timer32Enable(uint8_t timerNum);
|
||||||
|
void timer32Disable(uint8_t timerNum);
|
||||||
|
void timer32Reset(uint8_t timerNum);
|
||||||
|
void timer32Init(uint8_t timerNum, uint32_t timerInterval);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,347 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file uart.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section DESCRIPTION
|
||||||
|
|
||||||
|
Generic code for UART-based communication. Incoming text is stored
|
||||||
|
in a FIFO Queue for safer processing.
|
||||||
|
|
||||||
|
@section Example: Sending text via UART
|
||||||
|
|
||||||
|
@code
|
||||||
|
#include "core/cpu/cpu.h"
|
||||||
|
#include "core/uart/uart.h"
|
||||||
|
...
|
||||||
|
#define UARTBUFFERSIZE 5
|
||||||
|
...
|
||||||
|
cpuInit();
|
||||||
|
uartInit(57600);
|
||||||
|
...
|
||||||
|
uint8_t uartBuffer[UARTBUFFERSIZE] = { 'T', 'e', 's', 't', '\n' };
|
||||||
|
|
||||||
|
// Send contents of uartBuffer
|
||||||
|
uartSend((uint8_t *)uartBuffer, UARTBUFFERSIZE);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@section Example: Reading from UART
|
||||||
|
|
||||||
|
@code
|
||||||
|
|
||||||
|
#include "core/cpu/cpu.h"
|
||||||
|
#include "core/uart/uart.h"
|
||||||
|
|
||||||
|
cpuInit();
|
||||||
|
uartInit(57600);
|
||||||
|
|
||||||
|
// Get a reference to the UART control block
|
||||||
|
uart_pcb_t *pcb = uartGetPCB();
|
||||||
|
|
||||||
|
// Read any text available in the queue
|
||||||
|
while (uartRxBufferDataPending())
|
||||||
|
{
|
||||||
|
// Read the first available character
|
||||||
|
uint8_t c = uartRxBufferRead();
|
||||||
|
|
||||||
|
// read out the data in the buffer and echo it back to the host.
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '\r':
|
||||||
|
printf("\n\r");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("%c", c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endcode
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <string.h>
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
#ifdef CFG_INTERFACE_UART
|
||||||
|
#include "core/cmd/cmd.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
UART protocol control block, which is used to safely access the
|
||||||
|
RX FIFO buffer from elsewhere in the code. This should be accessed
|
||||||
|
through 'uartGetPCB()'.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
static uart_pcb_t pcb;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
IRQ to handle incoming data, etc.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void UART_IRQHandler(void)
|
||||||
|
{
|
||||||
|
uint8_t IIRValue, LSRValue;
|
||||||
|
uint8_t Dummy = Dummy;
|
||||||
|
|
||||||
|
IIRValue = UART_U0IIR;
|
||||||
|
IIRValue &= ~(UART_U0IIR_IntStatus_MASK); /* skip pending bit in IIR */
|
||||||
|
IIRValue &= UART_U0IIR_IntId_MASK; /* check bit 1~3, interrupt identification */
|
||||||
|
|
||||||
|
// 1.) Check receiver line status
|
||||||
|
if (IIRValue == UART_U0IIR_IntId_RLS)
|
||||||
|
{
|
||||||
|
LSRValue = UART_U0LSR;
|
||||||
|
// Check for errors
|
||||||
|
if (LSRValue & (UART_U0LSR_OE | UART_U0LSR_PE | UART_U0LSR_FE | UART_U0LSR_RXFE | UART_U0LSR_BI))
|
||||||
|
{
|
||||||
|
/* There are errors or break interrupt */
|
||||||
|
/* Read LSR will clear the interrupt */
|
||||||
|
pcb.status = LSRValue;
|
||||||
|
Dummy = UART_U0RBR; /* Dummy read on RX to clear interrupt, then bail out */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// No error and receive data is ready
|
||||||
|
if (LSRValue & UART_U0LSR_RDR_DATA)
|
||||||
|
{
|
||||||
|
/* If no error on RLS, normal ready, save into the data buffer. */
|
||||||
|
/* Note: read RBR will clear the interrupt */
|
||||||
|
uartRxBufferWrite(UART_U0RBR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.) Check receive data available
|
||||||
|
else if (IIRValue == UART_U0IIR_IntId_RDA)
|
||||||
|
{
|
||||||
|
// Add incoming text to UART buffer
|
||||||
|
uartRxBufferWrite(UART_U0RBR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3.) Check character timeout indicator
|
||||||
|
else if (IIRValue == UART_U0IIR_IntId_CTI)
|
||||||
|
{
|
||||||
|
/* Bit 9 as the CTI error */
|
||||||
|
pcb.status |= 0x100;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4.) Check THRE (transmit holding register empty)
|
||||||
|
else if (IIRValue == UART_U0IIR_IntId_THRE)
|
||||||
|
{
|
||||||
|
/* Check status in the LSR to see if valid data in U0THR or not */
|
||||||
|
LSRValue = UART_U0LSR;
|
||||||
|
if (LSRValue & UART_U0LSR_THRE)
|
||||||
|
{
|
||||||
|
pcb.pending_tx_data = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pcb.pending_tx_data= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Get a pointer to the UART's protocol control block, which can
|
||||||
|
be used to control the RX FIFO buffer and check whether UART
|
||||||
|
has already been initialised or not.
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
// Make sure that UART is initialised
|
||||||
|
uart_pcb_t *pcb = uartGetPCB();
|
||||||
|
if (!pcb->initialised)
|
||||||
|
{
|
||||||
|
uartInit(CFG_UART_BAUDRATE);
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
uart_pcb_t *uartGetPCB()
|
||||||
|
{
|
||||||
|
return &pcb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Initialises UART at the specified baud rate.
|
||||||
|
|
||||||
|
@param[in] baudRate
|
||||||
|
The baud rate to use when configuring the UART.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void uartInit(uint32_t baudrate)
|
||||||
|
{
|
||||||
|
uint32_t fDiv;
|
||||||
|
uint32_t regVal;
|
||||||
|
|
||||||
|
NVIC_DisableIRQ(UART_IRQn);
|
||||||
|
|
||||||
|
// Clear protocol control blocks
|
||||||
|
memset(&pcb, 0, sizeof(uart_pcb_t));
|
||||||
|
pcb.pending_tx_data = 0;
|
||||||
|
uartRxBufferInit();
|
||||||
|
|
||||||
|
/* Set 1.6 UART RXD */
|
||||||
|
IOCON_PIO1_6 &= ~IOCON_PIO1_6_FUNC_MASK;
|
||||||
|
IOCON_PIO1_6 |= IOCON_PIO1_6_FUNC_UART_RXD;
|
||||||
|
|
||||||
|
/* Set 1.7 UART TXD */
|
||||||
|
IOCON_PIO1_7 &= ~IOCON_PIO1_7_FUNC_MASK;
|
||||||
|
IOCON_PIO1_7 |= IOCON_PIO1_7_FUNC_UART_TXD;
|
||||||
|
|
||||||
|
/* Enable UART clock */
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_UART);
|
||||||
|
SCB_UARTCLKDIV = SCB_UARTCLKDIV_DIV1; /* divided by 1 */
|
||||||
|
|
||||||
|
/* 8 bits, no Parity, 1 Stop bit */
|
||||||
|
UART_U0LCR = (UART_U0LCR_Word_Length_Select_8Chars |
|
||||||
|
UART_U0LCR_Stop_Bit_Select_1Bits |
|
||||||
|
UART_U0LCR_Parity_Disabled |
|
||||||
|
UART_U0LCR_Parity_Select_OddParity |
|
||||||
|
UART_U0LCR_Break_Control_Disabled |
|
||||||
|
UART_U0LCR_Divisor_Latch_Access_Enabled);
|
||||||
|
|
||||||
|
/* Baud rate */
|
||||||
|
regVal = SCB_UARTCLKDIV;
|
||||||
|
fDiv = (((CFG_CPU_CCLK * SCB_SYSAHBCLKDIV)/regVal)/16)/baudrate;
|
||||||
|
|
||||||
|
UART_U0DLM = fDiv / 256;
|
||||||
|
UART_U0DLL = fDiv % 256;
|
||||||
|
|
||||||
|
/* Set DLAB back to 0 */
|
||||||
|
UART_U0LCR = (UART_U0LCR_Word_Length_Select_8Chars |
|
||||||
|
UART_U0LCR_Stop_Bit_Select_1Bits |
|
||||||
|
UART_U0LCR_Parity_Disabled |
|
||||||
|
UART_U0LCR_Parity_Select_OddParity |
|
||||||
|
UART_U0LCR_Break_Control_Disabled |
|
||||||
|
UART_U0LCR_Divisor_Latch_Access_Disabled);
|
||||||
|
|
||||||
|
/* Enable and reset TX and RX FIFO. */
|
||||||
|
UART_U0FCR = (UART_U0FCR_FIFO_Enabled |
|
||||||
|
UART_U0FCR_Rx_FIFO_Reset |
|
||||||
|
UART_U0FCR_Tx_FIFO_Reset);
|
||||||
|
|
||||||
|
/* Read to clear the line status. */
|
||||||
|
regVal = UART_U0LSR;
|
||||||
|
|
||||||
|
/* Ensure a clean start, no data in either TX or RX FIFO. */
|
||||||
|
while (( UART_U0LSR & (UART_U0LSR_THRE|UART_U0LSR_TEMT)) != (UART_U0LSR_THRE|UART_U0LSR_TEMT) );
|
||||||
|
while ( UART_U0LSR & UART_U0LSR_RDR_DATA )
|
||||||
|
{
|
||||||
|
/* Dump data from RX FIFO */
|
||||||
|
regVal = UART_U0RBR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the initialised flag in the protocol control block */
|
||||||
|
pcb.initialised = 1;
|
||||||
|
pcb.baudrate = baudrate;
|
||||||
|
|
||||||
|
/* Enable the UART Interrupt */
|
||||||
|
NVIC_EnableIRQ(UART_IRQn);
|
||||||
|
UART_U0IER = UART_U0IER_RBR_Interrupt_Enabled | UART_U0IER_RLS_Interrupt_Enabled;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Sends the contents of supplied text buffer over UART.
|
||||||
|
|
||||||
|
@param[in] bufferPtr
|
||||||
|
Pointer to the text buffer
|
||||||
|
@param[in] bufferPtr
|
||||||
|
The size of the text buffer
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
// Set 5-character text buffer
|
||||||
|
uint8_t uartBuffer[5] = { 'T', 'e', 's', 't', '\n' };
|
||||||
|
// Send contents of uartBuffer
|
||||||
|
uartSend((uint8_t *)uartBuffer, 5);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void uartSend (uint8_t *bufferPtr, uint32_t length)
|
||||||
|
{
|
||||||
|
while (length != 0)
|
||||||
|
{
|
||||||
|
/* THRE status, contain valid data */
|
||||||
|
while ( !(UART_U0LSR & UART_U0LSR_THRE) );
|
||||||
|
UART_U0THR = *bufferPtr;
|
||||||
|
|
||||||
|
bufferPtr++;
|
||||||
|
length--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Sends a single byte over UART.
|
||||||
|
|
||||||
|
@param[in] byte
|
||||||
|
Byte value to send
|
||||||
|
|
||||||
|
@section Example
|
||||||
|
|
||||||
|
@code
|
||||||
|
// Send 0xFF over UART
|
||||||
|
uartSendByte(0xFF);
|
||||||
|
// Send 'B' over UART (note single quotes)
|
||||||
|
uartSendByte('B');
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void uartSendByte (uint8_t byte)
|
||||||
|
{
|
||||||
|
/* THRE status, contain valid data */
|
||||||
|
while ( !(UART_U0LSR & UART_U0LSR_THRE) );
|
||||||
|
UART_U0THR = byte;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file uart.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __UART_H__
|
||||||
|
#define __UART_H__
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
// Buffer used for circular fifo
|
||||||
|
typedef struct _uart_buffer_t
|
||||||
|
{
|
||||||
|
uint8_t ep_dir;
|
||||||
|
volatile uint8_t len;
|
||||||
|
volatile uint8_t wr_ptr;
|
||||||
|
volatile uint8_t rd_ptr;
|
||||||
|
uint8_t buf[CFG_UART_BUFSIZE];
|
||||||
|
} uart_buffer_t;
|
||||||
|
|
||||||
|
// UART Protocol control block
|
||||||
|
typedef struct _uart_pcb_t
|
||||||
|
{
|
||||||
|
BOOL initialised;
|
||||||
|
uint32_t baudrate;
|
||||||
|
uint32_t status;
|
||||||
|
uint32_t pending_tx_data;
|
||||||
|
uart_buffer_t rxfifo;
|
||||||
|
} uart_pcb_t;
|
||||||
|
|
||||||
|
void UART_IRQHandler(void);
|
||||||
|
uart_pcb_t *uartGetPCB();
|
||||||
|
void uartInit(uint32_t Baudrate);
|
||||||
|
void uartSend(uint8_t *BufferPtr, uint32_t Length);
|
||||||
|
void uartSendByte (uint8_t byte);
|
||||||
|
|
||||||
|
// Rx Buffer access control
|
||||||
|
void uartRxBufferInit();
|
||||||
|
uint8_t uartRxBufferRead();
|
||||||
|
void uartRxBufferWrite(uint8_t data);
|
||||||
|
void uartRxBufferClearFIFO();
|
||||||
|
uint8_t uartRxBufferDataPending();
|
||||||
|
bool uartRxBufferReadArray(byte_t* rx, size_t* len);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*******************************************************************
|
||||||
|
Copyright (C) 2009 FreakLabs
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS 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.
|
||||||
|
|
||||||
|
Originally written by Christopher Wang aka Akiba.
|
||||||
|
Please post support questions to the FreakLabs forum.
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file uart_buf.c
|
||||||
|
@author Christopher Wang (Freaklabs)
|
||||||
|
Modified by: K. Townsend (microBuilder.eu)
|
||||||
|
@date 19 May 2010
|
||||||
|
|
||||||
|
Original code taken from the FreakUSB Open Source USB Device Stack
|
||||||
|
http://freaklabs.org/index.php/FreakUSB-Open-Source-USB-Device-Stack.html
|
||||||
|
|
||||||
|
If it works well, you can thank Akiba at Freaklabs. If it fails
|
||||||
|
miserably, you can blame me (since parts of it it were rather
|
||||||
|
ungraciously modified). :-)
|
||||||
|
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#include "uart.h"
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Initialises the RX FIFO buffer
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void uartRxBufferInit()
|
||||||
|
{
|
||||||
|
uart_pcb_t *pcb = uartGetPCB();
|
||||||
|
pcb->rxfifo.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Read one byte out of the RX buffer. This function will return the byte
|
||||||
|
located at the array index of the read pointer, and then increment the
|
||||||
|
read pointer index. If the read pointer exceeds the maximum buffer
|
||||||
|
size, it will roll over to zero.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
uint8_t uartRxBufferRead()
|
||||||
|
{
|
||||||
|
uart_pcb_t *pcb = uartGetPCB();
|
||||||
|
uint8_t data;
|
||||||
|
|
||||||
|
data = pcb->rxfifo.buf[pcb->rxfifo.rd_ptr];
|
||||||
|
pcb->rxfifo.rd_ptr = (pcb->rxfifo.rd_ptr + 1) % CFG_UART_BUFSIZE;
|
||||||
|
pcb->rxfifo.len--;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Read byte array from uart
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
bool uartRxBufferReadArray(byte_t* rx, size_t* len)
|
||||||
|
{
|
||||||
|
uart_pcb_t *pcb = uartGetPCB();
|
||||||
|
*len = 0;
|
||||||
|
|
||||||
|
while(pcb->rxfifo.len != 0)
|
||||||
|
{
|
||||||
|
(*rx) = uartRxBufferRead();
|
||||||
|
(*len)++;
|
||||||
|
rx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*len != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Write one byte into the RX buffer. This function will write one
|
||||||
|
byte into the array index specified by the write pointer and increment
|
||||||
|
the write index. If the write index exceeds the max buffer size, then it
|
||||||
|
will roll over to zero.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void uartRxBufferWrite(uint8_t data)
|
||||||
|
{
|
||||||
|
uart_pcb_t *pcb = uartGetPCB();
|
||||||
|
|
||||||
|
pcb->rxfifo.buf[pcb->rxfifo.wr_ptr] = data;
|
||||||
|
pcb->rxfifo.wr_ptr = (pcb->rxfifo.wr_ptr + 1) % CFG_UART_BUFSIZE;
|
||||||
|
pcb->rxfifo.len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Clear the fifo read and write pointers and set the length to zero.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void uartRxBufferClearFIFO()
|
||||||
|
{
|
||||||
|
uart_pcb_t *pcb = uartGetPCB();
|
||||||
|
|
||||||
|
pcb->rxfifo.rd_ptr = 0;
|
||||||
|
pcb->rxfifo.wr_ptr = 0;
|
||||||
|
pcb->rxfifo.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Check whether there is any data pending on the RX buffer.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
uint8_t uartRxBufferDataPending()
|
||||||
|
{
|
||||||
|
uart_pcb_t *pcb = uartGetPCB();
|
||||||
|
|
||||||
|
if (pcb->rxfifo.len != 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,236 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: CDC.h
|
||||||
|
* Purpose: USB Communication Device Class Definitions
|
||||||
|
* Version: V1.00
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef __CDC_H
|
||||||
|
#define __CDC_H
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* Definitions based on usbcdc11.pdf (www.usb.org)
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
// Communication device class specification version 1.10
|
||||||
|
#define CDC_V1_10 0x0110
|
||||||
|
|
||||||
|
// Communication interface class code
|
||||||
|
// (usbcdc11.pdf, 4.2, Table 15)
|
||||||
|
#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02
|
||||||
|
|
||||||
|
// Communication interface class subclass codes
|
||||||
|
// (usbcdc11.pdf, 4.3, Table 16)
|
||||||
|
#define CDC_DIRECT_LINE_CONTROL_MODEL 0x01
|
||||||
|
#define CDC_ABSTRACT_CONTROL_MODEL 0x02
|
||||||
|
#define CDC_TELEPHONE_CONTROL_MODEL 0x03
|
||||||
|
#define CDC_MULTI_CHANNEL_CONTROL_MODEL 0x04
|
||||||
|
#define CDC_CAPI_CONTROL_MODEL 0x05
|
||||||
|
#define CDC_ETHERNET_NETWORKING_CONTROL_MODEL 0x06
|
||||||
|
#define CDC_ATM_NETWORKING_CONTROL_MODEL 0x07
|
||||||
|
|
||||||
|
// Communication interface class control protocol codes
|
||||||
|
// (usbcdc11.pdf, 4.4, Table 17)
|
||||||
|
#define CDC_PROTOCOL_COMMON_AT_COMMANDS 0x01
|
||||||
|
|
||||||
|
// Data interface class code
|
||||||
|
// (usbcdc11.pdf, 4.5, Table 18)
|
||||||
|
#define CDC_DATA_INTERFACE_CLASS 0x0A
|
||||||
|
|
||||||
|
// Data interface class protocol codes
|
||||||
|
// (usbcdc11.pdf, 4.7, Table 19)
|
||||||
|
#define CDC_PROTOCOL_ISDN_BRI 0x30
|
||||||
|
#define CDC_PROTOCOL_HDLC 0x31
|
||||||
|
#define CDC_PROTOCOL_TRANSPARENT 0x32
|
||||||
|
#define CDC_PROTOCOL_Q921_MANAGEMENT 0x50
|
||||||
|
#define CDC_PROTOCOL_Q921_DATA_LINK 0x51
|
||||||
|
#define CDC_PROTOCOL_Q921_MULTIPLEXOR 0x52
|
||||||
|
#define CDC_PROTOCOL_V42 0x90
|
||||||
|
#define CDC_PROTOCOL_EURO_ISDN 0x91
|
||||||
|
#define CDC_PROTOCOL_V24_RATE_ADAPTATION 0x92
|
||||||
|
#define CDC_PROTOCOL_CAPI 0x93
|
||||||
|
#define CDC_PROTOCOL_HOST_BASED_DRIVER 0xFD
|
||||||
|
#define CDC_PROTOCOL_DESCRIBED_IN_PUFD 0xFE
|
||||||
|
|
||||||
|
// Type values for bDescriptorType field of functional descriptors
|
||||||
|
// (usbcdc11.pdf, 5.2.3, Table 24)
|
||||||
|
#define CDC_CS_INTERFACE 0x24
|
||||||
|
#define CDC_CS_ENDPOINT 0x25
|
||||||
|
|
||||||
|
// Type values for bDescriptorSubtype field of functional descriptors
|
||||||
|
// (usbcdc11.pdf, 5.2.3, Table 25)
|
||||||
|
#define CDC_HEADER 0x00
|
||||||
|
#define CDC_CALL_MANAGEMENT 0x01
|
||||||
|
#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02
|
||||||
|
#define CDC_DIRECT_LINE_MANAGEMENT 0x03
|
||||||
|
#define CDC_TELEPHONE_RINGER 0x04
|
||||||
|
#define CDC_REPORTING_CAPABILITIES 0x05
|
||||||
|
#define CDC_UNION 0x06
|
||||||
|
#define CDC_COUNTRY_SELECTION 0x07
|
||||||
|
#define CDC_TELEPHONE_OPERATIONAL_MODES 0x08
|
||||||
|
#define CDC_USB_TERMINAL 0x09
|
||||||
|
#define CDC_NETWORK_CHANNEL 0x0A
|
||||||
|
#define CDC_PROTOCOL_UNIT 0x0B
|
||||||
|
#define CDC_EXTENSION_UNIT 0x0C
|
||||||
|
#define CDC_MULTI_CHANNEL_MANAGEMENT 0x0D
|
||||||
|
#define CDC_CAPI_CONTROL_MANAGEMENT 0x0E
|
||||||
|
#define CDC_ETHERNET_NETWORKING 0x0F
|
||||||
|
#define CDC_ATM_NETWORKING 0x10
|
||||||
|
|
||||||
|
// CDC class-specific request codes
|
||||||
|
// (usbcdc11.pdf, 6.2, Table 46)
|
||||||
|
// see Table 45 for info about the specific requests.
|
||||||
|
#define CDC_SEND_ENCAPSULATED_COMMAND 0x00
|
||||||
|
#define CDC_GET_ENCAPSULATED_RESPONSE 0x01
|
||||||
|
#define CDC_SET_COMM_FEATURE 0x02
|
||||||
|
#define CDC_GET_COMM_FEATURE 0x03
|
||||||
|
#define CDC_CLEAR_COMM_FEATURE 0x04
|
||||||
|
#define CDC_SET_AUX_LINE_STATE 0x10
|
||||||
|
#define CDC_SET_HOOK_STATE 0x11
|
||||||
|
#define CDC_PULSE_SETUP 0x12
|
||||||
|
#define CDC_SEND_PULSE 0x13
|
||||||
|
#define CDC_SET_PULSE_TIME 0x14
|
||||||
|
#define CDC_RING_AUX_JACK 0x15
|
||||||
|
#define CDC_SET_LINE_CODING 0x20
|
||||||
|
#define CDC_GET_LINE_CODING 0x21
|
||||||
|
#define CDC_SET_CONTROL_LINE_STATE 0x22
|
||||||
|
#define CDC_SEND_BREAK 0x23
|
||||||
|
#define CDC_SET_RINGER_PARMS 0x30
|
||||||
|
#define CDC_GET_RINGER_PARMS 0x31
|
||||||
|
#define CDC_SET_OPERATION_PARMS 0x32
|
||||||
|
#define CDC_GET_OPERATION_PARMS 0x33
|
||||||
|
#define CDC_SET_LINE_PARMS 0x34
|
||||||
|
#define CDC_GET_LINE_PARMS 0x35
|
||||||
|
#define CDC_DIAL_DIGITS 0x36
|
||||||
|
#define CDC_SET_UNIT_PARAMETER 0x37
|
||||||
|
#define CDC_GET_UNIT_PARAMETER 0x38
|
||||||
|
#define CDC_CLEAR_UNIT_PARAMETER 0x39
|
||||||
|
#define CDC_GET_PROFILE 0x3A
|
||||||
|
#define CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
|
||||||
|
#define CDC_SET_ETHERNET_PMP_FILTER 0x41
|
||||||
|
#define CDC_GET_ETHERNET_PMP_FILTER 0x42
|
||||||
|
#define CDC_SET_ETHERNET_PACKET_FILTER 0x43
|
||||||
|
#define CDC_GET_ETHERNET_STATISTIC 0x44
|
||||||
|
#define CDC_SET_ATM_DATA_FORMAT 0x50
|
||||||
|
#define CDC_GET_ATM_DEVICE_STATISTICS 0x51
|
||||||
|
#define CDC_SET_ATM_DEFAULT_VC 0x52
|
||||||
|
#define CDC_GET_ATM_VC_STATISTICS 0x53
|
||||||
|
|
||||||
|
// Communication feature selector codes
|
||||||
|
// (usbcdc11.pdf, 6.2.2..6.2.4, Table 47)
|
||||||
|
#define CDC_ABSTRACT_STATE 0x01
|
||||||
|
#define CDC_COUNTRY_SETTING 0x02
|
||||||
|
|
||||||
|
// Feature Status returned for ABSTRACT_STATE Selector
|
||||||
|
// (usbcdc11.pdf, 6.2.3, Table 48)
|
||||||
|
#define CDC_IDLE_SETTING (1 << 0)
|
||||||
|
#define CDC_DATA_MULTPLEXED_STATE (1 << 1)
|
||||||
|
|
||||||
|
|
||||||
|
// Control signal bitmap values for the SetControlLineState request
|
||||||
|
// (usbcdc11.pdf, 6.2.14, Table 51)
|
||||||
|
#define CDC_DTE_PRESENT (1 << 0)
|
||||||
|
#define CDC_ACTIVATE_CARRIER (1 << 1)
|
||||||
|
|
||||||
|
// CDC class-specific notification codes
|
||||||
|
// (usbcdc11.pdf, 6.3, Table 68)
|
||||||
|
// see Table 67 for Info about class-specific notifications
|
||||||
|
#define CDC_NOTIFICATION_NETWORK_CONNECTION 0x00
|
||||||
|
#define CDC_RESPONSE_AVAILABLE 0x01
|
||||||
|
#define CDC_AUX_JACK_HOOK_STATE 0x08
|
||||||
|
#define CDC_RING_DETECT 0x09
|
||||||
|
#define CDC_NOTIFICATION_SERIAL_STATE 0x20
|
||||||
|
#define CDC_CALL_STATE_CHANGE 0x28
|
||||||
|
#define CDC_LINE_STATE_CHANGE 0x29
|
||||||
|
#define CDC_CONNECTION_SPEED_CHANGE 0x2A
|
||||||
|
|
||||||
|
// UART state bitmap values (Serial state notification).
|
||||||
|
// (usbcdc11.pdf, 6.3.5, Table 69)
|
||||||
|
#define CDC_SERIAL_STATE_OVERRUN (1 << 6) // receive data overrun error has occurred
|
||||||
|
#define CDC_SERIAL_STATE_PARITY (1 << 5) // parity error has occurred
|
||||||
|
#define CDC_SERIAL_STATE_FRAMING (1 << 4) // framing error has occurred
|
||||||
|
#define CDC_SERIAL_STATE_RING (1 << 3) // state of ring signal detection
|
||||||
|
#define CDC_SERIAL_STATE_BREAK (1 << 2) // state of break detection
|
||||||
|
#define CDC_SERIAL_STATE_TX_CARRIER (1 << 1) // state of transmission carrier
|
||||||
|
#define CDC_SERIAL_STATE_RX_CARRIER (1 << 0) // state of receiver carrier
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* Structures based on usbcdc11.pdf (www.usb.org)
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// Header functional descriptor
|
||||||
|
// (usbcdc11.pdf, 5.2.3.1)
|
||||||
|
// This header must precede any list of class-specific descriptors.
|
||||||
|
typedef struct _CDC_HEADER_DESCRIPTOR{
|
||||||
|
uint8_t bFunctionLength; // size of this descriptor in bytes
|
||||||
|
uint8_t bDescriptorType; // CS_INTERFACE descriptor type
|
||||||
|
uint8_t bDescriptorSubtype; // Header functional descriptor subtype
|
||||||
|
uint16_t bcdCDC; // USB CDC specification release version
|
||||||
|
} __attribute__((packed)) CDC_HEADER_DESCRIPTOR;
|
||||||
|
|
||||||
|
//Call management functional descriptor
|
||||||
|
// (usbcdc11.pdf, 5.2.3.2)
|
||||||
|
// Describes the processing of calls for the communication class interface.
|
||||||
|
typedef struct _CDC_CALL_MANAGEMENT_DESCRIPTOR {
|
||||||
|
uint8_t bFunctionLength; // size of this descriptor in bytes
|
||||||
|
uint8_t bDescriptorType; // CS_INTERFACE descriptor type
|
||||||
|
uint8_t bDescriptorSubtype; // call management functional descriptor subtype
|
||||||
|
uint8_t bmCapabilities; // capabilities that this configuration supports
|
||||||
|
uint8_t bDataInterface; // interface number of the data class interface used for call management (optional)
|
||||||
|
} __attribute__((packed)) CDC_CALL_MANAGEMENT_DESCRIPTOR;
|
||||||
|
|
||||||
|
// Abstract control management functional descriptor
|
||||||
|
// (usbcdc11.pdf, 5.2.3.3)
|
||||||
|
// Describes the command supported by the communication interface class with the Abstract Control Model subclass code.
|
||||||
|
typedef struct _CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR {
|
||||||
|
uint8_t bFunctionLength; // size of this descriptor in bytes
|
||||||
|
uint8_t bDescriptorType; // CS_INTERFACE descriptor type
|
||||||
|
uint8_t bDescriptorSubtype; // abstract control management functional descriptor subtype
|
||||||
|
uint8_t bmCapabilities; // capabilities supported by this configuration
|
||||||
|
} __attribute__((packed)) CDC_ABSTRACT_CONTROL_MANAGEMENT_DESCRIPTOR;
|
||||||
|
|
||||||
|
// Union functional descriptors
|
||||||
|
// (usbcdc11.pdf, 5.2.3.8)
|
||||||
|
// Describes the relationship between a group of interfaces that can be considered to form a functional unit.
|
||||||
|
typedef struct _CDC_UNION_DESCRIPTOR {
|
||||||
|
uint8_t bFunctionLength; // size of this descriptor in bytes
|
||||||
|
uint8_t bDescriptorType; // CS_INTERFACE descriptor type
|
||||||
|
uint8_t bDescriptorSubtype; // union functional descriptor subtype
|
||||||
|
uint8_t bMasterInterface; // interface number designated as master
|
||||||
|
} __attribute__((packed)) CDC_UNION_DESCRIPTOR;
|
||||||
|
|
||||||
|
// Union functional descriptors with one slave interface
|
||||||
|
// (usbcdc11.pdf, 5.2.3.8)
|
||||||
|
typedef struct _CDC_UNION_1SLAVE_DESCRIPTOR {
|
||||||
|
CDC_UNION_DESCRIPTOR sUnion; // Union functional descriptor
|
||||||
|
uint8_t bSlaveInterfaces[1]; // Slave interface 0
|
||||||
|
} __attribute__((packed)) CDC_UNION_1SLAVE_DESCRIPTOR;
|
||||||
|
|
||||||
|
// Line coding structure
|
||||||
|
// Format of the data returned when a GetLineCoding request is received
|
||||||
|
// (usbcdc11.pdf, 6.2.13)
|
||||||
|
typedef struct _CDC_LINE_CODING {
|
||||||
|
uint32_t dwDTERate; // Data terminal rate in bits per second
|
||||||
|
uint8_t bCharFormat; // Number of stop bits
|
||||||
|
uint8_t bParityType; // Parity bit type
|
||||||
|
uint8_t bDataBits; // Number of data bits
|
||||||
|
} __attribute__((packed)) CDC_LINE_CODING;
|
||||||
|
|
||||||
|
// Notification header
|
||||||
|
// Data sent on the notification endpoint must follow this header.
|
||||||
|
// see USB_SETUP_PACKET in file usb.h
|
||||||
|
typedef USB_SETUP_PACKET CDC_NOTIFICATION_HEADER;
|
||||||
|
|
||||||
|
#endif /* __CDC_H */
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*******************************************************************
|
||||||
|
Copyright (C) 2009 FreakLabs
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the the copyright holder nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS 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.
|
||||||
|
|
||||||
|
Originally written by Christopher Wang aka Akiba.
|
||||||
|
Please post support questions to the FreakLabs forum.
|
||||||
|
*******************************************************************/
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file cdc_buf.c
|
||||||
|
@author Christopher Wang (Freaklabs)
|
||||||
|
Modified by: K. Townsend (microBuilder.eu)
|
||||||
|
@date 19 May 2010
|
||||||
|
|
||||||
|
Original code taken from the FreakUSB Open Source USB Device Stack
|
||||||
|
http://freaklabs.org/index.php/FreakUSB-Open-Source-USB-Device-Stack.html
|
||||||
|
|
||||||
|
If it works well, you can thank Akiba at Freaklabs. If it fails
|
||||||
|
miserably, you can blame me (since parts of it it were rather
|
||||||
|
ungraciously modified). :-)
|
||||||
|
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#include "cdc_buf.h"
|
||||||
|
|
||||||
|
static cdc_buffer_t cdcfifo;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Gets a pointer to the fifo buffer
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
cdc_buffer_t *cdcGetBuffer()
|
||||||
|
{
|
||||||
|
return &cdcfifo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Initialises the RX FIFO buffer
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void cdcBufferInit()
|
||||||
|
{
|
||||||
|
cdcfifo.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Read one byte out of the RX buffer. This function will return the byte
|
||||||
|
located at the array index of the read pointer, and then increment the
|
||||||
|
read pointer index. If the read pointer exceeds the maximum buffer
|
||||||
|
size, it will roll over to zero.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
uint8_t cdcBufferRead()
|
||||||
|
{
|
||||||
|
uint8_t data;
|
||||||
|
|
||||||
|
data = cdcfifo.buf[cdcfifo.rd_ptr];
|
||||||
|
cdcfifo.rd_ptr = (cdcfifo.rd_ptr + 1) % CFG_USBCDC_BUFFERSIZE;
|
||||||
|
cdcfifo.len--;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Reads x bytes from cdc buffer
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
uint32_t cdcBufferReadLen(uint8_t* buf, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t counter, actual;
|
||||||
|
counter = actual = 0;
|
||||||
|
|
||||||
|
while(counter != len)
|
||||||
|
{
|
||||||
|
// Make sure we don't exceed buffer limits
|
||||||
|
if (cdcfifo.len > 0)
|
||||||
|
{
|
||||||
|
buf[counter] = cdcBufferRead();
|
||||||
|
actual++;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Write one byte into the RX buffer. This function will write one
|
||||||
|
byte into the array index specified by the write pointer and increment
|
||||||
|
the write index. If the write index exceeds the max buffer size, then it
|
||||||
|
will roll over to zero.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void cdcBufferWrite(uint8_t data)
|
||||||
|
{
|
||||||
|
cdcfifo.buf[cdcfifo.wr_ptr] = data;
|
||||||
|
cdcfifo.wr_ptr = (cdcfifo.wr_ptr + 1) % CFG_USBCDC_BUFFERSIZE;
|
||||||
|
cdcfifo.len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Clear the fifo read and write pointers and set the length to zero.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void cdcBufferClearFIFO()
|
||||||
|
{
|
||||||
|
cdcfifo.rd_ptr = 0;
|
||||||
|
cdcfifo.wr_ptr = 0;
|
||||||
|
cdcfifo.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Check whether there is any data pending on the RX buffer.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
uint8_t cdcBufferDataPending()
|
||||||
|
{
|
||||||
|
if (cdcfifo.len != 0)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* Name: cdc_buf.h
|
||||||
|
* Purpose: usb cdc buffer handling
|
||||||
|
* Version: V1.00
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef __CDC_BUF_H__
|
||||||
|
#define __CDC_BUF_H__
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
// Buffer used for circular fifo
|
||||||
|
typedef struct _cdc_buffer_t
|
||||||
|
{
|
||||||
|
volatile uint8_t len;
|
||||||
|
volatile uint8_t wr_ptr;
|
||||||
|
volatile uint8_t rd_ptr;
|
||||||
|
uint8_t buf[CFG_USBCDC_BUFFERSIZE];
|
||||||
|
} cdc_buffer_t;
|
||||||
|
|
||||||
|
cdc_buffer_t * cdcGetBuffer();
|
||||||
|
void cdcBufferInit();
|
||||||
|
uint8_t cdcBufferRead();
|
||||||
|
uint32_t cdcBufferReadLen(uint8_t* buf, uint32_t len);
|
||||||
|
void cdcBufferWrite(uint8_t data);
|
||||||
|
void cdcBufferClearFIFO();
|
||||||
|
uint8_t cdcBufferDataPending();
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,351 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: cdcuser.c
|
||||||
|
* Purpose: USB Communication Device Class User module
|
||||||
|
* Version: V1.10
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
#include "usb.h"
|
||||||
|
#include "usbhw.h"
|
||||||
|
#include "usbcfg.h"
|
||||||
|
#include "usbcore.h"
|
||||||
|
#include "cdc.h"
|
||||||
|
#include "cdcuser.h"
|
||||||
|
#include "cdc_buf.h"
|
||||||
|
|
||||||
|
// unsigned char BulkBufIn [64]; // Buffer to store USB IN packet
|
||||||
|
unsigned char BulkBufOut [64]; // Buffer to store USB OUT packet
|
||||||
|
unsigned char NotificationBuf [10];
|
||||||
|
|
||||||
|
CDC_LINE_CODING CDC_LineCoding = {CFG_USBCDC_BAUDRATE, 0, 0, 8};
|
||||||
|
unsigned short CDC_SerialState = 0x0000;
|
||||||
|
unsigned short CDC_DepInEmpty = 1; // Data IN EP is empty
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
We need a buffer for incoming data on USB port because USB receives
|
||||||
|
much faster than UART transmits
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
/* Buffer masks */
|
||||||
|
#define CDC_BUF_SIZE (64) // Output buffer in bytes (power 2)
|
||||||
|
// large enough for file transfer
|
||||||
|
#define CDC_BUF_MASK (CDC_BUF_SIZE-1ul)
|
||||||
|
|
||||||
|
/* Buffer read / write macros */
|
||||||
|
#define CDC_BUF_RESET(cdcBuf) (cdcBuf.rdIdx = cdcBuf.wrIdx = 0)
|
||||||
|
#define CDC_BUF_WR(cdcBuf, dataIn) (cdcBuf.data[CDC_BUF_MASK & cdcBuf.wrIdx++] = (dataIn))
|
||||||
|
#define CDC_BUF_RD(cdcBuf) (cdcBuf.data[CDC_BUF_MASK & cdcBuf.rdIdx++])
|
||||||
|
#define CDC_BUF_EMPTY(cdcBuf) (cdcBuf.rdIdx == cdcBuf.wrIdx)
|
||||||
|
#define CDC_BUF_FULL(cdcBuf) (cdcBuf.rdIdx == cdcBuf.wrIdx+1)
|
||||||
|
#define CDC_BUF_COUNT(cdcBuf) (CDC_BUF_MASK & (cdcBuf.wrIdx - cdcBuf.rdIdx))
|
||||||
|
|
||||||
|
|
||||||
|
// CDC output buffer
|
||||||
|
typedef struct __CDC_BUF_T
|
||||||
|
{
|
||||||
|
unsigned char data[CDC_BUF_SIZE];
|
||||||
|
volatile unsigned int wrIdx;
|
||||||
|
volatile unsigned int rdIdx;
|
||||||
|
} CDC_BUF_T;
|
||||||
|
|
||||||
|
CDC_BUF_T CDC_OutBuf; // buffer for all CDC Out data
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
read data from CDC_OutBuf
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
int CDC_RdOutBuf (char *buffer, const int *length)
|
||||||
|
{
|
||||||
|
int bytesToRead, bytesRead;
|
||||||
|
|
||||||
|
/* Read *length bytes, block if *bytes are not avaialable */
|
||||||
|
bytesToRead = *length;
|
||||||
|
bytesToRead = (bytesToRead < (*length)) ? bytesToRead : (*length);
|
||||||
|
bytesRead = bytesToRead;
|
||||||
|
|
||||||
|
|
||||||
|
// ... add code to check for underrun
|
||||||
|
|
||||||
|
while (bytesToRead--) {
|
||||||
|
*buffer++ = CDC_BUF_RD(CDC_OutBuf);
|
||||||
|
}
|
||||||
|
return (bytesRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
write data to CDC_OutBuf
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
int CDC_WrOutBuf (const char *buffer, int *length)
|
||||||
|
{
|
||||||
|
int bytesToWrite, bytesWritten;
|
||||||
|
|
||||||
|
// Write *length bytes
|
||||||
|
bytesToWrite = *length;
|
||||||
|
bytesWritten = bytesToWrite;
|
||||||
|
|
||||||
|
|
||||||
|
// ... add code to check for overwrite
|
||||||
|
|
||||||
|
while (bytesToWrite) {
|
||||||
|
CDC_BUF_WR(CDC_OutBuf, *buffer++); // Copy Data to buffer
|
||||||
|
bytesToWrite--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bytesWritten);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
check if character(s) are available at CDC_OutBuf
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
int CDC_OutBufAvailChar (int *availChar)
|
||||||
|
{
|
||||||
|
*availChar = CDC_BUF_COUNT(CDC_OutBuf);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
/* end Buffer handling */
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
CDC Initialisation
|
||||||
|
Initializes the data structures and serial port
|
||||||
|
Parameters: None
|
||||||
|
Return Value: None
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
void CDC_Init (void)
|
||||||
|
{
|
||||||
|
CDC_DepInEmpty = 1;
|
||||||
|
CDC_SerialState = CDC_GetSerialState();
|
||||||
|
|
||||||
|
CDC_BUF_RESET(CDC_OutBuf);
|
||||||
|
|
||||||
|
// Initialise the CDC buffer. This is required to buffer outgoing
|
||||||
|
// data (MCU to PC) since data can only be sent 64 bytes per frame
|
||||||
|
// with at least 1ms between frames. To see how the buffer is used,
|
||||||
|
// see 'puts' in systeminit.c
|
||||||
|
cdcBufferInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
CDC SendEncapsulatedCommand Request Callback
|
||||||
|
Called automatically on CDC SEND_ENCAPSULATED_COMMAND Request
|
||||||
|
Parameters: None (global SetupPacket and EP0Buf)
|
||||||
|
Return Value: TRUE - Success, FALSE - Error
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t CDC_SendEncapsulatedCommand (void)
|
||||||
|
{
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
CDC GetEncapsulatedResponse Request Callback
|
||||||
|
Called automatically on CDC Get_ENCAPSULATED_RESPONSE Request
|
||||||
|
Parameters: None (global SetupPacket and EP0Buf)
|
||||||
|
Return Value: TRUE - Success, FALSE - Error
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t CDC_GetEncapsulatedResponse (void)
|
||||||
|
{
|
||||||
|
/* ... add code to handle request */
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
CDC SetCommFeature Request Callback
|
||||||
|
Called automatically on CDC Set_COMM_FATURE Request
|
||||||
|
Parameters: FeatureSelector
|
||||||
|
Return Value: TRUE - Success, FALSE - Error
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t CDC_SetCommFeature (unsigned short wFeatureSelector)
|
||||||
|
{
|
||||||
|
/* ... add code to handle request */
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
CDC GetCommFeature Request Callback
|
||||||
|
Called automatically on CDC Get_COMM_FATURE Request
|
||||||
|
Parameters: FeatureSelector
|
||||||
|
Return Value: TRUE - Success, FALSE - Error
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t CDC_GetCommFeature (unsigned short wFeatureSelector)
|
||||||
|
{
|
||||||
|
/* ... add code to handle request */
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
CDC ClearCommFeature Request Callback
|
||||||
|
Called automatically on CDC CLEAR_COMM_FATURE Request
|
||||||
|
Parameters: FeatureSelector
|
||||||
|
Return Value: TRUE - Success, FALSE - Error
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t CDC_ClearCommFeature (unsigned short wFeatureSelector)
|
||||||
|
{
|
||||||
|
/* ... add code to handle request */
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
CDC SetLineCoding Request Callback
|
||||||
|
Called automatically on CDC SET_LINE_CODING Request
|
||||||
|
Parameters: none (global SetupPacket and EP0Buf)
|
||||||
|
Return Value: TRUE - Success, FALSE - Error
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t CDC_SetLineCoding (void)
|
||||||
|
{
|
||||||
|
CDC_LineCoding.dwDTERate = (EP0Buf[0] << 0)
|
||||||
|
| (EP0Buf[1] << 8)
|
||||||
|
| (EP0Buf[2] << 16)
|
||||||
|
| (EP0Buf[3] << 24);
|
||||||
|
CDC_LineCoding.bCharFormat = EP0Buf[4];
|
||||||
|
CDC_LineCoding.bParityType = EP0Buf[5];
|
||||||
|
CDC_LineCoding.bDataBits = EP0Buf[6];
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
CDC GetLineCoding Request Callback
|
||||||
|
Called automatically on CDC GET_LINE_CODING Request
|
||||||
|
Parameters: None (global SetupPacket and EP0Buf)
|
||||||
|
Return Value: TRUE - Success, FALSE - Error
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t CDC_GetLineCoding (void)
|
||||||
|
{
|
||||||
|
EP0Buf[0] = (CDC_LineCoding.dwDTERate >> 0) & 0xFF;
|
||||||
|
EP0Buf[1] = (CDC_LineCoding.dwDTERate >> 8) & 0xFF;
|
||||||
|
EP0Buf[2] = (CDC_LineCoding.dwDTERate >> 16) & 0xFF;
|
||||||
|
EP0Buf[3] = (CDC_LineCoding.dwDTERate >> 24) & 0xFF;
|
||||||
|
EP0Buf[4] = CDC_LineCoding.bCharFormat;
|
||||||
|
EP0Buf[5] = CDC_LineCoding.bParityType;
|
||||||
|
EP0Buf[6] = CDC_LineCoding.bDataBits;
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
CDC SetControlLineState Request Callback
|
||||||
|
Called automatically on CDC SET_CONTROL_LINE_STATE Request
|
||||||
|
Parameters: ControlSignalBitmap
|
||||||
|
Return Value: TRUE - Success, FALSE - Error
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t CDC_SetControlLineState (unsigned short wControlSignalBitmap) {
|
||||||
|
|
||||||
|
/* ... add code to handle request */
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
CDC SendBreak Request Callback
|
||||||
|
Called automatically on CDC Set_COMM_FATURE Request
|
||||||
|
Parameters: 0xFFFF start of Break
|
||||||
|
0x0000 stop of Break
|
||||||
|
0x#### Duration of Break
|
||||||
|
Return Value: TRUE - Success, FALSE - Error
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t CDC_SendBreak (unsigned short wDurationOfBreak) {
|
||||||
|
|
||||||
|
/* ... add code to handle request */
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
CDC_BulkIn call on DataIn Request
|
||||||
|
Parameters: none
|
||||||
|
Return Value: none
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
void CDC_BulkIn(void)
|
||||||
|
{
|
||||||
|
// int numBytesRead, numBytesAvail;
|
||||||
|
//
|
||||||
|
// // ToDo: Modify BulkIn to send incoming data to USB
|
||||||
|
//
|
||||||
|
// ser_AvailChar (&numBytesAvail);
|
||||||
|
//
|
||||||
|
// // ... add code to check for overwrite
|
||||||
|
//
|
||||||
|
// numBytesRead = ser_Read ((char *)&BulkBufIn[0], &numBytesAvail);
|
||||||
|
//
|
||||||
|
// // send over USB
|
||||||
|
// if (numBytesRead > 0) {
|
||||||
|
// USB_WriteEP (CDC_DEP_IN, &BulkBufIn[0], numBytesRead);
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// CDC_DepInEmpty = 1;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
CDC_BulkOut call on DataOut Request
|
||||||
|
Parameters: none
|
||||||
|
Return Value: none
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
void CDC_BulkOut(void)
|
||||||
|
{
|
||||||
|
int numBytesRead;
|
||||||
|
|
||||||
|
// get data from USB into intermediate buffer
|
||||||
|
numBytesRead = USB_ReadEP(CDC_DEP_OUT, &BulkBufOut[0]);
|
||||||
|
|
||||||
|
// ... add code to check for overwrite
|
||||||
|
|
||||||
|
// store data in a buffer to transmit it over serial interface
|
||||||
|
CDC_WrOutBuf ((char *)&BulkBufOut[0], &numBytesRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
Get the SERIAL_STATE as defined in usbcdc11.pdf, 6.3.5, Table 69.
|
||||||
|
Parameters: none
|
||||||
|
Return Value: SerialState as defined in usbcdc11.pdf
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
unsigned short CDC_GetSerialState (void)
|
||||||
|
{
|
||||||
|
CDC_SerialState = 0;
|
||||||
|
|
||||||
|
return (CDC_SerialState);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
Send the SERIAL_STATE notification as defined in usbcdc11.pdf, 6.3.5.
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
void CDC_NotificationIn (void)
|
||||||
|
{
|
||||||
|
NotificationBuf[0] = 0xA1; // bmRequestType
|
||||||
|
NotificationBuf[1] = CDC_NOTIFICATION_SERIAL_STATE; // bNotification (SERIAL_STATE)
|
||||||
|
NotificationBuf[2] = 0x00; // wValue
|
||||||
|
NotificationBuf[3] = 0x00;
|
||||||
|
NotificationBuf[4] = 0x00; // wIndex (Interface #, LSB first)
|
||||||
|
NotificationBuf[5] = 0x00;
|
||||||
|
NotificationBuf[6] = 0x02; // wLength (Data length = 2 bytes, LSB first)
|
||||||
|
NotificationBuf[7] = 0x00;
|
||||||
|
NotificationBuf[8] = (CDC_SerialState >> 0) & 0xFF; // UART State Bitmap (16bits, LSB first)
|
||||||
|
NotificationBuf[9] = (CDC_SerialState >> 8) & 0xFF;
|
||||||
|
|
||||||
|
USB_WriteEP (CDC_CEP_IN, &NotificationBuf[0], 10); // send notification
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: cdcuser.h
|
||||||
|
* Purpose: USB Communication Device Class User module Definitions
|
||||||
|
* Version: V1.10
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef __CDCUSER_H__
|
||||||
|
#define __CDCUSER_H__
|
||||||
|
|
||||||
|
/* CDC buffer handling */
|
||||||
|
extern int CDC_RdOutBuf (char *buffer, const int *length);
|
||||||
|
extern int CDC_WrOutBuf (const char *buffer, int *length);
|
||||||
|
extern int CDC_OutBufAvailChar (int *availChar);
|
||||||
|
|
||||||
|
|
||||||
|
/* CDC Data In/Out Endpoint Address */
|
||||||
|
#define CDC_DEP_IN 0x83
|
||||||
|
#define CDC_DEP_OUT 0x03
|
||||||
|
|
||||||
|
/* CDC Communication In Endpoint Address */
|
||||||
|
#define CDC_CEP_IN 0x81
|
||||||
|
|
||||||
|
/* CDC Requests Callback Functions */
|
||||||
|
extern uint32_t CDC_SendEncapsulatedCommand (void);
|
||||||
|
extern uint32_t CDC_GetEncapsulatedResponse (void);
|
||||||
|
extern uint32_t CDC_SetCommFeature (unsigned short wFeatureSelector);
|
||||||
|
extern uint32_t CDC_GetCommFeature (unsigned short wFeatureSelector);
|
||||||
|
extern uint32_t CDC_ClearCommFeature (unsigned short wFeatureSelector);
|
||||||
|
extern uint32_t CDC_GetLineCoding (void);
|
||||||
|
extern uint32_t CDC_SetLineCoding (void);
|
||||||
|
extern uint32_t CDC_SetControlLineState (unsigned short wControlSignalBitmap);
|
||||||
|
extern uint32_t CDC_SendBreak (unsigned short wDurationOfBreak);
|
||||||
|
|
||||||
|
/* CDC Bulk Callback Functions */
|
||||||
|
extern void CDC_BulkIn (void);
|
||||||
|
extern void CDC_BulkOut (void);
|
||||||
|
|
||||||
|
/* CDC Notification Callback Function */
|
||||||
|
extern void CDC_NotificationIn (void);
|
||||||
|
|
||||||
|
/* CDC Initialization Function */
|
||||||
|
extern void CDC_Init (void);
|
||||||
|
|
||||||
|
/* CDC prepare the SERAIAL_STATE */
|
||||||
|
extern unsigned short CDC_GetSerialState (void);
|
||||||
|
|
||||||
|
/* flow control */
|
||||||
|
extern unsigned short CDC_DepInEmpty; // DataEndPoint IN empty
|
||||||
|
|
||||||
|
#endif /* __CDCUSER_H__ */
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
* config.h: config file for usbcdc example for NXP LPC13xx Family
|
||||||
|
* Microprocessors
|
||||||
|
*
|
||||||
|
* Copyright(C) 2008, NXP Semiconductor
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* History
|
||||||
|
* 2008.07.19 ver 1.00 Preliminary version, first Release
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Overview:
|
||||||
|
This example shows how to use the USB driver to implement a CDC class USB peripheral.
|
||||||
|
To run this example, you must attach a USB cable to the board. See
|
||||||
|
the "Getting Started Guide" appendix for details.
|
||||||
|
|
||||||
|
How to use:
|
||||||
|
Click the debug toolbar button.
|
||||||
|
Click the go button.
|
||||||
|
Plug the LPCXpresso's target side into a PC using a USB cable retrofit
|
||||||
|
or a 3rd party base board.
|
||||||
|
|
||||||
|
* You should be able to see a new COM port on your PC.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
#define USB_VENDOR_ID CFG_USB_VID // Vendor ID
|
||||||
|
#define USB_PROD_ID CFG_USB_PID // Product ID
|
||||||
|
#define USB_DEVICE 0x0100 // Device ID
|
||||||
|
|
||||||
|
#define LED_PORT 0 // Port for led
|
||||||
|
#define LED_BIT 7 // Bit on port for led
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************************************************************
|
||||||
|
** End Of File
|
||||||
|
*********************************************************************************/
|
|
@ -0,0 +1,228 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: usb.h
|
||||||
|
* Purpose: USB Definitions
|
||||||
|
* Version: V1.20
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef __USB_H__
|
||||||
|
#define __USB_H__
|
||||||
|
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
uint16_t W;
|
||||||
|
struct {
|
||||||
|
uint8_t L;
|
||||||
|
uint8_t H;
|
||||||
|
} __attribute__((packed)) WB;
|
||||||
|
} __attribute__((packed)) WORD_BYTE;
|
||||||
|
|
||||||
|
|
||||||
|
/* bmRequestType.Dir */
|
||||||
|
#define REQUEST_HOST_TO_DEVICE 0
|
||||||
|
#define REQUEST_DEVICE_TO_HOST 1
|
||||||
|
|
||||||
|
/* bmRequestType.Type */
|
||||||
|
#define REQUEST_STANDARD 0
|
||||||
|
#define REQUEST_CLASS 1
|
||||||
|
#define REQUEST_VENDOR 2
|
||||||
|
#define REQUEST_RESERVED 3
|
||||||
|
|
||||||
|
/* bmRequestType.Recipient */
|
||||||
|
#define REQUEST_TO_DEVICE 0
|
||||||
|
#define REQUEST_TO_INTERFACE 1
|
||||||
|
#define REQUEST_TO_ENDPOINT 2
|
||||||
|
#define REQUEST_TO_OTHER 3
|
||||||
|
|
||||||
|
/* bmRequestType Definition */
|
||||||
|
typedef union _REQUEST_TYPE {
|
||||||
|
struct _BM {
|
||||||
|
uint8_t Recipient : 5;
|
||||||
|
uint8_t Type : 2;
|
||||||
|
uint8_t Dir : 1;
|
||||||
|
} __attribute__((packed)) BM;
|
||||||
|
uint8_t B;
|
||||||
|
} __attribute__((packed)) REQUEST_TYPE;
|
||||||
|
|
||||||
|
/* USB Standard Request Codes */
|
||||||
|
#define USB_REQUEST_GET_STATUS 0
|
||||||
|
#define USB_REQUEST_CLEAR_FEATURE 1
|
||||||
|
#define USB_REQUEST_SET_FEATURE 3
|
||||||
|
#define USB_REQUEST_SET_ADDRESS 5
|
||||||
|
#define USB_REQUEST_GET_DESCRIPTOR 6
|
||||||
|
#define USB_REQUEST_SET_DESCRIPTOR 7
|
||||||
|
#define USB_REQUEST_GET_CONFIGURATION 8
|
||||||
|
#define USB_REQUEST_SET_CONFIGURATION 9
|
||||||
|
#define USB_REQUEST_GET_INTERFACE 10
|
||||||
|
#define USB_REQUEST_SET_INTERFACE 11
|
||||||
|
#define USB_REQUEST_SYNC_FRAME 12
|
||||||
|
|
||||||
|
/* USB GET_STATUS Bit Values */
|
||||||
|
#define USB_GETSTATUS_SELF_POWERED 0x01
|
||||||
|
#define USB_GETSTATUS_REMOTE_WAKEUP 0x02
|
||||||
|
#define USB_GETSTATUS_ENDPOINT_STALL 0x01
|
||||||
|
|
||||||
|
/* USB Standard Feature selectors */
|
||||||
|
#define USB_FEATURE_ENDPOINT_STALL 0
|
||||||
|
#define USB_FEATURE_REMOTE_WAKEUP 1
|
||||||
|
|
||||||
|
/* USB Default Control Pipe Setup Packet */
|
||||||
|
typedef struct _USB_SETUP_PACKET {
|
||||||
|
REQUEST_TYPE bmRequestType;
|
||||||
|
uint8_t bRequest;
|
||||||
|
WORD_BYTE wValue;
|
||||||
|
WORD_BYTE wIndex;
|
||||||
|
uint16_t wLength;
|
||||||
|
} __attribute__((packed)) USB_SETUP_PACKET;
|
||||||
|
|
||||||
|
|
||||||
|
/* USB Descriptor Types */
|
||||||
|
#define USB_DEVICE_DESCRIPTOR_TYPE 1
|
||||||
|
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
|
||||||
|
#define USB_STRING_DESCRIPTOR_TYPE 3
|
||||||
|
#define USB_INTERFACE_DESCRIPTOR_TYPE 4
|
||||||
|
#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
|
||||||
|
#define USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE 6
|
||||||
|
#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE 7
|
||||||
|
#define USB_INTERFACE_POWER_DESCRIPTOR_TYPE 8
|
||||||
|
#define USB_OTG_DESCRIPTOR_TYPE 9
|
||||||
|
#define USB_DEBUG_DESCRIPTOR_TYPE 10
|
||||||
|
#define USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE 11
|
||||||
|
|
||||||
|
/* USB Device Classes */
|
||||||
|
#define USB_DEVICE_CLASS_RESERVED 0x00
|
||||||
|
#define USB_DEVICE_CLASS_AUDIO 0x01
|
||||||
|
#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02
|
||||||
|
#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03
|
||||||
|
#define USB_DEVICE_CLASS_MONITOR 0x04
|
||||||
|
#define USB_DEVICE_CLASS_PHYSICAL_INTERFACE 0x05
|
||||||
|
#define USB_DEVICE_CLASS_POWER 0x06
|
||||||
|
#define USB_DEVICE_CLASS_PRINTER 0x07
|
||||||
|
#define USB_DEVICE_CLASS_STORAGE 0x08
|
||||||
|
#define USB_DEVICE_CLASS_HUB 0x09
|
||||||
|
#define USB_DEVICE_CLASS_MISCELLANEOUS 0xEF
|
||||||
|
#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF
|
||||||
|
|
||||||
|
/* bmAttributes in Configuration Descriptor */
|
||||||
|
#define USB_CONFIG_POWERED_MASK 0x40
|
||||||
|
#define USB_CONFIG_BUS_POWERED 0x80
|
||||||
|
#define USB_CONFIG_SELF_POWERED 0xC0
|
||||||
|
#define USB_CONFIG_REMOTE_WAKEUP 0x20
|
||||||
|
|
||||||
|
/* bMaxPower in Configuration Descriptor */
|
||||||
|
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
|
||||||
|
|
||||||
|
/* bEndpointAddress in Endpoint Descriptor */
|
||||||
|
#define USB_ENDPOINT_DIRECTION_MASK 0x80
|
||||||
|
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
|
||||||
|
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
|
||||||
|
|
||||||
|
/* bmAttributes in Endpoint Descriptor */
|
||||||
|
#define USB_ENDPOINT_TYPE_MASK 0x03
|
||||||
|
#define USB_ENDPOINT_TYPE_CONTROL 0x00
|
||||||
|
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
|
||||||
|
#define USB_ENDPOINT_TYPE_BULK 0x02
|
||||||
|
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
|
||||||
|
#define USB_ENDPOINT_SYNC_MASK 0x0C
|
||||||
|
#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION 0x00
|
||||||
|
#define USB_ENDPOINT_SYNC_ASYNCHRONOUS 0x04
|
||||||
|
#define USB_ENDPOINT_SYNC_ADAPTIVE 0x08
|
||||||
|
#define USB_ENDPOINT_SYNC_SYNCHRONOUS 0x0C
|
||||||
|
#define USB_ENDPOINT_USAGE_MASK 0x30
|
||||||
|
#define USB_ENDPOINT_USAGE_DATA 0x00
|
||||||
|
#define USB_ENDPOINT_USAGE_FEEDBACK 0x10
|
||||||
|
#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK 0x20
|
||||||
|
#define USB_ENDPOINT_USAGE_RESERVED 0x30
|
||||||
|
|
||||||
|
/* USB Standard Device Descriptor */
|
||||||
|
typedef struct _USB_DEVICE_DESCRIPTOR {
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint16_t bcdUSB;
|
||||||
|
uint8_t bDeviceClass;
|
||||||
|
uint8_t bDeviceSubClass;
|
||||||
|
uint8_t bDeviceProtocol;
|
||||||
|
uint8_t bMaxPacketSize0;
|
||||||
|
uint16_t idVendor;
|
||||||
|
uint16_t idProduct;
|
||||||
|
uint16_t bcdDevice;
|
||||||
|
uint8_t iManufacturer;
|
||||||
|
uint8_t iProduct;
|
||||||
|
uint8_t iSerialNumber;
|
||||||
|
uint8_t bNumConfigurations;
|
||||||
|
} __attribute__((packed)) USB_DEVICE_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* USB 2.0 Device Qualifier Descriptor */
|
||||||
|
typedef struct _USB_DEVICE_QUALIFIER_DESCRIPTOR {
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint16_t bcdUSB;
|
||||||
|
uint8_t bDeviceClass;
|
||||||
|
uint8_t bDeviceSubClass;
|
||||||
|
uint8_t bDeviceProtocol;
|
||||||
|
uint8_t bMaxPacketSize0;
|
||||||
|
uint8_t bNumConfigurations;
|
||||||
|
uint8_t bReserved;
|
||||||
|
} __attribute__((packed)) USB_DEVICE_QUALIFIER_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* USB Standard Configuration Descriptor */
|
||||||
|
typedef struct _USB_CONFIGURATION_DESCRIPTOR {
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint16_t wTotalLength;
|
||||||
|
uint8_t bNumInterfaces;
|
||||||
|
uint8_t bConfigurationValue;
|
||||||
|
uint8_t iConfiguration;
|
||||||
|
uint8_t bmAttributes;
|
||||||
|
uint8_t bMaxPower;
|
||||||
|
} __attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* USB Standard Interface Descriptor */
|
||||||
|
typedef struct _USB_INTERFACE_DESCRIPTOR {
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint8_t bInterfaceNumber;
|
||||||
|
uint8_t bAlternateSetting;
|
||||||
|
uint8_t bNumEndpoints;
|
||||||
|
uint8_t bInterfaceClass;
|
||||||
|
uint8_t bInterfaceSubClass;
|
||||||
|
uint8_t bInterfaceProtocol;
|
||||||
|
uint8_t iInterface;
|
||||||
|
} __attribute__((packed)) USB_INTERFACE_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* USB Standard Endpoint Descriptor */
|
||||||
|
typedef struct _USB_ENDPOINT_DESCRIPTOR {
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint8_t bEndpointAddress;
|
||||||
|
uint8_t bmAttributes;
|
||||||
|
uint16_t wMaxPacketSize;
|
||||||
|
uint8_t bInterval;
|
||||||
|
} __attribute__((packed)) USB_ENDPOINT_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* USB String Descriptor */
|
||||||
|
typedef struct _USB_STRING_DESCRIPTOR {
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint16_t bString/*[]*/;
|
||||||
|
} __attribute__((packed)) USB_STRING_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* USB Common Descriptor */
|
||||||
|
typedef struct _USB_COMMON_DESCRIPTOR {
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
} __attribute__((packed)) USB_COMMON_DESCRIPTOR;
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __USB_H__ */
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: usbcfg.h
|
||||||
|
* Purpose: USB Custom Configuration
|
||||||
|
* Version: V1.20
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* History:
|
||||||
|
* V1.20 Added vendor specific support
|
||||||
|
* V1.00 Initial Version
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef __USBCFG_H__
|
||||||
|
#define __USBCFG_H__
|
||||||
|
|
||||||
|
|
||||||
|
//*** <<< Use Configuration Wizard in Context Menu >>> ***
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// <h> USB Configuration
|
||||||
|
// <o0> USB Power
|
||||||
|
// <i> Default Power Setting
|
||||||
|
// <0=> Bus-powered
|
||||||
|
// <1=> Self-powered
|
||||||
|
// <o1> Max Number of Interfaces <1-256>
|
||||||
|
// <o2> Max Number of Endpoints <1-32>
|
||||||
|
// <o3> Max Endpoint 0 Packet Size
|
||||||
|
// <8=> 8 Bytes <16=> 16 Bytes <32=> 32 Bytes <64=> 64 Bytes
|
||||||
|
// <e4> DMA Transfer
|
||||||
|
// <i> Use DMA for selected Endpoints
|
||||||
|
// <o5.0> Endpoint 0 Out
|
||||||
|
// <o5.1> Endpoint 0 In
|
||||||
|
// <o5.2> Endpoint 1 Out
|
||||||
|
// <o5.3> Endpoint 1 In
|
||||||
|
// <o5.4> Endpoint 2 Out
|
||||||
|
// <o5.5> Endpoint 2 In
|
||||||
|
// <o5.6> Endpoint 3 Out
|
||||||
|
// <o5.7> Endpoint 3 In
|
||||||
|
// <o5.8> Endpoint 4 Out
|
||||||
|
// <o5.9> Endpoint 4 In
|
||||||
|
// </e>
|
||||||
|
// </h>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define USB_POWER 0
|
||||||
|
#define USB_IF_NUM 1
|
||||||
|
#define USB_LOGIC_EP_NUM 5
|
||||||
|
#define USB_EP_NUM 10
|
||||||
|
#define USB_MAX_PACKET0 64
|
||||||
|
|
||||||
|
/*
|
||||||
|
// <h> USB Event Handlers
|
||||||
|
// <h> Device Events
|
||||||
|
// <o0.0> Power Event
|
||||||
|
// <o1.0> Reset Event
|
||||||
|
// <o2.0> Suspend Event
|
||||||
|
// <o3.0> Resume Event
|
||||||
|
// <o4.0> Remote Wakeup Event
|
||||||
|
// <o5.0> Start of Frame Event
|
||||||
|
// <o6.0> Error Event
|
||||||
|
// </h>
|
||||||
|
// <h> Endpoint Events
|
||||||
|
// <o7.0> Endpoint 0 Event
|
||||||
|
// <o7.1> Endpoint 1 Event
|
||||||
|
// <o7.2> Endpoint 2 Event
|
||||||
|
// <o7.3> Endpoint 3 Event
|
||||||
|
// <o7.4> Endpoint 4 Event
|
||||||
|
// <o7.5> Endpoint 5 Event
|
||||||
|
// <o7.6> Endpoint 6 Event
|
||||||
|
// <o7.7> Endpoint 7 Event
|
||||||
|
// <o7.8> Endpoint 8 Event
|
||||||
|
// <o7.9> Endpoint 9 Event
|
||||||
|
// <o7.10> Endpoint 10 Event
|
||||||
|
// <o7.11> Endpoint 11 Event
|
||||||
|
// <o7.12> Endpoint 12 Event
|
||||||
|
// <o7.13> Endpoint 13 Event
|
||||||
|
// <o7.14> Endpoint 14 Event
|
||||||
|
// <o7.15> Endpoint 15 Event
|
||||||
|
// </h>
|
||||||
|
// <h> USB Core Events
|
||||||
|
// <o8.0> Set Configuration Event
|
||||||
|
// <o9.0> Set Interface Event
|
||||||
|
// <o10.0> Set/Clear Feature Event
|
||||||
|
// </h>
|
||||||
|
// </h>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define USB_POWER_EVENT 0
|
||||||
|
#define USB_RESET_EVENT 1
|
||||||
|
#define USB_SUSPEND_EVENT 1
|
||||||
|
#define USB_RESUME_EVENT 1
|
||||||
|
#define USB_WAKEUP_EVENT 0
|
||||||
|
#define USB_SOF_EVENT 1
|
||||||
|
#define USB_ERROR_EVENT 0
|
||||||
|
#define USB_EP_EVENT 0x000B
|
||||||
|
#define USB_CONFIGURE_EVENT 1
|
||||||
|
#define USB_INTERFACE_EVENT 0
|
||||||
|
#define USB_FEATURE_EVENT 0
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// <e0> USB Class Support
|
||||||
|
// <i> enables USB Class specific Requests
|
||||||
|
// <e1> Human Interface Device (HID)
|
||||||
|
// <o2> Interface Number <0-255>
|
||||||
|
// </e>
|
||||||
|
// <e3> Mass Storage
|
||||||
|
// <o4> Interface Number <0-255>
|
||||||
|
// </e>
|
||||||
|
// <e5> Audio Device
|
||||||
|
// <o6> Control Interface Number <0-255>
|
||||||
|
// <o7> Streaming Interface 1 Number <0-255>
|
||||||
|
// <o8> Streaming Interface 2 Number <0-255>
|
||||||
|
// </e>
|
||||||
|
// <e9> Communication Device
|
||||||
|
// <o10> Control Interface Number <0-255>
|
||||||
|
// <o11> Bulk Interface Number <0-255>
|
||||||
|
// <o12> Max Communication Device Buffer Size
|
||||||
|
// <8=> 8 Bytes <16=> 16 Bytes <32=> 32 Bytes <64=> 64 Bytes
|
||||||
|
// </e>
|
||||||
|
// </e>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define USB_CLASS 1
|
||||||
|
#define USB_HID 0
|
||||||
|
#define USB_HID_IF_NUM 0
|
||||||
|
#define USB_MSC 0
|
||||||
|
#define USB_MSC_IF_NUM 0
|
||||||
|
#define USB_AUDIO 0
|
||||||
|
#define USB_ADC_CIF_NUM 0
|
||||||
|
#define USB_ADC_SIF1_NUM 1
|
||||||
|
#define USB_ADC_SIF2_NUM 2
|
||||||
|
#define USB_CDC 1
|
||||||
|
#define USB_CDC_CIF_NUM 0
|
||||||
|
#define USB_CDC_DIF_NUM 1
|
||||||
|
#define USB_CDC_BUFSIZE CFG_USBCDC_BUFSIZE
|
||||||
|
|
||||||
|
/*
|
||||||
|
// <e0> USB Vendor Support
|
||||||
|
// <i> enables USB Vendor specific Requests
|
||||||
|
// </e>
|
||||||
|
*/
|
||||||
|
#define USB_VENDOR 0
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __USBCFG_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,88 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: usbcore.h
|
||||||
|
* Purpose: USB Core Definitions
|
||||||
|
* Version: V1.20
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef __USBCORE_H__
|
||||||
|
#define __USBCORE_H__
|
||||||
|
|
||||||
|
#include "usbcfg.h"
|
||||||
|
|
||||||
|
/* USB Endpoint Data Structure */
|
||||||
|
typedef struct _USB_EP_DATA {
|
||||||
|
uint8_t *pData;
|
||||||
|
uint16_t Count;
|
||||||
|
} USB_EP_DATA;
|
||||||
|
|
||||||
|
/* USB Core Global Variables */
|
||||||
|
extern uint16_t USB_DeviceStatus;
|
||||||
|
extern uint8_t USB_DeviceAddress;
|
||||||
|
volatile extern uint8_t USB_Configuration;
|
||||||
|
extern uint32_t USB_EndPointMask;
|
||||||
|
extern uint32_t USB_EndPointHalt;
|
||||||
|
extern uint32_t USB_EndPointStall;
|
||||||
|
extern uint8_t USB_AltSetting[USB_IF_NUM];
|
||||||
|
|
||||||
|
|
||||||
|
/* USB Endpoint 0 Buffer */
|
||||||
|
extern uint8_t EP0Buf[USB_MAX_PACKET0];
|
||||||
|
|
||||||
|
/* USB Endpoint 0 Data Info */
|
||||||
|
extern USB_EP_DATA EP0Data;
|
||||||
|
|
||||||
|
/* USB Setup Packet */
|
||||||
|
extern USB_SETUP_PACKET SetupPacket;
|
||||||
|
|
||||||
|
/* USB Core Functions */
|
||||||
|
extern void USB_ResetCore (void);
|
||||||
|
|
||||||
|
/* Newer C compilers make it really difficult to add
|
||||||
|
* an integer to a pointer */
|
||||||
|
static inline void UsbAddPtr(void **vpptr, uint32_t n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a number of bytes to a pointer's address
|
||||||
|
* Harder than you might think. Some compilers say:
|
||||||
|
* Expected an lvalue -- Assignment expects its first operand to be
|
||||||
|
* an lvalue. Please note that a cast removes the lvaluedness of an
|
||||||
|
* expression.
|
||||||
|
*
|
||||||
|
* vpptr = void pointer to pointer
|
||||||
|
* n = number of bytes to add to pointer
|
||||||
|
* Call looks like: AddPtr((void **)&myPointer, 8);
|
||||||
|
*/
|
||||||
|
static inline void UsbAddPtr(void **vpptr, uint32_t n)
|
||||||
|
{
|
||||||
|
/* Declare a pointer to a pointer to a byte. Only a byte pointer
|
||||||
|
* can be incremented by a number of bytes. Other pointers will
|
||||||
|
* increment by a multiple of what they point to.
|
||||||
|
*/
|
||||||
|
uint8_t **bpptr;
|
||||||
|
|
||||||
|
/* Convert our void pointer to a pointer to a byte pointer to a pointer */
|
||||||
|
bpptr = (uint8_t **)vpptr;
|
||||||
|
|
||||||
|
/* Add 'n' bytes to our pointer value */
|
||||||
|
(*bpptr) += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __USBCORE_H__ */
|
|
@ -0,0 +1,202 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: usbdesc.c
|
||||||
|
* Purpose: USB Descriptors
|
||||||
|
* Version: V1.20
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* History:
|
||||||
|
* V1.20 Changed string descriptor handling
|
||||||
|
* V1.00 Initial Version
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
#include "projectconfig.h"
|
||||||
|
#include "usb.h"
|
||||||
|
#include "cdc.h"
|
||||||
|
#include "usbcfg.h"
|
||||||
|
#include "usbdesc.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* USB Standard Device Descriptor */
|
||||||
|
const uint8_t USB_DeviceDescriptor[] = {
|
||||||
|
USB_DEVICE_DESC_SIZE, /* bLength */
|
||||||
|
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
WBVAL(0x0200), /* 2.0 */ /* bcdUSB */
|
||||||
|
USB_DEVICE_CLASS_COMMUNICATIONS, /* bDeviceClass CDC*/
|
||||||
|
0x00, /* bDeviceSubClass */
|
||||||
|
0x00, /* bDeviceProtocol */
|
||||||
|
USB_MAX_PACKET0, /* bMaxPacketSize0 */
|
||||||
|
WBVAL(USB_VENDOR_ID), /* idVendor */
|
||||||
|
WBVAL(USB_PROD_ID), /* idProduct */
|
||||||
|
WBVAL(USB_DEVICE), /* 1.00 */ /* bcdDevice */
|
||||||
|
0x01, /* iManufacturer */
|
||||||
|
0x02, /* iProduct */
|
||||||
|
0x03, /* iSerialNumber */
|
||||||
|
0x01 /* bNumConfigurations: one possible configuration*/
|
||||||
|
};
|
||||||
|
|
||||||
|
/* USB Configuration Descriptor */
|
||||||
|
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
|
||||||
|
const uint8_t USB_ConfigDescriptor[] = {
|
||||||
|
/* Configuration 1 */
|
||||||
|
USB_CONFIGUARTION_DESC_SIZE, /* bLength */
|
||||||
|
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
WBVAL( /* wTotalLength */
|
||||||
|
1*USB_CONFIGUARTION_DESC_SIZE +
|
||||||
|
1*USB_INTERFACE_DESC_SIZE + /* communication interface */
|
||||||
|
0x0013 + /* CDC functions */
|
||||||
|
1*USB_ENDPOINT_DESC_SIZE + /* interrupt endpoint */
|
||||||
|
1*USB_INTERFACE_DESC_SIZE + /* data interface */
|
||||||
|
2*USB_ENDPOINT_DESC_SIZE /* bulk endpoints */
|
||||||
|
),
|
||||||
|
0x02, /* bNumInterfaces */
|
||||||
|
0x01, /* bConfigurationValue: 0x01 is used to select this configuration */
|
||||||
|
0x00, /* iConfiguration: no string to describe this configuration */
|
||||||
|
USB_CONFIG_BUS_POWERED /*|*/ /* bmAttributes */
|
||||||
|
/*USB_CONFIG_REMOTE_WAKEUP*/,
|
||||||
|
USB_CONFIG_POWER_MA(100), /* bMaxPower, device power consumption is 100 mA */
|
||||||
|
/* Interface 0, Alternate Setting 0, Communication class interface descriptor */
|
||||||
|
USB_INTERFACE_DESC_SIZE, /* bLength */
|
||||||
|
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
USB_CDC_CIF_NUM, /* bInterfaceNumber: Number of Interface */
|
||||||
|
0x00, /* bAlternateSetting: Alternate setting */
|
||||||
|
0x01, /* bNumEndpoints: One endpoint used */
|
||||||
|
CDC_COMMUNICATION_INTERFACE_CLASS, /* bInterfaceClass: Communication Interface Class */
|
||||||
|
CDC_ABSTRACT_CONTROL_MODEL, /* bInterfaceSubClass: Abstract Control Model */
|
||||||
|
0x00, /* bInterfaceProtocol: no protocol used */
|
||||||
|
0x5E, /* iInterface: */
|
||||||
|
/*Header Functional Descriptor*/
|
||||||
|
0x05, /* bLength: Endpoint Descriptor size */
|
||||||
|
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */
|
||||||
|
CDC_HEADER, /* bDescriptorSubtype: Header Func Desc */
|
||||||
|
WBVAL(CDC_V1_10), /* 1.10 */ /* bcdCDC */
|
||||||
|
/*Call Management Functional Descriptor*/
|
||||||
|
0x05, /* bFunctionLength */
|
||||||
|
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */
|
||||||
|
CDC_CALL_MANAGEMENT, /* bDescriptorSubtype: Call Management Func Desc */
|
||||||
|
0x01, /* bmCapabilities: device handles call management */
|
||||||
|
0x01, /* bDataInterface: CDC data IF ID */
|
||||||
|
/*Abstract Control Management Functional Descriptor*/
|
||||||
|
0x04, /* bFunctionLength */
|
||||||
|
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */
|
||||||
|
CDC_ABSTRACT_CONTROL_MANAGEMENT, /* bDescriptorSubtype: Abstract Control Management desc */
|
||||||
|
0x02, /* bmCapabilities: SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported */
|
||||||
|
/*Union Functional Descriptor*/
|
||||||
|
0x05, /* bFunctionLength */
|
||||||
|
CDC_CS_INTERFACE, /* bDescriptorType: CS_INTERFACE */
|
||||||
|
CDC_UNION, /* bDescriptorSubtype: Union func desc */
|
||||||
|
USB_CDC_CIF_NUM, /* bMasterInterface: Communication class interface is master */
|
||||||
|
USB_CDC_DIF_NUM, /* bSlaveInterface0: Data class interface is slave 0 */
|
||||||
|
/*Endpoint 1 Descriptor*/ /* event notification (optional) */
|
||||||
|
USB_ENDPOINT_DESC_SIZE, /* bLength */
|
||||||
|
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
USB_ENDPOINT_IN(1), /* bEndpointAddress */
|
||||||
|
USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */
|
||||||
|
WBVAL(0x0010), /* wMaxPacketSize */
|
||||||
|
0x02, /* 2ms */ /* bInterval */
|
||||||
|
/* Interface 1, Alternate Setting 0, Data class interface descriptor*/
|
||||||
|
USB_INTERFACE_DESC_SIZE, /* bLength */
|
||||||
|
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
USB_CDC_DIF_NUM, /* bInterfaceNumber: Number of Interface */
|
||||||
|
0x00, /* bAlternateSetting: no alternate setting */
|
||||||
|
0x02, /* bNumEndpoints: two endpoints used */
|
||||||
|
CDC_DATA_INTERFACE_CLASS, /* bInterfaceClass: Data Interface Class */
|
||||||
|
0x00, /* bInterfaceSubClass: no subclass available */
|
||||||
|
0x00, /* bInterfaceProtocol: no protocol used */
|
||||||
|
0x5E, /* iInterface: */
|
||||||
|
/* Endpoint, EP3 Bulk Out */
|
||||||
|
USB_ENDPOINT_DESC_SIZE, /* bLength */
|
||||||
|
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
USB_ENDPOINT_OUT(3), /* bEndpointAddress */
|
||||||
|
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */
|
||||||
|
WBVAL(64), /* wMaxPacketSize */
|
||||||
|
0x00, /* bInterval: ignore for Bulk transfer */
|
||||||
|
/* Endpoint, EP3 Bulk In */
|
||||||
|
USB_ENDPOINT_DESC_SIZE, /* bLength */
|
||||||
|
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
USB_ENDPOINT_IN(3), /* bEndpointAddress */
|
||||||
|
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */
|
||||||
|
WBVAL(64), /* wMaxPacketSize */
|
||||||
|
0x00, /* bInterval: ignore for Bulk transfer */
|
||||||
|
/* Terminator */
|
||||||
|
0 /* bLength */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* USB String Descriptor (optional) */
|
||||||
|
const uint8_t USB_StringDescriptor[] = {
|
||||||
|
/* Index 0x00: LANGID Codes */
|
||||||
|
0x04, /* bLength */
|
||||||
|
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
WBVAL(0x0409), /* US English */ /* wLANGID */
|
||||||
|
/* Index 0x01: Manufacturer */
|
||||||
|
(13*2 + 2), /* bLength (13 Char + Type + lenght) */
|
||||||
|
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
'M',0,
|
||||||
|
'I',0,
|
||||||
|
'C',0,
|
||||||
|
'R',0,
|
||||||
|
'O',0,
|
||||||
|
'B',0,
|
||||||
|
'U',0,
|
||||||
|
'I',0,
|
||||||
|
'L',0,
|
||||||
|
'D',0,
|
||||||
|
'E',0,
|
||||||
|
'R',0,
|
||||||
|
' ',0,
|
||||||
|
/* Index 0x02: Product */
|
||||||
|
(17*2 + 2), /* bLength ( 17 Char + Type + lenght) */
|
||||||
|
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
'L',0,
|
||||||
|
'P',0,
|
||||||
|
'C',0,
|
||||||
|
'1',0,
|
||||||
|
'3',0,
|
||||||
|
'4',0,
|
||||||
|
'3',0,
|
||||||
|
' ',0,
|
||||||
|
'C',0,
|
||||||
|
'O',0,
|
||||||
|
'M',0,
|
||||||
|
' ',0,
|
||||||
|
'P',0,
|
||||||
|
'O',0,
|
||||||
|
'R',0,
|
||||||
|
'T',0,
|
||||||
|
' ',0,
|
||||||
|
/* Index 0x03: Serial Number */
|
||||||
|
(12*2 + 2), /* bLength (12 Char + Type + lenght) */
|
||||||
|
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
'D',0,
|
||||||
|
'E',0,
|
||||||
|
'M',0,
|
||||||
|
'O',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
/* Index 0x04: Interface 0, Alternate Setting 0 */
|
||||||
|
( 4*2 + 2), /* bLength (4 Char + Type + lenght) */
|
||||||
|
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
'V',0,
|
||||||
|
'C',0,
|
||||||
|
'O',0,
|
||||||
|
'M',0,
|
||||||
|
};
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: usbdesc.h
|
||||||
|
* Purpose: USB Descriptors Definitions
|
||||||
|
* Version: V1.20
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef __USBDESC_H__
|
||||||
|
#define __USBDESC_H__
|
||||||
|
|
||||||
|
|
||||||
|
#define WBVAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
|
||||||
|
|
||||||
|
#define USB_DEVICE_DESC_SIZE (sizeof(USB_DEVICE_DESCRIPTOR))
|
||||||
|
#define USB_CONFIGUARTION_DESC_SIZE (sizeof(USB_CONFIGURATION_DESCRIPTOR))
|
||||||
|
#define USB_INTERFACE_DESC_SIZE (sizeof(USB_INTERFACE_DESCRIPTOR))
|
||||||
|
#define USB_ENDPOINT_DESC_SIZE (sizeof(USB_ENDPOINT_DESCRIPTOR))
|
||||||
|
|
||||||
|
extern const uint8_t USB_DeviceDescriptor[];
|
||||||
|
extern const uint8_t USB_ConfigDescriptor[];
|
||||||
|
extern const uint8_t USB_StringDescriptor[];
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __USBDESC_H__ */
|
|
@ -0,0 +1,606 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: usbhw.c
|
||||||
|
* Purpose: USB Hardware Layer Module for Philips LPC17xx
|
||||||
|
* Version: V1.20
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* History:
|
||||||
|
* V1.20 Added USB_ClearEPBuf
|
||||||
|
* V1.00 Initial Version
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
#include "projectconfig.h" /* LPC13xx definitions */
|
||||||
|
#include "usb.h"
|
||||||
|
#include "usbcfg.h"
|
||||||
|
#include "usbreg.h"
|
||||||
|
#include "usbhw.h"
|
||||||
|
#include "usbcore.h"
|
||||||
|
#include "usbuser.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB and IO Clock configuration only.
|
||||||
|
* The same as call PeriClkIOInit(IOCON_USB);
|
||||||
|
* The purpose is to reduce the code space for
|
||||||
|
* overall USB project and reserve code space for
|
||||||
|
* USB debugging.
|
||||||
|
* Parameters: None
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
void USBIOClkConfig( void )
|
||||||
|
{
|
||||||
|
/* Enable AHB clock to the GPIO domain. */
|
||||||
|
SCB_SYSAHBCLKCTRL |= SCB_SYSAHBCLKCTRL_GPIO;
|
||||||
|
|
||||||
|
/* Enable Timer32_1, IOCON, and USB blocks */
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT32B1 | SCB_SYSAHBCLKCTRL_IOCON | SCB_SYSAHBCLKCTRL_USB_REG);
|
||||||
|
|
||||||
|
// Setup USB clock
|
||||||
|
SCB_PDRUNCFG &= ~(SCB_PDSLEEPCFG_USBPAD_PD); // Power-up USB PHY
|
||||||
|
SCB_PDRUNCFG &= ~(SCB_PDSLEEPCFG_USBPLL_PD); // Power-up USB PLL
|
||||||
|
|
||||||
|
SCB_USBPLLCLKSEL = SCB_USBPLLCLKSEL_SOURCE_MAINOSC; // Select PLL Input
|
||||||
|
SCB_USBPLLCLKUEN = SCB_USBPLLCLKUEN_UPDATE; // Update Clock Source
|
||||||
|
SCB_USBPLLCLKUEN = SCB_USBPLLCLKUEN_DISABLE; // Toggle Update Register
|
||||||
|
SCB_USBPLLCLKUEN = SCB_USBPLLCLKUEN_UPDATE;
|
||||||
|
|
||||||
|
// Wait until the USB clock is updated
|
||||||
|
while (!(SCB_USBPLLCLKUEN & SCB_USBPLLCLKUEN_UPDATE));
|
||||||
|
|
||||||
|
// Set USB clock to 48MHz (12MHz x 4)
|
||||||
|
SCB_USBPLLCTRL = (SCB_USBPLLCTRL_MULT_4);
|
||||||
|
while (!(SCB_USBPLLSTAT & SCB_USBPLLSTAT_LOCK)); // Wait Until PLL Locked
|
||||||
|
SCB_USBCLKSEL = SCB_USBCLKSEL_SOURCE_USBPLLOUT;
|
||||||
|
|
||||||
|
// Set USB pin functions
|
||||||
|
IOCON_PIO0_1 &= ~IOCON_PIO0_1_FUNC_MASK;
|
||||||
|
IOCON_PIO0_1 |= IOCON_PIO0_1_FUNC_CLKOUT; // CLK OUT
|
||||||
|
IOCON_PIO0_3 &= ~IOCON_PIO0_3_FUNC_MASK;
|
||||||
|
IOCON_PIO0_3 |= IOCON_PIO0_3_FUNC_USB_VBUS; // VBus
|
||||||
|
IOCON_PIO0_6 &= ~IOCON_PIO0_6_FUNC_MASK;
|
||||||
|
IOCON_PIO0_6 |= IOCON_PIO0_6_FUNC_USB_CONNECT; // Soft Connect
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delay number of clock cycles
|
||||||
|
* Parameters: Delay length
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void delay (uint32_t length )
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for ( i = 0; i < length; i++ )
|
||||||
|
{
|
||||||
|
__asm("nop");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get Endpoint Physical Address
|
||||||
|
* Parameters: EPNum: Endpoint Number
|
||||||
|
* EPNum.0..3: Address
|
||||||
|
* EPNum.7: Dir
|
||||||
|
* Return Value: Endpoint Physical Address
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t EPAdr (uint32_t EPNum)
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
val = (EPNum & 0x0F) << 1;
|
||||||
|
if (EPNum & 0x80) {
|
||||||
|
val += 1;
|
||||||
|
}
|
||||||
|
return (val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write Command
|
||||||
|
* Parameters: cmd: Command
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void WrCmd (uint32_t cmd)
|
||||||
|
{
|
||||||
|
USB_DEVINTCLR = CCEMTY_INT;
|
||||||
|
USB_CMDCODE = cmd;
|
||||||
|
while ((USB_DEVINTST & (CCEMTY_INT | DEV_STAT_INT)) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write Command Data
|
||||||
|
* Parameters: cmd: Command
|
||||||
|
* val: Data
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void WrCmdDat (uint32_t cmd, uint32_t val)
|
||||||
|
{
|
||||||
|
WrCmd(cmd);
|
||||||
|
WrCmd(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write Command to Endpoint
|
||||||
|
* Parameters: cmd: Command
|
||||||
|
* val: Data
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void WrCmdEP (uint32_t EPNum, uint32_t cmd)
|
||||||
|
{
|
||||||
|
WrCmd(CMD_SEL_EP(EPAdr(EPNum)));
|
||||||
|
WrCmd(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read Command Data
|
||||||
|
* Parameters: cmd: Command
|
||||||
|
* Return Value: Data Value
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t RdCmdDat (uint32_t cmd)
|
||||||
|
{
|
||||||
|
USB_DEVINTCLR = CCEMTY_INT | CDFULL_INT;
|
||||||
|
USB_CMDCODE = cmd;
|
||||||
|
while ((USB_DEVINTST & (CDFULL_INT | DEV_STAT_INT)) == 0);
|
||||||
|
return (USB_CMDDATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Initialize Function
|
||||||
|
* Called by the User to initialize USB
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_Init (void)
|
||||||
|
{
|
||||||
|
// Setup USB clock and pins
|
||||||
|
USBIOClkConfig();
|
||||||
|
|
||||||
|
#if USB_FIQ_EVENT
|
||||||
|
/* It's important that only BULK and FRAME(ISO) can be routed
|
||||||
|
to FIQ. */
|
||||||
|
USB_DEVFIQSEL = 0x01; /* SOF Use FIQ */
|
||||||
|
|
||||||
|
/* Enable the USB Interrupt */
|
||||||
|
NVIC_EnableIRQ(USB_FIQn);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Enable the USB Interrupt */
|
||||||
|
NVIC_EnableIRQ(USB_IRQn);
|
||||||
|
|
||||||
|
USB_Reset();
|
||||||
|
USB_SetAddress(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Connect Function
|
||||||
|
* Called by the User to Connect/Disconnect USB
|
||||||
|
* Parameters: con: Connect/Disconnect
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_Connect (uint32_t con)
|
||||||
|
{
|
||||||
|
WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(con ? DEV_CON : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Reset Function
|
||||||
|
* Called automatically on USB Reset
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_Reset (void)
|
||||||
|
{
|
||||||
|
USB_DEVINTCLR = 0x000FFFFF;
|
||||||
|
/* Enable all eight(8) EPs, note: EP won't be ready until it's
|
||||||
|
configured/enabled when device sending SetEPStatus command
|
||||||
|
to the command engine. */
|
||||||
|
USB_DEVINTEN = DEV_STAT_INT | (0xFF<<1) |
|
||||||
|
(USB_SOF_EVENT ? FRAME_INT : 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Suspend Function
|
||||||
|
* Called automatically on USB Suspend
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_Suspend (void)
|
||||||
|
{
|
||||||
|
/* Performed by Hardware */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Resume Function
|
||||||
|
* Called automatically on USB Resume
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_Resume (void)
|
||||||
|
{
|
||||||
|
/* Performed by Hardware */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Remote Wakeup Function
|
||||||
|
* Called automatically on USB Remote Wakeup
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_WakeUp (void)
|
||||||
|
{
|
||||||
|
if (USB_DeviceStatus & USB_GETSTATUS_REMOTE_WAKEUP)
|
||||||
|
{
|
||||||
|
WrCmdDat(CMD_SET_DEV_STAT, DAT_WR_BYTE(DEV_CON));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Remote Wakeup Configuration Function
|
||||||
|
* Parameters: cfg: Enable/Disable
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_WakeUpCfg (uint32_t cfg)
|
||||||
|
{
|
||||||
|
cfg = cfg; /* Not needed */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Set Address Function
|
||||||
|
* Parameters: adr: USB Address
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_SetAddress (uint32_t adr)
|
||||||
|
{
|
||||||
|
WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /* Don't wait for next */
|
||||||
|
WrCmdDat(CMD_SET_ADDR, DAT_WR_BYTE(DEV_EN | adr)); /* Setup Status Phase */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Configure Function
|
||||||
|
* Parameters: cfg: Configure/Deconfigure
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_Configure (uint32_t cfg)
|
||||||
|
{
|
||||||
|
WrCmdDat(CMD_CFG_DEV, DAT_WR_BYTE(cfg ? CONF_DVICE : 0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configure USB Endpoint according to Descriptor
|
||||||
|
* Parameters: pEPD: Pointer to Endpoint Descriptor
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set Direction for USB Control Endpoint
|
||||||
|
* Parameters: dir: Out (dir == 0), In (dir <> 0)
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_DirCtrlEP (uint32_t dir)
|
||||||
|
{
|
||||||
|
dir = dir; /* Not needed */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable USB Endpoint
|
||||||
|
* Parameters: EPNum: Endpoint Number
|
||||||
|
* EPNum.0..3: Address
|
||||||
|
* EPNum.7: Dir
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_EnableEP (uint32_t EPNum)
|
||||||
|
{
|
||||||
|
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable USB Endpoint
|
||||||
|
* Parameters: EPNum: Endpoint Number
|
||||||
|
* EPNum.0..3: Address
|
||||||
|
* EPNum.7: Dir
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_DisableEP (uint32_t EPNum)
|
||||||
|
{
|
||||||
|
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_DA));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset USB Endpoint
|
||||||
|
* Parameters: EPNum: Endpoint Number
|
||||||
|
* EPNum.0..3: Address
|
||||||
|
* EPNum.7: Dir
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_ResetEP (uint32_t EPNum)
|
||||||
|
{
|
||||||
|
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set Stall for USB Endpoint
|
||||||
|
* Parameters: EPNum: Endpoint Number
|
||||||
|
* EPNum.0..3: Address
|
||||||
|
* EPNum.7: Dir
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_SetStallEP (uint32_t EPNum)
|
||||||
|
{
|
||||||
|
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(EP_STAT_ST));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear Stall for USB Endpoint
|
||||||
|
* Parameters: EPNum: Endpoint Number
|
||||||
|
* EPNum.0..3: Address
|
||||||
|
* EPNum.7: Dir
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_ClrStallEP (uint32_t EPNum)
|
||||||
|
{
|
||||||
|
WrCmdDat(CMD_SET_EP_STAT(EPAdr(EPNum)), DAT_WR_BYTE(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear USB Endpoint Buffer
|
||||||
|
* Parameters: EPNum: Endpoint Number
|
||||||
|
* EPNum.0..3: Address
|
||||||
|
* EPNum.7: Dir
|
||||||
|
* Return Value: None
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_ClearEPBuf (uint32_t EPNum)
|
||||||
|
{
|
||||||
|
WrCmdEP(EPNum, CMD_CLR_BUF);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read USB Endpoint Data
|
||||||
|
* Parameters: EPNum: Endpoint Number
|
||||||
|
* EPNum.0..3: Address
|
||||||
|
* EPNum.7: Dir
|
||||||
|
* pData: Pointer to Data Buffer
|
||||||
|
* Return Value: Number of bytes read
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t USB_ReadEP (uint32_t EPNum, uint8_t *pData)
|
||||||
|
{
|
||||||
|
uint32_t cnt, n;
|
||||||
|
|
||||||
|
USB_CTRL = ((EPNum & 0x0F) << 2) | CTRL_RD_EN;
|
||||||
|
/* 3 clock cycles to fetch the packet length from RAM. */
|
||||||
|
delay( 5 );
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cnt = USB_RXPLEN;
|
||||||
|
} while ((cnt & PKT_DV) == 0);
|
||||||
|
cnt &= PKT_LNGTH_MASK;
|
||||||
|
|
||||||
|
for (n = 0; n < (cnt + 3) / 4; n++)
|
||||||
|
{
|
||||||
|
*((uint32_t __attribute__((packed)) *)pData) = USB_RXDATA;
|
||||||
|
pData += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_CTRL = 0;
|
||||||
|
|
||||||
|
if ((EPNum & 0x80) != 0x04)
|
||||||
|
{ /* Non-Isochronous Endpoint */
|
||||||
|
WrCmdEP(EPNum, CMD_CLR_BUF);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write USB Endpoint Data
|
||||||
|
* Parameters: EPNum: Endpoint Number
|
||||||
|
* EPNum.0..3: Address
|
||||||
|
* EPNum.7: Dir
|
||||||
|
* pData: Pointer to Data Buffer
|
||||||
|
* cnt: Number of bytes to write
|
||||||
|
* Return Value: Number of bytes written
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t USB_WriteEP (uint32_t EPNum, uint8_t *pData, uint32_t cnt)
|
||||||
|
{
|
||||||
|
uint32_t n;
|
||||||
|
|
||||||
|
USB_CTRL = ((EPNum & 0x0F) << 2) | CTRL_WR_EN;
|
||||||
|
/* 3 clock cycles to fetch the packet length from RAM. */
|
||||||
|
delay( 5 );
|
||||||
|
USB_TXPLEN = cnt;
|
||||||
|
|
||||||
|
for (n = 0; n < (cnt + 3) / 4; n++)
|
||||||
|
{
|
||||||
|
USB_TXDATA = *((uint32_t __attribute__((packed)) *)pData);
|
||||||
|
pData += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
USB_CTRL = 0;
|
||||||
|
|
||||||
|
WrCmdEP(EPNum, CMD_VALID_BUF);
|
||||||
|
|
||||||
|
return (cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get USB Last Frame Number
|
||||||
|
* Parameters: None
|
||||||
|
* Return Value: Frame Number
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint32_t USB_GetFrame (void)
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
WrCmd(CMD_RD_FRAME);
|
||||||
|
val = RdCmdDat(DAT_RD_FRAME);
|
||||||
|
val = val | (RdCmdDat(DAT_RD_FRAME) << 8);
|
||||||
|
|
||||||
|
return (val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Interrupt Service Routine
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CFG_USBCDC
|
||||||
|
void USB_IRQHandler (void)
|
||||||
|
{
|
||||||
|
uint32_t disr, val, n, m;
|
||||||
|
|
||||||
|
disr = USB_DEVINTST; /* Device Interrupt Status */
|
||||||
|
USB_DEVINTCLR = disr;
|
||||||
|
|
||||||
|
/* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
|
||||||
|
if (disr & DEV_STAT_INT)
|
||||||
|
{
|
||||||
|
WrCmd(CMD_GET_DEV_STAT);
|
||||||
|
val = RdCmdDat(DAT_GET_DEV_STAT); /* Device Status */
|
||||||
|
if (val & DEV_RST) { /* Reset */
|
||||||
|
USB_Reset();
|
||||||
|
#if USB_RESET_EVENT
|
||||||
|
USB_Reset_Event();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (val & DEV_CON_CH) { /* Connect change */
|
||||||
|
#if USB_POWER_EVENT
|
||||||
|
USB_Power_Event(val & DEV_CON);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (val & DEV_SUS_CH) { /* Suspend/Resume */
|
||||||
|
if (val & DEV_SUS) { /* Suspend */
|
||||||
|
USB_Suspend();
|
||||||
|
#if USB_SUSPEND_EVENT
|
||||||
|
USB_Suspend_Event();
|
||||||
|
#endif
|
||||||
|
} else { /* Resume */
|
||||||
|
USB_Resume();
|
||||||
|
#if USB_RESUME_EVENT
|
||||||
|
USB_Resume_Event();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto isr_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if USB_SOF_EVENT
|
||||||
|
/* Start of Frame Interrupt */
|
||||||
|
if (disr & FRAME_INT)
|
||||||
|
{
|
||||||
|
USB_DEVINTCLR = FRAME_INT;
|
||||||
|
USB_SOF_Event();
|
||||||
|
// SOFIRQCount++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USB_ERROR_EVENT
|
||||||
|
/* NO error interrupt anymore, below code can be used
|
||||||
|
as example to get error status from command engine. */
|
||||||
|
/* Error Interrupt */
|
||||||
|
if (disr & ERR_INT)
|
||||||
|
{
|
||||||
|
WrCmd(CMD_RD_ERR_STAT);
|
||||||
|
val = RdCmdDat(DAT_RD_ERR_STAT);
|
||||||
|
USB_Error_Event(val);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Endpoint's Interrupt */
|
||||||
|
if (disr & (0xFF<<1)) {
|
||||||
|
/* if any of the EP0 through EP7 is set, or bit 1 through 9 on disr */
|
||||||
|
for (n = 0; n < USB_EP_NUM; n++) { /* Check All Endpoints */
|
||||||
|
/* skip frame interrupt at bit 0 in disr */
|
||||||
|
// if (disr & ((1 << n)<<1)) {
|
||||||
|
if ((disr>>1) & (1 << n)) {
|
||||||
|
m = n >> 1;
|
||||||
|
/* clear EP interrupt by sending cmd to the command engine. */
|
||||||
|
WrCmd(CMD_SEL_EP_CLRI(n));
|
||||||
|
val = RdCmdDat(DAT_SEL_EP_CLRI(n));
|
||||||
|
if ((n & 1) == 0) { /* OUT Endpoint */
|
||||||
|
if (n == 0) { /* Control OUT Endpoint */
|
||||||
|
if (val & EP_SEL_STP) { /* Setup Packet */
|
||||||
|
if (USB_P_EP[0]) {
|
||||||
|
USB_P_EP[0](USB_EVT_SETUP);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (USB_P_EP[m]) {
|
||||||
|
USB_P_EP[m](USB_EVT_OUT);
|
||||||
|
}
|
||||||
|
} else { /* IN Endpoint */
|
||||||
|
if (USB_P_EP[m]) {
|
||||||
|
USB_P_EP[m](USB_EVT_IN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isr_end:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: usbhw.h
|
||||||
|
* Purpose: USB Hardware Layer Definitions
|
||||||
|
* Version: V1.20
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* History:
|
||||||
|
* V1.20 Added USB_ClearEPBuf
|
||||||
|
* V1.00 Initial Version
|
||||||
|
*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef __USBHW_H__
|
||||||
|
#define __USBHW_H__
|
||||||
|
|
||||||
|
|
||||||
|
/* USB Error Codes */
|
||||||
|
#define USB_ERR_PID 0x0001 /* PID Error */
|
||||||
|
#define USB_ERR_UEPKT 0x0002 /* Unexpected Packet */
|
||||||
|
#define USB_ERR_DCRC 0x0004 /* Data CRC Error */
|
||||||
|
#define USB_ERR_TIMOUT 0x0008 /* Bus Time-out Error */
|
||||||
|
#define USB_ERR_EOP 0x0010 /* End of Packet Error */
|
||||||
|
#define USB_ERR_B_OVRN 0x0020 /* Buffer Overrun */
|
||||||
|
#define USB_ERR_BTSTF 0x0040 /* Bit Stuff Error */
|
||||||
|
#define USB_ERR_TGL 0x0080 /* Toggle Bit Error */
|
||||||
|
|
||||||
|
/* USB Hardware Functions */
|
||||||
|
extern void USBIOClkConfig (void);
|
||||||
|
extern void USB_Init (void);
|
||||||
|
extern void USB_Connect (uint32_t con);
|
||||||
|
extern void USB_Reset (void);
|
||||||
|
extern void USB_Suspend (void);
|
||||||
|
extern void USB_Resume (void);
|
||||||
|
extern void USB_WakeUp (void);
|
||||||
|
extern void USB_WakeUpCfg (uint32_t cfg);
|
||||||
|
extern void USB_SetAddress (uint32_t adr);
|
||||||
|
extern void USB_Configure (uint32_t cfg);
|
||||||
|
extern void USB_ConfigEP (USB_ENDPOINT_DESCRIPTOR *pEPD);
|
||||||
|
extern void USB_DirCtrlEP (uint32_t dir);
|
||||||
|
extern void USB_EnableEP (uint32_t EPNum);
|
||||||
|
extern void USB_DisableEP (uint32_t EPNum);
|
||||||
|
extern void USB_ResetEP (uint32_t EPNum);
|
||||||
|
extern void USB_SetStallEP (uint32_t EPNum);
|
||||||
|
extern void USB_ClrStallEP (uint32_t EPNum);
|
||||||
|
extern void USB_ClearEPBuf (uint32_t EPNum);
|
||||||
|
extern uint32_t USB_ReadEP (uint32_t EPNum, uint8_t *pData);
|
||||||
|
extern uint32_t USB_WriteEP (uint32_t EPNum, uint8_t *pData, uint32_t cnt);
|
||||||
|
extern uint32_t USB_GetFrame(void);
|
||||||
|
extern void USB_IRQHandler (void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __USBHW_H__ */
|
|
@ -0,0 +1,134 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: USBREG.H
|
||||||
|
* Purpose: USB Hardware Layer Definitions for NXP LPC13xx
|
||||||
|
* Version: V1.20
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef __USBREG_H
|
||||||
|
#define __USBREG_H
|
||||||
|
|
||||||
|
/* Device Interrupt Bit Definitions */
|
||||||
|
#define FRAME_INT (0x1<<0)
|
||||||
|
#define EP0_INT (0x1<<1)
|
||||||
|
#define EP1_INT (0x1<<2)
|
||||||
|
#define EP2_INT (0x1<<3)
|
||||||
|
#define EP3_INT (0x1<<4)
|
||||||
|
#define EP4_INT (0x1<<5)
|
||||||
|
#define EP5_INT (0x1<<6)
|
||||||
|
#define EP6_INT (0x1<<7)
|
||||||
|
#define EP7_INT (0x1<<8)
|
||||||
|
#define DEV_STAT_INT (0x1<<9)
|
||||||
|
#define CCEMTY_INT (0x1<<10)
|
||||||
|
#define CDFULL_INT (0x1<<11)
|
||||||
|
#define RxENDPKT_INT (0x1<<12)
|
||||||
|
#define TxENDPKT_INT (0x1<<13)
|
||||||
|
|
||||||
|
/* Rx & Tx Packet Length Definitions */
|
||||||
|
#define PKT_LNGTH_MASK 0x000003FF
|
||||||
|
#define PKT_DV 0x00000400
|
||||||
|
#define PKT_RDY 0x00000800
|
||||||
|
|
||||||
|
/* USB Control Definitions */
|
||||||
|
#define CTRL_RD_EN 0x00000001
|
||||||
|
#define CTRL_WR_EN 0x00000002
|
||||||
|
|
||||||
|
/* Command Codes */
|
||||||
|
#define CMD_SET_ADDR 0x00D00500
|
||||||
|
#define CMD_CFG_DEV 0x00D80500
|
||||||
|
#define CMD_SET_MODE 0x00F30500
|
||||||
|
#define CMD_RD_INT 0x00F40500
|
||||||
|
#define DAT_RD_INT 0x00F40200
|
||||||
|
#define CMD_RD_FRAME 0x00F50500
|
||||||
|
#define DAT_RD_FRAME 0x00F50200
|
||||||
|
#define CMD_RD_CHIP_ID 0x00FD0500
|
||||||
|
#define DAT_RD_CHIP_ID 0x00FD0200
|
||||||
|
|
||||||
|
#define CMD_SET_DEV_STAT 0x00FE0500
|
||||||
|
#define CMD_GET_DEV_STAT 0x00FE0500
|
||||||
|
#define DAT_GET_DEV_STAT 0x00FE0200
|
||||||
|
#define CMD_GET_ERR_CODE 0x00FF0500
|
||||||
|
#define DAT_GET_ERR_CODE 0x00FF0200
|
||||||
|
|
||||||
|
#define DAT_WR_BYTE(x) (0x00000100 | ((x) << 16))
|
||||||
|
#define CMD_SEL_EP(x) (0x00000500 | ((x) << 16))
|
||||||
|
#define DAT_SEL_EP(x) (0x00000200 | ((x) << 16))
|
||||||
|
#define CMD_SEL_EP_CLRI(x) (0x00400500 | ((x) << 16))
|
||||||
|
#define DAT_SEL_EP_CLRI(x) (0x00400200 | ((x) << 16))
|
||||||
|
#define CMD_SET_EP_STAT(x) (0x00400500 | ((x) << 16))
|
||||||
|
#define CMD_CLR_BUF 0x00F20500
|
||||||
|
#define CMD_VALID_BUF 0x00FA0500
|
||||||
|
|
||||||
|
/* Device Address Register Definitions */
|
||||||
|
#define DEV_ADDR_MASK 0x7F
|
||||||
|
#define DEV_EN 0x80
|
||||||
|
|
||||||
|
/* Device Configure Register Definitions */
|
||||||
|
#define CONF_DVICE 0x01
|
||||||
|
|
||||||
|
/* Device Mode Register Definitions */
|
||||||
|
#define AP_CLK 0x01
|
||||||
|
#define INAK_CI 0x02
|
||||||
|
#define INAK_CO 0x04
|
||||||
|
#define INAK_AI 0x08
|
||||||
|
#define INAK_AO 0x10
|
||||||
|
|
||||||
|
/* Device Status Register Definitions */
|
||||||
|
#define DEV_CON 0x01
|
||||||
|
#define DEV_CON_CH 0x02
|
||||||
|
#define DEV_SUS 0x04
|
||||||
|
#define DEV_SUS_CH 0x08
|
||||||
|
#define DEV_RST 0x10
|
||||||
|
|
||||||
|
/* Error Code Register Definitions */
|
||||||
|
#define ERR_EC_MASK 0x0F
|
||||||
|
#define ERR_EA 0x10
|
||||||
|
|
||||||
|
/* Error Status Register Definitions */
|
||||||
|
#define ERR_NOERROR 0x00
|
||||||
|
#define ERR_PID_ENCODE 0x01
|
||||||
|
#define ERR_UNKNOWN_PID 0x02
|
||||||
|
#define ERR_UNEXPECT_PKT 0x03
|
||||||
|
#define ERR_TCRC 0x04
|
||||||
|
#define ERR_DCRC 0x05
|
||||||
|
#define ERR_TIMEOUT 0x06
|
||||||
|
#define ERR_BABBIE 0x07
|
||||||
|
#define ERR_EOF_PKT 0x08
|
||||||
|
#define ERR_TX_RX_NAK 0x09
|
||||||
|
#define ERR_SENT_STALL 0x0A
|
||||||
|
#define ERR_BUF_OVERRUN 0x0B
|
||||||
|
#define ERR_SENT_EPT_PKT 0x0C
|
||||||
|
#define ERR_BIT_STUFF 0x0D
|
||||||
|
#define ERR_SYNC 0x0E
|
||||||
|
#define ERR_TOGGLE_BIT 0x0F
|
||||||
|
|
||||||
|
/* Endpoint Select Register Definitions */
|
||||||
|
#define EP_SEL_F 0x01
|
||||||
|
#define EP_SEL_ST 0x02
|
||||||
|
#define EP_SEL_STP 0x04
|
||||||
|
#define EP_SEL_PO 0x08
|
||||||
|
#define EP_SEL_EPN 0x10
|
||||||
|
#define EP_SEL_B_1_FULL 0x20
|
||||||
|
#define EP_SEL_B_2_FULL 0x40
|
||||||
|
|
||||||
|
/* Endpoint Status Register Definitions */
|
||||||
|
#define EP_STAT_ST 0x01
|
||||||
|
#define EP_STAT_DA 0x20
|
||||||
|
#define EP_STAT_RF_MO 0x40
|
||||||
|
#define EP_STAT_CND_ST 0x80
|
||||||
|
|
||||||
|
/* Clear Buffer Register Definitions */
|
||||||
|
#define CLR_BUF_PO 0x01
|
||||||
|
|
||||||
|
#endif /* __USBREG_H */
|
|
@ -0,0 +1,208 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: usbuser.c
|
||||||
|
* Purpose: USB Custom User Module
|
||||||
|
* Version: V1.20
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
#include "usb.h"
|
||||||
|
#include "usbcfg.h"
|
||||||
|
#include "usbhw.h"
|
||||||
|
#include "usbcore.h"
|
||||||
|
#include "usbuser.h"
|
||||||
|
#include "cdcuser.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Power Event Callback
|
||||||
|
* Called automatically on USB Power Event
|
||||||
|
* Parameter: power: On(TRUE)/Off(FALSE)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if USB_POWER_EVENT
|
||||||
|
void USB_Power_Event (uint32_t power) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Reset Event Callback
|
||||||
|
* Called automatically on USB Reset Event
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if USB_RESET_EVENT
|
||||||
|
void USB_Reset_Event (void) {
|
||||||
|
USB_ResetCore();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Suspend Event Callback
|
||||||
|
* Called automatically on USB Suspend Event
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if USB_SUSPEND_EVENT
|
||||||
|
void USB_Suspend_Event (void) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Resume Event Callback
|
||||||
|
* Called automatically on USB Resume Event
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if USB_RESUME_EVENT
|
||||||
|
void USB_Resume_Event (void) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Remote Wakeup Event Callback
|
||||||
|
* Called automatically on USB Remote Wakeup Event
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if USB_WAKEUP_EVENT
|
||||||
|
void USB_WakeUp_Event (void) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Start of Frame Event Callback
|
||||||
|
* Called automatically on USB Start of Frame Event
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if USB_SOF_EVENT
|
||||||
|
void USB_SOF_Event (void) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Error Event Callback
|
||||||
|
* Called automatically on USB Error Event
|
||||||
|
* Parameter: error: Error Code
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if USB_ERROR_EVENT
|
||||||
|
void USB_Error_Event (uint32_t error) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Set Configuration Event Callback
|
||||||
|
* Called automatically on USB Set Configuration Request
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if USB_CONFIGURE_EVENT
|
||||||
|
void USB_Configure_Event (void) {
|
||||||
|
|
||||||
|
if (USB_Configuration) { /* Check if USB is configured */
|
||||||
|
/* add your code here */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Set Interface Event Callback
|
||||||
|
* Called automatically on USB Set Interface Request
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if USB_INTERFACE_EVENT
|
||||||
|
void USB_Interface_Event (void) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Set/Clear Feature Event Callback
|
||||||
|
* Called automatically on USB Set/Clear Feature Request
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if USB_FEATURE_EVENT
|
||||||
|
void USB_Feature_Event (void) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define P_EP(n) ((USB_EP_EVENT & (1 << (n))) ? USB_EndPoint##n : NULL)
|
||||||
|
|
||||||
|
/* USB Endpoint Events Callback Pointers */
|
||||||
|
void (* const USB_P_EP[USB_LOGIC_EP_NUM]) (uint32_t event) = {
|
||||||
|
P_EP(0),
|
||||||
|
P_EP(1),
|
||||||
|
P_EP(2),
|
||||||
|
P_EP(3),
|
||||||
|
P_EP(4),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Endpoint 1 Event Callback
|
||||||
|
* Called automatically on USB Endpoint 1 Event
|
||||||
|
* Parameter: event
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_EndPoint1 (uint32_t event) {
|
||||||
|
uint16_t temp;
|
||||||
|
static uint16_t serialState;
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case USB_EVT_IN:
|
||||||
|
temp = CDC_GetSerialState();
|
||||||
|
if (serialState != temp) {
|
||||||
|
serialState = temp;
|
||||||
|
CDC_NotificationIn(); /* send SERIAL_STATE notification */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Endpoint 2 Event Callback
|
||||||
|
* Called automatically on USB Endpoint 2 Event
|
||||||
|
* Parameter: event
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_EndPoint2 (uint32_t event)
|
||||||
|
{
|
||||||
|
event = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB Endpoint 3 Event Callback
|
||||||
|
* Called automatically on USB Endpoint 3 Event
|
||||||
|
* Parameter: event
|
||||||
|
*/
|
||||||
|
|
||||||
|
void USB_EndPoint3 (uint32_t event) {
|
||||||
|
switch (event) {
|
||||||
|
case USB_EVT_OUT:
|
||||||
|
CDC_BulkOut (); /* data received from Host */
|
||||||
|
break;
|
||||||
|
case USB_EVT_IN:
|
||||||
|
CDC_BulkIn (); /* data expected from Host */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: USBUSER.H
|
||||||
|
* Purpose: USB Custom User Definitions
|
||||||
|
* Version: V1.10
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005-2009 Keil Software.
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef __USBUSER_H__
|
||||||
|
#define __USBUSER_H__
|
||||||
|
|
||||||
|
|
||||||
|
/* USB Device Events Callback Functions */
|
||||||
|
extern void USB_Power_Event (uint32_t power);
|
||||||
|
extern void USB_Reset_Event (void);
|
||||||
|
extern void USB_Suspend_Event (void);
|
||||||
|
extern void USB_Resume_Event (void);
|
||||||
|
extern void USB_WakeUp_Event (void);
|
||||||
|
extern void USB_SOF_Event (void);
|
||||||
|
extern void USB_Error_Event (uint32_t error);
|
||||||
|
|
||||||
|
/* USB Endpoint Callback Events */
|
||||||
|
#define USB_EVT_SETUP 1 /* Setup Packet */
|
||||||
|
#define USB_EVT_OUT 2 /* OUT Packet */
|
||||||
|
#define USB_EVT_IN 3 /* IN Packet */
|
||||||
|
#define USB_EVT_OUT_NAK 4 /* OUT Packet - Not Acknowledged */
|
||||||
|
#define USB_EVT_IN_NAK 5 /* IN Packet - Not Acknowledged */
|
||||||
|
#define USB_EVT_OUT_STALL 6 /* OUT Packet - Stalled */
|
||||||
|
#define USB_EVT_IN_STALL 7 /* IN Packet - Stalled */
|
||||||
|
|
||||||
|
/* USB Endpoint Events Callback Pointers */
|
||||||
|
extern void (* const USB_P_EP[USB_LOGIC_EP_NUM])(uint32_t event);
|
||||||
|
|
||||||
|
/* USB Endpoint Events Callback Functions */
|
||||||
|
extern void USB_EndPoint0 (uint32_t event);
|
||||||
|
extern void USB_EndPoint1 (uint32_t event);
|
||||||
|
extern void USB_EndPoint2 (uint32_t event);
|
||||||
|
extern void USB_EndPoint3 (uint32_t event);
|
||||||
|
extern void USB_EndPoint4 (uint32_t event);
|
||||||
|
|
||||||
|
/* USB Core Events Callback Functions */
|
||||||
|
extern void USB_Configure_Event (void);
|
||||||
|
extern void USB_Interface_Event (void);
|
||||||
|
extern void USB_Feature_Event (void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __USBUSER_H__ */
|
|
@ -0,0 +1,240 @@
|
||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
* U S B - K e r n e l
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* Name: usb.h
|
||||||
|
* Purpose: USB Definitions
|
||||||
|
* Version: V1.20
|
||||||
|
*----------------------------------------------------------------------------
|
||||||
|
* This software is supplied "AS IS" without any warranties, express,
|
||||||
|
* implied or statutory, including but not limited to the implied
|
||||||
|
* warranties of fitness for purpose, satisfactory quality and
|
||||||
|
* noninfringement. Keil extends you a royalty-free right to reproduce
|
||||||
|
* and distribute executable files created using this software for use
|
||||||
|
* on NXP Semiconductors LPC microcontroller devices only. Nothing else
|
||||||
|
* gives you the right to use this software.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Keil - An ARM Company. All rights reserved.
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef __USB_H__
|
||||||
|
#define __USB_H__
|
||||||
|
|
||||||
|
#include "sysdefs.h"
|
||||||
|
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
uint16_t W;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t L;
|
||||||
|
uint8_t H;
|
||||||
|
} __attribute__ ((packed)) WB;
|
||||||
|
} __attribute__ ((packed)) WORD_BYTE;
|
||||||
|
|
||||||
|
|
||||||
|
/* bmRequestType.Dir */
|
||||||
|
#define REQUEST_HOST_TO_DEVICE 0
|
||||||
|
#define REQUEST_DEVICE_TO_HOST 1
|
||||||
|
|
||||||
|
/* bmRequestType.Type */
|
||||||
|
#define REQUEST_STANDARD 0
|
||||||
|
#define REQUEST_CLASS 1
|
||||||
|
#define REQUEST_VENDOR 2
|
||||||
|
#define REQUEST_RESERVED 3
|
||||||
|
|
||||||
|
/* bmRequestType.Recipient */
|
||||||
|
#define REQUEST_TO_DEVICE 0
|
||||||
|
#define REQUEST_TO_INTERFACE 1
|
||||||
|
#define REQUEST_TO_ENDPOINT 2
|
||||||
|
#define REQUEST_TO_OTHER 3
|
||||||
|
|
||||||
|
/* bmRequestType Definition */
|
||||||
|
typedef union _REQUEST_TYPE
|
||||||
|
{
|
||||||
|
struct _BM
|
||||||
|
{
|
||||||
|
uint8_t Recipient : 5;
|
||||||
|
uint8_t Type : 2;
|
||||||
|
uint8_t Dir : 1;
|
||||||
|
} __attribute__ ((packed)) BM;
|
||||||
|
uint8_t B;
|
||||||
|
} __attribute__ ((packed)) REQUEST_TYPE;
|
||||||
|
|
||||||
|
/* USB Standard Request Codes */
|
||||||
|
#define USB_REQUEST_GET_STATUS 0
|
||||||
|
#define USB_REQUEST_CLEAR_FEATURE 1
|
||||||
|
#define USB_REQUEST_SET_FEATURE 3
|
||||||
|
#define USB_REQUEST_SET_ADDRESS 5
|
||||||
|
#define USB_REQUEST_GET_DESCRIPTOR 6
|
||||||
|
#define USB_REQUEST_SET_DESCRIPTOR 7
|
||||||
|
#define USB_REQUEST_GET_CONFIGURATION 8
|
||||||
|
#define USB_REQUEST_SET_CONFIGURATION 9
|
||||||
|
#define USB_REQUEST_GET_INTERFACE 10
|
||||||
|
#define USB_REQUEST_SET_INTERFACE 11
|
||||||
|
#define USB_REQUEST_SYNC_FRAME 12
|
||||||
|
|
||||||
|
/* USB GET_STATUS Bit Values */
|
||||||
|
#define USB_GETSTATUS_SELF_POWERED 0x01
|
||||||
|
#define USB_GETSTATUS_REMOTE_WAKEUP 0x02
|
||||||
|
#define USB_GETSTATUS_ENDPOINT_STALL 0x01
|
||||||
|
|
||||||
|
/* USB Standard Feature selectors */
|
||||||
|
#define USB_FEATURE_ENDPOINT_STALL 0
|
||||||
|
#define USB_FEATURE_REMOTE_WAKEUP 1
|
||||||
|
|
||||||
|
/* USB Default Control Pipe Setup Packet */
|
||||||
|
typedef struct _USB_SETUP_PACKET
|
||||||
|
{
|
||||||
|
REQUEST_TYPE bmRequestType;
|
||||||
|
uint8_t bRequest;
|
||||||
|
WORD_BYTE wValue;
|
||||||
|
WORD_BYTE wIndex;
|
||||||
|
uint16_t wLength;
|
||||||
|
} __attribute__ ((packed)) USB_SETUP_PACKET;
|
||||||
|
|
||||||
|
|
||||||
|
/* USB Descriptor Types */
|
||||||
|
#define USB_DEVICE_DESCRIPTOR_TYPE 1
|
||||||
|
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
|
||||||
|
#define USB_STRING_DESCRIPTOR_TYPE 3
|
||||||
|
#define USB_INTERFACE_DESCRIPTOR_TYPE 4
|
||||||
|
#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
|
||||||
|
#define USB_DEVICE_QUALIFIER_DESCRIPTOR_TYPE 6
|
||||||
|
#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR_TYPE 7
|
||||||
|
#define USB_INTERFACE_POWER_DESCRIPTOR_TYPE 8
|
||||||
|
#define USB_OTG_DESCRIPTOR_TYPE 9
|
||||||
|
#define USB_DEBUG_DESCRIPTOR_TYPE 10
|
||||||
|
#define USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE 11
|
||||||
|
|
||||||
|
/* USB Device Classes */
|
||||||
|
#define USB_DEVICE_CLASS_RESERVED 0x00
|
||||||
|
#define USB_DEVICE_CLASS_AUDIO 0x01
|
||||||
|
#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02
|
||||||
|
#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03
|
||||||
|
#define USB_DEVICE_CLASS_MONITOR 0x04
|
||||||
|
#define USB_DEVICE_CLASS_PHYSICAL_INTERFACE 0x05
|
||||||
|
#define USB_DEVICE_CLASS_POWER 0x06
|
||||||
|
#define USB_DEVICE_CLASS_PRINTER 0x07
|
||||||
|
#define USB_DEVICE_CLASS_STORAGE 0x08
|
||||||
|
#define USB_DEVICE_CLASS_HUB 0x09
|
||||||
|
#define USB_DEVICE_CLASS_MISCELLANEOUS 0xEF
|
||||||
|
#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF
|
||||||
|
|
||||||
|
/* bmAttributes in Configuration Descriptor */
|
||||||
|
#define USB_CONFIG_POWERED_MASK 0x40
|
||||||
|
#define USB_CONFIG_BUS_POWERED 0x80
|
||||||
|
#define USB_CONFIG_SELF_POWERED 0xC0
|
||||||
|
#define USB_CONFIG_REMOTE_WAKEUP 0x20
|
||||||
|
|
||||||
|
/* bMaxPower in Configuration Descriptor */
|
||||||
|
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
|
||||||
|
|
||||||
|
/* bEndpointAddress in Endpoint Descriptor */
|
||||||
|
#define USB_ENDPOINT_DIRECTION_MASK 0x80
|
||||||
|
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
|
||||||
|
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
|
||||||
|
|
||||||
|
/* bmAttributes in Endpoint Descriptor */
|
||||||
|
#define USB_ENDPOINT_TYPE_MASK 0x03
|
||||||
|
#define USB_ENDPOINT_TYPE_CONTROL 0x00
|
||||||
|
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
|
||||||
|
#define USB_ENDPOINT_TYPE_BULK 0x02
|
||||||
|
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
|
||||||
|
#define USB_ENDPOINT_SYNC_MASK 0x0C
|
||||||
|
#define USB_ENDPOINT_SYNC_NO_SYNCHRONIZATION 0x00
|
||||||
|
#define USB_ENDPOINT_SYNC_ASYNCHRONOUS 0x04
|
||||||
|
#define USB_ENDPOINT_SYNC_ADAPTIVE 0x08
|
||||||
|
#define USB_ENDPOINT_SYNC_SYNCHRONOUS 0x0C
|
||||||
|
#define USB_ENDPOINT_USAGE_MASK 0x30
|
||||||
|
#define USB_ENDPOINT_USAGE_DATA 0x00
|
||||||
|
#define USB_ENDPOINT_USAGE_FEEDBACK 0x10
|
||||||
|
#define USB_ENDPOINT_USAGE_IMPLICIT_FEEDBACK 0x20
|
||||||
|
#define USB_ENDPOINT_USAGE_RESERVED 0x30
|
||||||
|
|
||||||
|
/* USB Standard Device Descriptor */
|
||||||
|
typedef struct _USB_DEVICE_DESCRIPTOR
|
||||||
|
{
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint16_t bcdUSB;
|
||||||
|
uint8_t bDeviceClass;
|
||||||
|
uint8_t bDeviceSubClass;
|
||||||
|
uint8_t bDeviceProtocol;
|
||||||
|
uint8_t bMaxPacketSize0;
|
||||||
|
uint16_t idVendor;
|
||||||
|
uint16_t idProduct;
|
||||||
|
uint16_t bcdDevice;
|
||||||
|
uint8_t iManufacturer;
|
||||||
|
uint8_t iProduct;
|
||||||
|
uint8_t iSerialNumber;
|
||||||
|
uint8_t bNumConfigurations;
|
||||||
|
} __attribute__ ((packed)) USB_DEVICE_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* USB 2.0 Device Qualifier Descriptor */
|
||||||
|
typedef struct _USB_DEVICE_QUALIFIER_DESCRIPTOR
|
||||||
|
{
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint16_t bcdUSB;
|
||||||
|
uint8_t bDeviceClass;
|
||||||
|
uint8_t bDeviceSubClass;
|
||||||
|
uint8_t bDeviceProtocol;
|
||||||
|
uint8_t bMaxPacketSize0;
|
||||||
|
uint8_t bNumConfigurations;
|
||||||
|
uint8_t bReserved;
|
||||||
|
} __attribute__ ((packed)) USB_DEVICE_QUALIFIER_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* USB Standard Configuration Descriptor */
|
||||||
|
typedef struct _USB_CONFIGURATION_DESCRIPTOR
|
||||||
|
{
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint16_t wTotalLength;
|
||||||
|
uint8_t bNumInterfaces;
|
||||||
|
uint8_t bConfigurationValue;
|
||||||
|
uint8_t iConfiguration;
|
||||||
|
uint8_t bmAttributes;
|
||||||
|
uint8_t bMaxPower;
|
||||||
|
} __attribute__ ((packed)) USB_CONFIGURATION_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* USB Standard Interface Descriptor */
|
||||||
|
typedef struct _USB_INTERFACE_DESCRIPTOR
|
||||||
|
{
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint8_t bInterfaceNumber;
|
||||||
|
uint8_t bAlternateSetting;
|
||||||
|
uint8_t bNumEndpoints;
|
||||||
|
uint8_t bInterfaceClass;
|
||||||
|
uint8_t bInterfaceSubClass;
|
||||||
|
uint8_t bInterfaceProtocol;
|
||||||
|
uint8_t iInterface;
|
||||||
|
} __attribute__ ((packed)) USB_INTERFACE_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* USB Standard Endpoint Descriptor */
|
||||||
|
typedef struct _USB_ENDPOINT_DESCRIPTOR
|
||||||
|
{
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint8_t bEndpointAddress;
|
||||||
|
uint8_t bmAttributes;
|
||||||
|
uint16_t wMaxPacketSize;
|
||||||
|
uint8_t bInterval;
|
||||||
|
} __attribute__ ((packed)) USB_ENDPOINT_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* USB String Descriptor */
|
||||||
|
typedef struct _USB_STRING_DESCRIPTOR
|
||||||
|
{
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint16_t bString/*[]*/;
|
||||||
|
} __attribute__ ((packed)) USB_STRING_DESCRIPTOR;
|
||||||
|
|
||||||
|
/* USB Common Descriptor */
|
||||||
|
typedef struct _USB_COMMON_DESCRIPTOR
|
||||||
|
{
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
} __attribute__ ((packed)) USB_COMMON_DESCRIPTOR;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,115 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file usbconfig.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "usb.h"
|
||||||
|
#include "usbconfig.h"
|
||||||
|
|
||||||
|
#ifndef WBVAL
|
||||||
|
#define WBVAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* USB String Descriptor (optional) */
|
||||||
|
const uint8_t USB_HIDStringDescriptor[] =
|
||||||
|
{
|
||||||
|
/* Index 0x00: LANGID Codes */
|
||||||
|
0x04, /* bLength */
|
||||||
|
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
WBVAL(0x0409), /* US English */ /* wLANGID */
|
||||||
|
/* Index 0x04: Manufacturer */
|
||||||
|
0x1C, /* bLength */
|
||||||
|
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
'm',0,
|
||||||
|
'i',0,
|
||||||
|
'c',0,
|
||||||
|
'r',0,
|
||||||
|
'o',0,
|
||||||
|
'B',0,
|
||||||
|
'u',0,
|
||||||
|
'i',0,
|
||||||
|
'l',0,
|
||||||
|
'd',0,
|
||||||
|
'e',0,
|
||||||
|
'r',0,
|
||||||
|
' ',0,
|
||||||
|
/* Index 0x20: Product */
|
||||||
|
0x28, /* bLength */
|
||||||
|
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
'L',0,
|
||||||
|
'P',0,
|
||||||
|
'C',0,
|
||||||
|
'1',0,
|
||||||
|
'3',0,
|
||||||
|
'4',0,
|
||||||
|
'3',0,
|
||||||
|
' ',0,
|
||||||
|
'R',0,
|
||||||
|
'e',0,
|
||||||
|
'f',0,
|
||||||
|
'.',0,
|
||||||
|
' ',0,
|
||||||
|
'B',0,
|
||||||
|
'o',0,
|
||||||
|
'a',0,
|
||||||
|
'r',0,
|
||||||
|
'd',0,
|
||||||
|
' ',0,
|
||||||
|
/* Index 0x48: Serial Number */
|
||||||
|
0x1A, /* bLength */
|
||||||
|
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
'0',0,
|
||||||
|
/* Index 0x62: Interface 0, Alternate Setting 0 */
|
||||||
|
0x0E, /* bLength */
|
||||||
|
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
|
||||||
|
'H',0,
|
||||||
|
'I',0,
|
||||||
|
'D',0,
|
||||||
|
' ',0,
|
||||||
|
' ',0,
|
||||||
|
' ',0,
|
||||||
|
};
|
|
@ -0,0 +1,66 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file usbconfig.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _USBCONFIG_H_
|
||||||
|
#define _USBCONFIG_H_
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
#define USB_VENDOR_ID CFG_USB_VID // Vendor ID
|
||||||
|
#define USB_PROD_ID CFG_USB_PID // Product ID
|
||||||
|
#define USB_DEVICE 0x0100 // Device ID
|
||||||
|
|
||||||
|
#define WBVAL(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
|
||||||
|
|
||||||
|
#define USB_DEVICE_DESC_SIZE (sizeof(USB_DEVICE_DESCRIPTOR))
|
||||||
|
#define USB_CONFIGUARTION_DESC_SIZE (sizeof(USB_CONFIGURATION_DESCRIPTOR))
|
||||||
|
#define USB_INTERFACE_DESC_SIZE (sizeof(USB_INTERFACE_DESCRIPTOR))
|
||||||
|
#define USB_ENDPOINT_DESC_SIZE (sizeof(USB_ENDPOINT_DESCRIPTOR))
|
||||||
|
|
||||||
|
#define HID_DESC_OFFSET 0x0012
|
||||||
|
#define HID_DESC_SIZE (sizeof(HID_DESCRIPTOR))
|
||||||
|
#define HID_REPORT_DESC_SIZE (sizeof(HID_ReportDescriptor))
|
||||||
|
|
||||||
|
extern const uint8_t USB_DeviceDescriptor[];
|
||||||
|
extern const uint8_t USB_ConfigDescriptor[];
|
||||||
|
extern const uint8_t USB_HIDStringDescriptor[];
|
||||||
|
|
||||||
|
extern const uint8_t HID_ReportDescriptor[];
|
||||||
|
extern const uint16_t HID_ReportDescSize;
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,222 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file usbhid.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <string.h>
|
||||||
|
|
||||||
|
#include "core/usbhid-rom/usb.h"
|
||||||
|
#include "core/usbhid-rom/usbconfig.h"
|
||||||
|
#include "core/rom_drivers.h"
|
||||||
|
#include "core/gpio/gpio.h"
|
||||||
|
#include "core/adc/adc.h"
|
||||||
|
#include "core/systick/systick.h"
|
||||||
|
|
||||||
|
#include "usbhid.h"
|
||||||
|
|
||||||
|
USB_DEV_INFO DeviceInfo;
|
||||||
|
HID_DEVICE_INFO HidDevInfo;
|
||||||
|
ROM ** rom = (ROM **)0x1fff1ff8;
|
||||||
|
|
||||||
|
typedef struct usbhid_out_s
|
||||||
|
{
|
||||||
|
uint16_t gpio1Dir;
|
||||||
|
uint16_t gpio1Data;
|
||||||
|
uint16_t gpio2Dir;
|
||||||
|
uint16_t gpio2Data;
|
||||||
|
uint16_t gpio3Dir;
|
||||||
|
uint16_t gpio3Data;
|
||||||
|
uint16_t adc0;
|
||||||
|
uint16_t adc1;
|
||||||
|
uint16_t adc2;
|
||||||
|
uint16_t adc3;
|
||||||
|
uint32_t systicks;
|
||||||
|
uint32_t rollovers;
|
||||||
|
} usbhid_out_t;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Gets the HID In Report (the report going from the LPC1343 to
|
||||||
|
the USB host)
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void usbHIDGetInReport (uint8_t src[], uint32_t length)
|
||||||
|
{
|
||||||
|
usbhid_out_t out;
|
||||||
|
|
||||||
|
out.gpio1Dir = GPIO_GPIO1DIR;
|
||||||
|
out.gpio1Data = GPIO_GPIO1DATA;
|
||||||
|
out.gpio2Dir = GPIO_GPIO2DIR;
|
||||||
|
out.gpio2Data = GPIO_GPIO2DATA;
|
||||||
|
out.gpio3Dir = GPIO_GPIO3DIR;
|
||||||
|
out.gpio3Data = GPIO_GPIO3DATA;
|
||||||
|
out.adc0 = adcRead(0);
|
||||||
|
out.adc1 = adcRead(1);
|
||||||
|
out.adc2 = adcRead(2);
|
||||||
|
out.adc3 = adcRead(3);
|
||||||
|
out.systicks = systickGetTicks();
|
||||||
|
out.rollovers = systickGetRollovers();
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
memcpy(&src[i], &out.gpio1Dir, sizeof out.gpio1Dir);
|
||||||
|
i += sizeof out.gpio1Dir;
|
||||||
|
memcpy(&src[i], &out.gpio1Data, sizeof out.gpio1Data);
|
||||||
|
i += sizeof out.gpio1Data;
|
||||||
|
memcpy(&src[i], &out.gpio2Dir, sizeof out.gpio2Dir);
|
||||||
|
i += sizeof out.gpio2Dir;
|
||||||
|
memcpy(&src[i], &out.gpio2Data, sizeof out.gpio2Data);
|
||||||
|
i += sizeof out.gpio2Data;
|
||||||
|
memcpy(&src[i], &out.gpio3Dir, sizeof out.gpio3Dir);
|
||||||
|
i += sizeof out.gpio3Dir;
|
||||||
|
memcpy(&src[i], &out.gpio3Data, sizeof out.gpio3Data);
|
||||||
|
i += sizeof out.gpio3Data;
|
||||||
|
memcpy(&src[i], &out.adc0, sizeof out.adc0);
|
||||||
|
i += sizeof out.adc0;
|
||||||
|
memcpy(&src[i], &out.adc1, sizeof out.adc1);
|
||||||
|
i += sizeof out.adc1;
|
||||||
|
memcpy(&src[i], &out.adc2, sizeof out.adc2);
|
||||||
|
i += sizeof out.adc2;
|
||||||
|
memcpy(&src[i], &out.adc3, sizeof out.adc3);
|
||||||
|
i += sizeof out.adc3;
|
||||||
|
memcpy(&src[i], &out.systicks, sizeof out.systicks);
|
||||||
|
i += sizeof out.systicks;
|
||||||
|
memcpy(&src[i], &out.rollovers, sizeof out.rollovers);
|
||||||
|
i += sizeof out.rollovers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Sets the HID Out Report (the report coming in from the USB
|
||||||
|
host to the LPC1343).
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void usbHIDSetOutReport (uint8_t dst[], uint32_t length)
|
||||||
|
{
|
||||||
|
uint8_t PCOutReportData = dst[0];
|
||||||
|
// Check bit 0 in the incoming report to determine is LED should
|
||||||
|
// be enabled or disabled (1 = enabled, 0 = disabled)
|
||||||
|
if (PCOutReportData & (1<<0))
|
||||||
|
{
|
||||||
|
// Enable LED (set low)
|
||||||
|
gpioSetValue (CFG_LED_PORT, CFG_LED_PIN, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Disable LED (set high)
|
||||||
|
gpioSetValue (CFG_LED_PORT, CFG_LED_PIN, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Initialises the USB port
|
||||||
|
|
||||||
|
The ROM-based USB HID code is capable of configuring the PLL and pins
|
||||||
|
for USB, but there seems to be a bug in the code that sets the system
|
||||||
|
clock to 48MHz (normally the USB and System clocks can be configured
|
||||||
|
seperately). As such, this code does not use the "init_clk_pins()"
|
||||||
|
function in the rom, and the USB clock and pins are manually
|
||||||
|
configured.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void usbHIDInit (void)
|
||||||
|
{
|
||||||
|
// Setup USB clock
|
||||||
|
SCB_PDRUNCFG &= ~(SCB_PDSLEEPCFG_USBPAD_PD); // Power-up USB PHY
|
||||||
|
SCB_PDRUNCFG &= ~(SCB_PDSLEEPCFG_USBPLL_PD); // Power-up USB PLL
|
||||||
|
|
||||||
|
SCB_USBPLLCLKSEL = SCB_USBPLLCLKSEL_SOURCE_MAINOSC; // Select PLL Input
|
||||||
|
SCB_USBPLLCLKUEN = SCB_USBPLLCLKUEN_UPDATE; // Update Clock Source
|
||||||
|
SCB_USBPLLCLKUEN = SCB_USBPLLCLKUEN_DISABLE; // Toggle Update Register
|
||||||
|
SCB_USBPLLCLKUEN = SCB_USBPLLCLKUEN_UPDATE;
|
||||||
|
|
||||||
|
// Wait until the USB clock is updated
|
||||||
|
while (!(SCB_USBPLLCLKUEN & SCB_USBPLLCLKUEN_UPDATE));
|
||||||
|
|
||||||
|
// Set USB clock to 48MHz (12MHz x 4)
|
||||||
|
SCB_USBPLLCTRL = (SCB_USBPLLCTRL_MULT_4);
|
||||||
|
while (!(SCB_USBPLLSTAT & SCB_USBPLLSTAT_LOCK)); // Wait Until PLL Locked
|
||||||
|
SCB_USBCLKSEL = SCB_USBCLKSEL_SOURCE_USBPLLOUT;
|
||||||
|
|
||||||
|
// Set USB pin functions
|
||||||
|
IOCON_PIO0_1 &= ~IOCON_PIO0_1_FUNC_MASK;
|
||||||
|
IOCON_PIO0_1 |= IOCON_PIO0_1_FUNC_CLKOUT; // CLK OUT
|
||||||
|
IOCON_PIO0_3 &= ~IOCON_PIO0_3_FUNC_MASK;
|
||||||
|
IOCON_PIO0_3 |= IOCON_PIO0_3_FUNC_USB_VBUS; // VBus
|
||||||
|
IOCON_PIO0_6 &= ~IOCON_PIO0_6_FUNC_MASK;
|
||||||
|
IOCON_PIO0_6 |= IOCON_PIO0_6_FUNC_USB_CONNECT; // Soft Connect
|
||||||
|
|
||||||
|
// Disable internal resistor on VBUS (0.3)
|
||||||
|
gpioSetPullup(&IOCON_PIO0_3, gpioPullupMode_Inactive);
|
||||||
|
|
||||||
|
// HID Device Info
|
||||||
|
volatile int n;
|
||||||
|
HidDevInfo.idVendor = USB_VENDOR_ID;
|
||||||
|
HidDevInfo.idProduct = USB_PROD_ID;
|
||||||
|
HidDevInfo.bcdDevice = USB_DEVICE;
|
||||||
|
HidDevInfo.StrDescPtr = (uint32_t)&USB_HIDStringDescriptor[0];
|
||||||
|
HidDevInfo.InReportCount = sizeof(usbhid_out_t);
|
||||||
|
HidDevInfo.OutReportCount = 1;
|
||||||
|
HidDevInfo.SampleInterval = 0x20;
|
||||||
|
HidDevInfo.InReport = usbHIDGetInReport;
|
||||||
|
HidDevInfo.OutReport = usbHIDSetOutReport;
|
||||||
|
|
||||||
|
DeviceInfo.DevType = USB_DEVICE_CLASS_HUMAN_INTERFACE;
|
||||||
|
DeviceInfo.DevDetailPtr = (uint32_t)&HidDevInfo;
|
||||||
|
|
||||||
|
/* Enable Timer32_1, IOCON, and USB blocks (for USB ROM driver) */
|
||||||
|
SCB_SYSAHBCLKCTRL |= (SCB_SYSAHBCLKCTRL_CT32B1 | SCB_SYSAHBCLKCTRL_IOCON | SCB_SYSAHBCLKCTRL_USB_REG);
|
||||||
|
|
||||||
|
/* Use pll and pin init function in rom */
|
||||||
|
/* Warning: This will also set the system clock to 48MHz! */
|
||||||
|
// (*rom)->pUSBD->init_clk_pins();
|
||||||
|
|
||||||
|
/* insert a delay between clk init and usb init */
|
||||||
|
for (n = 0; n < 75; n++) {__asm("nop");}
|
||||||
|
|
||||||
|
(*rom)->pUSBD->init(&DeviceInfo); /* USB Initialization */
|
||||||
|
(*rom)->pUSBD->connect(true); /* USB Connect */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Passes the USB interrupt to the internal ROM-based handler
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
#ifdef CFG_USBHID
|
||||||
|
void USB_IRQHandler()
|
||||||
|
{
|
||||||
|
(*rom)->pUSBD->isr();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file usbhid.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _USBCONFIG_H_
|
||||||
|
#define _USBCONFIG_H_
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
void usbHIDGetInReport (uint8_t src[], uint32_t length);
|
||||||
|
void usbHIDSetOutReport (uint8_t dst[], uint32_t length);
|
||||||
|
void usbHIDInit (void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,152 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file wdt.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section DESCRIPTION
|
||||||
|
|
||||||
|
Sets up the watchdog timer (WDT). The WDT allows you to monitor
|
||||||
|
whether the device is still executing properly. If the watchdog
|
||||||
|
isn't 'fed' within a pre-determined delay, it will raise an interrupt
|
||||||
|
allowing you to decide if you want to reset the device, etc.
|
||||||
|
|
||||||
|
@code
|
||||||
|
#include "core/cpu/cpu.h"
|
||||||
|
#include "core/wdt/wdt.h"
|
||||||
|
...
|
||||||
|
cpuInit();
|
||||||
|
|
||||||
|
// Initialise wdt with no reset on timeout
|
||||||
|
wdtInit(false);
|
||||||
|
|
||||||
|
// Pat the watchdog (to start the timer)
|
||||||
|
wdtFeed();
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
// Keep the watchdog happy by regularly feeding it
|
||||||
|
wdtFeed();
|
||||||
|
}
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "wdt.h"
|
||||||
|
|
||||||
|
#define WDT_FEED_VALUE (0x003FFFFF)
|
||||||
|
|
||||||
|
volatile uint32_t wdt_counter;
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
IRQ Handler when the watchdog times out. Any actions that you wish
|
||||||
|
to take when a timeout occurs should be called from here.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void WDT_IRQHandler(void)
|
||||||
|
{
|
||||||
|
/* Clear the time-out interrupt flag */
|
||||||
|
WDT_WDMOD &= ~WDT_WDMOD_WDTOF;
|
||||||
|
wdt_counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Setup the clock for the watchdog timer. The default setting is 250kHz.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
static void wdtClockSetup (void)
|
||||||
|
{
|
||||||
|
/* Watchdog Configuration */
|
||||||
|
/* Freq. = 0.5MHz, div = 2: WDT_OSC = 250kHz */
|
||||||
|
SCB_WDTOSCCTRL = SCB_WDTOSCCTRL_FREQSEL_0_5MHZ |
|
||||||
|
SCB_WDTOSCCTRL_DIVSEL_DIV2;
|
||||||
|
|
||||||
|
/* Set clock source (use WDT oscillator) */
|
||||||
|
SCB_WDTCLKSEL = SCB_WDTCLKSEL_SOURCE_WATCHDOGOSC;
|
||||||
|
SCB_WDTCLKUEN = SCB_WDTCLKUEN_UPDATE;
|
||||||
|
SCB_WDTCLKUEN = SCB_WDTCLKUEN_DISABLE;
|
||||||
|
SCB_WDTCLKUEN = SCB_WDTCLKUEN_UPDATE;
|
||||||
|
|
||||||
|
/* Wait until updated */
|
||||||
|
while (!(SCB_WDTCLKUEN & SCB_WDTCLKUEN_UPDATE));
|
||||||
|
|
||||||
|
/* Set divider */
|
||||||
|
SCB_WDTCLKDIV = SCB_WDTCLKDIV_DIV1;
|
||||||
|
|
||||||
|
/* Enable WDT clock */
|
||||||
|
SCB_PDRUNCFG &= ~(SCB_PDRUNCFG_WDTOSC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Initialises the watchdog timer and sets up the interrupt.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void wdtInit (bool reset)
|
||||||
|
{
|
||||||
|
/* Setup the WDT clock */
|
||||||
|
wdtClockSetup();
|
||||||
|
|
||||||
|
/* Enable AHB clock to the WDT domain. */
|
||||||
|
SCB_SYSAHBCLKCTRL |= SCB_SYSAHBCLKCTRL_WDT;
|
||||||
|
|
||||||
|
wdt_counter = 0;
|
||||||
|
|
||||||
|
/* Enable the WDT interrupt */
|
||||||
|
NVIC_EnableIRQ(WDT_IRQn);
|
||||||
|
|
||||||
|
/* Set timeout value (must be at least 0x000000FF) */
|
||||||
|
WDT_WDTC = WDT_FEED_VALUE;
|
||||||
|
|
||||||
|
/* Enable the watchdog timer (without system reset) */
|
||||||
|
WDT_WDMOD = WDT_WDMOD_WDEN_ENABLED |
|
||||||
|
reset ? WDT_WDMOD_WDRESET_ENABLED : WDT_WDMOD_WDRESET_DISABLED ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
Feeds the watchdog to keep it from timing out. Interrupts will be
|
||||||
|
disabled while feeding the watchdog.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
void wdtFeed (void)
|
||||||
|
{
|
||||||
|
/* Pet the watchdog */
|
||||||
|
__disable_irq();
|
||||||
|
WDT_WDFEED = WDT_WDFEED_FEED1;
|
||||||
|
WDT_WDFEED = WDT_WDFEED_FEED2;
|
||||||
|
__enable_irq();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file wdt.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _WDT_H_
|
||||||
|
#define _WDT_H_
|
||||||
|
|
||||||
|
#include "projectconfig.h"
|
||||||
|
|
||||||
|
void wdtInit (bool reset);
|
||||||
|
void wdtFeed (void);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,170 @@
|
||||||
|
/*
|
||||||
|
* Software License Agreement (BSD License)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Roel Verdult
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The GCC compiler defines the current architecture derived from the -mcpu argument.
|
||||||
|
// When target cpu is the cortex-m0, it automatically defines __ARM_ARCH_6M__
|
||||||
|
#ifndef __ARM_ARCH_6M__
|
||||||
|
#error "The target ARM cpu must be Cortex-M0 compatible (-mcpu=cortex-m0)"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Declare a weak alias macro as described in the GCC manual[1][2]
|
||||||
|
#define WEAK_ALIAS(f) __attribute__ ((weak, alias (#f)));
|
||||||
|
#define SECTION(s) __attribute__ ((section(s)))
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Forward undefined IRQ handlers to an infinite loop function. The Handlers
|
||||||
|
* are weakly aliased which means that (re)definitions will overide these.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
void irq_undefined() {
|
||||||
|
// Do nothing when occured interrupt is not defined, just keep looping
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAN_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void SSP1_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void I2C_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void TIMER16_0_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void TIMER16_1_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void TIMER32_0_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void TIMER32_1_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void SSP0_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void UART_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void USB_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void USB_FIQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void ADC_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void WDT_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void BOD_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void FMC_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void PIOINT3_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void PIOINT2_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void PIOINT1_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void PIOINT0_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void WAKEUP_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Forward undefined fault handlers to an infinite loop function. The Handlers
|
||||||
|
* are weakly aliased which means that (re)definitions will overide these.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void fault_undefined() {
|
||||||
|
// Do nothing when occured interrupt is not defined, just keep looping
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NMI_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void HardFault_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void MemManage_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void BusFault_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void UsageFault_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void SVCall_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void DebugMon_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void PendSV_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void SysTick_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Forward undefined IRQ handlers to an infinite loop function. The Handlers
|
||||||
|
* are weakly aliased which means that (re)definitions will overide these.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
// Prototype the entry values, which are handled by the linker script
|
||||||
|
extern void* stack_entry;
|
||||||
|
extern void boot_entry(void);
|
||||||
|
|
||||||
|
// Defined irq vectors using simple c code following the description in a white
|
||||||
|
// paper from ARM[3] and code example from Simonsson Fun Technologies[4].
|
||||||
|
// These vectors are placed at the memory location defined in the linker script
|
||||||
|
const void *vectors[] SECTION(".irq_vectors") =
|
||||||
|
{
|
||||||
|
// Stack and program reset entry point
|
||||||
|
&stack_entry, // The initial stack pointer
|
||||||
|
boot_entry, // The reset handler
|
||||||
|
|
||||||
|
// Various fault handlers
|
||||||
|
NMI_Handler, // The NMI handler
|
||||||
|
HardFault_Handler, // The hard fault handler
|
||||||
|
MemManage_Handler, // MemManage_Handler
|
||||||
|
BusFault_Handler, // BusFault_Handler
|
||||||
|
UsageFault_Handler, // UsageFault_Handler
|
||||||
|
0, // Reserved
|
||||||
|
0, // Reserved
|
||||||
|
0, // Reserved
|
||||||
|
0, // Reserved
|
||||||
|
SVCall_Handler, // SVCall handler
|
||||||
|
DebugMon_Handler, // DebugMon_Handler
|
||||||
|
0, // Reserved
|
||||||
|
PendSV_Handler, // The PendSV handler
|
||||||
|
SysTick_Handler, // The SysTick handler
|
||||||
|
|
||||||
|
// Wakeup I/O pins handlers
|
||||||
|
WAKEUP_IRQHandler, // PIO0_0 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_1 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_2 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_3 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_4 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_5 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_6 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_7 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_8 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_9 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_10 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_11 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_0 Wakeup
|
||||||
|
|
||||||
|
// Specific peripheral irq handlers
|
||||||
|
CAN_IRQHandler, // CAN
|
||||||
|
SSP1_IRQHandler, // SSP1
|
||||||
|
I2C_IRQHandler, // I2C0
|
||||||
|
TIMER16_0_IRQHandler, // CT16B0 (16-bit Timer 0)
|
||||||
|
TIMER16_1_IRQHandler, // CT16B1 (16-bit Timer 1)
|
||||||
|
TIMER32_0_IRQHandler, // CT32B0 (32-bit Timer 0)
|
||||||
|
TIMER32_1_IRQHandler, // CT32B1 (32-bit Timer 1)
|
||||||
|
SSP0_IRQHandler, // SSP0
|
||||||
|
UART_IRQHandler, // UART0
|
||||||
|
USB_IRQHandler, // USB IRQ
|
||||||
|
USB_FIQHandler, // USB FIQ
|
||||||
|
ADC_IRQHandler, // ADC (A/D Converter)
|
||||||
|
WDT_IRQHandler, // WDT (Watchdog Timer)
|
||||||
|
BOD_IRQHandler, // BOD (Brownout Detect)
|
||||||
|
FMC_IRQHandler, // Flash (IP2111 Flash Memory Controller)
|
||||||
|
PIOINT3_IRQHandler, // PIO INT3
|
||||||
|
PIOINT2_IRQHandler, // PIO INT2
|
||||||
|
PIOINT1_IRQHandler, // PIO INT1
|
||||||
|
PIOINT0_IRQHandler, // PIO INT0
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* References
|
||||||
|
* [1] http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
|
||||||
|
* [2] http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html
|
||||||
|
* [3] http://www.arm.com/files/pdf/Cortex-M3_programming_for_ARM7_developers.pdf
|
||||||
|
* [4] http://fun-tech.se/stm32/OlimexBlinky/mini.php
|
||||||
|
*****************************************************************************/
|
||||||
|
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* Software License Agreement (BSD License)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Roel Verdult
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The GCC compiler defines the current architecture derived from the -mcpu argument.
|
||||||
|
// When target cpu is the cortex-m3, it automatically defines __ARM_ARCH_7M__
|
||||||
|
#ifndef __ARM_ARCH_7M__
|
||||||
|
#error "The target ARM cpu must be Cortex-M3 compatible (-mcpu=cortex-m3)"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Declare a weak alias macro as described in the GCC manual[1][2]
|
||||||
|
#define WEAK_ALIAS(f) __attribute__ ((weak, alias (#f)));
|
||||||
|
#define SECTION(s) __attribute__ ((section(s)))
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Forward undefined IRQ handlers to an infinite loop function. The Handlers
|
||||||
|
* are weakly aliased which means that (re)definitions will overide these.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
void irq_undefined() {
|
||||||
|
// Do nothing when occured interrupt is not defined, just keep looping
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2C_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void TIMER16_0_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void TIMER16_1_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void TIMER32_0_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void TIMER32_1_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void SSP_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void UART_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void USB_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void USB_FIQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void ADC_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void WDT_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void BOD_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void FMC_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void PIOINT3_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void PIOINT2_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void PIOINT1_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void PIOINT0_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
void WAKEUP_IRQHandler(void) WEAK_ALIAS(irq_undefined);
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Forward undefined fault handlers to an infinite loop function. The Handlers
|
||||||
|
* are weakly aliased which means that (re)definitions will overide these.
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void fault_undefined() {
|
||||||
|
// Do nothing when occured interrupt is not defined, just keep looping
|
||||||
|
while(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NMI_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void HardFault_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void MemManage_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void BusFault_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void UsageFault_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void SVCall_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void DebugMon_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void PendSV_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
void SysTick_Handler(void) WEAK_ALIAS(fault_undefined);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* Forward undefined IRQ handlers to an infinite loop function. The Handlers
|
||||||
|
* are weakly aliased which means that (re)definitions will overide these.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
// Prototype the entry values, which are handled by the linker script
|
||||||
|
extern void* stack_entry;
|
||||||
|
extern void boot_entry(void);
|
||||||
|
|
||||||
|
// Defined irq vectors using simple c code following the description in a white
|
||||||
|
// paper from ARM[3] and code example from Simonsson Fun Technologies[4].
|
||||||
|
// These vectors are placed at the memory location defined in the linker script
|
||||||
|
const void *vectors[] SECTION(".irq_vectors") =
|
||||||
|
{
|
||||||
|
// Stack and program reset entry point
|
||||||
|
&stack_entry, // The initial stack pointer
|
||||||
|
boot_entry, // The reset handler
|
||||||
|
|
||||||
|
// Various fault handlers
|
||||||
|
NMI_Handler, // The NMI handler
|
||||||
|
HardFault_Handler, // The hard fault handler
|
||||||
|
MemManage_Handler, // The MPU fault handler
|
||||||
|
BusFault_Handler, // The bus fault handler
|
||||||
|
UsageFault_Handler, // The usage fault handler
|
||||||
|
0, // Reserved
|
||||||
|
0, // Reserved
|
||||||
|
0, // Reserved
|
||||||
|
0, // Reserved
|
||||||
|
SVCall_Handler, // SVCall handler
|
||||||
|
DebugMon_Handler, // Debug monitor handler
|
||||||
|
0, // Reserved
|
||||||
|
PendSV_Handler, // The PendSV handler
|
||||||
|
SysTick_Handler, // The SysTick handler
|
||||||
|
|
||||||
|
// Wakeup I/O pins handlers
|
||||||
|
WAKEUP_IRQHandler, // PIO0_0 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_1 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_2 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_3 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_4 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_5 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_6 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_7 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_8 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_9 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_10 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO0_11 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_0 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_1 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_2 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_3 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_4 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_5 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_6 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_7 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_8 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_9 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_10 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO1_11 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO2_0 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO2_1 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO2_2 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO2_3 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO2_4 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO2_5 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO2_6 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO2_7 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO2_8 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO2_9 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO2_10 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO2_11 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO3_0 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO3_1 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO3_2 Wakeup
|
||||||
|
WAKEUP_IRQHandler, // PIO3_3 Wakeup
|
||||||
|
|
||||||
|
// Specific peripheral irq handlers
|
||||||
|
I2C_IRQHandler, // I2C0
|
||||||
|
TIMER16_0_IRQHandler, // CT16B0 (16-bit Timer 0)
|
||||||
|
TIMER16_1_IRQHandler, // CT16B1 (16-bit Timer 1)
|
||||||
|
TIMER32_0_IRQHandler, // CT32B0 (32-bit Timer 0)
|
||||||
|
TIMER32_1_IRQHandler, // CT32B1 (32-bit Timer 1)
|
||||||
|
SSP_IRQHandler, // SSP0
|
||||||
|
UART_IRQHandler, // UART0
|
||||||
|
USB_IRQHandler, // USB IRQ
|
||||||
|
USB_FIQHandler, // USB FIQ
|
||||||
|
ADC_IRQHandler, // ADC (A/D Converter)
|
||||||
|
WDT_IRQHandler, // WDT (Watchdog Timer)
|
||||||
|
BOD_IRQHandler, // BOD (Brownout Detect)
|
||||||
|
FMC_IRQHandler, // Flash (IP2111 Flash Memory Controller)
|
||||||
|
PIOINT3_IRQHandler, // PIO INT3
|
||||||
|
PIOINT2_IRQHandler, // PIO INT2
|
||||||
|
PIOINT1_IRQHandler, // PIO INT1
|
||||||
|
PIOINT0_IRQHandler, // PIO INT0
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* References
|
||||||
|
* [1] http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
|
||||||
|
* [2] http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html
|
||||||
|
* [3] http://www.arm.com/files/pdf/Cortex-M3_programming_for_ARM7_developers.pdf
|
||||||
|
* [4] http://fun-tech.se/stm32/OlimexBlinky/mini.php
|
||||||
|
*****************************************************************************/
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Software License Agreement (BSD License)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Roel Verdult
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// These are defined and created by the linker, locating them in memory
|
||||||
|
extern unsigned char _etext;
|
||||||
|
extern unsigned char _data;
|
||||||
|
extern unsigned char _edata;
|
||||||
|
extern unsigned char _bss;
|
||||||
|
extern unsigned char _ebss;
|
||||||
|
|
||||||
|
// Prototype the required startup functions
|
||||||
|
extern void main(void);
|
||||||
|
|
||||||
|
// The entry point of the application, prepare segments,
|
||||||
|
// initialize the cpu and execute main()
|
||||||
|
void boot_entry(void)
|
||||||
|
{
|
||||||
|
register unsigned char *src, *dst;
|
||||||
|
|
||||||
|
// Get physical data address and copy it to sram
|
||||||
|
src = &_etext;
|
||||||
|
dst = &_data;
|
||||||
|
while(dst < &_edata) {
|
||||||
|
*dst++ = *src++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the bss segment
|
||||||
|
dst = &_bss;
|
||||||
|
while(dst < &_ebss) {
|
||||||
|
*dst++ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute the code at the program entry point
|
||||||
|
main();
|
||||||
|
|
||||||
|
// Do nothing when returned from main, just keep looping
|
||||||
|
while(1);
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Software License Agreement (BSD License)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Roel Verdult
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
sram_top = ORIGIN(sram) + LENGTH(sram);
|
||||||
|
ENTRY(boot_entry)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
KEEP(*(.irq_vectors))
|
||||||
|
*(.text*)
|
||||||
|
*(.rodata*)
|
||||||
|
} > flash
|
||||||
|
|
||||||
|
/*
|
||||||
|
* More information about Special Section Indexes is available in the
|
||||||
|
* free "ELF for the ARM Architecture" document from ARM Limited
|
||||||
|
* http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } > flash
|
||||||
|
__exidx_start = .;
|
||||||
|
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } > flash
|
||||||
|
__exidx_end = .;
|
||||||
|
|
||||||
|
_etext = .;
|
||||||
|
|
||||||
|
.data : AT (__exidx_end)
|
||||||
|
{
|
||||||
|
_data = .;
|
||||||
|
*(vtable)
|
||||||
|
*(.data*)
|
||||||
|
_edata = .;
|
||||||
|
} > sram
|
||||||
|
|
||||||
|
/* zero initialized data */
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
_bss = .;
|
||||||
|
*(.bss*)
|
||||||
|
*(COMMON)
|
||||||
|
_ebss = .;
|
||||||
|
} > sram
|
||||||
|
|
||||||
|
end = .;
|
||||||
|
|
||||||
|
/* For GDB compatibility we decrease the top with 16 bytes */
|
||||||
|
stack_entry = sram_top - 16;
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file sysdefs.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _SYSDEFS_H_
|
||||||
|
#define _SYSDEFS_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
// Stay compatible with ugly "windows" style
|
||||||
|
#define BOOL bool
|
||||||
|
#define TRUE true
|
||||||
|
#define FALSE false
|
||||||
|
|
||||||
|
typedef volatile uint8_t REG8;
|
||||||
|
typedef volatile uint16_t REG16;
|
||||||
|
typedef volatile uint32_t REG32;
|
||||||
|
typedef unsigned char byte_t;
|
||||||
|
|
||||||
|
#define pREG8 (REG8 *)
|
||||||
|
#define pREG16 (REG16 *)
|
||||||
|
#define pREG32 (REG32 *)
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL ((void *) 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
CC = gcc
|
||||||
|
LD = gcc
|
||||||
|
LDFLAGS = -Wall -O4 -std=c99
|
||||||
|
EXES = lpcrc
|
||||||
|
|
||||||
|
all: $(EXES)
|
||||||
|
|
||||||
|
% : %.c
|
||||||
|
$(LD) $(LDFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(EXES)
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* Software License Agreement (BSD License)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2010, Roel Verdult
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define BLOCK_COUNT 7
|
||||||
|
#define BLOCK_LENGTH 4
|
||||||
|
#define BLOCK_TOTAL (BLOCK_COUNT*BLOCK_LENGTH)
|
||||||
|
|
||||||
|
typedef unsigned char byte_t;
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
FILE* pf;
|
||||||
|
byte_t buf[BLOCK_TOTAL];
|
||||||
|
uint32_t crc = 0;
|
||||||
|
uint32_t block;
|
||||||
|
|
||||||
|
// Check for required arguments
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
printf("syntax: lpcrc <firmware.bin>\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to open the supplied firmware
|
||||||
|
if ((pf = fopen(argv[1],"rb+")) == NULL)
|
||||||
|
{
|
||||||
|
printf("error: could not open file [%s] with write access\n",argv[1]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read out the data blocks used for crc calculation
|
||||||
|
if (fread(buf,1,BLOCK_TOTAL,pf) != BLOCK_TOTAL)
|
||||||
|
{
|
||||||
|
printf("error: could not read required bytes\n");
|
||||||
|
fclose(pf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the crc value
|
||||||
|
for (block=0; block<BLOCK_COUNT; block++)
|
||||||
|
{
|
||||||
|
crc += *((uint32_t*)(buf+(block*BLOCK_LENGTH)));
|
||||||
|
}
|
||||||
|
crc = (~crc) + 1;
|
||||||
|
|
||||||
|
// Reposition the file stream indicator to switch between read and write
|
||||||
|
if (fseek(pf,0,SEEK_CUR) != 0)
|
||||||
|
{
|
||||||
|
printf("error: could not switch from read to write mode\n");
|
||||||
|
fclose(pf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the crc back to the file
|
||||||
|
if (fwrite((byte_t*)&crc,1,BLOCK_LENGTH,pf) != BLOCK_LENGTH)
|
||||||
|
{
|
||||||
|
printf("error: could not write crc back to file\n");
|
||||||
|
fclose(pf);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("succesfully updated crc to: %08x\n",crc);
|
||||||
|
fclose(pf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue