From 89ee198a04df6e0fee2f7bbad39a99798f9d7afa Mon Sep 17 00:00:00 2001 From: Roland Sahlsten Date: Tue, 24 May 2011 21:02:43 +0000 Subject: First version of MainProcessingUnit mpu. git-svn-id: https://svn.spreadspace.org/mur.sat@27 7de4ea59-55d0-425e-a1af-a3118ea81d4c --- software/mpu/.cproject | 885 +++++++++++++++++++++++++++++++++ software/mpu/.project | 82 +++ software/mpu/Debug/makefile | 55 ++ software/mpu/src/cam/cam.c | 8 + software/mpu/src/cam/cam.h | 12 + software/mpu/src/cr_startup_lpc13.c | 359 +++++++++++++ software/mpu/src/gpio/gpio.c | 378 ++++++++++++++ software/mpu/src/gpio/gpio.h | 66 +++ software/mpu/src/lightsens/lightsens.c | 8 + software/mpu/src/lightsens/lightsens.h | 12 + software/mpu/src/mpu_main.c | 74 +++ software/mpu/src/ssp/ssp.c | 224 +++++++++ software/mpu/src/ssp/ssp.h | 109 ++++ software/mpu/src/ssp/ssptest.c | 190 +++++++ software/mpu/src/uart/uart.c | 189 +++++++ software/mpu/src/uart/uart.h | 55 ++ 16 files changed, 2706 insertions(+) create mode 100644 software/mpu/.cproject create mode 100644 software/mpu/.project create mode 100644 software/mpu/Debug/makefile create mode 100644 software/mpu/src/cam/cam.c create mode 100644 software/mpu/src/cam/cam.h create mode 100644 software/mpu/src/cr_startup_lpc13.c create mode 100644 software/mpu/src/gpio/gpio.c create mode 100644 software/mpu/src/gpio/gpio.h create mode 100644 software/mpu/src/lightsens/lightsens.c create mode 100644 software/mpu/src/lightsens/lightsens.h create mode 100644 software/mpu/src/mpu_main.c create mode 100644 software/mpu/src/ssp/ssp.c create mode 100644 software/mpu/src/ssp/ssp.h create mode 100644 software/mpu/src/ssp/ssptest.c create mode 100644 software/mpu/src/uart/uart.c create mode 100644 software/mpu/src/uart/uart.h (limited to 'software') diff --git a/software/mpu/.cproject b/software/mpu/.cproject new file mode 100644 index 0000000..d571ec1 --- /dev/null +++ b/software/mpu/.cproject @@ -0,0 +1,885 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<?xml version="1.0" encoding="UTF-8"?> +<TargetConfig> +<Properties property_0="" property_1="" property_2="" property_3="NXP" property_4="LPC1343" property_count="5" version="1"/> +<infoList vendor="NXP"> +<info chip="LPC1343" match_id="0x3d00002b" name="LPC1343" stub="crt_emu_lpc11_13_nxp"> +<chip> +<name>LPC1343</name> +<family>LPC13xx</family> +<vendor>NXP (formerly Philips)</vendor> +<reset board="None" core="Real" sys="Real"/> +<clock changeable="TRUE" freq="12MHz" is_accurate="TRUE"/> +<memory can_program="true" id="Flash" is_ro="true" type="Flash"/> +<memory id="RAM" type="RAM"/> +<memory id="Periph" is_volatile="true" type="Peripheral"/> +<memoryInstance derived_from="Flash" id="MFlash32" location="0x00000000" size="0x8000"/> +<memoryInstance derived_from="RAM" id="RamLoc8" location="0x10000000" size="0x2000"/> +<prog_flash blocksz="0x1000" location="0" maxprgbuff="0x1000" progwithcode="TRUE" size="0x8000"/> +<peripheralInstance derived_from="LPC17_NVIC" determined="infoFile" id="NVIC" location="0xE000E000"/> +<peripheralInstance derived_from="LPC11_13_TIMER32" determined="infoFile" id="TIMER0" location="0x40014000"/> +<peripheralInstance derived_from="LPC11_13_TIMER32" determined="infoFile" id="TIMER1" location="0x40018000"/> +<peripheralInstance derived_from="LPC1xxx_UART_MODEM" determined="infoFile" id="UART0" location="0x40008000"/> +<peripheralInstance derived_from="LPC11_13_SSP" determined="infoFile" id="SSP" location="0x40040000"/> +<peripheralInstance derived_from="LPC11_13_ADC" determined="infoFile" id="ADC" location="0x4001c000"/> +<peripheralInstance derived_from="LPC11_13_I2C" determined="infoFile" id="I2C0" location="0x40000000"/> +<peripheralInstance derived_from="CM3_DCR" determined="infoFile" id="DCR" location="0xE000EDF0"/> +<peripheralInstance derived_from="LPC13_SYSCTL" determined="infoFile" id="SYSCTL" location="0x40048000"/> +<peripheralInstance derived_from="LPC11_13_PMU" determined="infoFile" id="PMU" location="0x40038000"/> +<peripheralInstance derived_from="LPC11_13_IOCON" determined="infoFile" id="IOCON" location="0x40044000"/> +<peripheralInstance derived_from="LPC11_13_GPIO" determined="infoFile" id="GPIO0" location="0x50000000"/> +<peripheralInstance derived_from="LPC11_13_GPIO" determined="infoFile" id="GPIO1" location="0x50010000"/> +<peripheralInstance derived_from="LPC11_13_GPIO" determined="infoFile" id="GPIO2" location="0x50020000"/> +<peripheralInstance derived_from="LPC11_13_GPIO" determined="infoFile" id="GPIO3" location="0x50030000"/> +<peripheralInstance derived_from="LPC11_13_TIMER16" determined="infoFile" id="TMR160" location="0x4000c000"/> +<peripheralInstance derived_from="LPC11_13_TIMER16" determined="infoFile" id="TMR161" location="0x40010000"/> +<peripheralInstance derived_from="LPC11_13_USBDEV" determined="infoFile" id="USB" location="0x40020000"/> +<peripheralInstance derived_from="LPC11_13_WDT" determined="infoFile" id="WDT" location="0x40004000"/> +</chip> +<processor> +<name gcc_name="cortex-m3">Cortex-M3</name> +<family>Cortex-M</family> +</processor> +<link href="nxp_lpc11_13_peripheral.xme" show="embed" type="simple"/> +</info> +</infoList> +</TargetConfig> + + diff --git a/software/mpu/.project b/software/mpu/.project new file mode 100644 index 0000000..28fde1f --- /dev/null +++ b/software/mpu/.project @@ -0,0 +1,82 @@ + + + mpu + + + CMSISv1p30_LPC13xx + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.buildLocation + ${workspace_loc:/mpu/Debug} + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/software/mpu/Debug/makefile b/software/mpu/Debug/makefile new file mode 100644 index 0000000..00df9a2 --- /dev/null +++ b/software/mpu/Debug/makefile @@ -0,0 +1,55 @@ +################################################################################ +# Automatically-generated file. Do not edit! +################################################################################ + +-include ../makefile.init + +RM := rm -rf + +# All of the sources participating in the build are defined here +-include sources.mk +-include subdir.mk +-include src/uart/subdir.mk +-include src/ssp/subdir.mk +-include src/subdir.mk +-include src/lightsens/subdir.mk +-include src/gpio/subdir.mk +-include src/cam/subdir.mk +-include objects.mk + +ifneq ($(MAKECMDGOALS),clean) +ifneq ($(strip $(C_DEPS)),) +-include $(C_DEPS) +endif +endif + +-include ../makefile.defs + +# Add inputs and outputs from these tool invocations to the build variables + +# All Target +all: mpu.axf + +# Tool invocations +mpu.axf: $(OBJS) $(USER_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: MCU Linker' + arm-none-eabi-gcc -nostdlib -L"D:\Data\FH\8.Semester\MurSat\workspace\CMSISv1p30_LPC13xx\Debug" -Xlinker --gc-sections -Xlinker -Map=mpu.map -mcpu=cortex-m3 -mthumb -T "mpu_Debug.ld" -o"mpu.axf" $(OBJS) $(USER_OBJS) $(LIBS) + @echo 'Finished building target: $@' + @echo ' ' + $(MAKE) --no-print-directory post-build + +# Other Targets +clean: + -$(RM) $(OBJS)$(C_DEPS)$(EXECUTABLES) mpu.axf + -@echo ' ' + +post-build: + -@echo 'Performing post-build steps' + -arm-none-eabi-size mpu.axf; # arm-none-eabi-objcopy -O ihex mpu.axf mpu.hex ; + -@echo ' ' + +.PHONY: all clean dependents +.SECONDARY: post-build + +-include ../makefile.targets diff --git a/software/mpu/src/cam/cam.c b/software/mpu/src/cam/cam.c new file mode 100644 index 0000000..076e3e4 --- /dev/null +++ b/software/mpu/src/cam/cam.c @@ -0,0 +1,8 @@ +/* + * cam.c + * + * Created on: 24.05.2011 + * Author: Roland + */ + +#include "cam.h" diff --git a/software/mpu/src/cam/cam.h b/software/mpu/src/cam/cam.h new file mode 100644 index 0000000..6d2525c --- /dev/null +++ b/software/mpu/src/cam/cam.h @@ -0,0 +1,12 @@ +/* + * cam.h + * + * Created on: 24.05.2011 + * Author: Roland + */ + +#ifndef CAM_H_ +#define CAM_H_ + + +#endif /* CAM_H_ */ diff --git a/software/mpu/src/cr_startup_lpc13.c b/software/mpu/src/cr_startup_lpc13.c new file mode 100644 index 0000000..a749437 --- /dev/null +++ b/software/mpu/src/cr_startup_lpc13.c @@ -0,0 +1,359 @@ +//***************************************************************************** +// +--+ +// | ++----+ +// +-++ | +// | | +// +-+--+ | +// | +--+--+ +// +----+ Copyright (c) 2009 Code Red Technologies Ltd. +// +// Microcontroller Startup code for use with Red Suite +// +// Software License Agreement +// +// The software is owned by Code Red Technologies and/or its suppliers, and is +// protected under applicable copyright laws. All rights are reserved. Any +// use in violation of the foregoing restrictions may subject the user to criminal +// sanctions under applicable laws, as well as to civil liability for the breach +// of the terms and conditions of this license. +// +// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED +// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. +// USE OF THIS SOFTWARE FOR COMMERCIAL DEVELOPMENT AND/OR EDUCATION IS SUBJECT +// TO A CURRENT END USER LICENSE AGREEMENT (COMMERCIAL OR EDUCATIONAL) WITH +// CODE RED TECHNOLOGIES LTD. +// +//***************************************************************************** +#define WEAK __attribute__ ((weak)) +#define ALIAS(f) __attribute__ ((weak, alias (#f))) + +// Code Red - if CMSIS is being used, then SystemInit() routine +// will be called by startup code rather than in application's main() +#ifdef __USE_CMSIS +#include "system_LPC13xx.h" +#endif + +//***************************************************************************** +// +// Forward declaration of the default handlers. These are aliased. +// When the application defines a handler (with the same name), this will +// automatically take precedence over these weak definitions +// +//***************************************************************************** + void Reset_Handler(void); + void ResetISR(void) ALIAS(Reset_Handler); +WEAK void NMI_Handler(void); +WEAK void HardFault_Handler(void); +WEAK void MemManage_Handler(void); +WEAK void BusFault_Handler(void); +WEAK void UsageFault_Handler(void); +WEAK void SVCall_Handler(void); +WEAK void DebugMon_Handler(void); +WEAK void PendSV_Handler(void); +WEAK void SysTick_Handler(void); + +//***************************************************************************** +// +// Forward declaration of the specific IRQ handlers. These are aliased +// to the IntDefaultHandler, which is a 'forever' loop. When the application +// defines a handler (with the same name), this will automatically take +// precedence over these weak definitions +// +//***************************************************************************** + +void I2C_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER16_0_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER16_1_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER32_0_IRQHandler (void) ALIAS(IntDefaultHandler); +void TIMER32_1_IRQHandler (void) ALIAS(IntDefaultHandler); +void SSP_IRQHandler (void) ALIAS(IntDefaultHandler); +void UART_IRQHandler (void) ALIAS(IntDefaultHandler); +void USB_IRQHandler (void) ALIAS(IntDefaultHandler); +void USB_FIQHandler (void) ALIAS(IntDefaultHandler); +void ADC_IRQHandler (void) ALIAS(IntDefaultHandler); +void WDT_IRQHandler (void) ALIAS(IntDefaultHandler); +void BOD_IRQHandler (void) ALIAS(IntDefaultHandler); +void FMC_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIOINT3_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIOINT2_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIOINT1_IRQHandler (void) ALIAS(IntDefaultHandler); +void PIOINT0_IRQHandler (void) ALIAS(IntDefaultHandler); +void WAKEUP_IRQHandler (void) ALIAS(IntDefaultHandler); + +//***************************************************************************** +// +// The entry point for the application. +// __main() is the entry point for redlib based applications +// main() is the entry point for newlib based applications +// +//***************************************************************************** +extern WEAK void __main(void); +extern WEAK void main(void); +//***************************************************************************** +// +// External declaration for the pointer to the stack top from the Linker Script +// +//***************************************************************************** +extern void _vStackTop; + +//***************************************************************************** +// +// The vector table. Note that the proper constructs must be placed on this to +// ensure that it ends up at physical address 0x0000.0000. +// +//***************************************************************************** +__attribute__ ((section(".isr_vector"))) +void (* const g_pfnVectors[])(void) = +{ + // Core Level - CM3 + (void *)&_vStackTop, // The initial stack pointer + Reset_Handler, // The reset handler + 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 sources (40 ea.) for the I/O pins: + // PIO0 (0:11) + // PIO1 (0:11) + // PIO2 (0:11) + // PIO3 (0:3) + 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 + + 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 + +}; + +//***************************************************************************** +// +// The following are constructs created by the linker, indicating where the +// the "data" and "bss" segments reside in memory. The initializers for the +// for the "data" segment resides immediately following the "text" segment. +// +//***************************************************************************** +extern unsigned long _etext; +extern unsigned long _data; +extern unsigned long _edata; +extern unsigned long _bss; +extern unsigned long _ebss; + +//***************************************************************************** +// +// This is the code that gets called when the processor first starts execution +// following a reset event. Only the absolutely necessary set is performed, +// after which the application supplied entry() routine is called. Any fancy +// actions (such as making decisions based on the reset cause register, and +// resetting the bits in that register) are left solely in the hands of the +// application. +// +//***************************************************************************** +void +//ResetISR(void) +Reset_Handler(void) +{ + unsigned long *pulSrc, *pulDest; + + // + // Copy the data segment initializers from flash to SRAM. + // + pulSrc = &_etext; + for(pulDest = &_data; pulDest < &_edata; ) + { + *pulDest++ = *pulSrc++; + } + + // + // Zero fill the bss segment. This is done with inline assembly since this + // will clear the value of pulDest if it is not kept in a register. + // + __asm(" ldr r0, =_bss\n" + " ldr r1, =_ebss\n" + " mov r2, #0\n" + " .thumb_func\n" + "zero_loop:\n" + " cmp r0, r1\n" + " it lt\n" + " strlt r2, [r0], #4\n" + " blt zero_loop"); + +#ifdef __USE_CMSIS + SystemInit(); +#endif + + // + // Call the application's entry point. + // __main() is the entry point for redlib based applications (which calls main()) + // main() is the entry point for newlib based applications + // + if (__main) + __main() ; + else + main() ; + + // + // main() shouldn't return, but if it does, we'll just enter an infinite loop + // + while (1) { + ; + } +} + +//***************************************************************************** +// +// This is the code that gets called when the processor receives a NMI. This +// simply enters an infinite loop, preserving the system state for examination +// by a debugger. +// +//***************************************************************************** +void NMI_Handler(void) +{ + while(1) + { + } +} + +void HardFault_Handler(void) +{ + while(1) + { + } +} + +void MemManage_Handler(void) +{ + while(1) + { + } +} + +void BusFault_Handler(void) +{ + while(1) + { + } +} + +void UsageFault_Handler(void) +{ + while(1) + { + } +} + +void SVCall_Handler(void) +{ + while(1) + { + } +} + +void DebugMon_Handler(void) +{ + while(1) + { + } +} + +void PendSV_Handler(void) +{ + while(1) + { + } +} + +void SysTick_Handler(void) +{ + while(1) + { + } +} + +//***************************************************************************** +// +// Processor ends up here if an unexpected interrupt occurs or a handler +// is not present in the application code. +// +//***************************************************************************** + +static void IntDefaultHandler(void) +{ + // + // Go into an infinite loop. + // + while(1) + { + } +} diff --git a/software/mpu/src/gpio/gpio.c b/software/mpu/src/gpio/gpio.c new file mode 100644 index 0000000..84eee75 --- /dev/null +++ b/software/mpu/src/gpio/gpio.c @@ -0,0 +1,378 @@ +/***************************************************************************** + * gpio.c: GPIO C file for NXP LPC13xx Family Microprocessors + * + * Copyright(C) 2008, NXP Semiconductor + * All rights reserved. + * + * History + * 2008.07.20 ver 1.00 Preliminary version, first Release + * 2009.12.09 ver 1.05 Mod to use mask registers for GPIO writes + inlining (.h) + * +*****************************************************************************/ +#include "LPC13xx.h" /* LPC13xx Peripheral Registers */ +#include "gpio.h" + +/* =================== + * CodeRed - Modified file to extract out interrupt handler related code, + * which is really application project specific. + * Set TIMER16_GENERIC_INTS to 1 to reenable original code. + * =================== */ +//#define GPIO_GENERIC_INTS 1 + +#ifdef GPIO_GENERIC_INTS +volatile uint32_t gpio0_counter = 0; +volatile uint32_t gpio1_counter = 0; +volatile uint32_t gpio2_counter = 0; +volatile uint32_t gpio3_counter = 0; +volatile uint32_t p0_1_counter = 0; +volatile uint32_t p1_1_counter = 0; +volatile uint32_t p2_1_counter = 0; +volatile uint32_t p3_1_counter = 0; + +/***************************************************************************** +** Function name: PIOINT0_IRQHandler +** +** Descriptions: Use one GPIO pin(port0 pin1) as interrupt source +** +** parameters: None +** Returned value: None +** +*****************************************************************************/ +void PIOINT0_IRQHandler(void) +{ + uint32_t regVal; + + gpio0_counter++; + regVal = GPIOIntStatus( PORT0, 1 ); + if ( regVal ) + { + p0_1_counter++; + GPIOIntClear( PORT0, 1 ); + } + return; +} + +/***************************************************************************** +** Function name: PIOINT1_IRQHandler +** +** Descriptions: Use one GPIO pin(port1 pin1) as interrupt source +** +** parameters: None +** Returned value: None +** +*****************************************************************************/ +void PIOINT1_IRQHandler(void) +{ + uint32_t regVal; + + gpio1_counter++; + regVal = GPIOIntStatus( PORT1, 1 ); + if ( regVal ) + { + p1_1_counter++; + GPIOIntClear( PORT1, 1 ); + } + return; +} + +/***************************************************************************** +** Function name: PIOINT2_IRQHandler +** +** Descriptions: Use one GPIO pin(port2 pin1) as interrupt source +** +** parameters: None +** Returned value: None +** +*****************************************************************************/ +void PIOINT2_IRQHandler(void) +{ + uint32_t regVal; + + gpio2_counter++; + regVal = GPIOIntStatus( PORT2, 1 ); + if ( regVal ) + { + p2_1_counter++; + GPIOIntClear( PORT2, 1 ); + } + return; +} + +/***************************************************************************** +** Function name: PIOINT3_IRQHandler +** +** Descriptions: Use one GPIO pin(port3 pin1) as interrupt source +** +** parameters: None +** Returned value: None +** +*****************************************************************************/ +void PIOINT3_IRQHandler(void) +{ + uint32_t regVal; + + gpio3_counter++; + regVal = GPIOIntStatus( PORT3, 1 ); + if ( regVal ) + { + p3_1_counter++; + GPIOIntClear( PORT3, 1 ); + } + return; +} +#endif //GPIO_GENERIC_INTS + +/***************************************************************************** +** Function name: GPIOInit +** +** Descriptions: Initialize GPIO, install the +** GPIO interrupt handler +** +** parameters: None +** Returned value: true or false, return false if the VIC table +** is full and GPIO interrupt handler can be +** installed. +** +*****************************************************************************/ +void GPIOInit( void ) +{ + /* Enable AHB clock to the GPIO domain. */ + LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); + +#ifdef __JTAG_DISABLED + LPC_IOCON->JTAG_TDO_PIO1_1 &= ~0x07; + LPC_IOCON->JTAG_TDO_PIO1_1 |= 0x01; +#endif + + /* 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); + return; +} + +/***************************************************************************** +** Function name: GPIOSetInterrupt +** +** Descriptions: Set interrupt sense, event, etc. +** edge or level, 0 is edge, 1 is level +** single or double edge, 0 is single, 1 is double +** active high or low, etc. +** +** parameters: port num, bit position, sense, single/doube, polarity +** Returned value: None +** +*****************************************************************************/ +void GPIOSetInterrupt( uint32_t portNum, uint32_t bitPosi, uint32_t sense, + uint32_t single, uint32_t event ) +{ + switch ( portNum ) + { + case PORT0: + if ( sense == 0 ) + { + LPC_GPIO0->IS &= ~(0x1<IBE &= ~(0x1<IBE |= (0x1<IS |= (0x1<IEV &= ~(0x1<IEV |= (0x1<IS &= ~(0x1<IBE &= ~(0x1<IBE |= (0x1<IS |= (0x1<IEV &= ~(0x1<IEV |= (0x1<IS &= ~(0x1<IBE &= ~(0x1<IBE |= (0x1<IS |= (0x1<IEV &= ~(0x1<IEV |= (0x1<IS &= ~(0x1<IBE &= ~(0x1<IBE |= (0x1<IS |= (0x1<IEV &= ~(0x1<IEV |= (0x1<IE |= (0x1<IE |= (0x1<IE |= (0x1<IE |= (0x1<IE &= ~(0x1<IE &= ~(0x1<IE &= ~(0x1<IE &= ~(0x1<MIS & (0x1<MIS & (0x1<MIS & (0x1<MIS & (0x1<IC |= (0x1<IC |= (0x1<IC |= (0x1<IC |= (0x1<MASKED_ACCESS[(1<DIR |= 1<DIR &= ~(1<.c file. + */ + + uint32_t i; + + uint8_t src_addr[SSP_BUFSIZE]; + uint8_t dest_addr[SSP_BUFSIZE]; + +#if SSP_DEBUG + UARTInit(115200); +#endif + + SSPInit(); /* initialize SSP port, share pins with SPI0 + on port0(p0.15-18). */ + for ( i = 0; i < SSP_BUFSIZE; i++ ) + { + src_addr[i] = (uint8_t)i; + dest_addr[i] = 0; + } + +#if TX_RX_ONLY + /* For the inter-board communication, one board is set as + master transmit, the other is set to slave receive. */ +#if SSP_SLAVE + /* Slave receive */ + SSPReceive( (uint8_t *)dest_addr, SSP_BUFSIZE ); + for ( i = 0; i < SSP_BUFSIZE; i++ ) + { + if ( src_addr[i] != dest_addr[i] ) + { + while ( 1 ); /* Verification failure, fatal error */ + } + } +#else + /* Master transmit */ + SSPSend( (uint8_t *)src_addr, SSP_BUFSIZE); +#endif +#else + /* TX_RX_ONLY=0, it's either an internal loopback test + within SSP peripheral or communicate with a serial EEPROM. */ +#if LOOPBACK_MODE + LoopbackTest( src_addr, dest_addr ); +#else + SEEPROMTest( src_addr, dest_addr ); + /* If JTAG TCK is used as SSP clock, change the setting before + serial EEPROM test, restore after the test. */ +#ifdef __JTAG_DISABLED + LPC_IOCON->JTAG_TCK_PIO0_10 &= ~0x07; /* Restore JTAG_TCK */ +#endif +#endif /* endif NOT LOOPBACK_MODE */ +#endif /* endif NOT TX_RX_ONLY */ + return 0; +} diff --git a/software/mpu/src/ssp/ssp.c b/software/mpu/src/ssp/ssp.c new file mode 100644 index 0000000..edda1fd --- /dev/null +++ b/software/mpu/src/ssp/ssp.c @@ -0,0 +1,224 @@ +/***************************************************************************** + * ssp.c: SSP C file for NXP LPC13xx Family Microprocessors + * + * Copyright(C) 2008, NXP Semiconductor + * All rights reserved. + * + * History + * 2008.07.20 ver 1.00 Preliminary version, first Release + * +*****************************************************************************/ +#include "LPC13xx.h" /* LPC13xx Peripheral Registers */ +#include "../gpio/gpio.h" +#include "ssp.h" + +/* statistics of all the interrupts */ +volatile uint32_t interruptRxStat = 0; +volatile uint32_t interruptOverRunStat = 0; +volatile uint32_t interruptRxTimeoutStat = 0; + +/***************************************************************************** +** Function name: SSP_IRQHandler +** +** Descriptions: SSP port is used for SPI communication. +** SSP interrupt handler +** 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. +** +** parameters: None +** Returned value: None +** +*****************************************************************************/ +void SSP_IRQHandler(void) +{ + uint32_t regValue; + + regValue = LPC_SSP->MIS; + if ( regValue & SSPMIS_RORMIS ) /* Receive overrun interrupt */ + { + interruptOverRunStat++; + LPC_SSP->ICR = SSPICR_RORIC; /* clear interrupt */ + } + if ( regValue & SSPMIS_RTMIS ) /* Receive timeout interrupt */ + { + interruptRxTimeoutStat++; + LPC_SSP->ICR = SSPICR_RTIC; /* clear interrupt */ + } + + /* please be aware that, in main and ISR, CurrentRxIndex and CurrentTxIndex + are shared as global variables. It may create some race condition that main + and ISR manipulate these variables at the same time. SSPSR_BSY checking (polling) + in both main and ISR could prevent this kind of race condition */ + if ( regValue & SSPMIS_RXMIS ) /* Rx at least half full */ + { + interruptRxStat++; /* receive until it's empty */ + } + return; +} + +/***************************************************************************** +** Function name: SSPInit +** +** Descriptions: SSP port initialization routine +** +** parameters: None +** Returned value: None +** +*****************************************************************************/ +void SSPInit( void ) +{ + uint8_t i, Dummy=Dummy; + + LPC_SYSCON->PRESETCTRL |= (0x1<<0); + LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11); + LPC_SYSCON->SSPCLKDIV = 0x02; /* Divided by 2 */ + LPC_IOCON->PIO0_8 &= ~0x07; /* SSP I/O config */ + LPC_IOCON->PIO0_8 |= 0x01; /* SSP MISO */ + LPC_IOCON->PIO0_9 &= ~0x07; + LPC_IOCON->PIO0_9 |= 0x01; /* SSP MOSI */ +#ifdef __JTAG_DISABLED + LPC_IOCON->SCKLOC = 0x00; + LPC_IOCON->JTAG_TCK_PIO0_10 &= ~0x07; + LPC_IOCON->JTAG_TCK_PIO0_10 |= 0x02; /* SSP CLK */ +#endif + +#if 1 + /* On HummingBird 1(HB1), SSP CLK can be routed to different pins, + other than JTAG TCK, it's either P2.11 func. 1 or P0.6 func. 2. */ + LPC_IOCON->SCKLOC = 0x01; + LPC_IOCON->PIO2_11 = 0x01;/* P2.11 function 1 is SSP clock, need to combined + with IOCONSCKLOC register setting */ +#else + LPC_IOCON->SCKLOC = 0x02; + LPC_IOCON->PIO0_6 = 0x02; /* P0.6 function 2 is SSP clock, need to combined + with IOCONSCKLOC register setting */ +#endif + +#if USE_CS + LPC_IOCON->PIO0_2 &= ~0x07; + LPC_IOCON->PIO0_2 |= 0x01; /* SSP SSEL */ +#else + LPC_IOCON->PIO0_2 &= ~0x07; /* SSP SSEL is a GPIO pin */ + /* port0, bit 2 is set to GPIO output and high */ + GPIOSetDir( PORT0, 2, 1 ); + GPIOSetValue( PORT0, 2, 1 ); +#endif + + /* Set DSS data to 8-bit, Frame format SPI, CPOL = 0, CPHA = 0, and SCR is 15 */ + LPC_SSP->CR0 = 0x0707; + + /* SSPCPSR clock prescale register, master mode, minimum divisor is 0x02 */ + LPC_SSP->CPSR = 0x2; + + for ( i = 0; i < FIFOSIZE; i++ ) + { + Dummy = LPC_SSP->DR; /* clear the RxFIFO */ + } + + /* Enable the SSP Interrupt */ + NVIC_EnableIRQ(SSP_IRQn); + + /* Device select as master, SSP Enabled */ +#if LOOPBACK_MODE + LPC_SSP->CR1 = SSPCR1_LBM | SSPCR1_SSE; +#else +#if SSP_SLAVE + /* Slave mode */ + if ( LPC_SSP->CR1 & SSPCR1_SSE ) + { + /* The slave bit can't be set until SSE bit is zero. */ + LPC_SSP->CR1 &= ~SSPCR1_SSE; + } + LPC_SSP->CR1 = SSPCR1_MS; /* Enable slave bit first */ + LPC_SSP->CR1 |= SSPCR1_SSE; /* Enable SSP */ +#else + /* Master mode */ + LPC_SSP->CR1 = SSPCR1_SSE; +#endif +#endif + /* Set SSPINMS registers to enable interrupts */ + /* enable all error related interrupts */ + LPC_SSP->IMSC = SSPIMSC_RORIM | SSPIMSC_RTIM; + return; +} + +/***************************************************************************** +** Function name: SSPSend +** +** Descriptions: Send a block of data to the SSP port, the +** first parameter is the buffer pointer, the 2nd +** parameter is the block length. +** +** parameters: buffer pointer, and the block length +** Returned value: None +** +*****************************************************************************/ +void SSPSend( uint8_t *buf, uint32_t Length ) +{ + uint32_t i; + uint8_t Dummy = Dummy; + + for ( i = 0; i < Length; i++ ) + { + /* Move on only if NOT busy and TX FIFO not full. */ + while ( (LPC_SSP->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF ); + LPC_SSP->DR = *buf; + buf++; +#if !LOOPBACK_MODE + while ( (LPC_SSP->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE ); + /* 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 = LPC_SSP->DR; +#else + /* Wait until the Busy bit is cleared. */ + while ( LPC_SSP->SR & SSPSR_BSY ); +#endif + } + return; +} + +/***************************************************************************** +** Function name: SSPReceive +** Descriptions: the module will receive a block of data from +** the SSP, the 2nd parameter is the block +** length. +** parameters: buffer pointer, and block length +** Returned value: None +** +*****************************************************************************/ +void SSPReceive( uint8_t *buf, uint32_t Length ) +{ + uint32_t i; + + for ( i = 0; i < Length; i++ ) + { + /* As long as Receive FIFO is not empty, I can always receive. */ + /* If it's a loopback test, clock is shared for both TX and RX, + no need to write dummy byte to get clock to get the data */ + /* if it's a peer-to-peer communication, SSPDR needs to be written + before a read can take place. */ +#if !LOOPBACK_MODE +#if SSP_SLAVE + while ( !(LPC_SSP->SR & SSPSR_RNE) ); +#else + LPC_SSP->DR = 0xFF; + /* Wait until the Busy bit is cleared */ + while ( (LPC_SSP->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE ); +#endif +#else + while ( !(LPC_SSP->SR & SSPSR_RNE) ); +#endif + *buf = LPC_SSP->DR; + buf++; + + } + return; +} + +/****************************************************************************** +** End Of File +******************************************************************************/ + diff --git a/software/mpu/src/ssp/ssp.h b/software/mpu/src/ssp/ssp.h new file mode 100644 index 0000000..4491687 --- /dev/null +++ b/software/mpu/src/ssp/ssp.h @@ -0,0 +1,109 @@ +/***************************************************************************** + * ssp.h: Header file for NXP LPC134x Family Microprocessors + * + * Copyright(C) 2006, NXP Semiconductor + * All rights reserved. + * + * History + * 2006.07.19 ver 1.00 Preliminary version, first Release + * +******************************************************************************/ +#ifndef __SSP_H__ +#define __SSP_H__ + +/* There are there modes in SSP: loopback, master or slave. */ +/* Here are the combination of all the tests. +(1) LOOPBACK test: LOOPBACK_MODE=1, TX_RX_ONLY=0, USE_CS=1; +(2) Serial EEPROM test: LOOPBACK_MODE=0, TX_RX_ONLY=0, USE_CS=0; (default) +(3) TX(Master) Only: LOOPBACK_MODE=0, SSP_SLAVE=0, TX_RX_ONLY=1, USE_CS=1; +(4) RX(Slave) Only: LOOPBACK_MODE=0, SSP_SLAVE=1, TX_RX_ONLY=0, USE_CS=1 */ + +#define LOOPBACK_MODE 0 /* 1 is loopback, 0 is normal operation. */ +#define SSP_SLAVE 0 /* 1 is SLAVE mode, 0 is master mode */ +#define TX_RX_ONLY 0 /* 1 is TX or RX only depending on SSP_SLAVE + flag, 0 is either loopback mode or communicate + with a serial EEPROM. */ + +/* if USE_CS is zero, set SSEL as GPIO that you have total control of the sequence */ +/* When test serial SEEPROM(LOOPBACK_MODE=0, TX_RX_ONLY=0), set USE_CS to 0. */ +/* When LOOPBACK_MODE=1 or TX_RX_ONLY=1, set USE_CS to 1. */ + +#define USE_CS 0 +#define SSP_DEBUG 0 + +/* SPI read and write buffer size */ +#define SSP_BUFSIZE 16 +#define FIFOSIZE 8 + +#define DELAY_COUNT 10 +#define MAX_TIMEOUT 0xFF + +/* Port0.2 is the SSP select pin */ +#define SSP0_SEL (1 << 2) + +/* SSP Status register */ +#define SSPSR_TFE (1 << 0) +#define SSPSR_TNF (1 << 1) +#define SSPSR_RNE (1 << 2) +#define SSPSR_RFF (1 << 3) +#define SSPSR_BSY (1 << 4) + +/* SSP CR0 register */ +#define SSPCR0_DSS (1 << 0) +#define SSPCR0_FRF (1 << 4) +#define SSPCR0_SPO (1 << 6) +#define SSPCR0_SPH (1 << 7) +#define SSPCR0_SCR (1 << 8) + +/* SSP CR1 register */ +#define SSPCR1_LBM (1 << 0) +#define SSPCR1_SSE (1 << 1) +#define SSPCR1_MS (1 << 2) +#define SSPCR1_SOD (1 << 3) + +/* SSP Interrupt Mask Set/Clear register */ +#define SSPIMSC_RORIM (1 << 0) +#define SSPIMSC_RTIM (1 << 1) +#define SSPIMSC_RXIM (1 << 2) +#define SSPIMSC_TXIM (1 << 3) + +/* SSP0 Interrupt Status register */ +#define SSPRIS_RORRIS (1 << 0) +#define SSPRIS_RTRIS (1 << 1) +#define SSPRIS_RXRIS (1 << 2) +#define SSPRIS_TXRIS (1 << 3) + +/* SSP0 Masked Interrupt register */ +#define SSPMIS_RORMIS (1 << 0) +#define SSPMIS_RTMIS (1 << 1) +#define SSPMIS_RXMIS (1 << 2) +#define SSPMIS_TXMIS (1 << 3) + +/* SSP0 Interrupt clear register */ +#define SSPICR_RORIC (1 << 0) +#define SSPICR_RTIC (1 << 1) + +/* ATMEL SEEPROM command set */ +#define WREN 0x06 /* MSB A8 is set to 0, simplifying test */ +#define WRDI 0x04 +#define RDSR 0x05 +#define WRSR 0x01 +#define READ 0x03 +#define WRITE 0x02 + +/* RDSR status bit definition */ +#define RDSR_RDY 0x01 +#define RDSR_WEN 0x02 + +/* If RX_INTERRUPT is enabled, the SSP RX will be handled in the ISR +SSPReceive() will not be needed. */ +extern void SSP_IRQHandler (void); +extern void SSPInit( void ); +extern void SSPSend( uint8_t *Buf, uint32_t Length ); +extern void SSPReceive( uint8_t *buf, uint32_t Length ); + +#endif /* __SSP_H__ */ +/***************************************************************************** +** End Of File +******************************************************************************/ + diff --git a/software/mpu/src/ssp/ssptest.c b/software/mpu/src/ssp/ssptest.c new file mode 100644 index 0000000..119f8a7 --- /dev/null +++ b/software/mpu/src/ssp/ssptest.c @@ -0,0 +1,190 @@ +/***************************************************************************** + * ssptest.c: main C entry file for NXP LPC13xx Family Microprocessors + * + * Copyright(C) 2008, NXP Semiconductor + * All rights reserved. + * + * History + * 2008.07.19 ver 1.00 Preliminary version, first Release + * +******************************************************************************/ +#include "LPC13xx.h" /* LPC13xx definitions */ +#include "../gpio/gpio.h" +#include "ssp.h" +#if SSP_DEBUG +#include "uart.h" +#endif + +/***************************************************************************** +** Function name: LoopbackTest +** +** Descriptions: Loopback test +** +** parameters: None +** Returned value: None +** +*****************************************************************************/ +void LoopbackTest( uint8_t* src_addr, uint8_t* dest_addr ) +{ + uint32_t i; + +#if !USE_CS + /* Set SSEL pin to output low. */ + GPIOSetValue( PORT0, 2, 0 ); +#endif + i = 0; + while ( i <= SSP_BUFSIZE ) + { + /* to check the RXIM and TXIM interrupt, I send a block data at one time + based on the FIFOSIZE(8). */ + SSPSend( (uint8_t *)&src_addr[i], FIFOSIZE ); + /* If RX interrupt is enabled, below receive routine can be + also handled inside the ISR. */ + SSPReceive( (uint8_t *)&dest_addr[i], FIFOSIZE ); + i += FIFOSIZE; + } +#if !USE_CS + /* Set SSEL pin to output high. */ + GPIOSetValue( PORT0, 2, 1 ); +#endif + + /* verifying write and read data buffer. */ + for ( i = 0; i < SSP_BUFSIZE; i++ ) + { + if ( src_addr[i] != dest_addr[i] ) + { + while( 1 ); /* Verification failed */ + } + } + return; +} + +/***************************************************************************** +** Function name: SEEPROMTest +** +** Descriptions: Serial EEPROM(Atmel 25xxx) test +** +** parameters: None +** Returned value: None +** +*****************************************************************************/ +void SEEPROMTest( uint8_t* src_addr, uint8_t* dest_addr ) +{ + uint32_t i, timeout; +#if SSP_DEBUG + uint8_t temp[2]; +#endif + + LPC_IOCON->PIO0_2 &= ~0x07; /* SSP SSEL is a GPIO pin */ + GPIOSetValue( PORT0, 2, 1 ); + /* port0, bit 2 is set to GPIO output and high */ + GPIOSetDir( PORT0, 2, 1 ); + + GPIOSetValue( PORT0, 2, 0 ); + /* Test Atmel 25016 SPI SEEPROM. */ + src_addr[0] = WREN; /* set write enable latch */ + SSPSend( (uint8_t *)src_addr, 1 ); + GPIOSetValue( PORT0, 2, 1 ); + + for ( i = 0; i < DELAY_COUNT; i++ ); /* delay minimum 250ns */ + + GPIOSetValue( PORT0, 2, 0 ); + src_addr[0] = RDSR; /* check status to see if write enabled is latched */ + SSPSend( (uint8_t *)src_addr, 1 ); + SSPReceive( (uint8_t *)dest_addr, 1 ); + GPIOSetValue( PORT0, 2, 1 ); + if ( (dest_addr[0] & (RDSR_WEN|RDSR_RDY)) != RDSR_WEN ) + /* bit 0 to 0 is ready, bit 1 to 1 is write enable */ + { + while ( 1 ); + } + + for ( i = 0; i < SSP_BUFSIZE; i++ ) /* Init RD and WR buffer */ + { + src_addr[i+3] = i; /* leave three bytes for cmd and offset(16 bits) */ + dest_addr[i] = 0; + } + + /* please note the first two bytes of WR and RD buffer is used for + commands and offset, so only 2 through SSP_BUFSIZE is used for data read, + write, and comparison. */ + GPIOSetValue( PORT0, 2, 0 ); + src_addr[0] = WRITE; /* Write command is 0x02, low 256 bytes only */ + src_addr[1] = 0x00; /* write address offset MSB is 0x00 */ + src_addr[2] = 0x00; /* write address offset LSB is 0x00 */ + SSPSend( (uint8_t *)src_addr, SSP_BUFSIZE ); + GPIOSetValue( PORT0, 2, 1 ); + + for ( i = 0; i < 0x30000; i++ ); /* delay, minimum 3ms */ + + timeout = 0; + while ( timeout < MAX_TIMEOUT ) + { + GPIOSetValue( PORT0, 2, 0 ); + src_addr[0] = RDSR; /* check status to see if write cycle is done or not */ + SSPSend( (uint8_t *)src_addr, 1); + SSPReceive( (uint8_t *)dest_addr, 1 ); + GPIOSetValue( PORT0, 2, 1 ); + if ( (dest_addr[0] & RDSR_RDY) == 0x00 ) /* bit 0 to 0 is ready */ + { + break; + } + timeout++; + } + if ( timeout == MAX_TIMEOUT ) + { + while ( 1 ); + } + + for ( i = 0; i < DELAY_COUNT; i++ ); /* delay, minimum 250ns */ + + GPIOSetValue( PORT0, 2, 0 ); + src_addr[0] = READ; /* Read command is 0x03, low 256 bytes only */ + src_addr[1] = 0x00; /* Read address offset MSB is 0x00 */ + src_addr[2] = 0x00; /* Read address offset LSB is 0x00 */ + SSPSend( (uint8_t *)src_addr, 3 ); + SSPReceive( (uint8_t *)&dest_addr[3], SSP_BUFSIZE-3 ); + GPIOSetValue( PORT0, 2, 1 ); + + /* verifying, ignore the difference in the first two bytes */ + for ( i = 3; i < SSP_BUFSIZE; i++ ) + { + if ( src_addr[i] != dest_addr[i] ) + { +#if SSP_DEBUG + temp[0] = (dest_addr[i] & 0xF0) >> 4; + if ( (temp[0] >= 0) && (temp[0] <= 9) ) + { + temp[0] += 0x30; + } + else + { + temp[0] -= 0x0A; + temp[0] += 0x41; + } + temp[1] = dest_addr[i] & 0x0F; + if ( (temp[1] >= 0) && (temp[1] <= 9) ) + { + temp[1] += 0x30; + } + else + { + temp[1] -= 0x0A; + temp[1] += 0x41; + } + UARTSend((uint8_t *)&temp[0], 2); + UARTSend("\r\n", 2); +#endif + while( 1 ); /* Verification failed */ + } + } +#if SSP_DEBUG + UARTSend("PASS\r\n", 6); +#endif + return; +} + +/****************************************************************************** +** End Of File +******************************************************************************/ + diff --git a/software/mpu/src/uart/uart.c b/software/mpu/src/uart/uart.c new file mode 100644 index 0000000..b07b3d3 --- /dev/null +++ b/software/mpu/src/uart/uart.c @@ -0,0 +1,189 @@ +/***************************************************************************** + * uart.c: UART API file for NXP LPC13xx Family Microprocessors + * + * Copyright(C) 2008, NXP Semiconductor + * All rights reserved. + * + * History + * 2008.08.21 ver 1.00 Preliminary version, first Release + * +******************************************************************************/ +#include "LPC13xx.h" +#include "uart.h" + +// CodeRed - change for CMSIS 1.3 +#define SystemFrequency SystemCoreClock + +volatile uint32_t UARTStatus; +volatile uint8_t UARTTxEmpty = 1; +volatile uint8_t UARTBuffer[BUFSIZE]; +volatile uint32_t UARTCount = 0; + +/***************************************************************************** +** Function name: UART_IRQHandler +** +** Descriptions: UART interrupt handler +** +** parameters: None +** Returned value: None +** +*****************************************************************************/ +void UART_IRQHandler(void) +{ + uint8_t IIRValue, LSRValue; + uint8_t Dummy = Dummy; + + IIRValue = LPC_UART->IIR; + + IIRValue >>= 1; /* skip pending bit in IIR */ + IIRValue &= 0x07; /* check bit 1~3, interrupt identification */ + if (IIRValue == IIR_RLS) /* Receive Line Status */ + { + LSRValue = LPC_UART->LSR; + /* Receive Line Status */ + if (LSRValue & (LSR_OE | LSR_PE | LSR_FE | LSR_RXFE | LSR_BI)) + { + /* There are errors or break interrupt */ + /* Read LSR will clear the interrupt */ + UARTStatus = LSRValue; + Dummy = LPC_UART->RBR; /* Dummy read on RX to clear + interrupt, then bail out */ + return; + } + if (LSRValue & LSR_RDR) /* Receive Data Ready */ + { + /* If no error on RLS, normal ready, save into the data buffer. */ + /* Note: read RBR will clear the interrupt */ + UARTBuffer[UARTCount++] = LPC_UART->RBR; + if (UARTCount == BUFSIZE) + { + UARTCount = 0; /* buffer overflow */ + } + } + } + else if (IIRValue == IIR_RDA) /* Receive Data Available */ + { + /* Receive Data Available */ + UARTBuffer[UARTCount++] = LPC_UART->RBR; + if (UARTCount == BUFSIZE) + { + UARTCount = 0; /* buffer overflow */ + } + } + else if (IIRValue == IIR_CTI) /* Character timeout indicator */ + { + /* Character Time-out indicator */ + UARTStatus |= 0x100; /* Bit 9 as the CTI error */ + } + else if (IIRValue == IIR_THRE) /* THRE, transmit holding register empty */ + { + /* THRE interrupt */ + LSRValue = LPC_UART->LSR; /* Check status in the LSR to see if + valid data in U0THR or not */ + if (LSRValue & LSR_THRE) + { + UARTTxEmpty = 1; + } + else + { + UARTTxEmpty = 0; + } + } + return; +} + + + +/***************************************************************************** +** Function name: UARTInit +** +** Descriptions: Initialize UART0 port, setup pin select, +** clock, parity, stop bits, FIFO, etc. +** +** parameters: UART baudrate +** Returned value: None +** +*****************************************************************************/ +void UARTInit(uint32_t baudrate) +{ + uint32_t Fdiv; + uint32_t regVal; + + UARTTxEmpty = 1; + UARTCount = 0; + + NVIC_DisableIRQ(UART_IRQn); + + LPC_IOCON->PIO1_6 &= ~0x07; /* UART I/O config */ + LPC_IOCON->PIO1_6 |= 0x01; /* UART RXD */ + LPC_IOCON->PIO1_7 &= ~0x07; + LPC_IOCON->PIO1_7 |= 0x01; /* UART TXD */ + /* Enable UART clock */ + LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12); + LPC_SYSCON->UARTCLKDIV = 0x1; /* divided by 1 */ + + LPC_UART->LCR = 0x83; /* 8 bits, no Parity, 1 Stop bit */ + regVal = LPC_SYSCON->UARTCLKDIV; + Fdiv = (((SystemFrequency/LPC_SYSCON->SYSAHBCLKDIV)/regVal)/16)/baudrate ; /*baud rate */ + + LPC_UART->DLM = Fdiv / 256; + LPC_UART->DLL = Fdiv % 256; + LPC_UART->LCR = 0x03; /* DLAB = 0 */ + LPC_UART->FCR = 0x07; /* Enable and reset TX and RX FIFO. */ + + /* Read to clear the line status. */ + regVal = LPC_UART->LSR; + + /* Ensure a clean start, no data in either TX or RX FIFO. */ +// CodeRed - added parentheses around comparison in operand of & + while (( LPC_UART->LSR & (LSR_THRE|LSR_TEMT)) != (LSR_THRE|LSR_TEMT) ); + while ( LPC_UART->LSR & LSR_RDR ) + { + regVal = LPC_UART->RBR; /* Dump data from RX FIFO */ + } + + /* Enable the UART Interrupt */ + NVIC_EnableIRQ(UART_IRQn); + +#if TX_INTERRUPT + LPC_UART->IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART interrupt */ +#else + LPC_UART->IER = IER_RBR | IER_RLS; /* Enable UART interrupt */ +#endif + return; +} + +/***************************************************************************** +** Function name: UARTSend +** +** Descriptions: Send a block of data to the UART 0 port based +** on the data length +** +** parameters: buffer pointer, and data length +** Returned value: None +** +*****************************************************************************/ +void UARTSend(uint8_t *BufferPtr, uint32_t Length) +{ + + while ( Length != 0 ) + { + /* THRE status, contain valid data */ +#if !TX_INTERRUPT + while ( !(LPC_UART->LSR & LSR_THRE) ); + LPC_UART->THR = *BufferPtr; +#else + /* Below flag is set inside the interrupt handler when THRE occurs. */ + while ( !(UARTTxEmpty & 0x01) ); + LPC_UART->THR = *BufferPtr; + UARTTxEmpty = 0; /* not empty in the THR until it shifts out */ +#endif + BufferPtr++; + Length--; + } + return; +} + +/****************************************************************************** +** End Of File +******************************************************************************/ diff --git a/software/mpu/src/uart/uart.h b/software/mpu/src/uart/uart.h new file mode 100644 index 0000000..d729be8 --- /dev/null +++ b/software/mpu/src/uart/uart.h @@ -0,0 +1,55 @@ +/***************************************************************************** + * uart.h: Header file for NXP LPC13xx Family Microprocessors + * + * Copyright(C) 2008, NXP Semiconductor + * All rights reserved. + * + * History + * 2008.08.21 ver 1.00 Preliminary version, first Release + * +******************************************************************************/ +#ifndef __UART_H +#define __UART_H + + +#define RS485_ENABLED 0 +#define TX_INTERRUPT 0 /* 0 if TX uses polling, 1 interrupt driven. */ + +#define IER_RBR 0x01 +#define IER_THRE 0x02 +#define IER_RLS 0x04 + +#define IIR_PEND 0x01 +#define IIR_RLS 0x03 +#define IIR_RDA 0x02 +#define IIR_CTI 0x06 +#define IIR_THRE 0x01 + +#define LSR_RDR 0x01 +#define LSR_OE 0x02 +#define LSR_PE 0x04 +#define LSR_FE 0x08 +#define LSR_BI 0x10 +#define LSR_THRE 0x20 +#define LSR_TEMT 0x40 +#define LSR_RXFE 0x80 + +#define BUFSIZE 0x40 + +/* RS485 mode definition. */ +#define RS485_NMMEN (0x1<<0) +#define RS485_RXDIS (0x1<<1) +#define RS485_AADEN (0x1<<2) +#define RS485_SEL (0x1<<3) +#define RS485_DCTRL (0x1<<4) +#define RS485_OINV (0x1<<5) + + +void UARTInit(uint32_t Baudrate); +void UART_IRQHandler(void); +void UARTSend(uint8_t *BufferPtr, uint32_t Length); + +#endif /* end __UART_H */ +/***************************************************************************** +** End Of File +******************************************************************************/ -- cgit v1.2.3