EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Introduction to Lpc2000 needed.

Started by Senkumba Edwin February 6, 2008
>> Kids these days... Why, I remember when we had to program in 1's and
>> 0's, and we were lucky, lucky! I say to have the 0's!
>
> Gee, I thought the 1's were already provided for you when you erased
> the flash ! DoH !!

boB, I think jc was referring to 'programming' in the
sense of punching holes in Hollerith cards ...

http://en.wikipedia.org/wiki/Hollerith_cards

I suspect there was no flash way back when jc was a kid,
and had to walk uphill, through snow, to school ... both ways

:)

Dave

An Engineer's Guide to the LPC2100 Series

----- Original Message -----
From: "rtstofer"
To:
Sent: Saturday, February 09, 2008 11:20 PM
Subject: [lpc2000] Re: Introduction to Lpc2000 needed.
> --- In l..., "J.C. Wren" wrote:
>>
>> You had Hollerith cards? Lucky dog...
>>
>> --jc
>
> Sure, on the IBM 1130 and CDC 6600! But my Altair 8800 didn't have an
> EPROM bootloader for a year or so after I bought it. Toggle in the
> boot code for the paper tape reader (or audio cassette tape) and watch
> the LEDs blink and flash.
>
> Use the paper tape assembler to write the BIOS for CP/M, design and
> wire-wrap the FDC controller, write the image to a new 8" floppy and
> the rest is history!
>
> My current retro project is to take a Zilog EZ80Acclaim ZDOTS board
> http://www.zilog.com/products/partdetails.asp?id=eZ80F917050SBCG, build
> a PCB daughter board with a compact flash device and run CP/M on a 50
> MHz Z80. The whole thing will be about the size of a deck of playing
> cards.
>
> Last week, just for giggles, I got Palo Alto Tiny Basic running on the
> board. Pretty neat! I have been giving thought to enhancing it as
> a 'bot controller that is its' own development platform. Simple to
> program, completely flexible!

I remember giving a friend of mine who had built an S100 CP/M system the DDJ
listing of that BASIC interpreter, he keyed all the hex code in by hand and
got it working.

Leon
You had Hollerith cards? Lucky dog...

--jc

On Feb 9, 2008 2:55 PM, rtstofer wrote:
> --- In l..., David Hawkins wrote:
> >
> >
> >
> > >> Kids these days... Why, I remember when we had to program in
> 1's and
> > >> 0's, and we were lucky, lucky! I say to have the 0's!
> > >
> > > Gee, I thought the 1's were already provided for you when you
> erased
> > > the flash ! DoH !!
> >
> > boB, I think jc was referring to 'programming' in the
> > sense of punching holes in Hollerith cards ...
> >
> > http://en.wikipedia.org/wiki/Hollerith_cards
> >
> > I suspect there was no flash way back when jc was a kid,
> > and had to walk uphill, through snow, to school ... both ways
> >
> > :)
> >
> > Dave
> > I did it too! But I also had to carry the box of cards and the
> Fortran manual! Then add the printouts on the way back.
>
> Richard
>
>
Hi Fabio,
thanks for the helpful code, especially the IAP functions.

I have been using them, but found one problem in the following code:

#define ADDR_FLASH_BASEADDR 0x00010000

...
FlashWriteString(ADDR_FLASH_BASEADDR + 0x0400, "This is test");
FlashWriteByte(ADDR_FLASH_BASEADDR, -1);

FlashWriteString(ADDR_FLASH_BASEADDR + 0x0404, "This is test");
FlashWriteByte(ADDR_FLASH_BASEADDR, -1);
...
FlashWriteString simply calls FlashWriteByte() in a loop.

When I examine the Flash memory contents, I can see the following dump
starting at location 00010400:

00010400 54686973006861202061732000657374 This.ha as .est
00010410 00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ................
Does anyone have any idea why the result memory does not look like:

"ThisThis is a test"

Best regards,
Niksa

--- In l..., "Fabio Filippa" wrote:
>
> Hi mate,
> also I'm started some months ago with a new design based on LPC2106 and
> also my background was with PIC microcontrolloer
> programmed ASM and C. I've found no more help on books or forum and all
> I've do is just from my personal search and test, all the code
> provided below is stripped from a my personal written working
> application. I know that may be useful or not but this is what I've
> liked
> to see when I've started on working with this microcontroller and I've
> not found from anyone and anywhere, this the reason why I've decided
> to write this mini and not very well completed tutorial about this
> stuff. I know write this is a matter of time, but I'm for free
> opensource knowledge
> (not for opensource production project but for sharing the knowledge
> needed to build your own application :-)).
> I hope that thsi can be useful is some way, anyway I can write more
> detaild tutorial on solution and how to implement other stuff, also can
> be
> nice if other more skilled peple like to partecipate in a cook book
> writing for sharing their experience, this can be viewed as a my first
> starting contribute
> then don't shoot to the pianist please :-).
>
> Well as I written I can just spoke about my personal experience, I've
> started with the IAR Kickstart kit for LPC2106 and code my application
> in C language,
> most of the code was a simple porting from Microchip (Hi-Tech compiler)
> to the IAR system.
>
> In order to start you can use the IAR example (I remember this is named
> flashligth or somethings of similar), using this example you've all the
> scheleton for build a
> working application, you have just to write your code and make the
> integration for the interrupt handling.
>
> As used libray I've set:
>
> #include
> #include
> #include
> #include
> #include // registry definition
> #include "timer.h"
> #include "lpc210x.h"
> #include "io_macros.h"
> #include "Flash_usage.h" // Used to manage the Flash as EEPROM, see
> below to understand how to do it
> #include "math.h"
>
> ....
>
> I've written two interrupt function to manage the USART1, this ones was
> called USART1_rx and
> USART1_tx, here the function prototype:
>
> void USART1_rx(unsigned char);
> // USART1 (irq): callback function per RX
> void USART1_tx(void);
> // USART1 (irq): callback function per TX
>
> and the code for each function:
>
> void USART1_rx(unsigned char rxbyte)
> {
>
> asm("NOP");
> asm("NOP");
>
> SerRx = rxbyte; // read the data into the SerRx variable
>
> // Put your rx code here and when a valid command
> // is recognized set the rsFlag to 1, use this into the
> // main() routine to know when we've a valid command to process,
> // usually I set the process task at the end of the main cycle.
>
> return;
> }
>
> void USART1_tx(void)
> {
>
> asm("NOP");
> asm("NOP");
>
> // Put your tx code here
>
> return;
> }
>
> into the main() function you have to init the interrupt vector by using
> this provided function:
>
> LPC210xInitUART1Interrupt(USART1_rx, USART1_tx); // Init the callback
> function for use the USART1
>
> Of course I've implemented reading and transmitting over the serial port
> with interrupt, last question is how I can send data byte over
> the serial port with interrupt? Well more simple, I've just defined two
> buffer used in rx and tx and other useful variable:
>
> unsigned char SerRx; // USART1: char from rx
> unsigned char RxCtr; // USART1: counter of rx chars
> unsigned char TxCtr; // USART1: counter of tx chars
> unsigned char TxMaxChr; // USART1: maximum allowed rx char for
> preventing overflow
> unsigned char SerialBufferRx[MAXSERBUF]; // USART1: rx buffer
> unsigned char SerialBufferTx[MAXSERBUF]; // USART1: tx buffer
> unsigned char rsFlag; // USART1: flag used to signal into the main a
> valid received command
>
> .....
>
> The main things now is how I can transmit over serial port by using the
> interrupt feature, well is more simple, here my full code for
> the TX routine:
>
> void USART1_tx(void)
> {
>
> asm("NOP");
> asm("NOP");
>
> while(U1LSR_bit.THRE == 1)
> {
> if (TxMaxChr > 0)
> {
> if ((TxCtr + 1) > TxMaxChr) // Check if I've
> trasmitted all the char into the TX buffer
> {
> U1IER_bit.THREIE = 0; // reset the TX interrupt
> TxCtr = 0; // reset the
> trasmitting counter
> TxMaxChr = 0; // reset the total
> char counter that I've to be trasmitted
> }
> else
> {
> U1THR = SerialBufferTx[TxCtr]; // Send a char from
> the TX buffer
> TxCtr = TxCtr + 1; // Update the
> buffer pointer for the next char that has to be sended
> }
> }
> else
> break; // end of the while
> }
> return;
> }
>
> and also you've to use the following code to charge the buffer and start
> the TX with the interrupt (suppose to send the *OK*
> chars sequence):
>
> SerialBufferTx[0] = '*'; // First char to send
> SerialBufferTx[1] = 'O'
> SerialBufferTx[2] = 'K';
> SerialBufferTx[3] = '*'; // Last char to send
> TxMaxChr = 4; // Max number of chars to send
> TxCtr = 1; // Sended chars counter, set to 1 because
> the first char is sended now to activate the IRQ
>
> U1FCR_bit.TFR = 1; // Reset the UART1 FIFO TX
> swithout send any char
> U1THR = SerialBufferTx[0]; // Send the first chart, the
> others will be send automatically with the interrupt code
> U1IER_bit.THREIE = 1; // Enable the TX interrupt
>
> that's all, I've working hard to found this solutions and now this work
> very nicely witout trouble over all the production device, of course
> what you've to do
> is made your personal communication protocol (code has to be written
> into the USART1_rx function), and then you can write at the end of the
> microcontroller main
> loop into the main() function your command handler like below:
>
> void main() void
> {
> // Put here your code initialization, PLL, interrupt and so on
> ....
>
> // main working loop (infinite loop to keep alive the
> microcontroller)
> while(1)
> {
> // Write here your application code
>
> ....................................................................
>
> // Serial command handler
> if (rsFlag)
> {
> // Because the rsFlag is equal to 1 I've received a
> command
> // trough the serial port. Put your code here if the
> command is simple or
> // for better readability and coding style put all
> into a
> // dedicated function before the main().
>
>
> ....................................................................
>
> // End of the serial code processing
> rsFlag = 0;
> RxCtr = 0;
> for (index = 0; index < MAXSERBUF; index++) // RX
> buffer cleaning for next command
> SerialBufferRx[index]= '\0';
> }
> }
> }
>
> I think this is enough for now about the serial stuff.
>
>
> -------------------
> HOW TO SET THE PIN FUNCTION, DIRECTION AND STATE
>
> ------------------
> Some pin exibits multiple functions then you've to select what is the
> pin behaviour, this task can be achieved by using the
> PINSEL0 and PINSEL1 command like below:
>
> PINSEL0 = 0x50000; // Set the UART1 pins
> PINSEL1 = 0x00; //
>
> of course take a look on the LPC2106 datasheet in order to know what is
> the settings to do for other pins, in my application I've used the
> default one (0x00 for every line) and
> changed just the pin function to enable the USART 1.
>
> Into the PIC you've a bsf and bcf assembly instruction to set and clear
> a bit status, into the IAR C language set and clear and direction type
> was performed
> by using separate command, look at the following code to see how to do
> it:
>
> #define OUTPUT_TYPE 1
> #define INPUT_TYPE 0
>
> IODIR_bit.P0_4 = OUTPUT_TYPE; // Set the PO_4 line as output
>
> IOCLR_bit.P0_4 = 1; // Set the P0_4 value to 0 (0V)
> IOSET_bit.P0_4 = 1; // Set the PO_4 value to 1 (approx 3.3 V)
>
> Another example about set the line as input:
>
> IODIR_bit.P0_16 = INPUT_TYPE; // Set the PO_16 line as input
>
> to read the status of the PO_16 line configured as input write for
> example:
>
> if (IOPIN_bit.P0_16 == 0)
> {
> // make somethings if the PO_16 line has a low level applied
> }
>
>
>
> HOW TO USE THE FLASH MEMORY AS A INTERNAL EEPROM
>
>
> This is about pin settings, another issue is about the absence of the
> EEPROM memory like into the PIC one.
> As a workaround you can use some flash sector (I've used the block 14)
> in order to simulate the EEPROM behaviour, what I've did was
> read in a buffer the entire sector, make the change into the sector,
> write back the entire sector. You've to make
> a copy of the sector in a buffer because writing is a sector based
> operation.
> To do this I've make some change to a existent code and now the read and
> write operation is simple as into the PIC because
> all the needed stuff was performed under the hood.
>
> Here is the code that you've to put in a source file with name
> Flash_usage.c:
>
> // -------------- START OF THE CODE (Flash_usage.c)
> #include
> #include
> #include // For interrupt macro
> #include "Flash_usage.h"
>
> typedef struct SLayout {
> int sectors;
> int size;
> } Layout;
>
> static IAP iap_entry = (IAP)kIAPentry; // MCU flash firmware
> interface function.
> static unsigned long sectorbuf[WRITE_SIZE/4]; // The sector buffer must
> be word aligned.
> // The CPU clock speed (CCLK), the default value is used if no clock
> option is found.
> static int clock = CCLK;
>
> //
> // Returns the flash sector number for a given flash address.
> // Returns -1 if the address is outside the flash.
> //
>
> int CalculateSector(unsigned long addr, int *erase_sector)
> {
> int i;
> int j;
> int sector = 0;
> unsigned long current = 0;
>
> *erase_sector = 0;
> for (i = 0; flashLayout[i].sectors; i++)
> {
> for (j = 0; j < flashLayout[i].sectors; j++)
> {
> if (addr < current + flashLayout[i].size)
> {
> if (addr < current + WRITE_SIZE)
> {
> *erase_sector = 1;
> }
> return sector;
> }
> sector++;
> current += flashLayout[i].size;
> }
> }
> return -1;
> }
>
> //
>
> // Execute a flash firmware command.
> //
>
> int ExecuteCommand(unsigned long* cmd, unsigned long* status)
> {
> int ret;
>
> for (;;)
> {
> iap_entry(cmd, status);
> ret = status[0];
> if (ret != STATUS_BUSY)
> {
> return ret;
> }
> // Try again if busy.
> }
> }
>
> //
>
> // Program a sector. The device allows fractions of a sector to be
> written.
> // dst - the flash address to start writing at.
> // src - the address of the data buffer to be written.
> // size - the number of bytes in the data buffer to write.
> //
>
> unsigned char ProgramFlash(unsigned long dst, unsigned long* src, int
> size)
> {
> int i;
> int ret;
> int sector;
> int erase_sector;
> unsigned long sum;
> unsigned long cmd[6];
> unsigned long status[3];
>
> // User Flash mode
> MEMMAP = 1;
>
> // Disabilita interrupt
> __disable_interrupt();
>
> // Round up size to nearest allowable write size.
> for (i = 0; allowedWriteSizes[i]; i++)
> {
> if (size <= allowedWriteSizes[i])
> {
> size = allowedWriteSizes[i];
> break;
> }
> }
>
> sector = CalculateSector(dst, &erase_sector);
>
> if (dst + size > FLASH_SIZE || sector == -1)
> {
> return(0);
> }
>
> // Check for first part of sector 0 and that a reset vector is
> present,
> // note that the buffer is initialized to all 1's.
> if (sector == 0 && erase_sector && src[0] != 0xffffffff)
> {
> // Calculate exception vector 0x14 if the sector is zero and a
> reset address is present.
> sum = src[0] + src[1] + src[2] + src[3] +
> src[4] + src[6] + src[7];
> src[5] = -sum; // Vector 0x14.
> }
>
> // Prepare sector for erase.
> cmd[0] = CMD_PREPARE_SECTORS;
> cmd[1] = sector;
> cmd[2] = sector;
> ret = ExecuteCommand(cmd, status);
>
> if (ret != STATUS_CMD_SUCCESS)
> {
> return(0);
> }
>
> if (erase_sector)
> {
> // Erase sector.
> cmd[0] = CMD_ERASE_SECTORS;
> cmd[1] = sector;
> cmd[2] = sector;
> cmd[3] = clock;
> ret = ExecuteCommand(cmd, status);
> if (ret != STATUS_CMD_SUCCESS)
> {
> return(0);
> }
> }
>
> // Prepare sector for write.
> cmd[0] = CMD_PREPARE_SECTORS;
> cmd[1] = sector;
> cmd[2] = sector;
> ret = ExecuteCommand(cmd, status);
> if (ret != STATUS_CMD_SUCCESS)
> {
> return(0);
> }
>
> // Program sector.
> cmd[0] = CMD_COPY_RAM_TO_FLASH;
> cmd[1] = dst;
> cmd[2] = (unsigned long)src;
> cmd[3] = size;
> cmd[4] = clock;
> ret = ExecuteCommand(cmd, status);
>
> if (ret != STATUS_CMD_SUCCESS)
> {
> return(0);
> }
>
> // Enable the interrupt
> __enable_interrupt();
>
> // All was fine
> return(1);
> }
>
> //
>
> // Write one byte to flash at addr.
> // The bytes are first buffered in sectorbuf, this array is at first
> // filled with the old flash data and then updated with the new one.
> // The sectorbuf is written to the flash when it overflows or when
> // he user call the routine with byte equal to -1.
> //
>
> void FlashWriteByte(unsigned long addr, int byte)
> {
> int i;
> int offset; // Current offset into sector
> buffer.
> static int bytes = 0; // Number of bytes in the
> sector buffer (including gaps).
> static int base_addr; // Pysical address of the
> start of the sector.
> unsigned long flashaddr = 0x0001C000; // First address block 14
>
> restart:
> if (bytes == 0) // First byte of a new sector.
> {
> // This is the first time that we try to write some byte
> // then we've to check for the total byte remainder
> // before reach the maximum size, then the data storage
> // buffer will be initialized.
> bytes = addr % WRITE_SIZE;
> base_addr = addr - bytes; // Calculate physical start address of
> this sector.
>
> // Intialize sector buffer with the pre-existent data to
> // preserve all the remainder data which is stored in Flash.
> // Size il WRITE_SIZE / 4 due to the fact that flashbyte is 32 bit
> in length
> for (i = 0; i < WRITE_SIZE/4; i++)
> {
> sectorbuf[i] =*((unsigned long*)flashaddr);
> flashaddr += 4;
> }
> }
>
> // Write sector buffer to the flash memory if a flush is requested
> (byte = -1)
> // or the new byte address is beyond the sector buffer.
> if (byte == -1 || addr - base_addr >= WRITE_SIZE)
> {
> ProgramFlash(base_addr, sectorbuf, bytes);
>
> if (byte == -1)
> {
> return; // This was a flush operation, all data is written.
> }
>
> // We've write the data which is pushed into the storage sectorbuf
> // then we can reset the byte count for future writing
> bytes = 0;
>
> goto restart;
> }
>
> // Store byte in sector buffer.
> offset = addr - base_addr;
> ((unsigned char*)sectorbuf)[offset] = (byte & 0x00FF);
> bytes = offset + 1;
>
> return;
> }
> // ---------------END OF THE CODE (Flash_usage.c)
>
> there is also some other code to put in a header file with name
> Flash_usage.h.
>
> // -------------- START OF THE CODE (Flash_usage.h)
> #define CCLK 14746
>
> // The write size is not critical to performance.
> // 512 bytes is a good size that leaves as much room to the JTAG
> // read buffer as possible and is supported by all flash devices.
> #define WRITE_SIZE 512
>
> #define kIAPentry 0x7ffffff1
>
> enum {
> CMD_PREPARE_SECTORS = 50,
> CMD_COPY_RAM_TO_FLASH,
> CMD_ERASE_SECTORS,
> CMD_BLANK_CHECK_SECTORS,
> CMD_READ_PART_ID,
> CMD_READ_BOOT_CODE_VERSION,
> CMD_COMPARE,
> };
>
> enum {
> STATUS_CMD_SUCCESS = 0,
> STATUS_INVALID_COMMAND,
> STATUS_SRC_ADDR_ERROR,
> STATUS_DST_ADDR_ERROR,
> STATUS_SRC_ADDR_NOT_MAPPED,
> STATUS_DST_ADDR_NOT_MAPPED,
> STATUS_COUNT_ERROR,
> STATUS_INVALID_SECTOR,
> STATUS_SECTOR_NOT_BLANK,
> STATUS_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION,
> STATUS_COMPARE_ERROR,
> STATUS_BUSY,
> };
>
> typedef void (__thumb *IAP)(void*, void*);
>
> // --------------------------
> // Function definition
> // --------------------------
> int ExecuteCommand(unsigned long* , unsigned long* );
> unsigned char ProgramFlash(unsigned long , unsigned long* , int );
> void FlashWriteByte(unsigned long , int );
> // ---------------END OF THE CODE (Flash_usage.h)
>
> From a pratical point of view using the Flash require to set a sort of
> memory map, I've do it with a set of define
> statements as below:
>
> // -----------------------
> // DEFINE FLASH section data (block 14)
> // -----------------------
> #define ADDR_FLASH_BASEADDR 0x0001C000 // FLASH: first useful
> address
> #define ADDR_CODE_HYBYTE 0x0001C000 // FLASH: param1 (hi byte)
> device code
> #define ADDR_CODE_LOBYTE 0x0001C004 // FLASH: param1 (lo byte)
> device code
> #define ADDR_ADDRESS_BYTE 0x0001C008 // FLASH: param2 (one byte)
> device address (0x00 to 0xFF)
> #define ADDR_POWERON_HYBYTE 0x0001C00C // FLASH: param3 (hi byte)
> power on counter
> #define ADDR_POWERON_LOBYTE 0x0001C010 // FLASH: param3 (lo byte)
> power on counter
> ....
>
> and below ther is a example how you can use the Flashing routine, in
> this example I simply read back the power on counter
> from the flash, update the value by 1 and write back the updated value
> into the Flash, I've used this code on the starting of the
> main() code then every power up I can update the counter and know if the
> device was powered and the number of the time.
>
> // ---------------------------
> // Read the power on register update and write back into the Flash
> // ---------------------------
> ulFlashAddress = (unsigned long)ADDR_POWERON_LOBYTE;
> lobyte = *((int*)ulFlashAddress) & 0x000000FF;
> ulFlashAddress = (unsigned long)ADDR_POWERON_HYBYTE;
> hybyte = *((int*)ulFlashAddress) & 0x000000FF;
> iNumberPowerOn = hybyte * 256 + lobyte;
> iNumberPowerOn += 1;
> lobyte = iNumberPowerOn & 0x000000FF;
> hybyte = ((iNumberPowerOn & 0x0000FF00) >> 8) & 0x000000FF;
>
> ulFlashAddress = (unsigned long)ADDR_POWERON_LOBYTE;
> FlashWriteByte(ulFlashAddress, lobyte);
> ulFlashAddress = (unsigned long)ADDR_POWERON_HYBYTE;
> FlashWriteByte(ulFlashAddress, hybyte);
>
> ulFlashAddress=(unsigned long)ADDR_FLASH_BASEADDR;
> FlashWriteByte(ulFlashAddress, -1); // Update the Flash
>
> ....
>
>
> -------
> SPEED ISSUE, CORE CLOCK, PERIPHERAL CLOCK
>
> -------
>
> I've changed the micro from PIC to ARM into my design mainly for speed
> issue, take in mind that you've a internal PLL that is usful to keep the
> microcontroller core working at the maximum available speed (60 MHz for
> the PLC2106).
> To achieve this goal you've to work around two stuff, the peripheral
> clock frequency and the internal PLL.
>
> The output peripheral speed is a new feature respect the PIC
> microncontroller, you can choose to update the output at the
> external clock or the core clock, for my issue I've to use the maximum
> speed the I've set the peripheral clock equal to core clock
> and this one can be done by writing this statements:
>
> VPBDIV = 0x01;
>
> Also to reach the maximum core clock you've to set properly the internal
> PLL, to do this use a external crystal of 14,7456 MHz + 30ppm
> with two capacitors of 18 pF and set the internal PLL to work at the
> maximum frequency with the code listed below:
>
> // ------------------
> // Set the internal PLL to work with a core clock of 60 MHz
> // with a external clock of 14.745 MHz.
> // M = 4, P = 2
> // ------------------
> PLLCFG = 0x23;
> PLLCON = 0x01;
> PLLFEED = 0xAA;
> PLLFEED = 0x55;
> while (!(PLLSTAT & 0x400)) {}
> PLLCON = 0x03;
> PLLFEED = 0xAA;
> PLLFEED = 0x55;
>
> Also there is another stuff to keep in mind, core clock and peripheral
> clock is set at the same value and also at the maximum
> available frequency (60 MHz) but you drive the output pin from the code
> and this one can be executed on Flash or RAM memory.
> If the code will be executed from Flash you have a limit from the Flash
> access time then you can't reach the maximum output frequency,
> to overcome this you've two choice, use the MAM (Memory Acceleration
> Module) module or simply get the code executed from the ram.
> MAM is a trick to execute code from ram but is not useful if you have
> jump over the code because the fetch queue has to be updated and then
> the speed is limited by Flash access, I've used the ram execution
> option, only drawback is the used memory, but you reach the goal by
> carefully
> choosing what code or function has to be executed from ram.
> To do this simply add the keyword __ramfunc before the function
> declaration (no need to add it also to the function code), here is one
> example
> how to use it:
>
> // Function prototipe
> __ramfunc signed int ReadInterface(void);
>
> .....
>
> // Function definition
> signed int ReadInterface(void)
> {
> .......
> return readed_value;
> }
>
>
> INTERRUPT HANDLING
>
> Also interrupt handling is simple but different than into the PIC
> microcontrollers, into the ARM architecture you've a
> interrupt vector that must be filled with the function address that will
> be called on the interrupt event.
>
>
> FINAL REMARKS
>
> If you need more specifical infos let me know I'll be happy helping you
> in starting, I know the difficult also when I've started
> with this new microcontroller family I've do all by myself then now I
> can share my little knowledge/experience to other...
> I'm for open source knowledge :-)
>
> Best regards
> Fabio Filippa
>
>
> -----Messaggio originale-----
> Da: Senkumba Edwin [mailto:eddouble86@...]
> Inviato: mercoled6 febbraio 2008 6.33
> A: l...
> Oggetto: [lpc2000] Introduction to Lpc2000 needed.
>
>
>
> Hello Everyone,
> I am new to the microcontroller and am trying to understand it, i was
> reading up on PIC ucontrollers before and the book i was reading
> emphasised on using Assembly language. I was recently advised to look at
> using the Philips lpc2148 to control an RC toy car (my first project)
> but i dont know much about the lpc2000 series and found out that it is
> programmed in C, so the information i got from the PIC book wont be of
> much help.
> All i know about microcontrollers is that they have a couple of GPIO
> (that would general purpose Inout and output right?) and that these IO's
> are connected to the ports inside (like PORTA and PORTB for the PIC16F54
> i was reading on). The ports are arranged in a file cabinet system with
> each cabinet being a file register. This file registers store
> information which is accessed (or moved aorund) using the working
> register.
> So far thats as much as i know regarding the PIC16F5x. I need to know if
> what i know could help me with the lpc2148 and where i could get more
> information. I would aslo like to know the basic programming
> instructions used with the ucontroller, though am not so strong at using
> the C language but i am working on that right now. Any help would be
> much appreciated, thank you.
>
> P.S A little more about myself, I am an Engineering Undergraduate. So
> all the above Information search is school based.
>
> Edwin.
>
> __________________________________________________________
> Looking for last minute shopping deals?
> Find them fast with Yahoo! Search. http://tools.
>
> search.yahoo.com/newsearch/category.php?category=shopping
>
>
>
>
>
>
>
>
>
>
>

> -----Original Message-----
> From: l...
> [mailto:l...]On Behalf
> Of niksaorlic
> Sent: Tuesday, June 03, 2008 12:03 PM
> To: l...
> Subject: Re: R: [lpc2000] Introduction to Lpc2000 needed.
> Hi Fabio,
> thanks for the helpful code, especially the IAP functions.
>
> I have been using them, but found one problem in the following code:
>
> #define ADDR_FLASH_BASEADDR 0x00010000
>
> ...
> FlashWriteString(ADDR_FLASH_BASEADDR + 0x0400, "This is test");
> FlashWriteByte(ADDR_FLASH_BASEADDR, -1);
>
> FlashWriteString(ADDR_FLASH_BASEADDR + 0x0404, "This is test");
> FlashWriteByte(ADDR_FLASH_BASEADDR, -1);
> ...
> FlashWriteString simply calls FlashWriteByte() in a loop.
>
> When I examine the Flash memory contents, I can see the following dump
> starting at location 00010400:
>
> 00010400 54686973006861202061732000657374 This.ha as .est
> 00010410 00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ................
> Does anyone have any idea why the result memory does not look like:
>
> "ThisThis is a test"
>
> Best regards,
> Niksa
>

Yes, because this is flash memory, not RAM. You can't write data
on top of unerased bytes. Especially on the LPC parts, as they
use CRC checking on the flash. You must erase a sector before
you can write data to it.

In short, what you are doing is not allowed.

Mike
Hello,

There is a really good book for getting started with the lpc microcontrollers. Its called "insiders guide". Its available on the internet for free (not printable).
You can download it from here:

http://www.hitex.co.uk/arm/lpc2000book/

Fernando



niksaorlic escribi
Hi Fabio,
thanks for the helpful code, especially the IAP functions.

I have been using them, but found one problem in the following code:

#define ADDR_FLASH_BASEADDR 0x00010000

...
FlashWriteString(ADDR_FLASH_BASEADDR + 0x0400, "This is test");
FlashWriteByte(ADDR_FLASH_BASEADDR, -1);

FlashWriteString(ADDR_FLASH_BASEADDR + 0x0404, "This is test");
FlashWriteByte(ADDR_FLASH_BASEADDR, -1);
...

FlashWriteString simply calls FlashWriteByte() in a loop.

When I examine the Flash memory contents, I can see the following dump
starting at location 00010400:

00010400 54686973006861202061732000657374 This.ha as .est
00010410 00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF ................

Does anyone have any idea why the result memory does not look like:

"ThisThis is a test"

Best regards,
Niksa

--- In l..., "Fabio Filippa" wrote:
>
> Hi mate,
> also I'm started some months ago with a new design based on LPC2106 and
> also my background was with PIC microcontrolloer
> programmed ASM and C. I've found no more help on books or forum and all
> I've do is just from my personal search and test, all the code
> provided below is stripped from a my personal written working
> application. I know that may be useful or not but this is what I've
> liked
> to see when I've started on working with this microcontroller and I've
> not found from anyone and anywhere, this the reason why I've decided
> to write this mini and not very well completed tutorial about this
> stuff. I know write this is a matter of time, but I'm for free
> opensource knowledge
> (not for opensource production project but for sharing the knowledge
> needed to build your own application :-)).
> I hope that thsi can be useful is some way, anyway I can write more
> detaild tutorial on solution and how to implement other stuff, also can
> be
> nice if other more skilled peple like to partecipate in a cook book
> writing for sharing their experience, this can be viewed as a my first
> starting contribute
> then don't shoot to the pianist please :-).
>
> Well as I written I can just spoke about my personal experience, I've
> started with the IAR Kickstart kit for LPC2106 and code my application
> in C language,
> most of the code was a simple porting from Microchip (Hi-Tech compiler)
> to the IAR system.
>
> In order to start you can use the IAR example (I remember this is named
> flashligth or somethings of similar), using this example you've all the
> scheleton for build a
> working application, you have just to write your code and make the
> integration for the interrupt handling.
>
> As used libray I've set:
>
> #include
> #include
> #include
> #include
> #include // registry definition
> #include "timer.h"
> #include "lpc210x.h"
> #include "io_macros.h"
> #include "Flash_usage.h" // Used to manage the Flash as EEPROM, see
> below to understand how to do it
> #include "math.h"
>
> ....
>
> I've written two interrupt function to manage the USART1, this ones was
> called USART1_rx and
> USART1_tx, here the function prototype:
>
> void USART1_rx(unsigned char);
> // USART1 (irq): callback function per RX
> void USART1_tx(void);
> // USART1 (irq): callback function per TX
>
> and the code for each function:
>
> void USART1_rx(unsigned char rxbyte)
> {
>
> asm("NOP");
> asm("NOP");
>
> SerRx = rxbyte; // read the data into the SerRx variable
>
> // Put your rx code here and when a valid command
> // is recognized set the rsFlag to 1, use this into the
> // main() routine to know when we've a valid command to process,
> // usually I set the process task at the end of the main cycle.
>
> return;
> }
>
> void USART1_tx(void)
> {
>
> asm("NOP");
> asm("NOP");
>
> // Put your tx code here
>
> return;
> }
>
> into the main() function you have to init the interrupt vector by using
> this provided function:
>
> LPC210xInitUART1Interrupt(USART1_rx, USART1_tx); // Init the callback
> function for use the USART1
>
> Of course I've implemented reading and transmitting over the serial port
> with interrupt, last question is how I can send data byte over
> the serial port with interrupt? Well more simple, I've just defined two
> buffer used in rx and tx and other useful variable:
>
> unsigned char SerRx; // USART1: char from rx
> unsigned char RxCtr; // USART1: counter of rx chars
> unsigned char TxCtr; // USART1: counter of tx chars
> unsigned char TxMaxChr; // USART1: maximum allowed rx char for
> preventing overflow
> unsigned char SerialBufferRx[MAXSERBUF]; // USART1: rx buffer
> unsigned char SerialBufferTx[MAXSERBUF]; // USART1: tx buffer
> unsigned char rsFlag; // USART1: flag used to signal into the main a
> valid received command
>
> .....
>
> The main things now is how I can transmit over serial port by using the
> interrupt feature, well is more simple, here my full code for
> the TX routine:
>
> void USART1_tx(void)
> {
>
> asm("NOP");
> asm("NOP");
>
> while(U1LSR_bit.THRE == 1)
> {
> if (TxMaxChr > 0)
> {
> if ((TxCtr + 1) > TxMaxChr) // Check if I've
> trasmitted all the char into the TX buffer
> {
> U1IER_bit.THREIE = 0; // reset the TX interrupt
> TxCtr = 0; // reset the
> trasmitting counter
> TxMaxChr = 0; // reset the total
> char counter that I've to be trasmitted
> }
> else
> {
> U1THR = SerialBufferTx[TxCtr]; // Send a char from
> the TX buffer
> TxCtr = TxCtr + 1; // Update the
> buffer pointer for the next char that has to be sended
> }
> }
> else
> break; // end of the while
> }
> return;
> }
>
> and also you've to use the following code to charge the buffer and start
> the TX with the interrupt (suppose to send the *OK*
> chars sequence):
>
> SerialBufferTx[0] = '*'; // First char to send
> SerialBufferTx[1] = 'O'
> SerialBufferTx[2] = 'K';
> SerialBufferTx[3] = '*'; // Last char to send
> TxMaxChr = 4; // Max number of chars to send
> TxCtr = 1; // Sended chars counter, set to 1 because
> the first char is sended now to activate the IRQ
>
> U1FCR_bit.TFR = 1; // Reset the UART1 FIFO TX
> swithout send any char
> U1THR = SerialBufferTx[0]; // Send the first chart, the
> others will be send automatically with the interrupt code
> U1IER_bit.THREIE = 1; // Enable the TX interrupt
>
> that's all, I've working hard to found this solutions and now this work
> very nicely witout trouble over all the production device, of course
> what you've to do
> is made your personal communication protocol (code has to be written
> into the USART1_rx function), and then you can write at the end of the
> microcontroller main
> loop into the main() function your command handler like below:
>
> void main() void
> {
> // Put here your code initialization, PLL, interrupt and so on
> ....
>
> // main working loop (infinite loop to keep alive the
> microcontroller)
> while(1)
> {
> // Write here your application code
>
> ....................................................................
>
> // Serial command handler
> if (rsFlag)
> {
> // Because the rsFlag is equal to 1 I've received a
> command
> // trough the serial port. Put your code here if the
> command is simple or
> // for better readability and coding style put all
> into a
> // dedicated function before the main().
>
>
> ....................................................................
>
> // End of the serial code processing
> rsFlag = 0;
> RxCtr = 0;
> for (index = 0; index < MAXSERBUF; index++) // RX
> buffer cleaning for next command
> SerialBufferRx[index]= '\0';
> }
> }
> }
>
> I think this is enough for now about the serial stuff.
>
> ----------------------
> -------------------
> HOW TO SET THE PIN FUNCTION, DIRECTION AND STATE
> ----------------------
> ------------------
> Some pin exibits multiple functions then you've to select what is the
> pin behaviour, this task can be achieved by using the
> PINSEL0 and PINSEL1 command like below:
>
> PINSEL0 = 0x50000; // Set the UART1 pins
> PINSEL1 = 0x00; //
>
> of course take a look on the LPC2106 datasheet in order to know what is
> the settings to do for other pins, in my application I've used the
> default one (0x00 for every line) and
> changed just the pin function to enable the USART 1.
>
> Into the PIC you've a bsf and bcf assembly instruction to set and clear
> a bit status, into the IAR C language set and clear and direction type
> was performed
> by using separate command, look at the following code to see how to do
> it:
>
> #define OUTPUT_TYPE 1
> #define INPUT_TYPE 0
>
> IODIR_bit.P0_4 = OUTPUT_TYPE; // Set the PO_4 line as output
>
> IOCLR_bit.P0_4 = 1; // Set the P0_4 value to 0 (0V)
> IOSET_bit.P0_4 = 1; // Set the PO_4 value to 1 (approx 3.3 V)
>
> Another example about set the line as input:
>
> IODIR_bit.P0_16 = INPUT_TYPE; // Set the PO_16 line as input
>
> to read the status of the PO_16 line configured as input write for
> example:
>
> if (IOPIN_bit.P0_16 == 0)
> {
> // make somethings if the PO_16 line has a low level applied
> }
>
> ----------------------
>
> HOW TO USE THE FLASH MEMORY AS A INTERNAL EEPROM
> ----------------------
>
> This is about pin settings, another issue is about the absence of the
> EEPROM memory like into the PIC one.
> As a workaround you can use some flash sector (I've used the block 14)
> in order to simulate the EEPROM behaviour, what I've did was
> read in a buffer the entire sector, make the change into the sector,
> write back the entire sector. You've to make
> a copy of the sector in a buffer because writing is a sector based
> operation.
> To do this I've make some change to a existent code and now the read and
> write operation is simple as into the PIC because
> all the needed stuff was performed under the hood.
>
> Here is the code that you've to put in a source file with name
> Flash_usage.c:
>
> // -------------- START OF THE CODE (Flash_usage.c)
> #include
> #include
> #include // For interrupt macro
> #include "Flash_usage.h"
>
> typedef struct SLayout {
> int sectors;
> int size;
> } Layout;
>
> static IAP iap_entry = (IAP)kIAPentry; // MCU flash firmware
> interface function.
> static unsigned long sectorbuf[WRITE_SIZE/4]; // The sector buffer must
> be word aligned.
> // The CPU clock speed (CCLK), the default value is used if no clock
> option is found.
> static int clock = CCLK;
>
> //----------------------
> // Returns the flash sector number for a given flash address.
> // Returns -1 if the address is outside the flash.
> //
> ----------------------
> int CalculateSector(unsigned long addr, int *erase_sector)
> {
> int i;
> int j;
> int sector = 0;
> unsigned long current = 0;
>
> *erase_sector = 0;
> for (i = 0; flashLayout[i].sectors; i++)
> {
> for (j = 0; j < flashLayout[i].sectors; j++)
> {
> if (addr < current + flashLayout[i].size)
> {
> if (addr < current + WRITE_SIZE)
> {
> *erase_sector = 1;
> }
> return sector;
> }
> sector++;
> current += flashLayout[i].size;
> }
> }
> return -1;
> }
>
> //
> ----------------------
> // Execute a flash firmware command.
> //
> ----------------------
> int ExecuteCommand(unsigned long* cmd, unsigned long* status)
> {
> int ret;
>
> for (;;)
> {
> iap_entry(cmd, status);
> ret = status[0];
> if (ret != STATUS_BUSY)
> {
> return ret;
> }
> // Try again if busy.
> }
> }
>
> //
> ----------------------
> // Program a sector. The device allows fractions of a sector to be
> written.
> // dst - the flash address to start writing at.
> // src - the address of the data buffer to be written.
> // size - the number of bytes in the data buffer to write.
> //
> ----------------------
> unsigned char ProgramFlash(unsigned long dst, unsigned long* src, int
> size)
> {
> int i;
> int ret;
> int sector;
> int erase_sector;
> unsigned long sum;
> unsigned long cmd[6];
> unsigned long status[3];
>
> // User Flash mode
> MEMMAP = 1;
>
> // Disabilita interrupt
> __disable_interrupt();
>
> // Round up size to nearest allowable write size.
> for (i = 0; allowedWriteSizes[i]; i++)
> {
> if (size <= allowedWriteSizes[i])
> {
> size = allowedWriteSizes[i];
> break;
> }
> }
>
> sector = CalculateSector(dst, &erase_sector);
>
> if (dst + size > FLASH_SIZE || sector == -1)
> {
> return(0);
> }
>
> // Check for first part of sector 0 and that a reset vector is
> present,
> // note that the buffer is initialized to all 1's.
> if (sector == 0 && erase_sector && src[0] != 0xffffffff)
> {
> // Calculate exception vector 0x14 if the sector is zero and a
> reset address is present.
> sum = src[0] + src[1] + src[2] + src[3] +
> src[4] + src[6] + src[7];
> src[5] = -sum; // Vector 0x14.
> }
>
> // Prepare sector for erase.
> cmd[0] = CMD_PREPARE_SECTORS;
> cmd[1] = sector;
> cmd[2] = sector;
> ret = ExecuteCommand(cmd, status);
>
> if (ret != STATUS_CMD_SUCCESS)
> {
> return(0);
> }
>
> if (erase_sector)
> {
> // Erase sector.
> cmd[0] = CMD_ERASE_SECTORS;
> cmd[1] = sector;
> cmd[2] = sector;
> cmd[3] = clock;
> ret = ExecuteCommand(cmd, status);
> if (ret != STATUS_CMD_SUCCESS)
> {
> return(0);
> }
> }
>
> // Prepare sector for write.
> cmd[0] = CMD_PREPARE_SECTORS;
> cmd[1] = sector;
> cmd[2] = sector;
> ret = ExecuteCommand(cmd, status);
> if (ret != STATUS_CMD_SUCCESS)
> {
> return(0);
> }
>
> // Program sector.
> cmd[0] = CMD_COPY_RAM_TO_FLASH;
> cmd[1] = dst;
> cmd[2] = (unsigned long)src;
> cmd[3] = size;
> cmd[4] = clock;
> ret = ExecuteCommand(cmd, status);
>
> if (ret != STATUS_CMD_SUCCESS)
> {
> return(0);
> }
>
> // Enable the interrupt
> __enable_interrupt();
>
> // All was fine
> return(1);
> }
>
> //
> ----------------------
> // Write one byte to flash at addr.
> // The bytes are first buffered in sectorbuf, this array is at first
> // filled with the old flash data and then updated with the new one.
> // The sectorbuf is written to the flash when it overflows or when
> // he user call the routine with byte equal to -1.
> //
> ----------------------
> void FlashWriteByte(unsigned long addr, int byte)
> {
> int i;
> int offset; // Current offset into sector
> buffer.
> static int bytes = 0; // Number of bytes in the
> sector buffer (including gaps).
> static int base_addr; // Pysical address of the
> start of the sector.
> unsigned long flashaddr = 0x0001C000; // First address block 14
>
> restart:
> if (bytes == 0) // First byte of a new sector.
> {
> // This is the first time that we try to write some byte
> // then we've to check for the total byte remainder
> // before reach the maximum size, then the data storage
> // buffer will be initialized.
> bytes = addr % WRITE_SIZE;
> base_addr = addr - bytes; // Calculate physical start address of
> this sector.
>
> // Intialize sector buffer with the pre-existent data to
> // preserve all the remainder data which is stored in Flash.
> // Size il WRITE_SIZE / 4 due to the fact that flashbyte is 32 bit
> in length
> for (i = 0; i < WRITE_SIZE/4; i++)
> {
> sectorbuf[i] =*((unsigned long*)flashaddr);
> flashaddr += 4;
> }
> }
>
> // Write sector buffer to the flash memory if a flush is requested
> (byte = -1)
> // or the new byte address is beyond the sector buffer.
> if (byte == -1 || addr - base_addr >= WRITE_SIZE)
> {
> ProgramFlash(base_addr, sectorbuf, bytes);
>
> if (byte == -1)
> {
> return; // This was a flush operation, all data is written.
> }
>
> // We've write the data which is pushed into the storage sectorbuf
> // then we can reset the byte count for future writing
> bytes = 0;
>
> goto restart;
> }
>
> // Store byte in sector buffer.
> offset = addr - base_addr;
> ((unsigned char*)sectorbuf)[offset] = (byte & 0x00FF);
> bytes = offset + 1;
>
> return;
> }
> // ---------------END OF THE CODE (Flash_usage.c)
>
> there is also some other code to put in a header file with name
> Flash_usage.h.
>
> // -------------- START OF THE CODE (Flash_usage.h)
> #define CCLK 14746
>
> // The write size is not critical to performance.
> // 512 bytes is a good size that leaves as much room to the JTAG
> // read buffer as possible and is supported by all flash devices.
> #define WRITE_SIZE 512
>
> #define kIAPentry 0x7ffffff1
>
> enum {
> CMD_PREPARE_SECTORS = 50,
> CMD_COPY_RAM_TO_FLASH,
> CMD_ERASE_SECTORS,
> CMD_BLANK_CHECK_SECTORS,
> CMD_READ_PART_ID,
> CMD_READ_BOOT_CODE_VERSION,
> CMD_COMPARE,
> };
>
> enum {
> STATUS_CMD_SUCCESS = 0,
> STATUS_INVALID_COMMAND,
> STATUS_SRC_ADDR_ERROR,
> STATUS_DST_ADDR_ERROR,
> STATUS_SRC_ADDR_NOT_MAPPED,
> STATUS_DST_ADDR_NOT_MAPPED,
> STATUS_COUNT_ERROR,
> STATUS_INVALID_SECTOR,
> STATUS_SECTOR_NOT_BLANK,
> STATUS_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION,
> STATUS_COMPARE_ERROR,
> STATUS_BUSY,
> };
>
> typedef void (__thumb *IAP)(void*, void*);
>
> // --------------------------
> // Function definition
> // --------------------------
> int ExecuteCommand(unsigned long* , unsigned long* );
> unsigned char ProgramFlash(unsigned long , unsigned long* , int );
> void FlashWriteByte(unsigned long , int );
> // ---------------END OF THE CODE (Flash_usage.h)
>
> From a pratical point of view using the Flash require to set a sort of
> memory map, I've do it with a set of define
> statements as below:
>
> // ----------------------
> // DEFINE FLASH section data (block 14)
> // ----------------------
> #define ADDR_FLASH_BASEADDR 0x0001C000 // FLASH: first useful
> address
> #define ADDR_CODE_HYBYTE 0x0001C000 // FLASH: param1 (hi byte)
> device code
> #define ADDR_CODE_LOBYTE 0x0001C004 // FLASH: param1 (lo byte)
> device code
> #define ADDR_ADDRESS_BYTE 0x0001C008 // FLASH: param2 (one byte)
> device address (0x00 to 0xFF)
> #define ADDR_POWERON_HYBYTE 0x0001C00C // FLASH: param3 (hi byte)
> power on counter
> #define ADDR_POWERON_LOBYTE 0x0001C010 // FLASH: param3 (lo byte)
> power on counter
> ....
>
> and below ther is a example how you can use the Flashing routine, in
> this example I simply read back the power on counter
> from the flash, update the value by 1 and write back the updated value
> into the Flash, I've used this code on the starting of the
> main() code then every power up I can update the counter and know if the
> device was powered and the number of the time.
>
> // ----------------------
> // Read the power on register update and write back into the Flash
> // ----------------------
> ulFlashAddress = (unsigned long)ADDR_POWERON_LOBYTE;
> lobyte = *((int*)ulFlashAddress) & 0x000000FF;
> ulFlashAddress = (unsigned long)ADDR_POWERON_HYBYTE;
> hybyte = *((int*)ulFlashAddress) & 0x000000FF;
> iNumberPowerOn = hybyte * 256 + lobyte;
> iNumberPowerOn += 1;
> lobyte = iNumberPowerOn & 0x000000FF;
> hybyte = ((iNumberPowerOn & 0x0000FF00) >> 8) & 0x000000FF;
>
> ulFlashAddress = (unsigned long)ADDR_POWERON_LOBYTE;
> FlashWriteByte(ulFlashAddress, lobyte);
> ulFlashAddress = (unsigned long)ADDR_POWERON_HYBYTE;
> FlashWriteByte(ulFlashAddress, hybyte);
>
> ulFlashAddress=(unsigned long)ADDR_FLASH_BASEADDR;
> FlashWriteByte(ulFlashAddress, -1); // Update the Flash
>
> ....
>
> ----------------------
> -------
> SPEED ISSUE, CORE CLOCK, PERIPHERAL CLOCK
> ----------------------
> -------
>
> I've changed the micro from PIC to ARM into my design mainly for speed
> issue, take in mind that you've a internal PLL that is usful to keep the
> microcontroller core working at the maximum available speed (60 MHz for
> the PLC2106).
> To achieve this goal you've to work around two stuff, the peripheral
> clock frequency and the internal PLL.
>
> The output peripheral speed is a new feature respect the PIC
> microncontroller, you can choose to update the output at the
> external clock or the core clock, for my issue I've to use the maximum
> speed the I've set the peripheral clock equal to core clock
> and this one can be done by writing this statements:
>
> VPBDIV = 0x01;
>
> Also to reach the maximum core clock you've to set properly the internal
> PLL, to do this use a external crystal of 14,7456 MHz + 30ppm
> with two capacitors of 18 pF and set the internal PLL to work at the
> maximum frequency with the code listed below:
>
> // ------------------
> // Set the internal PLL to work with a core clock of 60 MHz
> // with a external clock of 14.745 MHz.
> // M = 4, P = 2
> // ------------------
> PLLCFG = 0x23;
> PLLCON = 0x01;
> PLLFEED = 0xAA;
> PLLFEED = 0x55;
> while (!(PLLSTAT & 0x400)) {}
> PLLCON = 0x03;
> PLLFEED = 0xAA;
> PLLFEED = 0x55;
>
> Also there is another stuff to keep in mind, core clock and peripheral
> clock is set at the same value and also at the maximum
> available frequency (60 MHz) but you drive the output pin from the code
> and this one can be executed on Flash or RAM memory.
> If the code will be executed from Flash you have a limit from the Flash
> access time then you can't reach the maximum output frequency,
> to overcome this you've two choice, use the MAM (Memory Acceleration
> Module) module or simply get the code executed from the ram.
> MAM is a trick to execute code from ram but is not useful if you have
> jump over the code because the fetch queue has to be updated and then
> the speed is limited by Flash access, I've used the ram execution
> option, only drawback is the used memory, but you reach the goal by
> carefully
> choosing what code or function has to be executed from ram.
> To do this simply add the keyword __ramfunc before the function
> declaration (no need to add it also to the function code), here is one
> example
> how to use it:
>
> // Function prototipe
> __ramfunc signed int ReadInterface(void);
>
> .....
>
> // Function definition
> signed int ReadInterface(void)
> {
> .......
> return readed_value;
> }
>
>
> INTERRUPT HANDLING
>
> Also interrupt handling is simple but different than into the PIC
> microcontrollers, into the ARM architecture you've a
> interrupt vector that must be filled with the function address that will
> be called on the interrupt event.
>
>
> FINAL REMARKS
>
> If you need more specifical infos let me know I'll be happy helping you
> in starting, I know the difficult also when I've started
> with this new microcontroller family I've do all by myself then now I
> can share my little knowledge/experience to other...
> I'm for open source knowledge :-)
>
> Best regards
> Fabio Filippa
>
>
> -----Messaggio originale-----
> Da: Senkumba Edwin [mailto:eddouble86@...]
> Inviato: mercoled6 febbraio 2008 6.33
> A: l...
> Oggetto: [lpc2000] Introduction to Lpc2000 needed.
>
>
>
> Hello Everyone,
> I am new to the microcontroller and am trying to understand it, i was
> reading up on PIC ucontrollers before and the book i was reading
> emphasised on using Assembly language. I was recently advised to look at
> using the Philips lpc2148 to control an RC toy car (my first project)
> but i dont know much about the lpc2000 series and found out that it is
> programmed in C, so the information i got from the PIC book wont be of
> much help.
> All i know about microcontrollers is that they have a couple of GPIO
> (that would general purpose Inout and output right?) and that these IO's
> are connected to the ports inside (like PORTA and PORTB for the PIC16F54
> i was reading on). The ports are arranged in a file cabinet system with
> each cabinet being a file register. This file registers store
> information which is accessed (or moved aorund) using the working
> register.
> So far thats as much as i know regarding the PIC16F5x. I need to know if
> what i know could help me with the lpc2148 and where i could get more
> information. I would aslo like to know the basic programming
> instructions used with the ucontroller, though am not so strong at using
> the C language but i am working on that right now. Any help would be
> much appreciated, thank you.
>
> P.S A little more about myself, I am an Engineering Undergraduate. So
> all the above Information search is school based.
>
> Edwin.
>
> __________________________________________________________
> Looking for last minute shopping deals?
> Find them fast with Yahoo! Search. http://tools.
>
> search.yahoo.com/newsearch/category.php?category=shopping
>
>
>
>
>
>
>
>
>
>
>



__________________________________________________
Correo Yahoo!
Espacio para todos tus mensajes, antivirus y antispam gratis!
Abrtu cuenta ya! - http://correo.yahoo.com.ar



The 2024 Embedded Online Conference