Stripped down version of microbuilder.eu lpc1343codebase

I hope I didn't break anything too hard.
This commit is contained in:
Stefan `Sec` Zehl 2011-05-11 23:17:30 +02:00
commit 0c23bf065d
69 changed files with 15504 additions and 0 deletions

108
Makefile Normal file
View File

@ -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

85
core/Makefile Normal file
View File

@ -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

228
core/adc/adc.c Normal file
View File

@ -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;
}

47
core/adc/adc.h Normal file
View File

@ -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

296
core/cmd/cmd.c Normal file
View File

@ -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);
}

60
core/cmd/cmd.h Normal file
View File

@ -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

169
core/cpu/cpu.c Normal file
View File

@ -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);
}

76
core/cpu/cpu.h Normal file
View File

@ -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

550
core/gpio/gpio.c Normal file
View File

@ -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?
};

112
core/gpio/gpio.h Normal file
View File

@ -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

353
core/i2c/i2c.c Normal file
View File

@ -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
******************************************************************************/

83
core/i2c/i2c.h Normal file
View 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
*****************************************************************************/

57
core/iap/iap.c Normal file
View 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;
}

60
core/iap/iap.h Normal file
View File

@ -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

104
core/libc/ctype.c Normal file
View File

@ -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);
}

475
core/libc/stdio.c Executable file
View File

@ -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;
}

328
core/libc/string.c Executable file
View File

@ -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 */
}

3536
core/lpc134x.h Normal file

File diff suppressed because it is too large Load Diff

419
core/pmu/pmu.c Normal file
View File

@ -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
}

50
core/pmu/pmu.h Normal file
View File

@ -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

58
core/projectconfig.h Normal file
View File

@ -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)
/*=========================================================================*/

254
core/pwm/pwm.c Normal file
View File

@ -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;
}

50
core/pwm/pwm.h Normal file
View File

@ -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

58
core/rom_drivers.h Normal file
View File

@ -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

299
core/ssp/ssp.c Normal file
View File

@ -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;
}

85
core/ssp/ssp.h Normal file
View File

@ -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

65
core/sysdefs.h Normal file
View File

@ -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

280
core/sysinit.c Normal file
View File

@ -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

50
core/sysinit.h Normal file
View File

@ -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

229
core/systick/systick.c Normal file
View File

@ -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;
}

50
core/systick/systick.h Normal file
View File

@ -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

505
core/timer16/timer16.c Normal file
View File

@ -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;
}

59
core/timer16/timer16.h Normal file
View File

@ -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

344
core/timer32/timer32.c Normal file
View File

@ -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;
}

66
core/timer32/timer32.h Normal file
View File

@ -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

347
core/uart/uart.c Normal file
View File

@ -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;
}

78
core/uart/uart.h Normal file
View File

@ -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

149
core/uart/uart_buf.c Normal file
View File

@ -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;
}

236
core/usbcdc/cdc.h Normal file
View File

@ -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 */

161
core/usbcdc/cdc_buf.c Normal file
View File

@ -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;
}

29
core/usbcdc/cdc_buf.h Normal file
View File

@ -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

351
core/usbcdc/cdcuser.c Normal file
View File

@ -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
}

63
core/usbcdc/cdcuser.h Normal file
View File

@ -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__ */

40
core/usbcdc/config.h Normal file
View File

@ -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
*********************************************************************************/

228
core/usbcdc/usb.h Normal file
View 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__ */

157
core/usbcdc/usbcfg.h Normal file
View File

@ -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__ */

1058
core/usbcdc/usbcore.c Normal file

File diff suppressed because it is too large Load Diff

88
core/usbcdc/usbcore.h Normal file
View File

@ -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__ */

202
core/usbcdc/usbdesc.c Normal file
View File

@ -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,
};

35
core/usbcdc/usbdesc.h Normal file
View File

@ -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__ */

606
core/usbcdc/usbhw.c Normal file
View File

@ -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

62
core/usbcdc/usbhw.h Normal file
View File

@ -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__ */

134
core/usbcdc/usbreg.h Normal file
View File

@ -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 */

208
core/usbcdc/usbuser.c Normal file
View File

@ -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;
}
}

57
core/usbcdc/usbuser.h Normal file
View File

@ -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__ */

240
core/usbhid-rom/usb.h Normal file
View File

@ -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

115
core/usbhid-rom/usbconfig.c Normal file
View File

@ -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,
};

View File

@ -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

222
core/usbhid-rom/usbhid.c Normal file
View File

@ -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

46
core/usbhid-rom/usbhid.h Normal file
View File

@ -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

152
core/wdt/wdt.c Normal file
View File

@ -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();
}

47
core/wdt/wdt.h Normal file
View File

@ -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

170
lpc1xxx/LPC11xx_handlers.c Normal file
View File

@ -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
*****************************************************************************/

193
lpc1xxx/LPC13xx_handlers.c Normal file
View File

@ -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
*****************************************************************************/

65
lpc1xxx/LPC1xxx_startup.c Normal file
View File

@ -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);
}

77
lpc1xxx/linkscript.ld Normal file
View File

@ -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;
}

65
sysdefs.h Normal file
View File

@ -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

12
tools/Makefile Normal file
View File

@ -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)

97
tools/lpcrc.c Normal file
View File

@ -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;
}