Yahoo Groups archive

Lpc2000

Index last updated: 2026-04-28 23:31 UTC

Thread

Help w/ Interrupts

Help w/ Interrupts

2004-10-19 by peterburdine

I seem to be having this continuous problem with interrupts.  I can
seem to get time interrupts to work just fine, but I'm trying to get
the UART Tx interrupt and the I2C interrupt to work.  All it seems
that I ever get it to do is reset itself (as seen by the something
that is sent out repeated over and over again).  The strange thing is
that if I try and debug it with a JTAG interface, it does not reboot.
 In this code, the uart0 does not use the tx interrupt to send, it
just waits untill all data has been put in U0THR.

The reset appears to occur as soon as I enable the start bit in
I2CONSET [in i2c_txData()].  Code is written and compiled using Keil's
tools v3.05.

Here is my I2C code, is there something obvious?  I'd appreciate any
help on this.

Assembly for enabling/disabling ARM IRQs
	IRQ_MASK	EQU		0x80
	FIQ_MASK	EQU		0x40

AREA	ArmIRQs, CODE, READONLY

PUBLIC disableArmIRQ?A
disableArmIRQ?A	PROC	CODE32
	MRS		R0,			CPSR
	ORR		R0,			R0,		#IRQ_MASK
	MSR		CPSR_cxfs,	R0
	MOV		PC,			LR
ENDP

PUBLIC enableArmIRQ?A
enableArmIRQ?A	PROC	CODE32
	MRS		R0,			CPSR
	BIC		R0,			R0,		#IRQ_MASK
	MSR		CPSR_cxfs,	R0
	MOV		PC,			LR	
ENDP


i2c.h
#ifndef _I2C_H
#define _I2C_H

/***** INCLUDES
**************************************************************/
#include "LPC2294.h"
#include "chipParams.h"
#include "types.h"

#ifdef ENABLE_I2C

/***** DEFINES 
**************************************************************/
/* I2C Interface */
#define I2CONSET       (*((volatile unsigned char *) 0xE001C000))
#define I2STAT         (*((volatile unsigned char *) 0xE001C004))
#define I2DAT          (*((volatile unsigned char *) 0xE001C008))
#define I2ADR          (*((volatile unsigned char *) 0xE001C00C))
#define I2SCLH         (*((volatile unsigned short*) 0xE001C010))
#define I2SCLL         (*((volatile unsigned short*) 0xE001C014))
#define I2CONCLR       (*((volatile unsigned char *) 0xE001C018))


#define ENABLE_I2C_PINS	( PINSEL0 = ((PINSEL0&0xFFFFFF0F) |
PINSEL0_02_SCL | PINSEL0_03_SDA ) )
#define ENABLE_I2C_IRQ  ( VICIntEnable = (0x1 << I2C_IRQ) )
#define DISABLE_I2C_IRQ ( VICIntEnClr  = (0x1 << I2C_IRQ) )
#define ENABLE_I2C_AA	( I2CONSET |= (0x1 << 2))
#define DISABLE_I2C_AA	( I2CONCLR = (0x1 << 2))
#define I2C_BIT_RATE(rate)  (I2SCLH = I2SCLL =
((Uint16)(PERIPH_FREQ/2/rate)+10))
#define I2C_SEND_START	(I2CONSET |= (0x1 << 5))
#define I2C_SEND_STOP	(I2CONCLR = (0x1 << 4))

#define I2C_BUFFER_LENGTH 		32
#define I2C_RX_BUFFER_LENGTH 	32

enum I2C_MODE { MASTER_TX,
				MASTER_RX,
				SLAVE_TX,
				SLAVE_RX };


extern enum I2C_MODE i2cMode;
extern Uint16	i2c_bytesRemaining;
extern Uint8 	i2c_address;
extern Uint8	i2c_RdnWr;
extern Uint8 	i2c_buffer[];
extern Uint8	i2c_sendStop;
extern Uint16	i2c_pos;
extern Uint8 	i2c_rxComplete;
extern Uint16	i2c_rxWrPos;
extern Uint8	i2c_rxBuffer[];
extern Uint8	i2c_rxBytesRemaining;

/***** FUNCTION PROTOTYPES
****************************************************/
void i2c_config(Uint32 bitRate);
void i2c_isr (void);
void i2c_txData(Uint8 address, Uint8 * buffer, Uint16 length, Uint8
sendStop);
void i2c_rxData(Uint8 * buffer, Uint16 length);

#endif // ENABLE_I2C
#endif // _I2C_H


i2c.c
#include "i2c.h"
#include "uart.h"

extern	disableArmIRQ(void);
extern	enableArmIRQ(void);
enum I2C_MODE i2cMode;
Uint16	i2c_bytesRemaining = 0;
Uint8 	i2c_address;
Uint8	i2c_RdnWr;
Uint8 	i2c_buffer[I2C_BUFFER_LENGTH];
Uint8	i2c_sendStop;
Uint16	i2c_pos;
Uint8 	i2c_rxComplete;
Uint16	i2c_rxWrPos;
Uint8	i2c_rxBuffer[I2C_RX_BUFFER_LENGTH];
Uint8	i2c_rxBytesRemaining;

void i2c_config(Uint32 bitRate) {
  	ENABLE_I2C_PINS;

  	//I2C_BIT_RATE(bitRate);
	I2SCLH = I2SCLL = 160;
  	
	// Reset Everything
	I2CONCLR = 0x6C;

 	disableArmIRQ();
  	VICIntSelect &= ~(0x1 << 9);	// Select as IRQ
	VICVectAddr9 = (unsigned long) i2c_isr;
  	VICVectCntl9 = 0x20 | 9;
  	VICIntEnable |= (0x1 << 9);
 	enableArmIRQ();

 	i2cMode = SLAVE_RX;
  	I2CONSET |= (0x1 << 6);	// Enable I2C
}

void i2c_txData(Uint8 address, Uint8 * buffer, Uint16 length, Uint8
sendStop) {
	Uint16 i;

 	i2c_bytesRemaining = length;
	DISABLE_I2C_AA;
 	for(i = 0; i < length; i++)
 		i2c_buffer[i] = *(buffer++);
 	i2c_sendStop = sendStop;
 	i2c_RdnWr = 0;
 	i2c_address = address;
	i2c_rxBytesRemaining = I2C_RX_BUFFER_LENGTH;
	i2c_rxWrPos = 0;
	i2c_rxComplete = 0;

 	i2cMode = MASTER_TX;

	uart0_sendString("i2c about to send\n\r");
	I2C_SEND_START;  /******* RESET OCCURS HERE ***********/
	uart0_sendString("i2c send done\n\r");
}

void i2c_rxData(Uint8 * buffer, Uint16 length) {
	Uint16 i;

 	i2c_rxBytesRemaining = length;
	while(!i2c_rxComplete);
 	for(i = 0; i < length; i++)
 		i2c_buffer[i] = *(buffer++);

}

i2c_isr.c
#include "i2c.h"
#include "uart.h"

void i2c_isr (void) __irq {
	Uint8 code;
	uart0_sendString("i2c_isr");
	
	code = I2STAT;
	switch(i2cMode) {
		case MASTER_TX:
			switch(code) {
				case 0x08:  // First Start Transmitted
				case 0x10:	// Repeated Start
					// Write address and tell if it is read or write
					I2DAT = (i2c_address << 1) | i2c_RdnWr;
					I2CONCLR = (0x1 << 3);		// Clear SI
					break;
				case 0x18:	// Start + Wr sent, ACK received
				case 0x20:	// Start + Wr sent, Not ACK received
				case 0x28:  // Data byte sent, ACK recieved
				case 0x30:  // Data byte sent, Not Ack received
					if(i2c_bytesRemaining > 0) {
						I2DAT = i2c_buffer[i2c_pos++];
						i2c_bytesRemaining--;
					}
					else if(i2c_sendStop) {
						I2C_SEND_STOP; // Send Stop
					}
					else { // Change from master_tx to master_rx
						i2cMode = MASTER_RX;
						i2c_RdnWr = (~i2c_RdnWr)&0x1;
						i2c_sendStop = 1;
						i2c_pos = 0;
						i2c_rxComplete = 0;
						I2C_SEND_START;
					}
					I2CONCLR = (0x1 << 3);		// Clear SI
					break;
			}
			break;

		case MASTER_RX:	
			switch(code) {
				case	0x08:	// Start Has been sent
				case	0x10:	// RStart has been sent
					I2DAT = (i2c_address << 1) | i2c_RdnWr;					
					I2CONCLR = (0x1 << 3);		// Clear SI
					break;
				case	0x40:	// Waiting for data byte
					if(i2c_rxBytesRemaining > 1)
						ENABLE_I2C_AA;	// Ack data when it comes in
					else	
						DISABLE_I2C_AA; // Don't Ack data
					I2CONCLR = (0x1 << 3);		// Clear SI
					break;
				case	0x50:	// Data received, Ack sent
					i2c_rxBuffer[i2c_rxWrPos] = I2DAT;
					i2c_rxWrPos++;
					i2c_rxBytesRemaining--;
					if(i2c_rxBytesRemaining > 1)
						ENABLE_I2C_AA;
					else
						DISABLE_I2C_AA;
					I2CONCLR = (0x1 << 3);		// Clear SI
					break;
				case	0x58:	// Data received, NOT Ack sent
					i2c_rxComplete = 1; // Done receiving all requested data
					I2C_SEND_STOP;
					I2CONCLR = (0x1 << 3);		// Clear SI
					break;										
			}
			break;

		case SLAVE_TX:
			switch(code) {
			}
			break;

		case SLAVE_RX:
			switch(code) {
			}
			break;
	}
	VICVectAddr = 0x00000000;
}

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.