Download - Arm Cortex

Transcript
Page 1: Arm Cortex

MuZIC Internship

Report

Guillermo ALEJANDRE ALBA

8/21/2009

Page 2: Arm Cortex
Page 3: Arm Cortex

MuZIC Internship Report 2009

3

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Acknowledgments

First of all, I would like to thank my project manager Stephane Vannuffelen for giving me

the opportunity to work in Schlumberger and in the MuZIC project. I would also like to thank my

supervisor Carlos Merino, for his help and his support during these months. Their trust and

remarks have made possible this project.

Moving from university to a Schlumberger was not easy, because of the complexity of the

company and its organization. Therefore, I would like to thank the whole MuZIC project for

answering all of my questions and giving me the warmest welcome ever. Special thanks to Aitor

Albizua – the other intern of the team –, Christophe Rayssiguier – for all the meals we shared

together –, Amirauche Bouhlal – for the time spent in the lab –, and Damian Buisson and Jean-

François Sandoz – for their patience and help in some of the hardest parts of the project.

Nevertheless, this would not have been possible without the help of all the teachers in

Madrid, in Paris, and in Rennes, who taught me during me engineering degree. Finally, I would

like to thank my parents, for their support. Their efforts and the education they have given me

have made this possible.

Page 4: Arm Cortex

Abstract/ Resumen

IMPLEMENTACION DE APLICACIONES PARA TESTS DE UN

MICROCONTROLADOR

Autor: Alejandre Alba, Guillermo.

Director: Vannuffelen, Stephane.

Entidad Colaboradora: Schlumberger

RESUMEN DEL PROYECTO

El trabajo realizado dentro del marco de este proyecto consta de distintas tareas, cuyo hilo

conductor es el microprocesador sobre el que han sido programadas. En líneas generales, el

trabajo realizado dentro del equipo de desarrollo de firmware ha sido la implementación de

diferentes módulos de un módem. Dicho módem es utilizado para un sistema de transmisión

entre distintas localizaciones. El microprocesador en cuestión se trata de un Luminary

LM3S2965.

Así, podemos distinguir tres grandes ejes dentro del presente trabajo. El primero de ellos

consistió en la implementación de una UART (acrónimo del término inglés Universal

Asynchronous Receiver/Transmitter, Transmisor-Receptor Asíncrono Universal). El principal

objetivo de este elemento de hardware es controlar puertos y dispositivos serie: gestiona las

interrupciones de los dispositivos conectados al puerto serie y traduce los datos a enviar a

formato serie, de tal forma que puedan ser transmitidos y recibidos a través de los puertos (ver

Figure 1).

Figure 1 – Conexión PC-Microcontrolador

Page 5: Arm Cortex

MuZIC Internship Report 2009

5

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

El método utilizado para desarrollar esta aplicación podría denominarse como ‘creciente’. Así,

se empezó con un programa más sencillo que llevara a cabo únicamente la lectura y escritura

de puertos, al que se le fueron añadiendo elementos más complejos hasta llegar a la versión

definitiva.

El resultado es un programa que inicializa el reloj y los puertos del microprocesador y

configura la UART para una velocidad de 19200 bits por segundo. Además, se encarga del

encapsulado de datos para ser enviados al ordenador y del desencapsulado de los datos

procedentes del ordenador. Para hacer uso de las interrupciones, utiliza las listas FIFO de

recepción y transmisión disponibles en el microprocesador, así como algunas de las

interrupciones internas. La interrupción de recepción se activa una función de recepción que se

encarga de almacenar los datos en un buffer de recepción. Si el tamaño de los datos enviados

es inferior a un determinado tamaño, se activa una interrupción de tipo Time-Out. Esta

interrupción avisa al microprocesador de que hay elementos en la FIFO de recepción que no

han sido tratados, y se procede a la lectura de la FIFO hasta que ésta queda vacía. Después, se

escriben los datos en el buffer de transmisión y se envían. Finalmente, para garantizar que no

hay problemas de entrecruzado de información (debido a información que haya podido quedar

almacenada accidentalmente en cualquiera de las FIFOs), se procede a un reseteo sistemático

de los buffers, las FIFOs, y los contadores.

La segunda fase de programación de la UART consistió simplemente en la integración de las

funciones previamente implementadas dentro de un sistema tiempo real. En este caso, la

comunicación entre microprocesador y ordenador se realiza vía un protocolo previamente

establecido.

Figure 2 – Conexión FPGA-Microcontrolador

Page 6: Arm Cortex

La segunda línea de trabajo consistió en la programación de un bus SPI (Serial Protocol

Interface) entre una FPGA (Field Programmable Gate Array) y el microprocesador. El bus SPI

es un estándar de comunicaciones implementado por Motorola y utilizado para la transferencia

de información entre circuitos integrados en equipos electrónicos. En este caso, el

microprocesador hace de maestro, y la FPGA es el esclavo (ver Figure 2). Visto desde el

microprocesador, está compuesto de una línea con el reloj que regula las comunicaciones del

bus, una línea de dato entrante, una de dato saliente, y un pin de activación (chip select). El

código programado en el interior de la FPGA ha sido realizado por una empresa externa, y el

objetivo principal de la implementación de dicho bus fue verificar que la lógica de la FPGA

cumplía con las especificaciones dadas a la empresa externa. En líneas generales, la FPGA

recoge datos procedentes de un conversor A/D (también llamado ADC, Analog to Digital

Conversor), los trata, y se los pasa al microprocesador. Además, ha de ser capaz de enviar

señales a un PWM (Pulse-With Modulator). La lógica implementada en el interior de la FPGA

esta compuesta por diferentes módulos por lo que para proceder a su validación se

implementaron diversas funciones.

La metodología utilizada es similar a la de la implementación de la UART: Siguiendo las

especificaciones recibidas por el programador, se implementó un simple programa que

generara una señal de PWM constante y de valor conocido, que luego se fue mejorando para

permitir la interacción con todos los módulos de la FPGA. Ello permitió encontrar algunos

fallos en el código de la FPGA, que fueron transmitidos a la empresa encargada.

El resultado de este módulo ha sido una aplicación que permite interaccionar al

microprocesador con la FPGA. Configura la FPGA para el tratamiento de datos del ADC y

permite controlar el PWM a través de la FPGA.

Figure 3 – Conexión ADC-Microcontrolador

Page 7: Arm Cortex

MuZIC Internship Report 2009

7

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Por último, se llevó a cabo la programación del bus SPI entre el microprocesador y el ADC

(ver Figure 3). Este bus permite recoger datos del ADC sin necesidad de pasar por la FPGA

(por ejemplo, en caso de un fallo de la misma). Cada vez que el ADC tiene un dato disponible,

envía una señal al microprocesador. La configuración de base de dicho bus es similar a la

utilizada para la comunicación con la FPGA. Sin embargo, el microprocesador no necesita

enviar ninguna instrucción al ADC, por lo que la línea de transmisión no es utilizada.

Finalmente, aparecen dos líneas más: una (que llamaremos SYNC, de sincronización) se

encarga de sincronizar el ADC con el microprocesador antes de comenzar con la recepción de

datos; la otra (DRDY, del inglés “Data ReaDY”) avisa al microprocesador de que hay nuevos

datos disponibles en el ADC para el microprocesador.

El funcionamiento de este módulo es el siguiente: primero se realiza una configuración de los

puertos que serán utilizados. Después, se sincroniza el ADC con el microprocesador. Y

finalmente, se espera la generación de una interrupción por parte de DRDY para empezar a

recibir datos. El desarrollo de este modulo fue similar al realizado para el SPI de la FPGA:

cabe destacar, no obstante, el uso de interrupciones de tipo interno (las generadas por el SPI), y

de tipo externo (las generadas por el ADC a través de DRDY).

Esta aplicación permite la comunicación entre el ADC y el microprocesador y almacena los

datos procedentes del ADC en la memoria del microprocesador.

En conclusión, las aplicaciones implementadas para el microprocesador permiten interaccionar

con diferentes periféricos, todos ellos necesarios para el funcionamiento de nuestro módem.

Trabajan de forma casi exclusiva con interrupciones, lo que optimiza la gestión del tiempo del

microprocesador al hacer posible un tratamiento en función de las prioridades.

DESIGN AND IMPLEMENTATION OF AN APPLICATION USED FOR

AUTOMATIC TESTS OF AN ELECTRONIC BOARD

This project consists in different tasks whose meeting point is the microprocessor for which

they have been conceived. They aim different peripherals, but share the same microprocessor,

a Luminary LM3S2965.

Page 8: Arm Cortex

The project has been organized in three tasks clearly defined. The first was the implementation

of a UART in order to communicate the microprocessor with a computer. The second was the

programming of a SPI between the microprocessor and the FPGA (Field Programmable Gate

Array). The third one was the coding of another SPI connection, but this time between the

ADC and the microprocessor.

UART is the acronym for Universal Asynchronous Receiver/Transmitter. It is a piece of

computer hardware that translates between parallel-form data and serial-form data, and vice

versa. Two phases can be distinguished in the development of this connection. During the first

phase, only the reception and transmission where taken into account. A program was

conceived where received data from the computer arrived to the reception FIFO and was stored

inside the reception buffer. Then, data was copied to the transmission buffer and written into

the transmission FIFO in order to be sent back to the computer. Also, a LED was configured to

blink during the whole process, in order to verify that the program was working running.

The UART is configured so that the FIFO lists provided by the microprocessor are enabled, as

well as some of the preconfigured interruptions inside the microprocessor. The implemented

program initializes the system clock and the ports (those related with the LED and the UART),

configures the UART, and then gets inside an infinite loop whose only task is to make a LED

blink. The reception interruption is enabled every time the amount of data inside the reception

FIFO reaches 8 bytes, and reads them. After that, a function whose task is to store the received

data in the reception buffer is called. If the received data is not a multiple of 8 bytes, the

Timeout interruption is enabled. This interruption alerts the microprocessor whenever there is

unread data in the RX FIFO. Once triggered, the microprocessor will keep reading the RX

FIFO until it is empty. Afterwards, the data is written in the transmission buffer and the

transmission is initialized. In order to start sending data to the computer, the TX FIFO is

partially written: every time the amount of data stored in the TX FIFO is below 2 bytes, the

transmission interruption is enabled. This interruption partially refills the TX FIFO. Finally, in

order to make sure that no data has been left inside the FIFOs, a total reset of the buffers, the

FIFOs and the counters is performed.

The second part of the UART development was its integration inside a real time operating

system. Also, the encapsulation of the communication between computer and microprocessor

had to be taken into account: all the data coming from the computer is “cased” inside a

Page 9: Arm Cortex

MuZIC Internship Report 2009

9

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

protocol, so the first task of the microprocessor once the information has arrived is to “decase

it”. The same applies for the data going to the computer: an encapsulation of the data has to

take place before sending it.

An SPI (Serial Peripheral Interface Bus) is a synchronous serial data link standard named by

Motorola using a master/slave mode where the master device initiates the data frame. It

consists of four wires: the Serial Clock, the Master Output, the Master Input, and the Chip

Select. In this case, the Master is the microprocessor, and the FPGA the slave. An FPGA (Field

Programmable Gate Array) is a device that can be programmed using a logic circuit diagram or

a source code in a hardware description language to specify how the chip will work. The

programming of the FPGA was performed by a third party, and so by programming the SPI

bus, we wanted to check that the program inside the FPGA met the desired specifications.

The FPGA is supposed to read data from an ADC (Analog to Digital Converter), treat them,

and hand them out to the microprocessor. It is also in charge of controlling a PWM (Pulse

Width Modulator). Each of these tasks is performed by a different module. In order to verify

each one, a series of functions were programmed.

The work performed regarding the SPI bus was divided as follows: firstly, the FPGA logic was

implemented inside the chip, and I/Os were assigned. We proceeded with a verification of the

module in charge of supplying the ADC clock. After this, we went on with the implementation

of a program that would produce a constant output in the PWM pin. Finally, a full test bench

was programmed. It included writing the different tables in the FPGA memory, adjusting the

gain and the offset of the PWM, and starting the communication.

Lastly, another SPI bus was implemented, this time between the ADC and the microprocessor.

This bus is aimed to bypass the FPGA if necessary (for example, in case of an FPGA failure).

Every time the ADC has some data, it sends a signal to the microprocessor. As a response, the

microprocessor performs a dummy read in order to pass to the ADC the clock on which the

data will be written. The ADC can only send data in 8-bit packages, so in order to send the full

message (24 bits), three dummy reads are needed. The basic features of the preceding SPI have

been kept. Some minor modifications have been done, though: the data size in this case is

constant (8 bits), the TX line is not used (as no data has to be sent to the ADC), and two more

lines have been implemented. The first one is called SYNC (for synchronization), and it is

Page 10: Arm Cortex

used to synchronize the ADC with the microprocessor before starting the transmission. The

second one is DRDY, which alerts the microprocessor that new data is available in the ADC.

This module works as follows: first, the ports that will be used are configured; then, the ADC

is synchronized; and finally, we get inside an infinite loop, where we wait for an interruption

coming from the DRDY line. As we can see, this module is quite similar to the previous one,

except for the use of internal interruptions (triggered by the SPI) and external interruptions

(triggered by the ADC).

Page 11: Arm Cortex

MuZIC Internship Report 2009

11

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Contents

Acknowledgments .............................................................................................................. 3

Abstract/ Resumen ............................................................................................................ 4

Schlumberger Company Overview .................................................................................. 15

1. History ............................................................................................................................ 15

2. Schlumberger oilfield services ......................................................................................... 15

a. Western Geco ........................................................................................................................ 16

b. Drilling & Measurements ...................................................................................................... 16

c. Reservoir Evaluation Wireline .............................................................................................. 16

d. Well Services ......................................................................................................................... 17

e. Well Completion and Productivity ........................................................................................ 17

f. Schlumberger Information Services ...................................................................................... 17

g. Integrated Product Management ............................................................................................ 17

3. Schlumberger – Ribaud Product Centre.......................................................................... 17

Petroleum Well Vocabulary ............................................................................................. 19

The MuZIC Project ......................................................................................................... 21

1. Team composition ........................................................................................................... 21

2. Presentation of the project ............................................................................................... 21

3. Description of the project ................................................................................................ 22

4. The internship in the project ........................................................................................... 22

The MuZIC Firmware ..................................................................................................... 24

1. Introduction .................................................................................................................... 24

2. LM3S2965: A short Description ...................................................................................... 24

3. Microcontroller’s choice .................................................................................................. 25

4. The company: Luminary Micro, Inc. ............................................................................... 25

5. Project Overview ............................................................................................................. 26

The PC connection ........................................................................................................... 27

1. Introduction .................................................................................................................... 27

2. Main definitions .............................................................................................................. 27

3. Objective ......................................................................................................................... 27

4. Specifications ................................................................................................................... 28

5. Procedure used to attain the specifications ...................................................................... 29

6. Results ............................................................................................................................. 29

7. Remarks .......................................................................................................................... 35

The FPGA connection ...................................................................................................... 37

1. Introduction .................................................................................................................... 37

2. Main definitions .............................................................................................................. 37

3. Objectives ........................................................................................................................ 38

4. Specifications ................................................................................................................... 41

5. Procedure used to attain the specifications ...................................................................... 42

6. Results ............................................................................................................................. 42

7. Remarks .......................................................................................................................... 48

Page 12: Arm Cortex

The connection with the ADC .......................................................................................... 50

1. Introduction .................................................................................................................... 50

2. Main Definitions .............................................................................................................. 50

3. Objectives ........................................................................................................................ 50

4. Specifications ................................................................................................................... 51

5. Procedure used to attain the specifications ...................................................................... 51

6. Results ............................................................................................................................. 52

7. Remarks .......................................................................................................................... 54

Generation of PWM Commands ..................................................................................... 55

1. Introduction .................................................................................................................... 55

2. Main Definitions .............................................................................................................. 55

3. Objectives ........................................................................................................................ 55

4. Specifications ................................................................................................................... 56

5. Procedure used to attain the specifications ...................................................................... 57

6. Results ............................................................................................................................. 57

7. Remarks .......................................................................................................................... 60

Conclusion ....................................................................................................................... 61

References ........................................................................................................................ 62

1. Manuals ........................................................................................................................... 62

2. Websites .......................................................................................................................... 62

3. Software .......................................................................................................................... 62

Annex A: Peripheral’s Code ............................................................................................ 63

1. UART .............................................................................................................................. 63

main ................................................................................................................................................ 63

drv_uart.c ....................................................................................................................................... 63

drv_uart.h ....................................................................................................................................... 68

sytem_config.h ............................................................................................................................... 70

system_config.c .............................................................................................................................. 71

2. FPGA SPI connection code ................................................................................................. 72

spi_fpga_test_bench.c ................................................................................................................... 72

drv_spi_fpga.c ................................................................................................................................ 74

drv_spi_fpga.h ................................................................................................................................ 84

3. ADC .................................................................................................................................. 87

4. PWM ................................................................................................................................ 94

Annex B: Petroleum exploration and production ............................................................. 100

1. Exploration ..................................................................................................................... 100

2. Well construction ........................................................................................................... 101

3. Drilling ........................................................................................................................... 101

4. Logging ........................................................................................................................... 102

5. Casing ............................................................................................................................ 104

6. Cementing ...................................................................................................................... 104

7. Production tubing and packers ........................................................................................ 105

Table 1: Format of messages ..................................................................................................... 28

Table 2: FPGA Pin Assignment ................................................................................................ 47

Page 13: Arm Cortex

MuZIC Internship Report 2009

13

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Figure 1 – Conexión PC-Microcontrolador ................................................................................. 4 Figure 2 – Conexión FPGA-Microcontrolador ........................................................................... 5 Figure 3 – Conexión ADC-Microcontrolador ............................................................................. 6 Figure 4-Schlumberger Expertise Areas .................................................................................... 16 Figure 5-SRPC ........................................................................................................................... 18

Figure 6- Schlumberger Ribaud Product Center organization .................................................. 19 Figure 7- Petroleum well ........................................................................................................... 20

Figure 8 – MuZIC Team ............................................................................................................ 21

Figure 9 – Parts of the MuZIC project ...................................................................................... 22 Figure 10 – Connections Overview ........................................................................................... 26 Figure 11 - The UART module ................................................................................................. 30 Figure 12- Reception process .................................................................................................... 31

Figure 13 – UART Reception (less than 8 bytes). The Timeout interruption is triggered; all the RX FIFO is read ................................................................................................................ 32

Figure 14 – UART Reception (multiple of 8 bytes) (I): The reception interruption is triggered ........................................................................................................................................... 33

Figure 15 – UART Reception (multiple of 8 bytes) (II): Message read .................................... 33

Figure 16 - UART Reception (more than 8 bytes, not multiple) (I): Reception interruption + Timeout interruption .......................................................................................................... 34

Figure 17 - UART Reception (more than 8 bytes, not multiple) (II): Reading 8 first bytes ..... 34

Figure 18 - UART Reception (more than 8 bytes, not multiple) (III): Reading the data left .... 35

Figure 19 – Clock Polarity and Phase ....................................................................................... 38 Figure 20 – FPGA Treatment .................................................................................................... 39 Figure 21 – Rx Analog to Digital .............................................................................................. 39 Figure 22 – Rx FPGA ................................................................................................................ 40

Figure 23 – SPI module ............................................................................................................. 43

Figure 24 – First TX mode ........................................................................................................ 45

Figure 25– Second TX mode ..................................................................................................... 46 Figure 26 – First TX Mode ........................................................................................................ 47

Figure 27 – Second TX mode .................................................................................................... 47 Figure 28 – Faulty PWM signal ................................................................................................ 49 Figure 29 – ADC Module .......................................................................................................... 52

Figure 30 – ADC Interruption ................................................................................................... 53 Figure 31 – ADC Transmission ................................................................................................. 54 Figure 32 – ADC Transmission (detail): 24 bits ....................................................................... 54 Figure 33 – PWM Specifications ............................................................................................... 56 Figure 34 – Count-down Timer configuration .......................................................................... 58 Figure 35 – Dead bands ............................................................................................................. 59

Figure 36 – PWM with Dead-band ............................................................................................ 60 Figure 37 – PWM with Dead-Band (detail) .............................................................................. 60 Figure 38 – Mapping the ocean layer ...................................................................................... 100 Figure 39 – Trucks used to map the underground ................................................................... 101 Figure 40 - Drilling .................................................................................................................. 102

Figure 41 – A Wireline Tool ................................................................................................... 103

Page 14: Arm Cortex

Figure 42 – Recording Wireline results ................................................................................... 104

Page 15: Arm Cortex

MuZIC Internship Report 2009

15

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Schlumberger Company Overview

1. History

The birth of Schlumberger is the history of a technique. At the beginning of the 20th century,

the science of geophysics was new and was just beginning to use magnetic or gravimetric

methods to explore the internal structure of the Earth. The brothers Conrad and Marcel

Schlumberger conceived the idea that electrical measurements also offered great possibilities.

Working at first alone, then with a slowly growing number of associates, they extended the

electrical prospecting technique from the surface to the oil well. It was the birth of electrical well

logging.

2. Schlumberger oilfield services

Schlumberger is a global company providing technology services to the oil and gas industry.

Schlumberger Oilfield Services, headquartered in Paris and Houston, is the leading provider of

services, solutions and technology to the petroleum industry worldwide. The three values on

which the company is founded are people, technology and profit.

The company employs 87,000 people and is truly a diverse company with over 140

nationalities working in over 80 countries around the world. In 2008, Schlumberger revenue was

$ 27.16 billion.

Schlumberger’s competitors are Halliburton, Baker Hughes Inc. and other Oil & Gas

Equipment & Services companies.

Schlumberger Oilfield Services is the leading supplier of technology, information services

and solutions to the international petroleum industry. The business is managed within 27

GeoMarket regions grouped into three geographic areas: North and South America, Continental

Europe and Africa, Middle East and Asia, and Russia. The “GeoMarket” is a business unit that

brings together geographically focused teams to meet local needs and provide customized

solutions.

New technology development is managed through a series of service segments to capitalize

on technical synergies and introduce innovative solutions within GeoMarket regions. There are

seven main business segments reflecting the key areas of Schlumberger expertise as can be seen

in Figure 4.

Page 16: Arm Cortex

Figure 4-Schlumberger Expertise Areas

The seven main business segments are:

a. Western Geco

This is mainly a marine and land seismic acquisition and processing company owned and

managed by Schlumberger Reservoir Evaluation and Development.

b. Drilling & Measurements

This segment provides well construction services including well planning, direction drilling

(steering of the borehole), measurement while drilling (determining the azimuth and deviation of

the borehole) and logging while drilling (acquiring data on the rock and fluid types as one drills

through them).

c. Reservoir Evaluation Wireline

This segment provides the original Schlumberger services namely determination of the rock

types, fluid types, their pressures/mobility and acquisition of rock and fluid samples from

downhole.

Page 17: Arm Cortex

MuZIC Internship Report 2009

17

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

d. Well Services

This segment provides cementing (of the metal casing into the drilled borehole), coiled

tubing (intervention into wells using slim fit flexible pipes to perform remedial repairs) and

facing (using high pressure to fracture rock in order to improve the production of hydrocarbon)

services.

e. Well Completion and Productivity

This segment provides a range of service designed to manage and improve hydrocarbon

production and recovery. It includes subsurface safety valves, subsurface electrical and hydraulic

control valves, electrical submersible pumps, gas lifts systems, well testing services and remote

monitoring of pressure, temperature and flow rate downhole in oil and gas wells.

f. Schlumberger Information Services

This segment provides data management, data processing, data interpretation of the many

forms of data acquired throughout the exploration and production process from seismic to

production rates.

g. Integrated Product Management

This segment enables Schlumberger to deliver a fully integrated service such as delivering a

fully constructed well or management of hydrocarbon production from a particular field using the

many individual services available from Schlumberger or other oilfield service companies.

3. Schlumberger – Ribaud Product Centre

The Schlumberger-Ribaud Product Centre (SRPC) (Figure 5), situated in Clamart, in the

South of Paris, is the largest Schlumberger technology and development center in Europe. Here

more than 500 scientists, engineers and technicians design and manufacture equipment and

systems for use in Schlumberger Oilfield Services businesses worldwide.

Page 18: Arm Cortex

Figure 5-SRPC

SRPC specializes in:

• Formation evaluation: Measurements in wells while drilling or via wireline cable.

Gives customers real time information about borehole formation.

• Production-related measurements: When the well is in production, meaning oil or gas

is being extracted from the well, production tools gives information such as pressure,

temperature or flow rate. These measurements are either used periodically or are

permanently installed in wells.

• Testing of hydrocarbon reservoirs: Downhole transient measurements and equipment

to handle produced fluids at surface.

• Cementing: Design of new chemical formulations for fluids used during well

construction. Before producing, the well’s casing are made to strengthen the well: this is

called cementing.

To have a better understanding of petroleum exploration and production, see Annex B:

Petroleum exploration and production.

The Figure 6 represents the Schlumberger Riboud Product Center organization:

Page 19: Arm Cortex

MuZIC Internship Report 2009

19

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Figure 6- Schlumberger Ribaud Product Center organization

SRPC is organized in métiers and disciplines. These two branches are organized as a matrix.

The disciplines regroup the segments described previously: Cased-Hole Products, Well

Integrity Technology, Formation Evaluation, Interpretation Products, Completions Services,

Well Testing Services and Quality Records. The discipline manager is responsible for projects

that produce tools and techniques that are required by the oilfield activities.

At Clamart, the métiers are organized under: Chemistry, Electrical, Mechanical, Software &

Appl.Maths, Physics and Manufacturing. The Métier manager is responsible for developing

technologies and competences of métier personnel to world-class level, in line with company

product development strategy and timing and in conformity to relevant standards.

Petroleum Well Vocabulary

This brief, but important section gives to the reader a first approach to the petroleum

vocabulary. Furthermore, it has its importance for understanding the next chapters, because there

are going to be pieces of vocabulary commonly used in this document, but not obvious to a

normal reader.

Page 20: Arm Cortex

Figure 7- Petroleum well

Figure 7 shows the main elements of a Petroleum Well:

• Well: Vertical gap man-made perforated on the ground for petroleum extraction

purposes.

• Casing: External metal tube that gives strength to the well. It is normally

surrounded by cement for not breaking the different ground layers.

• Tubing: Inside metal tube concentric with the casing that carries out the

petroleum. Its diameter is about 12-14 centimeters.

• Packer: Pressure valve that makes possible a physical separation between the

upper and the lower part of the well. Moreover, the pressure above and below are

not the same. It enables the tubing to pass through.

• Head of well: External part of the casing. It is used for opening and closing the

well.

• Reservoir: Physical deposit where petroleum, gas or oil are stocked.

Page 21: Arm Cortex

MuZIC Internship Report 2009

21

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

The MuZIC Project

1. Team composition

Figure 8 – MuZIC Team

The MuZIC team composition is shown in Figure 8. As we can see, it is highly

multidisciplinary and includes electronic engineers, mechanical engineers, physicists, firmware

engineers, software engineers and telecommunications engineers. A project manager coordinates

the project.

Even though the development of the internship has meant working with all of them, most

of its work has taken place with the firmware and the telecommunication engineers, Carlos

Merino and Guillaume Millot.

2. Presentation of the project

In the petroleum activity, understanding the different physical magnitudes, like pressure,

temperature, resistivity or permeability. All this information is extremely important for geologists

and petrophysicists: it is necessary to produce models that are critical to describe a reservoir and

define its appropriate production strategy.

In the previous section (see Error! Reference source not found.), we have seen that before

producing oil in a reservoir, different steps have to be taken previously. One of them is testing.

During part, the well produces for a certain period of time in order to obtain the data which will

enable a parametrization of the reservoir. As there is no connection between the parts of the

reservoir separated by the packer, testing tools cannot communicate with the surface. Thus,

Project Manager

Physicists Mechanical Engineers

Mechanical Intern

Firmware Engineer

Firmware Intern

Telecommunications

EngineerSoftware Engineer Electronic Engineers

Electronic Technician

Page 22: Arm Cortex

measures are stored inside a recording device in the testing tool, and read after the testing

process, when testing tools a retrieved from the well and taken back to surface.

In order to take accurate measures of the reservoir, these tools are set downhole for longer

periods of time that they should be. This is a waste of both time and money. Because the packer

makes any wired connection impossible, the goal of the MuZIC project is to develop a wireless

communication system which would allow communication in real time between testing tools

downhole and surface.

In parallel with the MuZIC project, other segments are already developing tools that

communicate with low frequency electromagnetic signals, but their data rate is not faster enough.

3. Description of the project

Section not shown due to confidentiality clause.

4. The internship in the project

The aim of this internship was to help the team in the development of the firmware of the

new microcontroller The new technology had to be introduced to the team and what is more: like

in every other project, deadlines and benchmarks had to be respected, so some other tasks were

performed in parallel of the firmware part. Figure 9 shows the different parts of the MuZIC

project. The lighter ones are those that became part of this internship.

Figure 9 – Parts of the MuZIC project

The tasks performed in each of these parts were:

Physical Concepts Mechanics Firmware

Electronics Telecommunication Surface Software

Simulations Lab Tests Field Tests

Page 23: Arm Cortex

MuZIC Internship Report 2009

23

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

• Firmware : This section took most of the internship’s time. It implied a deep study of the

microcontroller’s information (datasheet, characteristics, and examples) and a large

amount of peripheral programming.

• Electronics: In order to implement the various LM3S2965 peripherals, some small

electronic setups had to be done.

• Field tests: During the internship, several tests were performed in a real test well to

measure the performance of the system. Sometime of the internship was dedicated to the

treatment of field data, and a visit to the testing well was performed.

Page 24: Arm Cortex

The MuZIC Firmware

1. Introduction

In this section, we will discuss about the microcontroller chosen for the MuZIC project. We

will see its main features, describe briefly the company which created it (Luminary), and finally

explain the reasons that motivated this choice. For a more detailed description of the

microcontroller, please refer to the LM3S2965 Datasheet.

2. LM3S2965: A short Description

The LM3S2965 microcontroller is based on the ARM Cortex-M3 controller core (32 bit

RISC performance) operating at 50MHz with a 256kB single-cycle flash and 64 KB single-cycle

RAM. Below is a list of the main peripherals used by the microcontroller, as well as a short

description of its characteristics:

• 4 General Purpose Timers with RTC capability, each configurable as one 32-bit or two

16-bit timers. They can be configured as 24-bit System timers or 32-bit watchdog timers.

• 2 CAN controllers with disable automatic retransmission mode for TTCAN, a bit rate up

to 1Mb/s and 32-message objects with its own identifier mask. They support CAN

protocol version 2.0 A/B.

• 2 Synchronous Serial Interfaces (SSI) with master and slave modes for SPI, Microwire,

or TI synchronous serial.

• 2 I2C interfaces (master and slave).

• 3 16C550-type UART with IrDA support.

• An Analog-to-Digital Converter (ADC) with single and differential-input configurations,

4 10-bit channels (inputs) when used as single-ended inputs, and sample rate one million

samples/seconds.

• 3 Analog Comparators configurable to drive an output pin, generate an interrupt, or

initiate an ADC sample sequence. They can also compare external pin input to external

pin input or to internal programmable voltage reference.

• 3 PWM generator blocks (6 motion-control PWM outputs), each containing a 16-bit

counter, two comparators, a PWM generator, an output control block with PWM output

Page 25: Arm Cortex

MuZIC Internship Report 2009

25

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

enable of each PWM signal, and a dead-band generator. They can initiate an ADC

sample sequence.

• 56 5-V-tolerant input/outputs organized in 8 different ports (GPIOs), with programmable

interrupt generation, slew-rate control and drive strength, and a fast toggle capable of a

change every two clock cycles.

• On-chip Low Drop-Out (LDO) voltage regulator, a battery-backed hibernation module

with real-time clock and 256-bytes of non-volatile memory.

3. Microcontroller’s choice

The first, and most important reason for choosing the LM3S2965 was that it is able to

function under the working conditions established for the MuZIC project: high temperature, high

pressure, and long autonomy. Furthermore, it is the microcontroller which consumes the less

power given the harsh working conditions.

The Luminary’s micros have also other properties which make them interesting for

industrial applications. First, the ARM architecture used in Luminary Micro enables 32-bit

performance for the same price as 8-bit and 16-bit microcontrollers. Moreover, its Cortex-M3 is

easier to program (no need of assembly code), uses atomic operations, and is optimized for

single-cycle flash usage. Finally, all of the microcontrollers come with Stellaris Peripheral Driver

Library, which smoothes interaction with the different peripherals.

4. The company: Luminary Micro, Inc.

Luminary Micro, Inc. is an American company based in Austin, Texas. It was founded in

2004 and has 65 employees. Luminary Micro has been the first company to design, market, and

sell silicon implementations of the ARM Cortex-M3-processor. The company also provides

Stellaris family development kits which provide the hardware and software tools to develop and

prototype embedded applications.

The 14 May of the present year, Texas Instruments bought Luminary Micro. This has

induced for the moment some changes, especially in the present lines of microcontrollers. The

LM3S2965 has suffered some updates and modifications, and new error sheets have been

released.

Page 26: Arm Cortex

Being a relatively new company, Luminary microcontrollers use the latest technologies and

more advanced and sophisticated solutions. Unfortunately, it is also a bit

older microcontrollers which have been used in industry for much more applications.

some examples regarding this issue in the following sections.

The implementation of the different modules has been performed in a LM3S2965 evaluation

board, except for the hibernation module, for which different boards were used. In order to meet

the needs of the project, this board was modified during the first months, and the 8MHz quartz

was replaced by a 12.8MHz oscillator.

The implementation of the different modules has been performed in a LM3S2965 eval

board, except for the hibernation module, for which different boards were used. In order to meet

the needs of the project, this board was modified during the first months, and the 8MHz quartz

was replaced by a 12.8MHz oscillator.

5. Project Overview

Figure 10 shows a small diagram of how the different electronics are communicated

between them.

Being a relatively new company, Luminary microcontrollers use the latest technologies and

more advanced and sophisticated solutions. Unfortunately, it is also a bit more unstable than

trollers which have been used in industry for much more applications.

some examples regarding this issue in the following sections.

The implementation of the different modules has been performed in a LM3S2965 evaluation

ibernation module, for which different boards were used. In order to meet

the needs of the project, this board was modified during the first months, and the 8MHz quartz

was replaced by a 12.8MHz oscillator.

The implementation of the different modules has been performed in a LM3S2965 eval

board, except for the hibernation module, for which different boards were used. In order to meet

the needs of the project, this board was modified during the first months, and the 8MHz quartz

was replaced by a 12.8MHz oscillator.

shows a small diagram of how the different electronics are communicated

Figure 10 – Connections Overview

Being a relatively new company, Luminary microcontrollers use the latest technologies and

more unstable than

trollers which have been used in industry for much more applications. We will see

The implementation of the different modules has been performed in a LM3S2965 evaluation

ibernation module, for which different boards were used. In order to meet

the needs of the project, this board was modified during the first months, and the 8MHz quartz

The implementation of the different modules has been performed in a LM3S2965 evaluation

board, except for the hibernation module, for which different boards were used. In order to meet

the needs of the project, this board was modified during the first months, and the 8MHz quartz

shows a small diagram of how the different electronics are communicated

Page 27: Arm Cortex

MuZIC Internship Report 2009

27

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

The PC connection

1. Introduction

The first task was to deploy a way to communicate between the computer and the

microcontroller. The solution was to implement a Universal Asynchronous Receiver/Transmitter

(UART).

2. Main definitions

A Universal Asynchronous Receiver/Transmitter (UART) is a piece of computer hardware

that translates data between parallel and serial forms. They are commonly used for serial

communications over a computer or peripheral device serial port.

The UART takes bytes of data and transmits the individual bits in a sequential fashion. At

the destination, a second UART re-assembles the bits into complete bytes. Serial transmission of

digital information (bits) through a single wire or other medium is much more cost effective than

parallel transmission through multiple wires (in terms of reliability, amount of equipment, etc). A

UART is used to convert the transmitted information between its sequential and parallel form at

each end of the link. Each UART contains a shift register which is the fundamental method of

conversion between serial and parallel forms. The UART usually does not directly generate or

receive the external signals used between different items of equipment. Typically, separate

interface devices are used to convert the logic level signals of the UART to and from the external

signaling levels.

Nowadays, UARTs are commonly used with RS-232 (a standard for serial binary data

signals) for embedded systems communications.

For detailed information about the UART’s characteristics of the LM3S2965, please refer to

the Datasheet of the LM3S2965.

3. Objective

The microcontroller has to be able to communicate with the PC via surface software whose

mission is to act as an interface between the user and the computer. The surface software wraps

the user’s messages in a protocol shared with other tools used in downhole testing, and sends

Page 28: Arm Cortex

them to the microcontroller. Once there, the microcontroller has to unwraps them, and treat them.

All messages coming from the PC need to be answered, and they have to be wrapped before

being sent. Table 1 shows the format of the messages using this protocol.

Table 1: Format of messages

1 byte 1 byte 1 byte 1 byte N bytes 1 byte

SOF Length Device Command Data Checksum

A0h 2 to 255

A message sent using this protocol has a maximum size of 255 bytes. SOF means ‘Start Of

Frame’. Length contains the length of the whole message, including the wrapping. The number

of the device depends on the kind of tool which is sending or receiving the message. In our case,

the Device value for MuZIC is 5. The user’s orders are sent in the ‘Command’ byte. If the

message implies data transmission, N bytes are reserved for that purpose (N being a number of

bytes between 0 and 250). Finally, a checksum is performed to verify that the message is being

transmitted correctly.

Hence, this module has to configure the connection between microcontroller and PC,

manage the transmission and reception of messages between both, and perform a correct

wrapping and unwrapping of the messages.

4. Specifications

Taking into account the previous section, a list of specifications can be sorted out:

• As we have previously seen, there are more electronic components inside a MuZIC tool.

We have seen that the clock speed of the microcontroller depends not only on the

extreme working conditions, but also on the ADC, whose clock speed is set to 6.4MHz.

The highest speed at which the LM3S2965 can turn with no problems under these

conditions is 25.6MHz. But at the time this peripheral was implemented, there were no

available quartzes of that speed. So 12.6MHz quartz was used instead. This added a

limitation to the UART speed: no reception of messages is guaranteed at that clock speed

for baud rates higher than 57600. (See Software UART for Stellaris Microcontrollers

Applications Note for more information).

Page 29: Arm Cortex

MuZIC Internship Report 2009

29

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

• Wrapping and unwrapping functions have to be implemented. These functions have to

follow the protocol procedure shown above.

• The peripheral has to work using interruptions all the time, in order not to stop the

microcontroller.

5. Procedure used to attain the specifications

In order to accomplish a fully operational UART, an ‘incremental’ approach was put into

practice. First, the micro transmission’s functions were implemented. Once the transmission

signals were seen in the oscilloscope, the receiving functions were programmed. Finally, a test

bench where multiple receptions and transmissions could be tested (with echo) was set. The

whole testing process was verified with a blinking LED inside the main function to check that the

program was running while the different interruptions where triggered.

The second phase of the implementation was the programming of the wrapping and

unwrapping functions, and the implementation of the UART peripheral inside the Real Time

Operative System which will later be used in the final tool.

6. Results

The result is a UART module triggered via interruption mainly. The transmission has to be

called first in order to be initialized, but once it has been set the transmission uses interruptions to

work. As for the reception, an interruption is triggered every time data is received.

All the functions are implemented in the file drv_uart.c (Annex A: Peripheral’s Code). This

task manages and controls all low level UART communications on serial port with the PC. It has

been designed to:

• Receive data from the serial port using the reception interruption.

• Transmit via the serial port using the function StartTransmission (see Annex A:

Peripheral’s Code).

Figure 11 shows the UART access module structure:

Page 30: Arm Cortex

Figure

The communication between the PC and the LM3S2965 is done thro

communication using a RS232 transceiver (TRANSmitter

LM3S2965 evaluation board does not have an implemented transceiver, so an external one had to

be added.

The maximum possible baud rate was 57600. The imple

rate of 19200. An inferior baud rate was preferred in order to be sure that the UART was working

inside the performance limitations specified in

Applications Note. It has no parity

transmission and Reception FIFOs have also been enabled.

Before a message is sent, it is written in a 16

microcontroller sends it. The same goes for a

FIFOs (there is a transmission FIFO and a reception FIFO), a level has to be defined. This level

is used to trigger an interruption each time the amount of data stored inside the FIFO reaches that

level. The interruption will then alert the

the RX FIFO), or add more data to be sent (TX FIFO). The default level for both FIFOs is 8

bytes. In the case of this UART, the interruptions have been programmed to be

time we have more than 8 bytes in the RX FIFO, and less than 2 bytes in the TX FIFO.

shows a small diagram of how the reception works

Figure 11 - The UART module

The communication between the PC and the LM3S2965 is done through a RS232

communication using a RS232 transceiver (TRANSmitter - reCEIVER). This is so because the

LM3S2965 evaluation board does not have an implemented transceiver, so an external one had to

The maximum possible baud rate was 57600. The implemented UART works with

rate of 19200. An inferior baud rate was preferred in order to be sure that the UART was working

inside the performance limitations specified in Software UART for Stellaris Microcontrollers

. It has no parity or even parity, and one stop bit. It sends packets of 8 bits. The

transmission and Reception FIFOs have also been enabled.

Before a message is sent, it is written in a 16-byte FIFO list where it waits until the

sends it. The same goes for a message that has just been received. For both

FIFOs (there is a transmission FIFO and a reception FIFO), a level has to be defined. This level

is used to trigger an interruption each time the amount of data stored inside the FIFO reaches that

nterruption will then alert the microcontroller, who will read the FIFO (in the case of

the RX FIFO), or add more data to be sent (TX FIFO). The default level for both FIFOs is 8

bytes. In the case of this UART, the interruptions have been programmed to be triggered every

time we have more than 8 bytes in the RX FIFO, and less than 2 bytes in the TX FIFO.

l diagram of how the reception works.

ugh a RS232

reCEIVER). This is so because the

LM3S2965 evaluation board does not have an implemented transceiver, so an external one had to

mented UART works with a baud

rate of 19200. An inferior baud rate was preferred in order to be sure that the UART was working

Software UART for Stellaris Microcontrollers

or even parity, and one stop bit. It sends packets of 8 bits. The

byte FIFO list where it waits until the

message that has just been received. For both

FIFOs (there is a transmission FIFO and a reception FIFO), a level has to be defined. This level

is used to trigger an interruption each time the amount of data stored inside the FIFO reaches that

, who will read the FIFO (in the case of

the RX FIFO), or add more data to be sent (TX FIFO). The default level for both FIFOs is 8

triggered every

time we have more than 8 bytes in the RX FIFO, and less than 2 bytes in the TX FIFO. Figure 12

Page 31: Arm Cortex

31

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

All the interruptions from the UART are managed by the function

function is triggered by all the interruptions coming from the UART. It verifies which type of

interruption has appeared, then calls the function related with its treat

different types of interruptions: overrun error, break error, parity error, framing error, timeout

error, transmission error, and reception error. Interruptions can be enabled or disabled by means

of a mask register called Masked Inte

detect all of the interruptions except for the break error and the parity error.

In order to send a message using the UART, the

StartTransmission. This function will wait until the UART is free to be used by checking the

UART flag register. Then, it partially fills in the FIFO, in order to enable

interruption. The microcontroller

perform the communication between the PC and the LM3S2965

filled (at least 32 bits must be written into) in order to trigger the interruption related with the

transmission of information. This interruption is only triggered wheneve

inside the FIFO goes below a pre

Once the first interruption has been triggered, the Transmission interruption is called every time

the data stored in the FIFO is inferio

FIFO. Hence, the transmission works automatically after the first call of

MuZIC Internship Report

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Figure 12- Reception process All the interruptions from the UART are managed by the function UART0_Handler

function is triggered by all the interruptions coming from the UART. It verifies which type of

interruption has appeared, then calls the function related with its treatment. There are seven

different types of interruptions: overrun error, break error, parity error, framing error, timeout

error, transmission error, and reception error. Interruptions can be enabled or disabled by means

Masked Interrupt Status (MIS). This UART has been programmed to

detect all of the interruptions except for the break error and the parity error.

In order to send a message using the UART, the microcontroller has to call first the function

tion will wait until the UART is free to be used by checking the

UART flag register. Then, it partially fills in the FIFO, in order to enable the Transmission

microcontroller has implemented some interruptions that can be used to

between the PC and the LM3S2965. The FIFO needs to be partially

filled (at least 32 bits must be written into) in order to trigger the interruption related with the

transmission of information. This interruption is only triggered whenever the amount of data

nside the FIFO goes below a pre-determined level (in this case, 1/8 of the total FIFO, 2 bytes).

Once the first interruption has been triggered, the Transmission interruption is called every time

the data stored in the FIFO is inferior to that amount, and more data is written inside the TX

FIFO. Hence, the transmission works automatically after the first call of StartTransmission

ship Report 2009

UART0_Handler. This

function is triggered by all the interruptions coming from the UART. It verifies which type of

ment. There are seven

different types of interruptions: overrun error, break error, parity error, framing error, timeout

error, transmission error, and reception error. Interruptions can be enabled or disabled by means

This UART has been programmed to

has to call first the function

tion will wait until the UART is free to be used by checking the

the Transmission

has implemented some interruptions that can be used to

. The FIFO needs to be partially

filled (at least 32 bits must be written into) in order to trigger the interruption related with the

r the amount of data

determined level (in this case, 1/8 of the total FIFO, 2 bytes).

Once the first interruption has been triggered, the Transmission interruption is called every time

r to that amount, and more data is written inside the TX

StartTransmission.

Page 32: Arm Cortex

In order to receive a message, a similar system applies: but this time, an interruption is

triggered every time the Rx FIFO has more than 8 bytes in store. Thus, the UART has to take

into account three different scenarios when receiving a message:

1) Data size is inferior to 8 bytes: In this case, the Reception interruption is never

triggered (RX FIFO level has been set to 8 bytes). Nevertheless, the timeout interruption

is triggered. This interruption alerts the microcontroller whenever some data has arrived,

but hasn’t been read yet. It is set 32 bits after the reception of the data. This function

reads all the information until there is no more data left inside RX FIFO. Figure 13

shows an example.

Figure 13 – UART Reception (less than 8 bytes). The Timeout interruption is triggered; all the RX FIFO is read

2) Data size is equal to 8 bytes (or multiples of 8 bytes): The Reception interruption is

triggered, and all the data is read form the FIFO. The process is shown in Figure 14 and

Figure 15.

Page 33: Arm Cortex

MuZIC Internship Report 2009

33

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Figure 14 – UART Reception (multiple of 8 bytes) (I): The reception interruption is

triggered

Figure 15 – UART Reception (multiple of 8 bytes) (II): Message read

3) Data size is not a multiple of 8 bytes (and data is superior to 8 bytes): First, the

Reception interruption will be triggered, and 8 bytes will be read out of the RX FIFO.

Then (32 bits after), as more data is left inside the RX FIFO, the timeout interruption will

be triggered, and the rest of the data will be read. Figure 16, Figure 17 and Figure 18

show an example.

Page 34: Arm Cortex

Figure 16 - UART Reception (more than 8 bytes, not multiple) (I): Reception

interruption + Timeout interruption

Figure 17 - UART Reception (more than 8 bytes, not multiple) (II): Reading 8 first

bytes

Page 35: Arm Cortex

MuZIC Internship Report 2009

35

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Figure 18 - UART Reception (more than 8 bytes, not multiple) (III): Reading the

data left

In order to implement the UART module inside the RTOS, a wrapping and an unwrapping

function were implemented. The wrapping function takes the data which will be sent to the PC

and add the SOF byte, the length of the message, and a checksum. The unwrapping function is

used whenever a new message comes from the PC: it reads the type of command sent by the

computer, the length of the message and the data (if there is any).

In both interruptions, a series of tests are performed in order to verify that the content of the

data has not been damaged: this includes checking the SOF byte, the size of the data (which

cannot exceed the size of OSCAR buffer), and the total length of the message

7. Remarks

During the implementation of the peripheral, the following issues had to be sorted out:

• At first, the PC could not understand what the evaluation board was sending. The reason

for this was that there was no transducer in the evaluation board. A small setup

(including the RS232) was made between computer and LM3S2965 to solve it.

• Nevertheless, the biggest issue while implementing the UART was the management of

the TX and RX FIFOs. Even though the interruption registers were correctly configured,

we would not see any interruption trigger when writing in the TX FIFO. This was a

problem, because the amount of data sent was necessary in order to check that the whole

message was being sent to the PC. The reason was that no flag was set because the

amount of data written in the TX FIFO was not enough. The TX packets written in the

Page 36: Arm Cortex

FIFO had to be at least 16 bytes long to pull up the configured flag. Something similar

happened with the RX FIFO. Sometimes, received messages would not have a correct

checksum, even though the rest of the message was correct. This depended on the length

of the message and the interruption management. We discovered that not only a

reception interruption was needed, but also a time-out interruption. The time-out

interruption enabled a correct read of the RX FIFO whenever we knew there was data

left but the Rx flag would not raise.

• Finally, there were some issues regarding the code migration from a microcontroller

using a system clock of 8MHz (the one included in the evaluation board) to another one

using 12.6MHz. This was due to the PLL inside the micro. The PLL only works with

system clocks up to 8MHz, and the value of the crystal has to be specified before setting

it (See LM3S2965 Datasheet for more information). Although it was not used in our

case, we had to make sure that no crystal value was written in the system clock

configuration. Otherwise, the PLL got confused and the board got frozen, thus making

any reprogramming impossible.

Page 37: Arm Cortex

MuZIC Internship Report 2009

37

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

The FPGA connection

1. Introduction

In order to communicate between the FPGA and the microcontroller, another connection

had to be implemented. As the distance between both of them is a short one, the obvious choice

was to implement a Serial Peripheral Interface Bus (SPI).

2. Main definitions

A Field-Programmable Gate Array (FPGA) is a semiconductor that can be configured by the

customer after manufacturing. They are programmed either using logic circuit diagrams or source

code in hardware description language to specify how the chip will work. Hence, they can be

used to implement any logical function that a specific integrated circuit could perform, but with

the possibility to update the functionality once it is embedded in a circuit.

A Serial Peripheral Interface Bus (SPI) is a synchronous serial data link standard named by

Motorola that allows simultaneous communication in both directions (from device A to device B

and from device B to device A). Devices communicate in master/slave mode where the master

device initiates the data frame. Multiple slave devices are allowed with individual slave select

(chip select) lines.

Sometimes SPI is called a ‘four wire’ serial bus: the serial clock SCLK (output from

master), the serial data in SDI (input for master), the serial data out SDO (output from master),

and the chip select nCS (active low, output from master).

When working with a single slave device, the nCS can be fixed to active low, but some

slaves require the falling edge of the slave select in order to initiate action.

To begin a communication, the master first configures the clock using a frequency

supported by the slave. Then, it pulls the slave select low. If a waiting period is required (for

example, with ADC slaves), then the master must wait for at least that period of time before

starting to issue clock cycles. Finally, the full duplex communication takes place: the master

sends a bit, the slave reads it: and the slave sends a bit, the master reads it. The four operations

take always place, but they might not be always of interest for the user (like in the case of

dummy writes from the master in order to receive data from the slave: this is performed in order

Page 38: Arm Cortex

to give the clock to the slave, so that it can send data using it). Once the transmission is over, the

master stops sending the clock, and pulls up nCS.

In addition to setting the clock frequency, the mas

(CPOL) and phase (CPHA) respect to the data:

• At CPOL = 0, the base value of the clock is zero. Inversely, at CPOL = 1, the base value

of the clock is one.

• CPHA=0 means sample on the first clock edge, while CPHA=1

second clock edge, regardless of whether that clock edge is rising or falling. Note that

with CPHA=0, the data must be stable for half cycle before the first clock cycle.

Figure 19 shows a timing diagram with clock polarity and phase:

Figure

For detailed information about the

LM3S2965 Datasheet.

3. Objectives

As we have seen in the Mu

communication in oilfield operations. Part of the signal processing associated with the

transmission (TX) and reception

There are two ways in which the TX can function, and one way for the RX. In all modes, the

communication between microcontroller

to give the clock to the slave, so that it can send data using it). Once the transmission is over, the

master stops sending the clock, and pulls up nCS.

In addition to setting the clock frequency, the master must also configure the clock polarity

(CPOL) and phase (CPHA) respect to the data:

At CPOL = 0, the base value of the clock is zero. Inversely, at CPOL = 1, the base value

CPHA=0 means sample on the first clock edge, while CPHA=1 means sample on the

, regardless of whether that clock edge is rising or falling. Note that

with CPHA=0, the data must be stable for half cycle before the first clock cycle.

g diagram with clock polarity and phase:

Figure 19 – Clock Polarity and Phase

For detailed information about the SPI’s characteristics of the LM3S2965, please refer to the

the MuZIC Presentation of the project, this project tries to bring

communication in oilfield operations. Part of the signal processing associated with the

reception (RX) functions are implemented on the embedded FPGA

There are two ways in which the TX can function, and one way for the RX. In all modes, the

microcontroller and FPGA are done via SPI.

to give the clock to the slave, so that it can send data using it). Once the transmission is over, the

ter must also configure the clock polarity

At CPOL = 0, the base value of the clock is zero. Inversely, at CPOL = 1, the base value

means sample on the

, regardless of whether that clock edge is rising or falling. Note that

with CPHA=0, the data must be stable for half cycle before the first clock cycle.

please refer to the

project tries to bring

communication in oilfield operations. Part of the signal processing associated with the

the embedded FPGA.

There are two ways in which the TX can function, and one way for the RX. In all modes, the

Page 39: Arm Cortex

MuZIC Internship Report 2009

39

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

In the first implementation of the TX processing, the FPGA is in charge of the passband

processing, and the microcontroller performs the baseband processing. Figure 20 shows a

diagram of the steps followed by data inside the FPGA in this mode:

Figure 20 – FPGA Treatment

The I/Q complex signal sent by the microcontroller is interpolated by an interpolation factor,

then filtered using a Square-Root-Raised Cosine filter. The resulting signal is sampled and

shifted to passband, coded as 16-bit data and transformed into a real signal. After this, the signal

is interpolated and filtered using another Square-Root-Raised Cosine filter. The resulting signal

is finally scaled, and an offset is added in order to obtain positive values.

The second implementation of the TX processing is done entirely by the microcontroller. Its

output is directly a PWM signal which is transmitted to the FPGA at 100 KHz. It is used to

generate the PWM command signals which come out of the FPGA.

Lastly, the RX passband processing is performed by the FPGA, and the microcontroller is in

charge of the RX baseband processing. Figure 21 shows the data path from ADC to micro.

Figure 21 – Rx Analog to Digital

The ADC signal is first converted to baseband by mixing it with a complex exponential. The

result is an I/Q signal which is filtered using a Square-Root-Raised Cosine filter. This procedure

is performed five times, one for each of the carrier frequencies. Figure 22 shows a diagram of the

process, where Fc is one of the carrier signals.

Page 40: Arm Cortex

Figure 22 – Rx FPGA

In order to implement the different processing modes, the contractor delivered a program

which acted as a “black box” from the point of view of the microcontroller, with the following

FPGA inputs and outputs:

Inputs:

• ADC_DIN: Data coming from the ADC.

• ADC_nDRDY: Pin that tells the FPGA that a new data is ready to be read in the ADC.

• RST: Active-High Reset.

• CLK: Main system clock received from a 12.8MHz oscillator (in our case, the

microcontroller’s oscillator).

• nCS: SPI’s microcontroller’s chip select.

• SCLK: SPI’s microcontroller’s clock.

• SDin: SPI’s microcontroller’s data in.

Outputs:

• ADC_CLK: ADC’s main clock.

• ADC_MODE: ADC’s functioning mode

• ADC_FORM

• ADC_SCLK: SPI’s ADC’s clock.

• ADC_nSYNC: ADC’s synchronization pin.

• PWMout: PWM output.

• SDout: SPI’s microcontroller’s data out.

• DRQ: FPGA’s Data Request.

• RQ50k: FPGA’s PWM’s data request.

Page 41: Arm Cortex

MuZIC Internship Report 2009

41

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

• Error: For debugging purposes.

• RSTout: Microcontroller’s and/or ADC’s reset.

The module implemented in this section has to configure the FPGA for all the different

processing modes, and ensure that the PWM signal obtained at the end of the chain is correct. As

all the FPGA coding was performed by a contractor, the program has to check that the FPGA

code is correct and meets the specifications.

4. Specifications

Considering the previous section, the specifications for the SPI between the FPGA and the

microcontroller are the following:

• The peripheral has to work using interruptions whenever possible.

• The SPI has to use a clock speed of 2.56MHz. (F/5, where F=12.8MHz, the clock of the

FPGA).

• The messages are 24 bits long and can be divided in two parts: first, the command frame

(8 bits), and then the data frame (16 bits). The chip select (nCS) has to be pulled down at

the beginning of each transmission and pulled up at the end.

• The Data line has to be sampled on the falling edge of SCLK (CPOL=0).

• A library of commands and messages has to be implemented.

• The microcontroller has to be able to load into the memory of the FPGA the Sinewave

Memory (used when sampling), the two FIR filters and the gain and offset of the PWM.

• Once the FPGA has been duly programmed, the microcontroller has to be able to start a

transmission.

• After the configuration of the FPGA, the microcontroller has to send data in the

following situations:

o When in the second implementation of the TX processing, a new PWM value has to

be sent every rising edge of RQ50K (output FPGA signal).

o When in the first implementation of the TX processing, a new I/Q value has to be

send every rising edge of DRQ.

At the same time, the program has to check that the program inside the FPGA works as

specified:

• Pins have to be assigned to the FPGA, and the program has to be loaded inside, with no

errors.

Page 42: Arm Cortex

• All the modules which compose the FPGA program have to be verified, and have to

work according to the specifications:

o The SPI between the FPGA and the ADC. (adc_if.v)

o The Transmitter processing block. (coder.v)

o The Receiver processing block. (decoder.v)

o The PLL that generates the clock for the ADC and the FPGA (using the one from

the micro). (PLL12_8.v)

o The Power On Reset module. (por.v)

o The PWM generator. (pwm.v)

o The SPI interface with the microcontroller. (spi.v)

o The internal RAM memory where the tables will be loaded. (sram2.v)

5. Procedure used to attain the specifications

The procedure followed for the implementation of this module has been incremental. First,

the program had to be loaded into the FPGA and the pins had to be assigned. Once this was

performed, PLL12_8.v could be tested. Second, a simple SPI configuration (which only sent data

from the micro to the FPGA) was programmed. With this function properly configured, all of the

Transmission modes could be implemented, and coder.v, pwm.v, spi.v, and sram2.v could be

tested. At this point, a PWM output from the FPGA should be seen.

Concerning the implementation of the reception mode, it was decided to not to test it for the

moment, so it was not implemented in the following program.

6. Results

The result was a driver that configured the SPI and the FPGA for the Transmission modes.

Once the configuration of the processing mode has been done, the module works via

interruptions. Every time a rising edge coming from the FPGA’s DRQ or RQ50k outputs

(depending on the processing mode the micro is working) is received, an interruption is

triggered. Since no information was expected to come from the FPGA at this stage, no receiving

functions were programmed.

All the functions have been implemented in the file called drv_spi_fpga.c (Annex A:

Peripheral’s Code). This task manages and controls all low level SPI communications between

the FPGA and the LM3S2965. It has been designed to:

Page 43: Arm Cortex

43

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

• Configure the SPI connection with

• Configure the FPGA with the function

memory the Sinewave Mixer Table, the FIR coefficients

PWM gain and offset.

• Configure the interruption triggers for each TX processing mode using

ConfigurationTriggerRQ50k

using IntRQ50KHandler

• Reset the FPGA using the function

• Start TX transmission using the function

• Transmit data using the functions

• Stop the SPI transmission using the function

Figure 23 shows the SPI access module structure.

In order to test the different TX processing modes separately, a test bench was created

(spi_fpga_test_bench.c). This enables the user to choose between both modes before

programming the microcontroller

The desired SPI clock speed was not allowed by the LM3S2965. Instead, we had to choose

between 3.20MHz and 2.13MHz (12.8/4 and 12.8/6, respectively). After talking with the

contractor, (in order to check which of the two was best suppo

3.20MHz was chosen because it was faster.

MuZIC Internship Report

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Configure the SPI connection with SSI_ConfigureSPI.

Configure the FPGA with the function SSI_ConfigureFPGA. It writes on the FPGA

memory the Sinewave Mixer Table, the FIR coefficients (FIR tables 1 and 2)

gure the interruption triggers for each TX processing mode using

ConfigurationTriggerRQ50k and ConfigurationTriggerDRQ, and handle the interruption

IntRQ50KHandler and IntDRQHandler.

Reset the FPGA using the function SSI_ResetFPGA.

sion using the function SSI_SendStart.

Transmit data using the functions SSI_Send8 and SSI_Send16.

Stop the SPI transmission using the function SSI_Stop.

shows the SPI access module structure.

Figure 23 – SPI module

In order to test the different TX processing modes separately, a test bench was created

This enables the user to choose between both modes before

microcontroller and testing the selected mode.

The desired SPI clock speed was not allowed by the LM3S2965. Instead, we had to choose

between 3.20MHz and 2.13MHz (12.8/4 and 12.8/6, respectively). After talking with the

contractor, (in order to check which of the two was best supported by the FPGA’s program)

3.20MHz was chosen because it was faster. It is also compatible with the FPGA’s

ship Report 2009

. It writes on the FPGA

(FIR tables 1 and 2), and the

gure the interruption triggers for each TX processing mode using

, and handle the interruption

In order to test the different TX processing modes separately, a test bench was created

This enables the user to choose between both modes before

The desired SPI clock speed was not allowed by the LM3S2965. Instead, we had to choose

between 3.20MHz and 2.13MHz (12.8/4 and 12.8/6, respectively). After talking with the

rted by the FPGA’s program)

It is also compatible with the FPGA’s

Page 44: Arm Cortex

implementation (verified by the contractor). The SPI clock polarity has been set to 0, while the

clock phase is 1. The frame format used for the SPI is that defined Motorola. There was no need

in enabling the SPI’s FIFO’s because no data coming from the FPGA was expected and the TX’s

FIFO’s state could be checked in the flag register.

First, the program configures the system clock and enables the ports used by the SPI. Then,

it configures the interruptions and the SPI. Finally, if we are in the first TX processing mode,

PWM values are sent when asked by the FPGA. If the second TX processing mode is being set,

the FPGA is configured, and the simulation is started. Even though each TX processing mode

uses a different trigger, their configuration is exactly the same except for the number of the input

pin used: they both configure the micro to detect rising edges on that pin and enable an

interruption.

As we previously said, the FPGA is needs to receive 24-bit messages. Unfortunately, the

Luminary’s SPI’s maximum data size of a message is 16bits. So there was no way we could send

a 24-bit message, all in one block. The implemented solution pulls down the chip select, then

sends two packets of data, and finally pulls up again the chip select. The first packet is an 8-bit

packet (the command frame), the second one a 16-bit packet (the data frame). As both packets

are sent when the chip select is low, it makes no difference for the FPGA. There is a time delay

between both packets, but this could not be helped. The reason for this is that every time the data

size of the message is modified, the SPI has to be stopped and reconfigured. Apart from the

configuration time, there is a mandatory 3-system-clock-tick-delay after the configuration of a

peripheral. A waiting period is also imposed by the FPGA after each transmission, because no

reconfiguration is possible while the SPI is busy. Nevertheless, this delay does not keep the SPI

from working properly and dealing with the time restrictions imposed by the FPGA program.

In order to send a message to the FPGA, the microcontroller has to call the functions

SSI_Send8 and SSI_Send16. The first one stops the SPI, reconfigures its data size to be 8 bits,

pulls down the chip select, and sends the command frame. Once the data has been handed to the

TX FIFO, it also waits until it is not busy anymore. After this, SSI_Send16 is called. Its task is to

stop again the SPI, reconfigure it to send 16-bit messages, and send the data frame. When the SPI

is not busy anymore, the chip select is pulled up.

As we can see in the FPGA configuration functions, no interruptions are needed. Polling has

been used instead. This is so because of the nature of the functions: in the final RTOS version,

everything is configured before start using interruptions. Configuration has been conceived as a

sequential part, and no interruptions are used inside. For this reason, there are some times in

which a waiting instruction has been implemented. For example, when loading inside the FPGA

Page 45: Arm Cortex

45

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

the different tables. In order to prevent TX FIFO overflow, a

full?) has to be read every time a new element of the table is sent to

prevent the function from going faster than the SPI.

setting values of each processing mode and prepare the FPGA for transmission.

In order to start a transmission, the function

simply tells the FPGA that the transmission is going to start

Once the TX processing mode has been programmed, the implemented solution works using

interruptions. Whenever the FPGA needs a new data, it set a one in

(depending on the TX processing mode we are testing).

We can see in Figure 24

both modes.

MuZIC Internship Report

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

to prevent TX FIFO overflow, a state flag (called is the TX FIFO not

has to be read every time a new element of the table is sent to the FPGA. By doing this, we

prevent the function from going faster than the SPI. The microcontroller is able to load up the

setting values of each processing mode and prepare the FPGA for transmission.

rt a transmission, the function SSI_SendStart has to be called. This function

e transmission is going to start.

Once the TX processing mode has been programmed, the implemented solution works using

Whenever the FPGA needs a new data, it set a one in the RQ50k or in the DRQ pin

(depending on the TX processing mode we are testing).

and Figure 25 what happens when an interruption is triggered in

Figure 24 – First TX mode

ship Report 2009

is the TX FIFO not

the FPGA. By doing this, we

is able to load up the

be called. This function

Once the TX processing mode has been programmed, the implemented solution works using

the RQ50k or in the DRQ pin

what happens when an interruption is triggered in

Page 46: Arm Cortex

Figure

Note that in the first TX processing mode, the first I&Q values are sent “manually” using

the function SSI_SendISendQ. After the first val

interruption.

The rising edge is detected by the

interruption has its own handler (

the same actions. When any of these functions is called, the

is sent. In the case of IntRQ50KHandler

reset if the end of the table has been reached).

If the values asked by the

PWMout.

Figure 26 and Figure 27 show

Figure 25– Second TX mode

Note that in the first TX processing mode, the first I&Q values are sent “manually” using

the function SSI_SendISendQ. After the first values of I&Q have been sent, it enables the DRQ

The rising edge is detected by the microcontroller, which triggers an interruption. Each

interruption has its own handler (IntRQ50KHandler and IntDRQHandler), but they both perform

When any of these functions is called, the interruption is cleared and new data

IntRQ50KHandler, the index from the sine wave table is incremented (or

if the end of the table has been reached).

FPGA are duly sent, a PWM signal can be seen coming out from

show some transmissions using the different TX processing modes.

Note that in the first TX processing mode, the first I&Q values are sent “manually” using

ues of I&Q have been sent, it enables the DRQ

, which triggers an interruption. Each

), but they both perform

interruption is cleared and new data

table is incremented (or

FPGA are duly sent, a PWM signal can be seen coming out from

using the different TX processing modes.

Page 47: Arm Cortex

MuZIC Internship Report 2009

47

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Figure 26 – First TX Mode

Figure 27 – Second TX mode

While programming the FPGA with the contractor’s program, pins were assigned to it.

Table 2 shows all the FPGA inputs and outputs, with their associated pin.

Table 2: FPGA Pin Assignment

ADC PINS SYSTEM PINS SPI PINS

Input/Output Pin

Number

Input/Output Pin

Number

Input/Output Pin

Number

ADC_DIN 152 RST 14 nCS 5

ADC_nDRDY 143 CLK 134 SCLK 21

Page 48: Arm Cortex

ADC_CLK 155 DRQ 127 SDin 31

ADC_MODE 146 RQ50k 11 SDout 35

ADC_FORM 149 Error 2

ADC_SCLK 137 RSTout 18

ADC_nSYNC 140 PWMout 8

The FPGA implementation was performed with no errors. Configuring the SPI enabled the

test of the following modules: adc_if.c, coder.v, PLL12_8.v, pwm.v, spi.v, sram2.v. All of them

were proved to work as expected, except for coder.v, were some minor modifications has to be

performed regarding the gain and offset configurations of the PWM.

7. Remarks

This module took most of my internship’s time due to its complexity and the fact that third

party’s programs were involved. This needed a deeper understanding of the project, of the

specifications handed out to the contractor, and of the solution given by the contractor to those

specifications. Trying to connect the different visions of the project was the hardest part of it.

Several issues came out during the implementation of this part. As we will see during this

part, some of them needed the participation of the contractor, and a meeting was held during the

implementation of the SPI in order to clarify some points:

• The software platform required to program the FPGA with the contractor’s program was

a bit complicated, and some extra time was needed in order to be able to handle the new

environment and perform the required operations. Because it was the first time the

software was used by the team, a short document describing the steps to follow in order

to program the FPGA was written.

• In order to make sure that the information was being correctly sent via the SPI and

written on the FPGA’s memory, a reading function was implemented, with no success.

Even though the FPGA specifications clearly said that the FPGA’s program contained a

reading instruction, there was no such instruction. As no reading instruction had been

asked in the specification, the contractor did not program one, even though he wrote it in

the design documentation of the program. This issue was discussed in a later meeting

with the contractor, and it was finally decided that a reading option should be available in

Page 49: Arm Cortex

MuZIC Internship Report 2009

49

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

the FPGA program, at least for debugging purposes. The new version of the FPGA

program has not been tested yet.

• Once the second TX processing mode was implemented, some bugs were reported in the

PWM output. Figure 28 shows an image of the PWM signal.

Figure 28 – Faulty PWM signal

There were various reasons for this. First, the design documentation did not specify the

clock phase of the SPI, so it was set to its default value (zero). During the meeting with

the contractor, we were told that the needed value was 1, so the configuration of the SPI

had to be changed. Also, it was clear that the PWM and the SPI data were clearly not

synchronized. At an initial stage, the implemented program did not use an output signal

coming from the FPGA to trigger an interruption that would send a new value to the

FPGA. A timer of 50 KHz was set instead. Every time a timer interruption was triggered,

a new value was sent to the FPGA. This proved to be a misunderstanding of the

contractor’s design documentation from our side. As soon as this was noticed, a new

configuration was set, where new PWM values were sent every time the RQ50k signal

sent a rising edge. All of these modifications led to a satisfying PWM signal (see figures

from the previous section).

Page 50: Arm Cortex

The connection with the ADC

1. Introduction

The ADC also needed a communication link with the microcontroller. In order to do so,

another SPI was implemented between the LM3S2965. Much what was implemented in this

module was common to the previous one. Thus, all the common aspects will not be repeated in

this section. Instead, we will focus on those elements which differentiate this SPI connection

from the previous one.

2. Main Definitions

An Analog-to Digital Converter (ADC) is a device which converts continuous signals to

discrete digital numbers. A Digital-to-Analog Converter (DAC) performs the reverse operation.

Typically, an ADC is an electronic device that converts an input analog voltage to a digital

number proportional to the magnitude of the voltage. Most ADCs are linear, that is, the range of

the input value that map to each output value has a linear relationship with the output value.

ADCs are used virtually everywhere where an analog signal has to be processed, stored or

transported in digital form.

3. Objectives

We have seen in the previous sections that the downhole measures taken by the ADC have

to go through the FPGA before arriving to the micro. As long as the FPGA is functioning, the

system can work correctly. Unfortunately, there will be times when the FPGA will not be

working (for example, in case of an FPGA error). So in some situations it will be necessary to

bypass the FPGA and connect the ADC directly to the LM3S2965.

The following module has been implemented to make the system work without an FPGA. In

this case, the micro will be in charge of configuring the ADC and receiving its data.

The ADC used in this part contains the following inputs and outputs:

Inputs

• SPICLK: The clock of the SPI connection

• SDin: Data coming from the microcontroller.

• SYNC: Pin to synchronize the ADC with the microcontroller.

Page 51: Arm Cortex

MuZIC Internship Report 2009

51

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

• CS: Chip Select

Outputs:

• DRDY: Data ReaDY. Signal that informs the LM3S2965 of the arrival of new ADC

data.

• SDout: Data going out of the microcontroller.

4. Specifications

This module is expected to deliver an SPI between the ADC and the microcontroller with

the following characteristics:

• The ADC has to be calibrated before being used. Thus, a synchronization signal has to be

sent for 100ms to the SYNC pin.

• Once the configuration process has finished, the module has to work exclusively with

interruptions.

• The ADC will inform the microcontroller that new data is available by pulling down a

pin (DataReaDY pin). An interruption has to be triggered in order to handle the new

information.

• The ADC does not have a RAM memory, so it does not store data. That means that new

received values erase the precedent ones. The programmed module has to make sure that

the ADC data is read on time to prevent loss of information.

• It has to configure the SPI taking into account the needs of the ADC: the ADC data is 24

bits large, but its configuration only allows it to send this data to the microcontroller in

messages of 8 bits. The module has therefore to make sure that the 24 bits have correctly

arrived.

• As the master of the SPI connection is the LM3S2965, it is in charge of sending the SPI

clock to the ADC. So a dummy write has to be performed every time the ADC has new

data to send, in order to supply the ADC with the SPI clock.

5. Procedure used to attain the specifications

Most of this module was already implemented for the FPGA’s SPI, so the starting point for

the ADC’s SPI was the module from the previous section. The reception mode of the SPI was

developed from this code, and tested afterwards.

Page 52: Arm Cortex

6. Results

The result is another SPI driver that connected the ADC and the

Again, this module works via interruptions (once the configuration has been done).

This module uses two different types of interruptions: external interruptions (coming from

the ADC), and internal interruptions (coming from the SPI). In order to treat the first ones, the

microcontroller is configured to detect a falling edge in

the LM3S2965’s configuration)

simply performs a dummy write on the SPI

the transmission of the ADC data using the

InterruptSSIADCControl. This handler reads the masked interrupt status of the SPI, and treats the

different types of interruption which may occur: the reception interruption, the time

interruption, and the overrun interruption.

dummy reads are performed), so the overrun interruption has not been treated.

UART’s FIFOs, the trigger level cannot be configured. This means that a reception i

will only take place when more than half of the RX’s FIFO is full (more than 16 bytes). As the

data is only sent in 8-bit packets, this interruption will never be triggered. In fact, the only case to

be treated is the time-out interruption. Thi

read 32 bits after the data has arrived. When this interruption takes place, a read of the RX is

performed, as well as a new dummy write.

Figure 29 shows a small diagram of the tasks performed by this module

This driver first configures the input pin which will be used by the ADC to tell the

microcontroller that new data has arrived, and configures the SPI be

Then, it synchronizes the ADC, and enables the interruptions coming

DRDY pin. Finally, it enters an infinite loop where a blinking LED is set in order to check that

the program is running.

spi_adc_test_bench.c.

The result is another SPI driver that connected the ADC and the microcontroller

Again, this module works via interruptions (once the configuration has been done).

is module uses two different types of interruptions: external interruptions (coming from

the ADC), and internal interruptions (coming from the SPI). In order to treat the first ones, the

is configured to detect a falling edge in the DRDY signal (ADCIC

configuration), and the interruptions are handled using InterruptIC

simply performs a dummy write on the SPI in order to give the ADC the SPI clock, necessary for

the transmission of the ADC data using the SPI. The second type of interruptions are managed by

. This handler reads the masked interrupt status of the SPI, and treats the

different types of interruption which may occur: the reception interruption, the time

nd the overrun interruption. There is no need in sending data to the ADC (only

dummy reads are performed), so the overrun interruption has not been treated. Unlike with the

UART’s FIFOs, the trigger level cannot be configured. This means that a reception i

nly take place when more than half of the RX’s FIFO is full (more than 16 bytes). As the

bit packets, this interruption will never be triggered. In fact, the only case to

out interruption. This interruption will appear if received data has not been

read 32 bits after the data has arrived. When this interruption takes place, a read of the RX is

new dummy write.

small diagram of the tasks performed by this module

Figure 29 – ADC Module

This driver first configures the input pin which will be used by the ADC to tell the

that new data has arrived, and configures the SPI between this two devices.

Then, it synchronizes the ADC, and enables the interruptions coming from the SPI and

pin. Finally, it enters an infinite loop where a blinking LED is set in order to check that

The test bench used to test this module is stored in

microcontroller directly.

Again, this module works via interruptions (once the configuration has been done).

is module uses two different types of interruptions: external interruptions (coming from

the ADC), and internal interruptions (coming from the SPI). In order to treat the first ones, the

ADCIC is in charge of

InterruptIC, which

in order to give the ADC the SPI clock, necessary for

. The second type of interruptions are managed by

. This handler reads the masked interrupt status of the SPI, and treats the

different types of interruption which may occur: the reception interruption, the time-out

There is no need in sending data to the ADC (only

Unlike with the

UART’s FIFOs, the trigger level cannot be configured. This means that a reception interruption

nly take place when more than half of the RX’s FIFO is full (more than 16 bytes). As the

bit packets, this interruption will never be triggered. In fact, the only case to

s interruption will appear if received data has not been

read 32 bits after the data has arrived. When this interruption takes place, a read of the RX is

This driver first configures the input pin which will be used by the ADC to tell the

tween this two devices.

the SPI and the

pin. Finally, it enters an infinite loop where a blinking LED is set in order to check that

o test this module is stored in

Page 53: Arm Cortex

53

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

The SPI clock has been configured with a 2.13MHz

phase are set to zero. The frame format is that of Motorola. As data was going to be recei

from the ADC, the SPI’s FIFO’s had to be enabled.

set to 8 bits.

Figure 30 shows the path followed whenever new data is ready in the ADC.

Figure

Whenever the ADC has new data, DRDY is pulled down. This triggers an interruption

which performs a dummy write over the SPI connection (

dummy read is used by the ADC to write on the SPI (

reception interruption, where the first 8 bits of the 24

the microcontroller’s memory. At the same time, a dummy write is performed to enable the next

packet to be sent. A counter is also incremented to ke

interruption is called 3 times. Once the whole message has been

Figure 31 and Figure 32

microcontroller. We can see that the whole ADC message is read before a new one arrives.

MuZIC Internship Report

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

The SPI clock has been configured with a 2.13MHz-clock. Both clock polarity and clo

phase are set to zero. The frame format is that of Motorola. As data was going to be recei

s FIFO’s had to be enabled. Finally, the data size of the messages was

shows the path followed whenever new data is ready in the ADC.

Figure 30 – ADC Interruption

Whenever the ADC has new data, DRDY is pulled down. This triggers an interruption

which performs a dummy write over the SPI connection (SPI TX pin). The clock sent with the

dummy read is used by the ADC to write on the SPI (SPI RX pin). This message tri

reception interruption, where the first 8 bits of the 24-bit ADC’s message are read and stored in

’s memory. At the same time, a dummy write is performed to enable the next

packet to be sent. A counter is also incremented to keep track of the received parts. The reception

interruption is called 3 times. Once the whole message has been received, the counter is reset

32 show the SPI communication between the ADC and the

. We can see that the whole ADC message is read before a new one arrives.

ship Report 2009

clock. Both clock polarity and clock

phase are set to zero. The frame format is that of Motorola. As data was going to be received

Finally, the data size of the messages was

Whenever the ADC has new data, DRDY is pulled down. This triggers an interruption

). The clock sent with the

is message triggers the

bit ADC’s message are read and stored in

’s memory. At the same time, a dummy write is performed to enable the next

ep track of the received parts. The reception

received, the counter is reset.

he SPI communication between the ADC and the

. We can see that the whole ADC message is read before a new one arrives.

Page 54: Arm Cortex

Figure 31 – ADC Transmission

Figure 32 – ADC Transmission (detail): 24 bits

7. Remarks

In general, this driver did not cause major problems. Anyway, some issues occurred:

• When programming the reception interruptions, no interruptions were triggered, even

though the configuration was correct. This due to the fact that no reception interruption

actually took place, and that the one which was actually taking place was the time-out

interruption. Once this configured, we were able to read the ADC data.

• While developing the module, we were surprised to notice that more than the actual

number of interruptions were taking place. The reason for this was that the DRDY

interruption flag register was not being cleared after the interruption had been treated.

Not cleaning the flag caused false interruptions.

Page 55: Arm Cortex

MuZIC Internship Report 2009

55

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Generation of PWM Commands

1. Introduction

To round up the previous section, a PWM module was needed in order to fully bypass the

FPGA role in the MuZIC board. Fortunately, LM3S2965 counts with some PWM generators that

make this possible. The present section will discuss about the implementation of the Luminary’s

PWM.

2. Main Definitions

Pulse-Width Modulation (PWM) is a very efficient way of providing intermediate amounts

of electrical power between fully on fully off. A simple power switch with a typical power source

provides full power only, when switched on. PWM is a comparatively recent technique, made

practical by modern electronic power switches.

Basically, a PWM variable-power scheme switches the power quickly between fully on and

fully off in a signal. In any event, the switching rate is much faster than what would affect the

load, which is to say the device that uses the power. In practice, applying full power for part of

the time does not cause any problems; PWM is very practical.

The term duty cycle describes the proportion of on time to off time; a low duty cycle

corresponds to low power, because the power is off for most of the time. Duty cycle is expressed

in percent, 100% being fully on.

3. Objectives

This module has been conceived to complement the previous module (see The FPGA

connection). In order to bypass effectively the FPGA, all of the tasks performed by the later have

to be done by the LM3S2965. This includes the generation of the PWM command: once the

information from the ADC has been duly treated, it has to be used to generate the PWM

command that will diffuse the information over the MuZIC network.

The module that will be exposed in this chapter needs to simulate this: it has to take

information from the microcontroller’s memory and generate a series of PWM pulses.

Page 56: Arm Cortex

4. Specifications

Taking into consideration the characteristics of the PWM signal generated by the FPGA,

this module has to provide a PWM generator with the following characteristics:

• As the other peripherals, the PWM has to work via interruptions.

• A couple of left-aligned PWM signals.

• The second PWM signal has to be generated applying a dead band to the first one.

Equation 1 and Figure 33 show both PWM signals, and the relation between them.

Figure 33 – PWM Specifications

Equation 1 – PWM Period

Taking into consideration the system clock used by the microcontroller, the dead band

has to measure 10 clock ticks (10/12.8MHz seconds).

Page 57: Arm Cortex

MuZIC Internship Report 2009

57

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

5. Procedure used to attain the specifications

In order to implement a fully operational PWM with dead-bands, we decided to start first by

generating only one PWM signal with a constant output. After that, we added the dead-bands and

programmed the second signal. And lastly, we implemented an interruption which loaded a new

PWM output value from a table, in order to obtain the final PWM.

6. Results

Before explaining the characteristics of the implemented PWM, we will discuss shortly

about the functioning of the PWM generator of the LM3S2965, in order to have a better

understanding of the results.

The LM3S2965 can generate PWM signals using different methods, but they all use the

same principle, which is comparing a counter value to a series of user-programmed values. There

are two different counting modes. In the first one, the timer counts from the load value to zero,

and then goes back to the load value. In the second mode, the timer counts from zero to the load

value, then from the load value to zero, and so on. Generally, the first method is used for

generating left- or right-aligned PWM signals, while the second one is used for generating

center-aligned PWM signals. Since the following module has to reproduce the FPGA’s PWM

signal, we will focus on the first mode.

As we said, there are several comparators (precisely, two) in the PWM generator that

monitor the value of the counter. When either of them matches the counter, they output a single-

clock-cycle-width High pulse. These qualified pulses are used in the PWM generation process.

Since the second PWM signal depends on the first one, only the first of the comparators is used.

Figure 34 shows an example of a count-down timer configuration, with the different values used

in the PWM generation. The comparator used in our PWM signal is CompA.

Page 58: Arm Cortex

Figure 34 – Count-down Timer configuration

The Load value stores the frequency of the PWM output signal (since the PWM uses a

timer, the period of the signal is set by the time taken by the timer to count from Load to zero).

Note from the previous figure that every time the timer reaches zero, a pulse is generated. This

pulse will be used to change the CompA value and generate the final PWM signal. The PWM

generator takes the CompA pulse and generates a PWM signal. This signal passes through the

dead-band generator, where both output PWM signals are generated. The first output PWM

signal is the input signal with the rising edge delayed by a programmable amount. The second

output PWM signal is the inversion of the input signal with a programmable delay added

between the falling edge of the input signal and the rising edge of this new signal. The result is a

pair of active High signals where one is always High, except for a programmable amount of time

at transitions where both are Low. As we previously said, the dead-band delay prevents shoot-

through current from damaging the power electronics. Figure 35 shows the PWM signal created

using the dead-band generator.

Page 59: Arm Cortex

MuZIC Internship Report 2009

59

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Figure 35 – Dead bands

The present module contains a driver that configures the PWM peripheral of the

microcontroller and generates a couple of PWM signals using a dead-band generator. The timer

uses the main system clock to count in the count-down mode, with no synchronization mode

(there is no need in synchronizing the two output signals since they already are synchronized)

and a frequency of 100 KHz. Both dead bands are set to 380 ns (5 timer counts using a 12.8MHz

system clock). Once the configuration of the peripheral has been fully accomplished, the module

works via interruptions. Whenever the timer reaches zero, an interruption is triggered. This

interruption changes the CompA value in order to get a different PWM output.

All the functions have been implemented in the file called drv_pwm.c (Annex A:

Peripheral’s Code). This driver contains the configuration of the PWM peripheral as well as the

handler for the interruptions. It has been designed to:

• Configure the PWM 0 and its interruption triggers using PWM_Configure.

• Handle the interruption generated by a zero value in the timer to modify the value of the

CompA comparator (InterruptPWM0).

The function PWM_Configure configures the PWM clock and enables the port used by the

PWM 0. Then it sets the PWM outputs, and configures the PWM. It also initializes CompA with

a default value. Finally, it configures the PWM interruptions and starts the timer.

Every time we reach zero with the timer, the InterruptPWM0 handler is called. This function

loads a new CompA value from a table, and resets the table index when the end of the table is

reached.

Figure 36 and Figure 37 show the resulting output from the implemented module when

sending a 5000Hz sinusoid with the 100 KHz PWM of this module.

Page 60: Arm Cortex

Figure 36 – PWM with Dead-band

Figure 37 – PWM with Dead-Band (detail)

7. Remarks

This was the only peripheral with helpful example codes, so its implementation did not

arouse issues worth mentioning. The most delicate aspect of its configuration was understanding

how the LM3S2965’s PWM worked in order to program the correct configuration.

Page 61: Arm Cortex

MuZIC Internship Report 2009

61

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Conclusion

This internship has enabled me to learn many things about the petroleum activity in general,

as well as about Schlumberger’s outstanding position in the energy market. The world petroleum

industry requires the use of very advanced technologies and skills, and Schlumberger’s aim for

excellence and the highest technologic performance accentuates this. Nevertheless, it was the

cultural diversity which made this internship really unique. It was very challenging to share work

and ideas with so many different people.

Regarding the MuZIC project, the most gratifying part was being taken into consideration,

just like any other member of the team. I were given real responsibilities and real work, and

could participate as an active part in meetings.

When I arrived to the team five months ago, the MuZIC project had long been started, but a

new work line had just been opened with the use of a new microcontroller. In parallel with the

old MuZIC prototypes, a new version of the tool and new tests were being performed. This

allowed me to see many stages of a project at the same time, thus working with new prototypes

as well as performing real tests with the older tools. Field tests were a constant source of

problems and issues, which meant new challenges and many things to learn about. I have tried to

help with my initiative, but keeping always in mind my role as intern. Experience, as in

everywhere, is a grade that has to be taken into account.

I had the opportunity to learn how to work in a team project and how to a meeting should be

organized. The communication in the team was excellent. The hierarchy was almost flat.

Everyone in the team was important and all tasks were reflected directly in the final product.

My willingness to learn and help as much as possible in the different parts of the project

enabled me to give a hand in some lab tests and in the preparation of field tests.

Working at Schlumberger was a real chance and I have really enjoyed working in the

research and development part. Schlumberger is a perfect company for developing a professional

career in the energy business.

Page 62: Arm Cortex

References

1. Manuals

• LM3S2965 Datasheet (January 2009 Preliminary edition)

• Stellaris Peripheral Driver Library Manual

• Pro ASIC APA 300 Datasheet

2. Websites

• Luminary home page: www.luminarymicro.com

• Luminary forums: http://www.luminarymicro.com/forums

• Wikipedia: http://en.wikipedia.org

• Keil Embedded Development tools webpage: http://www.keil.com/

3. Software

• Matlab 2008, Keil Microvision 3, Libero 3.8

Page 63: Arm Cortex

MuZIC Internship Report 2009

63

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Annex A: Peripheral’s Code

1. UART

main

/************************************************** **************************************/ //INCLUDE /************************************************** **************************************/ #include "system_config.h" #include "drv_uart.h" #include "hw_ints.h" #include "hw_memmap.h" #include "hw_types.h" #include "debug.h" #include "gpio.h" #include "interrupt.h" #include "sysctl.h" #include "lm3s2965.h" #include "uart.h" #include "interrupt.h" #include "ssi.h" #include "oscarProtocol.h" /************************************************** ***************************************/ int main(void) { //Local variables unsigned long ulIdx = 0; volatile unsigned long ulLoop;

//Code (void) SYS_Configuration (); (void) UAR_Configure(); (void) UAR_ClearRXBuf ();

(void) SYS_Enable_Interruptions ();

while (1) { GPIO_PORTG_DATA_R |= 0x04; for(ulLoop = 0; ulLoop < 200000; ulLoop++) { } GPIO_PORTG_DATA_R &= ~(0x04); for(ulLoop = 0; ulLoop < 200000; ulLoop++) { } ulIdx++;

} }

drv_uart.c

//------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. drv_uart.c //------------------------------------------------- ------- //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- -------

Page 64: Arm Cortex

/************************************************** **************************************/ //INCLUDE /************************************************** **************************************/ #include "hw_ints.h" #include "hw_memmap.h" #include "hw_types.h" #include "debug.h" #include "gpio.h" #include "interrupt.h" #include "sysctl.h" #include "lm3s2965.h" #include "uart.h" #include "interrupt.h" #include "ssi.h" #include "oscarProtocol.h" #include "drv_uart.h" /************************************************** ***************************************/ /************************************************** **************************************/ //GLOBAL CONSTANTS, VARIABLES /************************************************** **************************************/ int amount_of_data_left = 0; //Number of bits that have not been sent still by the

//UART unsigned long data_to_be_sent = 0; //Data that has not been sent still by the UART unsigned char data[TX_BUF_SIZE]; unsigned char RXBuf[RX_BUF_SIZE]; unsigned char TXBuf[TX_BUF_SIZE]; int TXDataCount = 0; int RXDataCount = 0; int RXLenght = 0; int TXData_length = 0; int TXIndex = 0; unsigned char Cks = 0; int RxFIFO_empty = 0; long unsigned RXFIFO_reading = 0; int reception_error = 0; /************************************************** **************************************/ //LOCAL FUNCTIONS /************************************************** **************************************/ void InterruptUART0Transmission (void); void InterruptUART0Reception (void); /************************************************** **************************************/ //* Function: UAR_Configure //* Task: Configures the registers of the UART 0 /************************************************** **************************************/ void UAR_Configure (void) {

GPIO_PORTA_AFSEL_R |= 0x03; //Configuration of the Port A in order to be used //for the UART 0

GPIO_PORTA_DEN_R |= 0x03; SYSCTL_RCGC1_R |= ACTIVATE_UART0; //Enable use UA RT 0 UART0_CTL_R &= DISABLE_UART0; //Puts to zero bit 0 of UARTCTL (disables UART 0) UART0_LCRH_R &= FLUSH_UART0_FIFO; //Puts to zero bit 4 of UARTLCRH (disables FIFO's // UART 0) UART0_IBRD_R |= INTEGER_BDR; //Integer portion o f the Baud Rate Divisior UART0_FBRD_R |= FRACTION_BDR; //Fractional portio n of the Baud Rate Divisior UART0_LCRH_R |= UART0_PARAMETERS; //Writing of the desired serial parameters: //Baud Rate: 19196 Data Lenght: 8bits One sto p bit //No parity FIFOs enabled UART0_IM_R |= UART0_INTERRUPT; UART0_IFLS_R = UART0_FIFO_LEVELS; UART0_CTL_R |= ENABLE_UART0; //Puts to 1 bit 0 UA RTCTL (enables UART 0) UART0_ICR_R |= UART0_CLEAR_INTERRUPTIONS;

Page 65: Arm Cortex

MuZIC Internship Report 2009

65

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

} /************************************************** *******************************************/ //* Function: InterruptUART0Control //* Task: This function manages all the interruptio ns related with the UART0. It service // multiple interrupt // events in a single interrup service routine by reading the UART0 Masked Interrupt Status // (UARTMIS) register. The interrupt events are OR ed together before being sent to the // interrupt controller, so the UART can only gene rate a single interrupt request to the // controller at any given time. Hence the use of this function. The interruptions taken into // account by this function are: //* Overrun Error: Data has been lost due to full R X FIFO at the time of the reception. If this // error appears, the RX FIFO and the RXBuf are co mpletely erased, and a message is sent to // task control. //* Break Error: NA, this error is not taken into a ccount (not configured). //* Parity Error: NA, the UART0 is configured to wo rk without Parity Error Bit (not // configured). //* Framing Error: The received character does not have a valid stop bit (the UART0 has been // configured with one stop bit). If this error ap pears, the RX FIFO and the RXBuf are // completely erased, and a message is sent to tas k control. //* Receive Time-Out Error: The receive timeout int errupt is asserted when the receive FIFO is // not empty, and no further data is received over a 32-bit period. The receive timeout // interrupt is cleared either when the FIFO becom es empty through reading all the data, or // when a 1 is written to the corresponding bit in the UARTICR register. If this error // appears, we keep on reading the RX FIFO until t he RX FIFO is once again empty. /************************************************** **************************************/ void InterruptUART0Control (void) { int i; //Local variables unsigned long UART_interruption_status; UART_interruption_status = UART0_MIS_R; if((UART_interruption_status & UART0_OVERRUN_ERROR _INT)) { for (i=0; i< UART0_FIFO_LENGTH; i++) { RXBuf[i] = UART0_DR_R; } (void) UAR_ClearRXBuf (); reception_error = 1; UARTIntClear (UART0_BASE, UART0_OVERRUN_ERROR_INT ); } if((UART_interruption_status & UART0_BREAK_ERROR_I NT)) { UARTIntClear (UART0_BASE, UART0_BREAK_ERROR_INT); //To do } if((UART_interruption_status & UART0_PARITY_ERROR_ INT)) { UARTIntClear (UART0_BASE, UART0_PARITY_ERROR_INT) ; //To do } if((UART_interruption_status & UART0_FRAMING_ERROR _INT)) { for (i=0; i< UART0_FIFO_LENGTH; i++) { RXBuf[i] = UART0_DR_R; } (void) UAR_ClearRXBuf (); reception_error = 1; UARTIntClear (UART0_BASE, UART0_FRAMING_ERROR_INT ); } if((UART_interruption_status & UART0_TIMEOUT_ERROR _INT)) { do { RXBuf[RXDataCount] = UART0_DR_R;

Page 66: Arm Cortex

RXDataCount++; RxFIFO_empty = UART0_FR_R; RxFIFO_empty = RxFIFO_empty & MASK_RX_EMPTY_FIFO _FLAG; RxFIFO_empty = RxFIFO_empty >> 4; if (RXDataCount==2) { RXLenght = RXBuf[1]+ 3; } } while(RxFIFO_empty != 1); if (RXDataCount == RXLenght) { TXDataCount = RXLenght; RXDataCount = 0; RXLenght = 0; RxFIFO_empty = 0; UARTIntClear (UART0_BASE, UART_INT_RX); (void) UAR_Send (RXBuf); (void) UAR_ClearRXBuf (); } UARTIntClear (UART0_BASE, UART0_TIMEOUT_ERROR_INT ); } if((UART_interruption_status & UART0_TRANSMISSION_ INT)) { (void)InterruptUART0Transmission (); } if((UART_interruption_status & UART0_RECEPTION_INT )) { (void) InterruptUART0Reception (); } } /************************************************** **************************************/ //* Function: UAR_Send //* Task: Prepares all the information and which is going to be sent using the UART // In order to use the interruptions of the micro, the FIFO has to be filled in with // at least 32 bits(with trigger set to 1/8 full F IFO). That is, no interruption will be // triggered if less than 32 bits are sent in the first place /************************************************** **************************************/ void UAR_Send (unsigned char *data) { //Local variables unsigned long check_if_uart_busy; int i=0; check_if_uart_busy = UART0_FR_R;//See if the UART 0 is busy (checking bit 3 UART0_FR_R) check_if_uart_busy &= MASK_UART0_BUSY; //If UART 0 is busy, then bit 3 is set while (check_if_uart_busy); //Wait until the UART 0 has finished sending for(i=0;i<TXDataCount;i++) { TXBuf[i] = *data; data++; } for(i=0;i<4;i++) { UART0_DR_R = TXBuf[i]; //Writes in the Tx FIFO 32 bits TXDataCount--; //Updates information regarding t he amount of data and //the data that has to be sent TXIndex++; } } /************************************************** **************************************/ //* Function: InterruptUART0Transmission //* Task: Once the Tx FIFO has been initialized, th is interruption is triggered every time // the micro detects that there is = < 1/8 of the FIFO full. It cheks if there is data // left to be sent and updates the global variable s 'amount_of_data_left' and

Page 67: Arm Cortex

MuZIC Internship Report 2009

67

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

// 'data_to_be_sent' /************************************************** **************************************/ void InterruptUART0Transmission (void) { //Local variables if(TXDataCount > 0) //if there is data left, the i nterruption keeps sending data { UART0_DR_R = TXBuf[TXIndex]; TXDataCount--; TXIndex++; } if (TXDataCount <= 0) //if there is no more data, the interruption is disabled { TXIndex = 0; TXDataCount = 0; RXDataCount = 0; RXLenght = 0; UARTIntClear (UART0_BASE, UART_INT_TX); } } /************************************************** **************************************/ //* Function: InterruptUART0Reception //* Task: On reception of a message from the comput er, this fonction stores the data in a // variable for later use //ISSUES //* This function stores the received information i n a variable, but it doesn't trigger any // interruption to tell anyone that it has informa tion /************************************************** **************************************/ void InterruptUART0Reception (void) { int end_message = 0; RXBuf[RXDataCount] = UART0_DR_R; RXDataCount++; if (RXDataCount == 1) //Looking for SOF byte... { if(RXBuf[0] == SOF_BYTE) { //TODO Beginning of a new frame, start reception timeout } } if ((RXBuf[0] != SOF_BYTE)) { RXDataCount = 0; //TODO // first received byte is wrong, reset reception } RXBuf[RXDataCount] = UART0_DR_R; RXDataCount++; RXLenght = RXBuf[1]+ 3; //Looking for size of Re ceived message... if (RXLenght > OSCAR_BUF_SIZE) //Total lenght incl udes SOF byte, Checksum and length //byte itself { RXLenght = OSCAR_BUF_SIZE; } if ( RXDataCount > OSCAR_BUF_SIZE ) { RXDataCount = 0; //TODO //Reset reception } //If the frame has been fully received, stop timeo ut counter and wake up serial task

Page 68: Arm Cortex

//TODO RXBuf[RXDataCount] = UART0_DR_R; RXDataCount++; RXBuf[RXDataCount] = UART0_DR_R; RXDataCount++; RXBuf[RXDataCount] = UART0_DR_R; RXDataCount++; RXBuf[RXDataCount] = UART0_DR_R; RXDataCount++; RXBuf[RXDataCount] = UART0_DR_R; RXDataCount++; RXBuf[RXDataCount] = UART0_DR_R; RXDataCount++; if (RXDataCount == RXLenght) { end_message = 1; //TODO: Instead of putting a '1' in end_message, a flag has to be set TXDataCount = RXLenght; RXDataCount = 0; RXLenght = 0; UARTIntClear (UART0_BASE, UART_INT_RX); (void) UAR_Send (RXBuf); } } /************************************************** **************************************/ //* Function: UAR_ClearRXBuf //* Task: Resets the Reception Buffer and its index /************************************************** **************************************/ extern void UAR_ClearRXBuf (void) { int i; for(i=0;i<(RX_BUF_SIZE+1);i++) { RXBuf[i] = 0; } RXDataCount = 0; } /************************************************** **************************************/ //END /************************************************** **************************************/

drv_uart.h

//------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. drv_uart.h //------------------------------------------------- ------- //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- ------- #ifndef _DRV_UART_H_ #define _DRV_UART_H_ /************************************************** ******************************************** //GLOBAL DEFINE, MACROS /************************************************** ******************************************** //UART 0 Control Define #define ACTIVATE_UART0 0x00000001 //Assignment of a clock and functions to UART 0 by the micro

Page 69: Arm Cortex

MuZIC Internship Report 2009

69

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

#define DISABLE_UART0 0xfffe //Disables UART 0 in order to configure (UARTEN = 0) #define ENABLE_UART0 0x00000001 //Enables UART 0 #define FLUSH_UART0_FIFO 0xffef //Flush the trans mit UART FIFO's: #define ACTIVATE_UART0_INT 0x00000020//Enables the interruption of the UART in the system //writing directly in the NVIC register //(Interrupt Set-Enable register) //UART 0 General Configuration Define //Configuration of the Integer and the Fractional //Baud-Rate Divisor: //BRD = BRDI + BRDF = UARTSysClk / (16 * (Bits per second)) //INTEGER_BDR = BRDI //FRACTION_BDR = integer(BRDF*64 + 0.5) #define INTEGER_BDR 0x001a #define FRACTION_BDR 0x0003 #define UART_PARITY 0x00 //No parity #define UART_WORD_LENGHT 0x60 //Transmission of 8 bits #define UART_FIFO 0x10 //Enable FIFO buffers #define UART_TWO_STOP_BITS 0x00 //One stop bit #define UART_EVEN_PARITY 0x00 //No even parity #define UART_PARITY 0x00 //No parity #define UART_SEND_BREAK 0x00 //Normal use of the UART #define UART0_PARAMETERS (UART_PARITY | UART_WORD_L ENGHT | UART_FIFO | UART_TWO_STOP_BITS | UART_EVEN_PARITY | UART_PARITY | UART_SEND_BREAK) //UART 0 Interrupt Trigger Conditions #define UART0_RX_FIFO_LEVEL 0x00 //Triggers interru ption when RX FIFO is >= 1/8 full #define UART0_TX_FIFO_LEVEL 0x00 //Triggers interru ption when TX FIFO is >= 1/8 full #define UART0_FIFO_LEVELS (UART0_RX_FIFO_LEVEL | UA RT0_TX_FIFO_LEVEL) //UART 0 Interrupt Configuration Define #define UART_OVERRUN_ERROR_INTERRUPT 0x400 //"1" en ables interruptions due to Overrun Error #define UART_BREAK_ERROR_INTERRUPT 0x200 //"1" enab les interruptions due to Break Error #define UART_PARITY_ERROR_INTERRUPT 0x100 //"1" ena bles interruptions due to Parity Error #define UART_FRAMING_ERROR_INTERRUPT 0x080 //"1" en ables interruptions due to Framing Error #define UART_RECEIVE_TIME_OUT_INTERRUPT 0x040 //"1" enables interruptions due to Overrun // Error #define UART_TRANSMIT_INTERRUPT 0x020 //"1" enables interruptions due to Overrun Error #define UART_RECEIVE_INTERRUPT 0x010 //"1" enables interruptions due to Overrun Error #define UART0_INTERRUPT (UART_OVERRUN_ERROR_INTERRUPT | UART_RECEIVE_TIME_OUT_INTERRUPT | UART_BREAK_ERROR_INTERRUPT | UART_PARITY_ERROR_INTERRUPT | UART_FRAMING_ERROR_INTERRUPT | UART_TRANSMIT_INTERRUPT | UART_RECEIVE_INTERRUPT) #define UART0_OVERRUN_ERROR_INT 0x400 //Overrun Er ror Interruption bit #define UART0_BREAK_ERROR_INT 0x200 //Break Error Interruption bit #define UART0_PARITY_ERROR_INT 0x100 //Parity Err or Interruption bit #define UART0_FRAMING_ERROR_INT 0x080 //Framing Er ror Interruption bit #define UART0_TIMEOUT_ERROR_INT 0x040 //Time Out E rror Interruption bit #define UART0_TRANSMISSION_INT 0x020 //Transmissi on Interruption bit #define UART0_RECEPTION_INT 0x010 //Reception Int erruption bit #define UART0_CLEAR_INTERRUPTIONS (UART0_OVERRUN_ERROR_INT | UART0_BREAK_ERROR_INT | UART0_PARITY_ERROR_INT | UART0_FRAMING_ERROR_INT | UART0_TIMEOUT_ERROR_INT | UART0_TRANSMISSION_INT | UART0_RECEPTION_INT) //UART 0 Masks #define MASK_UART0_BUSY 0x08 //If bit 3 is set, U ART 0 is busy #define MASK_UART0_FLAG_RX_EMPTY 0x10 /************************************************** *******************************************/ // GLOBAL CONSTANTS, VARIABLES

Page 70: Arm Cortex

/************************************************** *******************************************/ #define RX_BUF_SIZE 60 #define TX_BUF_SIZE 60 #define MUZIC_DEVICE 0x06 #define MUZIC_COMMAND 0x10 #define MASK_RX_EMPTY_FIFO_FLAG 0x10 #define MASK_RX_ERRORS 0x0ff /************************************************** *******************************************/ //GENERIC API /************************************************** *******************************************/ extern void UAR_Configure (void); extern void UAR_Send (unsigned char *data); extern void InterruptUART0Control (void); extern void UAR_ClearRXBuf (void); #endif /************************************************** *******************************************/ //END /************************************************** *******************************************/

sytem_config.h

//------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. system_confi g.h //------------------------------------------------- ------- // Description what this module is used for........ ............... // // Tasks: //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- ------- #ifndef _SYSTEM_CONFIG_H_ #define _SYSTEM_CONFIG_H_ /************************************************** ***************************************************************/ //GLOBAL DEFINE, MACROS /************************************************** ***************************************************************/ //Pins #define PIN0 0x01 #define PIN1 0x02 #define PIN2 0x04 #define PIN3 0x08 #define PIN4 0x10 #define PIN5 0x20 #define PIN6 0x40 #define PIN7 0x80 //Ports #define PORTA 0x01 #define PORTB 0x02 #define PORTC 0x04 #define PORTD 0x08 #define PORTE 0x10 #define PORTF 0x20 #define PORTG 0x40 #define PORTH 0x80 //System activation of the interruptions #define INT_UART0 21

Page 71: Arm Cortex

MuZIC Internship Report 2009

71

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

/************************************************** *******************************************/ //GENERIC API /************************************************** *******************************************/ extern void SYS_Enable_Interruptions (void); extern void SYS_Configuration (void); #endif /************************************************** *******************************************/ //END /************************************************** *******************************************/

system_config.c

//------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. system_confi g.c //------------------------------------------------- ------- // Description ....................... // // Tasks: //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- ------- /************************************************** *************************************/ //ISSUES /************************************************** *************************************/ //* This file contains all the functions that need to be called before using the // microprocessor. //* All the functions related with the configuratio n of the system are placed here //* Interruptions must be enabled AFTER the configu ration of the system and all the // peripherials. Otherwise, the program will not f unction properly. /************************************************** *************************************/ /************************************************** **************************************/ //INCLUDE /************************************************** **************************************/ #include "common.h" #include "system_config.h" /************************************************** ***************************************/ /************************************************** **************************************/ //* Function: SYS_Configuration //* Task: Configures the system clock and the perip herials which will be used /************************************************** **************************************/ void SYS_Configuration (void) { SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN);

SYSCTL_RCGC2_R |= (PORTG | PORTA); //Activates the use of Port A and G

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

GPIO_PORTG_DIR_R = PIN2; //Configuration of the pin used by the LED

GPIO_PORTG_DEN_R = PIN2; } /************************************************** **************************************/

Page 72: Arm Cortex

//* Function: SYS_Activate_Interruptions //* Task: Enables the use of interruptions by the s ystem, and enables the interruptions // of the peripherials in use /************************************************** **************************************/ void SYS_Enable_Interruptions (void) { IntMasterEnable(); IntEnable(INT_UART0); } /************************************************** *******************************************/ //END /************************************************** *******************************************/

2. FPGA SPI connection code

spi_fpga_test_bench.c

//------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. spi_fpga_tes t_bench.c //------------------------------------------------- ------- // Description // // Tasks: This file contains the different tests us ed to check if the FPGA worked correctly in // the RX and Tx modes //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- ------- //------------------------------------------------- ------- // Include //------------------------------------------------- ------- #include "hw_ints.h" #include "hw_memmap.h" #include "hw_types.h" #include "debug.h" #include "gpio.h" #include "interrupt.h" #include "ssi.h" #include "sysctl.h" #include "lm3s2965.h" #include "drv_spi_fpga.h" #include "timer.h" //------------------------------------------------- -------- //Test benchs //------------------------------------------------- -------- //#define TEST_TX_PWM_DIRECT #define TEST_TX_PWM_INDIRECT //#define TEST_RX int main(void) { /////////////////////////////////////////////////// //////////////////////////////////////////// //Test 1:We control the PWM directly by sending the FPGA the values we want as PWM output /////////////////////////////////////////////////// //////////////////////////////////////////// #ifdef TEST_TX_PWM_DIRECT

unsigned long ulIdx = 0; volatile unsigned long ulLoop;

SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | S YSCTL_OSC_MAIN); // Set the clocking to run directly from the crysta l.

SYSCTL_RCGC2_R |= (PORTG | PORTA);

//Activates the use of Port A and G (used by the P WM)

Page 73: Arm Cortex

MuZIC Internship Report 2009

73

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); (void) ConfigurationTriggerRQ50K (); //This will configure the input signal RQ50K comin g from the FPGA as a rising edge //interruption (void) SSI_ConfigureSPI(); //Configuration of the SPI between the FPGA and the DSP SysCtlDelay(100); //FPGA Request (To be verified) IntMasterEnable(); //Enable Interruptions IntEnable(INT_GPIOA);

//Enable interruptions coming from the GPIOA (RQ50K interruptions)

while (1); #endif /////////////////////////////////////////////////// //////////////////////////////////////////// //Test 2: We load into the FPGA the Sinewave, the F IR tables, the PWM Gain and Offset. We start //the transmission and we send a I and a Q every ti me the FPGA asks for one. /////////////////////////////////////////////////// //////////////////////////////////////////// #ifdef TEST_TX_PWM_INDIRECT

volatile unsigned long ulLoop;

SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | S YSCTL_OSC_MAIN); // Set the clocking to run directly from the crysta l.

SYSCTL_RCGC2_R |= (PORTG | PORTA); //Activates the use of Port A and G (used by the PW M) SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);

(void) ConfigurationTriggerDRQ (); //This will configure the input signal DRQ coming from the FPGA as a rising edge // interruption (void) SSI_ConfigureSPI(); //Configuration of the SPI between the FPGA and th e DSP SysCtlDelay(100); //FPGA Request (To be verified) (void)SSI_ConfigureFPGA();

//We load into the FPGA the Sinewave and FIR 1 and FIR 2 tables. We load the PWM Gain // and Offset

(void)SSI_Simulation(); //We send the FC Parameter for DDFS and start the transmission (void) SSI_SendISendQ(); //We send I and Q and enable interruptions coming from DRQ while (1); #endif /////////////////////////////////////////////////// //////////////////////////////////////////// //Test 2: We load into the FPGA the Sinewave, the F IR tables, the PWM Gain and Offset. We start //the transmission and we send a I and a Q every ti me the FPGA asks for one. //ISSUES: The Rx has not been fully tested. Further more, the DRQ interruption has not been //configured to work in the Rx mode. On request, it is supposed to perform dummy writes in //order to give a clock to the FPGA where it can wr ite the message to the FPGA. /////////////////////////////////////////////////// ///////////////////////////////////////////

#ifdef TEST_RX unsigned long ulIdx = 0;

volatile unsigned long ulLoop; SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN);

// Set the clocking to run directly from the crysta l.

Page 74: Arm Cortex

SYSCTL_RCGC2_R |= (PORTG | PORTA); //Activates the use of Port A and G (used by the P WM) SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); (void) ConfigurationTriggerDRQ (); //This will configure the input signal DRQ coming from the FPGA as a rising edge //interruption (void) SSI_ConfigureSPI(); //Configuration of the SPI between the FPGA and th e DSP SysCtlDelay(100); //FPGA Request (To be verified) (void) SSI_ConfigRx(); //Configure the FPGa to work as Receiver SysCtlDelay(50); (void)SSI_StartDecoder(); IntMasterEnable(); //Enable Interruptions IntEnable(INT_GPIOA); while (1); #endif }

drv_spi_fpga.c

//------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. drv_spi_fpga .c //------------------------------------------------- ------- //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- ------- /************************************************** ******/ //ISSUES //*The conceived FPGA demands transmissions of 8+16 . // The following program sends alternates packages of 8 and 16 bits //(thus sending the order in a 8-bit package and th e data part in a 16-bit package) /************************************************** *******/ //------------------------------------------------- ------- // Include //------------------------------------------------- ------- #include "hw_ints.h" #include "hw_memmap.h" #include "hw_types.h" #include "debug.h" #include "gpio.h" #include "interrupt.h" #include "ssi.h" #include "sysctl.h" #include "lm3s2965.h" #include "drv_spi_fpga.h" #include "timer.h" //------------------------------------------------- ------- // Local Define, macro //------------------------------------------------- ------- //Sinewave Table static long tableSMicro [SIN_TABLE_LENGTH] = { REMOVED DUE TO CONFIDENTIALITY CLAUSE}; //FIR 1 Table static long tableFIRMicro_1 [NUMBER_FIR1_PARAMS] = { REMOVED DUE TO CONFIDENTIALITY CLAUSE};

Page 75: Arm Cortex

MuZIC Internship Report 2009

75

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

//FIR 2 Table static long tableFIRMicro_2 [NUMBER_FIR2_PARAMS] = { REMOVED DUE TO CONFIDENTIALITY CLAUSE}; //Sinewave test signal for the PWM direct mode (for Test purposes) static long Sinewave5000Hz [SINEWAVE_5000HZ_LENGHT] = { 246, 240, 223, 197, 164, 128, 92, 59, 33, 16, 10, 1 6, 33, 59, 92, 128, 164, 197, 223, 240}; //Most Significant Words of the Carrier Frequencies static long RxFrequenciesHigh [FIVE_CARRIER_FREQUEN CIES] = { REMOVED DUE TO CONFIDENTIALITY CLAUSE //Least Significant Words of the Carrier Frequencie s static long RxFrequenciesLow [FIVE_CARRIER_FREQUENC IES] = { REMOVED DUE TO CONFIDENTIALITY CLAUSE}; //------------------------------------------------- ------- // Global constants, variables //------------------------------------------------- ------- int index_sinewave5000Hz = 0; static unsigned char i_index = 0; static unsigned char index_sinewave_table = 0; static unsigned char index_fir1_table = 0; static unsigned char index_fir2_table = 0; static unsigned char i_frequency_high = 0; static unsigned char i_frequency_low = 0; //------------------------------------------------- ------- // Local functions //------------------------------------------------- ------- //FPGA Configuration static void SinewaveMemory (void); //Loads the Sin ewave Table into the FPGA static void FIRCoeffTable1 (void); //Loads the FIR 1 Table into the FPGA static void FIRCoeffTable2 (void); //Loads the FIR 2 Table into the FPGA void PWMGainOffset (void); //Configuration of the PWM Gain and Offset void FCParameter(void); //Configuration of the TX Frequency Carrier /************************************************** ********************/ //* Function: SSI_Configure //* Task: Configures the hardware in order to attai n the FPGA // needs of on the SPI /************************************************** *******************/ void SSI_ConfigureSPI (void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

//Enables the use of the GPIO where the SSI is SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI); //Enables the use of the SSI0 GPIOPinTypeSSI(GPIO_PORTA_BASE, SSI_CLK | SSI_ TX | SSI_RX);

//Enables SSI clock, TX, RX GPIO_PORTA_DIR_R |= 0x08; //Configuration of the SSI CS GPIO_PORTA_DEN_R |= 0x08; GPIO_PORTA_DATA_R |= 0x08; //SSI CS Initialized at high level SSI0_CR1_R = 0x0000; //Disables SSI operation in order to configure SSI0_CR0_R = (SCR | SPH | SPO | SPH | FRF | DSS_16 ); //SSI0 Configuration //Bit rate = FSSIClk / (CPSDVSR*(1+SCR)) = 3.2 0MHz //Bits 15-8: SCR = 1 //Bit 7: SPH = 1 (Serial Clock Phase)

Page 76: Arm Cortex

//Bit 6: SPO = 0 (Serial Clock Polarity) //Bits 5,4: FRF = 0 (Frame Format = SPI) //Bits 3-0: DSS = 16 (Data Size Select = 16 bit s by default) SSI0_CPSR_R = 0x0002; //Clock Prescale has to be an even number between 2 and 256 SSI0_CR1_R = 0x0002; //Enables SSI operation again } /************************************************** *******************************************/ //* Function: SSI_Stop //* Task: Disables the SPI /************************************************** *******************************************/ void SSI_Stop (void) { SSI0_CR1_R = 0x0000; //Stops the SSI } /************************************************** *******************************************/ //* Function: SSI_Send8 //* Task: Sends 8 bits data via SPI. First, it conf igures the SPI channel to a data size of // bits. // It waits for three periods, then pulls dowm the Chip Select,and finally sends the data. // Afterwards, we wait until we make sure that all the data has been correctly sent. //* This function is meant to be used to send the t ype of order to the FPGA //* WARNING!: In this case, the Chip Select won't b e pulled up until the data part of the // message (sent via SSI_Send16)has not been sent. /************************************************** *******************************************/ void SSI_Send8(long unsigned int data_to_be_sent) { SSI0_CR1_R = 0x0000; //Disable SSI operations in order to configure SSI0_CPSR_R = 0x0002; //Set the Pre Scaler to 2. The Pre Scaler has to b e an EVEN number between 2 and 256 SSI0_CR0_R = (SCR | SPH | SPO | SPH | FRF | DSS_8) ; //SPI Configuration SSI0_CR1_R = 0x0002; //Enable SSI operations SysCtlDelay (3); //The micro has to wait for 3 periods in order to use the peripheral GPIO_PORTA_DATA_R &= ~(0x08); //Pulling down Chip Select to start transmission (void) SSIDataPut(SSI_BASE, data_to_be_sent); //Se nding data while ((SSI0_SR_R & IS_SPI_BUSY)!=0);

//We wait until the SPI is not busy anymore

//GPIO_PORTA_DATA_R |= 0x08; //Release the SSI Chip Select } /************************************************** *******************************************/ //* Function: SSI_Send16 //* Task: Sends 16 bits data via SPI. First, it con figures the SPI channel to a data size of 16 // bits. // It waits for three periods, sends the data, and finally pulls up the Chip Select. We also // wait until we make sure that all the data has b een correctly sent. //* This function is meant to be used to send data to the FPGA //* WARNING!: We don't need to pull down the Chip S elect because it was already pulled down by // SSI_Send8, so we just have put it back to its o riginal level. /************************************************** *******************************************/ void SSI_Send16(long unsigned int data_to_be_sent) {

Page 77: Arm Cortex

MuZIC Internship Report 2009

77

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

SSI0_CR1_R = 0x0000; //Disable SSI operations in order to configure SSI0_CPSR_R = 0x0002;

//Set the Pre Scaler to 2. The Pre Scaler has to be an EVEN number between 2 and 256 SSI0_CR0_R = (SCR | SPH | SPO | SPH | FRF | DSS_16 ); //SPI Configuration SSI0_CR1_R = 0x0002; //Enable SSI operations SysCtlDelay (3); //The micro has to wait for 3 periods in order to use the peripheral

//GPIO_PORTA_DATA_R &= ~(0x08); //Pulling down Chip Select to start transmission (void) SSIDataPut(SSI_BASE, data_to_be_sent); while ((SSI0_SR_R & IS_SPI_BUSY)!=0); //We wait un til the SPI is not busy anymore GPIO_PORTA_DATA_R |= 0x08; //Release the SSI Chip Select } /************************************************** *******************************************/ //* Function: ConfigurationTriggerRQ50K //* Task: Configures Pin 6, Port A to be the input of the Data Request Signal at 50KHz sent by // the FPGA This sets an interruption which is tri ggered every time we have a rising edge in // the RQ50K signal sent by the FPGA. /************************************************** *******************************************/ void ConfigurationTriggerRQ50K (void) { GPIO_PORTA_ICR_R = (PIN7 | PIN6 | PIN5 | PIN4 | P IN3 | PIN2 | PIN1 | PIN0); //Clear all edge interruptions GPIO_PORTA_DEN_R = PIN6; //Set pin 6 as input GPIO_PORTA_IS_R = PIN6_SET_TO_EDGE_SENSITIVE; //Set edge-sensitive interruptions GPIO_PORTA_IBE_R = CONTROLLED_BY_INTERRUPT_EVENT; //Interrupt generation controlled by the Interrupt Event (GPIOIEV) GPIO_PORTA_IEV_R = RISING_EDGE_INTERRUPTION; //Configure pin 6 to trigger an interruption wh en rising edges GPIO_PORTA_IM_R = PIN6; //Interruptions coming from pin 6 are allowed GPIO_PORTA_ICR_R = (PIN7 | PIN6 | PIN5 | PIN4 | PI N3 | PIN2 | PIN1 | PIN0); //Clear all interruptions } /************************************************** *******************************************/ //* Function: IntRQ50KHandler //* Task: Handler for the interruptions coming from GPIO A Pin 6 used by the FPGA for // synchronisation. This interruption is triggered every time the micro sees a rising edge in // pin 6, port A. /************************************************** **************************************************************/ void IntRQ50KHandler(void) { //Local variables unsigned long data; //Code GPIO_PORTA_ICR_R = PIN6; //Clear interruptions from pin 6 data = (CMD_WRITE | DIRECT_PWM); (void) SSI_Send8(data); //data = ((50*i_index)*256) + ((50*i_index)+25); //i_index++; //Sending the command (Direct PWM)

data = ((Sinewave5000Hz[index_sinewave5000Hz]*256)+Sinewav e5000Hz[index_sinewave5000Hz+1]);

index_sinewave5000Hz = index_sinewave5000Hz+2;

Page 78: Arm Cortex

(void) SSI_Send16(data); //Sending the 5000Hz Sinewave (for debugging purpo ses) if (index_sinewave5000Hz == SINEWAVE_5000HZ_LENGHT )

//If we arrive to the end of the table, we reset th e index table { index_sinewave5000Hz = 0; } } /************************************************** *******************************************/ //* Function: SSI_ConfigureFPGA //* Task: Writes on the FPGA the Sinewave Memory Ta ble, the FIR 1 table, the FIR 2 table, the // PWM gain and offset /************************************************** *******************************************/ void SSI_ConfigureFPGA (void) { //Code (void) SSI_ResetFPGA (); //Reset FPGA before star ting configuration (void)SinewaveMemory(); //Load the Sinewave Memo ry into the FPGA (void)FIRCoeffTable1(); //Load the FIR Coefficie nt Table 1 (void)FIRCoeffTable2(); //Load the FIR Coefficie nt Table 2 (void)PWMGainOffset (); //Load PWM Gain and Offs et } /************************************************** *******************************************/ //* Function: SSI_ResetFPGA //* Task: Resets the FPGA (done prior to the config uration of the FPGA in order to make it // correctly) /************************************************** *******************************************/ void SSI_ResetFPGA (void) { //Local variables unsigned long data_to_be_sent; //Code data_to_be_sent = CMD_WRITE | COMMAND; //Reset the FPGA (void)SSI_Send8(data_to_be_sent); data_to_be_sent = RESET_FPGA; (void)SSI_Send16(data_to_be_sent); SysCtlDelay(30); //FPGA Request (To be verified) } /************************************************** ****************************************/ //* Function: SinewaveMemory //* Task: Writes on the FPGA the Sinewave Memory Ta ble //* WARNING!: It takes more time to send the data t o the FPGA than to write them down in // the TX FIFO. For that reason, we have to wait i f we see that the TX FIFO is full, in order // to prevent loss of data. // Every time we send a 24 bit message to the TX F IFO, we check if the TX FIFO is full. If the // TX FIFO is full, we wait until some data has be en transmitted to the FPGA. /************************************************** *******************************************/ static void SinewaveMemory (void) { //Local variables unsigned long data_to_be_sent; int i; //Code data_to_be_sent = CMD_SET_ADDR | MIXER_SINE_TABLE;

//Gives the address of the Sinewave Table (void)SSI_Send8(data_to_be_sent); data_to_be_sent = SINEWAVE_ADDRESS; (void)SSI_Send16(data_to_be_sent); for(i=0;i<SIN_TABLE_LENGTH;i++)

Page 79: Arm Cortex

MuZIC Internship Report 2009

79

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

{ data_to_be_sent = CMD_WRITE | MIXER_SINE_TABLE; //Writes a value (void)SSI_Send8(data_to_be_sent); data_to_be_sent = (tableSMicro [index_sinewave_t able]); index_sinewave_table++; (void)SSI_Send16(data_to_be_sent); while(!((SSI0_SR_R & IS_SSI_TX_FIFO_NOT_FULL)>>1) );

//It takes more time to send the data to the FPGA t han to write them down in the //TX FIFO. For that reason, we have to wait if we s ee that the TX FIFO is full, //in order to prevent loss of data

if (index_sinewave_table == SIN_TABLE_LENGTH) { index_sinewave_table = 0; } } SysCtlDelay(10); //FPGA Request (To be verified) } /************************************************** *******************************************/ //* Function: FIRCoeffTable1 //* Task: Writes on the FPGA the FIRCoeffTable1 //* WARNING!: It takes more time to send the data t o the FPGA than to write them down in the TX // FIFO. For that reason, we have to wait if we se e that the TX FIFO is full, in order to // prevent loss of data. // Every time we send a 24 bit message to the TX F IFO, we check if the TX FIFO is full. If the // TX FIFO is full,we wait until some data has bee n transmitted to the FPGA. /************************************************** *******************************************/ static void FIRCoeffTable1 (void) { //Local variables unsigned long data_to_be_sent; int i; //Code data_to_be_sent = CMD_SET_ADDR | FIR_COEFF; //Set the pointer... (void)SSI_Send8(data_to_be_sent); data_to_be_sent = FIR1_MEM_ADDRESS; //...to the FIR 1 Table address (void)SSI_Send16(data_to_be_sent); index_fir1_table = 0; //Before loading the table into the FPGA, we reset the index for(i=0;i<NUMBER_FIR1_PARAMS;i++) //Load the table into the FPGA Memory { data_to_be_sent = CMD_WRITE | FIR_COEFF; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = (tableFIRMicro_1 [index_fir1_t able]); index_fir1_table++; (void)SSI_Send16(data_to_be_sent); while(!((SSI0_SR_R & IS_SSI_TX_FIFO_NOT_FULL)>>1) );

//If the SPI TX FIFO is full, we wait until there i s enough space to keep on //loading the table

} SysCtlDelay(10); //FPGA Request (To be verified) } /************************************************** *******************************************/ //* Function: FIRCoeffTable2 //* Task: Writes on the FPGA the FIRCoeffTable1 //* WARNING!: It takes more time to send the data t o the FPGA than to write them down in the TX // FIFO. For that reason, we have to wait if we se e that the TX FIFO is full, in order to // prevent loss of data. // Every time we send a 24 bit message to the TX F IFO, we check if the TX FIFO is full. If the // TX FIFO is full, we wait until some data has be en transmitted to the FPGA. /************************************************** *******************************************/

Page 80: Arm Cortex

static void FIRCoeffTable2 (void) { //Local variables unsigned long data_to_be_sent; int i; //Code data_to_be_sent = CMD_SET_ADDR | FIR_COEFF; //Sett ing the pointer... (void)SSI_Send8(data_to_be_sent); data_to_be_sent = FIR2_MEM_ADDRESS; //...to the FIR 2 Table address (void)SSI_Send16(data_to_be_sent); index_fir2_table = 0; //Before loading the table into the FPGA, we reset the index for(i=0;i<NUMBER_FIR2_PARAMS;i++) //Load the table into the FPGA Memory { data_to_be_sent = CMD_WRITE | FIR_COEFF; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = (tableFIRMicro_2 [index_fir2_t able]); index_fir2_table++; (void)SSI_Send16(data_to_be_sent); while(!((SSI0_SR_R & IS_SSI_TX_FIFO_NOT_FULL)>>1) ); //If the SPI TX FIFO is full, we wait until there is enough space to keep on

// loading the table } SysCtlDelay(10); //FPGA Request (To be verified) } /************************************************** ********************/ //* Function: PWMGainOffset //* Task: Writes on the FPGA the FIRCoeffTable1 /************************************************** *******************/ void PWMGainOffset (void) { //Local variables unsigned long data_to_be_sent; //Code data_to_be_sent = CMD_SET_ADDR | FIR_COEFF; //Se tting the pointer... (void)SSI_Send8(data_to_be_sent); data_to_be_sent = PWM_GAIN_OFFSET_ADDRESS;

//...to the Gain & Offset memory address of the FPG A (void)SSI_Send16(data_to_be_sent); data_to_be_sent = CMD_WRITE | FIR_COEFF; //Write PWM Gain (void)SSI_Send8(data_to_be_sent); data_to_be_sent = PWM_GAIN; (void)SSI_Send16(data_to_be_sent); data_to_be_sent = CMD_WRITE | FIR_COEFF; //Write PWM Offset (void)SSI_Send8(data_to_be_sent); data_to_be_sent = PWM_OFFSET; (void)SSI_Send16(data_to_be_sent); SysCtlDelay(10); //FPGA Request (To be verified) } /************************************************** ******************************************/ //* Function: SSI_Simulation(void) //* Task: Launches the simulation of the Test Bench /************************************************** *******************************************/ void SSI_Simulation(void) { (void)FCParameter(); //Send the FC Parameter fo r DDFS (void)SSI_SendStart(); //Start Transmission }

Page 81: Arm Cortex

MuZIC Internship Report 2009

81

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

/************************************************** *******************************************/ //* Function: FCParameter(void) //* Task: Send the FC Parameter for DDFS /************************************************** *******************************************/ void FCParameter(void) { //Local variables unsigned long data_to_be_sent; //Code SysCtlDelay(30); //FPGA Request (To be verified) data_to_be_sent = CMD_WRITE | FC_MOD_FREQ_Q; //We send the Frequency Carrier (Q Part) (void)SSI_Send8(data_to_be_sent); data_to_be_sent = DDFS_MSWORD; (void)SSI_Send16(data_to_be_sent); data_to_be_sent = CMD_WRITE | FC_MOD_FREQ_I; //We send the Frequency Carrier (I Part) (void)SSI_Send8(data_to_be_sent); data_to_be_sent = DDFS_LSWORD; (void)SSI_Send16(data_to_be_sent); SysCtlDelay(10); //FPGA Request (To be verified) } /************************************************** *******************************************/ //* Function: SSI_SendStart(void) //* Task: Sends a start (starts transmission) /************************************************** *******************************************/ void SSI_SendStart(void) { //Local variables unsigned long data_to_be_sent; //Code data_to_be_sent = CMD_WRITE | COMMAND; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = START_TX; (void)SSI_Send16(data_to_be_sent); SysCtlDelay(30); //FPGA Request (To be verified) } /************************************************** *******************************************/ //* Function: SSI_SendISendQ(void) //* Task: Sends I then Q. Once the first values of I and Q have been sent, we enable the DRQ // trigger. Every time the FPGA asks for a new cou ple (I and Q), an interruption will send // them. /************************************************** *******************************************/ void SSI_SendISendQ(void) { //Local variables unsigned long data_to_be_sent; //Code data_to_be_sent = CMD_WRITE | I_DATA; //Sends I (void)SSI_Send8(data_to_be_sent); data_to_be_sent = I_MESSAGE; (void)SSI_Send16(data_to_be_sent); data_to_be_sent = CMD_WRITE | Q_DATA; //Sends Q (void)SSI_Send8(data_to_be_sent); data_to_be_sent = Q_MESSAGE; (void)SSI_Send16(data_to_be_sent); IntMasterEnable(); //Enable all interruptions IntEnable(INT_GPIOG); //Enagble interruptions coming from Port G (DRQ in terruptions)

Page 82: Arm Cortex

} /************************************************** *******************************************/ //* Function: ConfigurationTriggerDRQ //* Task: Configures Pin 6, Port A to be the input of the Data Request Signal at 50KHz sent by // the FPGA This sets an interruption which is tri ggered every time we have a rising edge in // the RQ50K signal sent by the FPGA. /************************************************** *******************************************/ void ConfigurationTriggerDRQ (void) { //Code GPIO_PORTG_ICR_R= (PIN7 | PIN6 | PIN5 | PIN4 | PIN 3 | PIN2 | PIN1 | PIN0);

//Clear all edge interruptions GPIO_PORTG_DEN_R|= PIN6; //Set pin 6 as input without touching the other pi ns GPIO_PORTG_IS_R = PIN6_SET_TO_EDGE_SENSITIVE; //Set edge-sensitive interruptions GPIO_PORTG_IBE_R = CONTROLLED_BY_INTERRUPT_EVENT; //Interrupt generation controlled by the Interrupt Event (GPIOIEV) GPIO_PORTG_IEV_R = RISING_EDGE_INTERRUPTION; //Configure pin 6 to trigger an interruption when rising edges GPIO_PORTG_IM_R = PIN6; //Interruptions coming from pin 6 are allowed GPIO_PORTG_ICR_R = (PIN7 | PIN6 | PIN5 | PIN4 | PI N3 | PIN2 | PIN1 | PIN0); //Clear all interruptions } /************************************************** *******************************************/ //* Function: InterruptDRQ //* Task: Handler for the interruptions coming from GPIO G Pin 6 used by the FPGA for data // request. This interruption is triggered every t ime the microprocessor sees a rising edge in // the data request signal coming from the FPGA. T hen, it sends I and Q. /************************************************** *******************************************/ void IntDRQHandler(void) { //Local Variables unsigned long data_to_be_sent; //Code GPIO_PORTG_ICR_R = PIN6; //Clear interruptions fr om pin 6 data_to_be_sent = CMD_WRITE | I_DATA; //Send I (void)SSI_Send8(data_to_be_sent); data_to_be_sent = I_MESSAGE; (void)SSI_Send16(data_to_be_sent); data_to_be_sent = CMD_WRITE | Q_DATA; //Send Q (void)SSI_Send8(data_to_be_sent); data_to_be_sent = Q_MESSAGE; (void)SSI_Send16(data_to_be_sent); } /************************************************** *******************************************/ //* Function: SSI_ConfigRx(void) //* Task: Sends the 5 frequencies that will be used in the FPGA for parallel decoding. This // includes the frequency, its phase, its sinus, a nd its cosinus. /************************************************** *******************************************/ void SSI_ConfigRx(void) { //Local variables unsigned long data_to_be_sent; int i = 0; //Code data_to_be_sent = CMD_SET_ADDR | FIR_COEFF; //Sett ing the pointer... (void)SSI_Send8(data_to_be_sent); data_to_be_sent = FIR2_MEM_ADDRESS; //...to the FIR 2 Table address (FIR Address 192) (void)SSI_Send16(data_to_be_sent);

Page 83: Arm Cortex

MuZIC Internship Report 2009

83

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

for (i = 0; i< FIVE_CARRIER_FREQUENCIES; i++)

//We load the characteristics of the 5 carrier sign als { data_to_be_sent = CMD_WRITE | FIR_COEFF; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = RxFrequenciesHigh[i_frequency_h igh]; i_frequency_high++; (void)SSI_Send16(data_to_be_sent); data_to_be_sent = CMD_WRITE | FIR_COEFF; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = RxFrequenciesLow[i_frequency_lo w]; i_frequency_low++; (void)SSI_Send16(data_to_be_sent); data_to_be_sent = CMD_WRITE | FIR_COEFF; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = PHASE_HIGH; (void)SSI_Send16(data_to_be_sent); data_to_be_sent = CMD_WRITE | FIR_COEFF; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = PHASE_LOW; (void)SSI_Send16(data_to_be_sent); data_to_be_sent = CMD_WRITE | Q_DATA; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = COSINUS; (void)SSI_Send16(data_to_be_sent); data_to_be_sent = CMD_WRITE | Q_DATA; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = SINUS; (void)SSI_Send16(data_to_be_sent); } } /************************************************** ******************************************/ //* Function: SSI_StartDecoder(void) //* Task: Start Decoding the data coming from the F PGA /************************************************** *******************************************/ void SSI_StartDecoder(void) { //Local variables unsigned long data_to_be_sent; //Code data_to_be_sent = CMD_WRITE | COMMAND; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = START_DECODER; (void)SSI_Send16(data_to_be_sent); } /************************************************** *******************************************/ //* Function: InterruptSSI //* Task: Handler used to manage the interruptions coming from the SSI used by the ADC. As the // data coming from the ADC will never be enough t o trigger the Receive FIFO interruption, the // only interruption which wil be used will be the Time out interruption. Therefore, a delay // of 32 bits will take place between the receptio n and the actual reading of the data. /************************************************** *******************************************/ void IntSSIHandler (void) { //Local variables unsigned long ssi_interruption_status; unsigned long data_read; unsigned long data_to_be_sent;

Page 84: Arm Cortex

//Code ssi_interruption_status = SSI0_MIS_R; if((ssi_interruption_status & IS_SSI_RECEIVE_FIFO_ INT)) { data_read = SSI0_DR_R;

//We read the data coming from the ADC and store it in the memory if (i_index == SIN_TABLE_LENGTH) { i_index = 0; //We reset the counter of the ADC } else { i_index++; data_to_be_sent = CMD_READ | MIXER_SINE_TABLE; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = DUMMY_WRITE; (void)SSI_Send16(data_to_be_sent); } } if((ssi_interruption_status & IS_SSI_TIME_OUT_INT) ) { data_read = SSI0_DR_R; if (i_index == SIN_TABLE_LENGTH) { i_index = 0; } else { i_index++; data_to_be_sent = CMD_READ | MIXER_SINE_TABLE; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = DUMMY_WRITE; (void)SSI_Send16(data_to_be_sent); } } if((ssi_interruption_status & IS_SSI_OVERRUN_INT)) { //TODO } } // ================================================ == // End

drv_spi_fpga.h

//------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. drv_spi_fpga .h //------------------------------------------------- ------- //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- ------- #ifndef _DRV_SPI_FPGA_H_ #define _DRV_SPI_FPGA_H_ //------------------------------------------------- ------- // Glocal Define, macro //------------------------------------------------- ------- //Microprocessor Pins #define PIN0 0x01 #define PIN1 0x02 #define PIN2 0x04

Page 85: Arm Cortex

MuZIC Internship Report 2009

85

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

#define PIN3 0x08 #define PIN4 0x10 #define PIN5 0x20 #define PIN6 0x40 #define PIN7 0x80 //Microprocessor Ports #define PORTA 0x01 #define PORTB 0x02 #define PORTC 0x04 #define PORTD 0x08 #define PORTE 0x10 #define PORTF 0x20 #define PORTG 0x40 #define PORTH 0x80 //Rising edge interruption trigger configuration #define PIN6_SET_TO_EDGE_SENSITIVE 0x00 #define CONTROLLED_BY_INTERRUPT_EVENT 0x00 #define RISING_EDGE_INTERRUPTION 0x40 //SSI Configuration //Pin Configuration #define SSI_CLK GPIO_PIN_2 #define SSI_CS GPIO_PIN_3 #define SSI_RX GPIO_PIN_4 #define SSI_TX GPIO_PIN_5 //SPI Configuration #define SCR (1<<8) //SCR = 1 #define SPH (1<<7) //SPH = 1 #define SPO (0<<6) //SPO = 0 #define FRF (0<<4) //Freescale SPI Format #define DSS_8 (0x7) //Data Size Select = 8 #define DSS_16 (0xf) //Data Size Select = 16 //Data size configuration #define DATA_SIZE_8 8 #define DATA_SIZE_16 16 //Micro-FPGA Communication //Operational Code #define CMD_NOP 0x00 //NOP #define CMD_SET_ADDR 0x10 //Set adress #define CMD_READ 0x20 //Read & increment pointer #define CMD_WRITE 0x40 //Write to adress & increment pointer //Channel (Generic requests) #define COMMAND 0x00 //Command/ Status re gsiters #define FIR_COEFF 0x04 //FIR Coefficients (1 28x16) #define MIXER_SINE_TABLE 0x06 //Mixer Sine t able (256x16) #define DIRECT_PWM 0x08 //Direct PWM #define DECODER_COEFF 0x0C //Decoder 145 FIR Co efficients Table (256x16) //Channel: I Data (nI_Q = 0) #define I_DATA 0x02 //I-Data #define FC_MOD_FREQ_I 0x0A //Fc Transmit Modu lation Frequency (15:0) //Channel: Q Data (nI_Q = 1) #define Q_DATA 0x03 //Q-Data #define FC_MOD_FREQ_Q 0x0B //Fc Transmit Mod ulation Frequency (31:16) //Memory Adresses of the FPGA #define SINEWAVE_ADDRESS 0x0000 #define FIR1_MEM_ADDRESS 0x0000 #define FIR2_MEM_ADDRESS 0x00C0 #define PWM_GAIN_OFFSET_ADDRESS 0x00B4 //Masks #define LSB_MASK 0x00FF //Least Significant Bi t's Mask #define IS_SPI_BUSY 0x0010 //If the SPI is busy, or the transmit FIFO is not e mpty, bit 4 SSISR register is set to 1 #define IS_SSI_TX_FIFO_NOT_FULL 0x02

Page 86: Arm Cortex

//If the Tx FIFO is not full, bit 1 SSISR register is set to 1 #define IS_SSI_RECEIVE_FIFO_INT 0x4 //To check if the received interruption coming from the SSI is due to a received message #define IS_SSI_TIME_OUT_INT 0x2 //To check if the received interruption coming from the SSI is due to a time-out #define IS_SSI_OVERRUN_INT 0x1 //To check if the received interruption coming from the SSI is due to an overrun //Sinewave Coefficient Values #define SIN_TABLE_LENGTH 256 //Lenght of the Sine wave Mixer Table //FIR Coefficient Values #define NUMBER_FIR1_PARAMS 145 //Lenght of the FI R 1 Table #define NUMBER_FIR2_PARAMS 49 //Lenght of the FIR 2 Table //TX Messages #define START_TRANSMITTER 0x0001 //Starts tranmis sion #define START_RECEIVER 0x0002 //Starts reception #define DUMMY_WRITE 0xaaaa //Message sent when d oing a dummy write #define PWM_GAIN 512 //Gain of the PWM #define PWM_OFFSET 128 //Offset of the PWM #define DDFS_MSWORD 0x4000 //Frequency of the carr ier (Most Significant Word) #define DDFS_LSWORD 0x0000 //Frequency of the car rier (Least Significant Word) #define START_TX 0x0001 //Starts Tx transmission ( sets bit 0) #define I_MESSAGE 30000 //Message when writing to I #define Q_MESSAGE 30000 //Message when writing to Q #define RESET_FPGA 0x0000 //Resets the FPGA //Rx Define #define FIVE_CARRIER_FREQUENCIES 5 //Carrier freque ncies used when coding and decoding //RX Messages #define PHASE_HIGH 0x0000 #define PHASE_LOW 0x0000 #define COSINUS 0x0000 #define SINUS 0x0000 #define START_DECODER 0x0002 //Other #define SINEWAVE_5000HZ_LENGHT 20 //Lenght of the 5 000Hz Sinewave table (For test purposes) //------------------------------------------------- ----------------- // Generic API //------------------------------------------------- ----------------- //Configuration of the SPI and the FPGA extern void SSI_ConfigureSPI (void); extern void SSI_ConfigureFPGA (void); extern void ConfigurationTriggerRQ50K (void); extern void ConfigurationTriggerDRQ (void); //Sending via SPI extern void SSI_Send16(long unsigned int data_to_be _sent); extern void SSI_Send8(long unsigned int data_to_be_ sent); //Interruptions extern void IntRQ50KHandler (void); extern void IntDRQHandler(void); extern void IntSSIHandler(void); //TX Bench (PWM indirect) extern void SSI_Simulation(void); extern void SSI_SendISendQ(void); extern void SSI_ResetFPGA (void); extern void SSI_SendStart(void); //RX Bench extern void SSI_ConfigRx(void); extern void SSI_StartDecoder(void); #endif

Page 87: Arm Cortex

MuZIC Internship Report 2009

87

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

// ================================================ == // End

3. ADC #include "hw_ints.h" #include "hw_memmap.h" #include "hw_types.h" #include "debug.h" #include "gpio.h" #include "interrupt.h" #include "ssi.h" #include "sysctl.h" #include "lm3s2965.h" #include "timer.h" #include "system_config.h" #include "drv_spi0_adc.h" #define SSI_CS GPIO_PIN_3 #define SSI_CLK GPIO_PIN_2 #define SSI_TX GPIO_PIN_5 #define SSI_RX GPIO_PIN_4 #define WAIT_1_CYCLE 1 int main(void) {

//Local variables unsigned long ulIdx = 0;

volatile unsigned long ulLoop; //Code (void) SYS_Configuration (); (void) ADCIC (); (void) ADC_SSI_Configure(); (void) ADC_Calibration(); //SysCtlDelay(100); (void) SYS_Enable_Interruptions (); while (1) { GPIO_PORTG_DATA_R |= 0x04; for(ulLoop = 0; ulLoop < 2000000; ulLoop++) { } GPIO_PORTG_DATA_R &= ~(0x04); for(ulLoop = 0; ulLoop < 2000000; ulLoop++) { } ulIdx++; } } /************************************************** *******************************************/ //END /************************************************** *******************************************/ //------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. drv_spi0_adc .c //------------------------------------------------- ------- //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- -------

Page 88: Arm Cortex

//------------------------------------------------- ------- // Include //------------------------------------------------- ------- #include "hw_ints.h" #include "hw_memmap.h" #include "hw_types.h" #include "debug.h" #include "gpio.h" #include "interrupt.h" #include "ssi.h" #include "sysctl.h" #include "lm3s2965.h" #include "drv_spi0_adc.h" #include "timer.h" #include "system_config.h" #include "comp.h" //------------------------------------------------- ------- // Global constants, variables //------------------------------------------------- ------- int adc_counter = 0; //Counter for the acquisition of data from the ADC unsigned long int ADC_received_data [4]; //To sto re the received data from the ADC unsigned short int dummy_write = DUMMY_WRITE; //Us ed to give the ADC the SPI clock //------------------------------------------------- ------- // Local functions //------------------------------------------------- ------- void InterruptIC(void); /************************************************** **************************************************************/ //* Function: ADC_SSI_Configure //* Task: Configures the hardware in order to attai n the ADC needs on the SPI. // Inputs: RX, // Outputs: SYNC, TX, SPI Clock /************************************************** **************************************************************/ extern void ADC_SSI_Configure (void) { //Code SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); / /Enables the use of the GPIO where the SSI is SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI); //Enables the use of the SSI0 GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_7) ; //We set the SYNC pin as an output GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_PIN _7); //We initialize SYNC at a high level GPIOPinTypeSSI(GPIO_PORTA_BASE, SSI_CLK | SSI_T X | SSI_RX); //Enables SSI clock, TX, RX SSI0_CR1_R = DISABLE_SSI; //Disables SSI operation in order to configure //SSI0 Configuration //Bit rate = FSSIClk / (CPSDVSR*(1+SCR)) = 2.1 3MHz //Bits 15-8: SCR = 2 //Bit 7: SPH = 0 (Serial Clock Phase) //Bit 6: SPO = 0 (Serial Clock Polarity) //Bits 5,4: FRF = 0 (Frame Format = SPI)

Page 89: Arm Cortex

MuZIC Internship Report 2009

89

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

//Bits 3-0: DSS = 16 (Data Size Select = 16 bi ts by default) SSI0_CR0_R = (SCR | SPH | SPO | SPH | FRF | DSS_8) ; SSI0_CPSR_R = CLOCK_PRESCALE_2; //Clock Prescale has to be an even number between 2 and 256 SSI0_IM_R = (INT_RX_FIFO | INT_TIME_OUT); //SSI0_IM_R = 0x06 Enables Receive FIFO and Receiv e Time-Out Masks (not Receive Overrun Interrupts) SSI0_ICR_R = (INT_TIME_OUT | INT_OVERRUN); //SSI0_ICR_R = 0x03 Clears all interruptions (exce pt Receive FIFO) SSI0_CR1_R = ENABLE_SSI; //Enables SSI operation again } /************************************************** **************************************************************/ //* Function: ADC_Interruprion_Compare //* Task: Sets pin 6 from GPIO A as a rising edge t riggered interrupt. /************************************************** **************************************************************/ extern void ADCIC (void) { //Code GPIO_PORTA_ICR_R = (PIN7 | PIN6 | PIN5 | PIN4 | PI N3 | PIN2 | PIN1 | PIN0); //Clear all edge interruptions GPIO_PORTA_DEN_R = PIN6; //Set pin 6 as input GPIO_PORTA_IS_R = ALL_EDGE_SENSITIVE; //Set edge-sensitive interruptions GPIO_PORTA_IBE_R = CONTROLLED_BY_INTERRUPT_EVENT; //Interrupt generation controlled by the Interrup t Event (GPIOIEV) GPIO_PORTA_IEV_R = FALLING_EDGE_INTERRUPTIONS; ` //Configure pin 6 to trigger an interruption whe n falling edges GPIO_PORTA_IM_R = PIN6; //Interruptions coming from pin 6 are allowed GPIO_PORTA_ICR_R = (PIN7 | PIN6 | PIN5 | PIN4 | PI N3 | PIN2 | PIN1 | PIN0); //Clear all interruptions } /************************************************** **************************************************************/ //* Function: ADC_SSI_Send8 //* Task: Sends 8 bits data via SPI. First, it conf igures the SPI channel to a data size of 8 bits. // Then, it sends the data. /************************************************** **************************************************************/ extern void ADC_SSI_Send8(long unsigned int data_to _be_sent) { //Code GPIO_PORTA_ICR_R = PIN6; //Clear interruptions from pin 6 (void) SSIDataPut(SSI_BASE, data_to_be_sent); //Sends the information to the ADC } /************************************************** **************************************************************/ //* Function: ADC_Calibration //* Task: The output SYNC_ADC is set to 0 during 10 0 ms in order to calibrate the ADC, then is set again to 1. /************************************************** **************************************************************/

Page 90: Arm Cortex

extern void ADC_Calibration (void) { //Code GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, !GPIO_PI N_7); //We set the SYNC pin to 0 SysCtlDelay (SYNC_TIME_100MS); //Waits for synchronisation with the ADC (100 ms) GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, GPIO_PIN _7); //Once the synchronisation has been done, we set SY NC to 1 } /************************************************** **************************************************************/ //* Function: InterruptSSIADCControl //* Task: Handler used to manage the interruptions coming from the SSI used by the ADC. // The handler can manage 3 different interruptions : // - Recieve FIFO: When the RX FIFO is half full or more. We read the FIFO, update the ADC counter and check if // a whole package has been received(24 bits). // - Time-Out: As the data coming from the ADC will never be enough to trigger the Receive FIFO interruption, // the Time-Out interruption is needed. This inte rruption is triggered whenever there is data inside the RX // which has not been read. It performs the same tasks as the Receive FIFO, but with a delay of 32 bits // - Overrun: This function can be implemented for the SPI, but it is of no use in the pesent code /************************************************** **************************************************************/ void InterruptSSIADCControl (void) { //Local variables unsigned long adc_ssi_interruption_status; //Code adc_ssi_interruption_status = SSI0_MIS_R; if((adc_ssi_interruption_status & SSI_ADC_RECEIVE_ FIFO)) { ADC_received_data [adc_counter] = SSI0_DR_R; //We read the data coming from the ADC and store it in the memory adc_counter++; //Update the adc_counter (counts the packets of 8 bits received from the ADC) if (adc_counter == HAVE_24_BITS_BEEN_READ) { adc_counter = 0; //We reset the counter of the ADC } else { (void)ADC_SSI_Send8(dummy_write); } } if((adc_ssi_interruption_status & SSI_ADC_TIME_OUT )) { ADC_received_data [adc_counter] = SSI0_DR_R; adc_counter++; if (adc_counter == HAVE_24_BITS_BEEN_READ) { adc_counter = 0; } else { (void)ADC_SSI_Send8(dummy_write); } } if((adc_ssi_interruption_status & SSI_ADC_OVERRUN) ) //TODO { } }

Page 91: Arm Cortex

MuZIC Internship Report 2009

91

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

/************************************************** ********************/ //* Function: InterruptIC //* Task: Handler used to manage the interruptions coming from GPIO A // used by the ADC. /************************************************** *******************/ void InterruptIC(void) { adc_counter = 0; //TODO: Activate the Chip Select of ADC (void)ADC_SSI_Send8(dummy_write); } // ================================================ == // End //------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. drv_spi0_adc .h //------------------------------------------------- ------- // Description ....................... // // Tasks: //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- ------- #ifndef _DRV_SPI_FPGA_H_ #define _DRV_SPI_FPGA_H_ //------------------------------------------------- ------- // Glocal Define, macro //------------------------------------------------- ------- //SSI Configuration #define DISABLE_SSI 0x0000 #define ENABLE_SSI 0x0002 #define CLOCK_PRESCALE_2 0x0002 //Set prescale to 2 (has to be an even number between 2 and 256) #define INT_RX_FIFO (1<<2) //Enable RX FIFO int errupt #define INT_TIME_OUT (1<<1) //Enable Time out in terrupt #define INT_OVERRUN (1) //Enable Overrun inter rupt #define SSI_CLK GPIO_PIN_2 #define SSI_CS GPIO_PIN_3 #define SSI_RX GPIO_PIN_4 #define SSI_TX GPIO_PIN_5 #define ADC_SYNC GPIO_PIN_6 #define ADC_DRDY GPIO_PIN_7 #define ANALOG_COMPARATOR_0 0 #define SSI_BASE 0x40008000 // SSI_ BASE is the address of the SSI transmit FIFO #define SCR (2<<8) //SCR = 2 #define SPH (0<<7) //SPH = 0 #define SPO (0<<6) //SPO = 0 #define SPH (0<<7) //SPH = 0 #define FRF (0<<4) //Freescale SPI Format #define DSS_8 (0x7) //Data Size Select = 8 #define DSS_16 (0xf) //Data Size Select = 16 #define DATA_SIZE_8 8 #define DATA_SIZE_16 16 #define IS_SPI_BUSY 0x0010 //If the SPI is busy, or the transmit FIFO is not empty, bit 4 SSISR register is set to 1

Page 92: Arm Cortex

#define IS_RX_FIFO_EMPTY 0x04 //Masks #define SSI_ADC_RECEIVE_FIFO 0x4 #define SSI_ADC_TIME_OUT 0x2 #define SSI_ADC_OVERRUN 0x1 #define ALL_EDGE_SENSITIVE 0x00 #define CONTROLLED_BY_INTERRUPT_EVENT 0x00 #define FALLING_EDGE_INTERRUPTIONS 0x00 #define DUMMY_WRITE 0xaa #define SYNC_TIME_100MS 427000 #define HAVE_24_BITS_BEEN_READ 2 //------------------------------------------------- ----------------- // Generic API //------------------------------------------------- ----------------- extern void ADC_SSI_Configure (void); extern void ADCIC (void); extern void ADC_Calibration (void); extern void ADC_SSI_Send8(long unsigned int data_to _be_sent); extern void InterruptIC(void) ; extern void InterruptSSIADCControl (void); #endif // ================================================ == // End //------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. system_confi g.c //------------------------------------------------- ------- // Description ....................... // // Tasks: //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- ------- /************************************************** **************************************/ //INCLUDE /************************************************** **************************************/ #include "hw_ints.h" #include "hw_memmap.h" #include "hw_types.h" #include "debug.h" #include "gpio.h" #include "interrupt.h" #include "ssi.h" #include "sysctl.h" #include "lm3s2965.h" #include "timer.h" #include "system_config.h" /************************************************** ***************************************/ /************************************************** **************************************/ //* Function: SYS_Configuration //* Task: Configures the system clock and the perip herials which will be used /************************************************** **************************************/ extern void SYS_Configuration (void) { SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN); SYSCTL_RCGC2_R |= (PORTG | PORTA); //Activates t he use of Port A and G SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);

Page 93: Arm Cortex

MuZIC Internship Report 2009

93

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

GPIO_PORTG_DIR_R = (PIN2); //Configuration of the pin used by the LED GPIO_PORTG_DEN_R = (PIN2); } /************************************************** **************************************/ //* Function: SYS_Activate_Interruptions //* Task: Enables the use of interruptions by the s ystem, and enables the interruptions // of the peripherials in use /************************************************** **************************************/ extern void SYS_Enable_Interruptions (void) { IntMasterEnable(); IntEnable(INT_GPIOA); IntEnable(INT_SSI0); } /************************************************** **************************************/ //* Function: SYS_Timer_Configuration //* Task: Configures the Timer 0 of the microproces sor. The Timer counts backwards starting // from a number set by the user. Once the Timer ha s been configured, it starts to count /************************************************** **************************************/ extern void SYS_Timer_Configuration (void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); //E nables the peripherial TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PE R); //Chooses the 32-bit, periodic counter TimerLoadSet(TIMER0_BASE, TIMER_A, COUNTER_20_M S); //Sets the timer to count 20ms TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT) ; //Enable interruption due to Timeout (end of count) TimerEnable(TIMER0_BASE, TIMER_A); //Enable the Timer A from Timer 0 (the only one which is used for this t ype of configuration) IntEnable(INT_TIMER0A); //Enables interruptions from Timer A } /************************************************** ***************************************************************/ //END /************************************************** ***************************************************************/ //------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. system_confi g.h //------------------------------------------------- ------- // Description what this module is used for........ ............... // // Tasks: //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- ------- #ifndef _SYSTEM_CONFIG_H_ #define _SYSTEM_CONFIG_H_ /************************************************** ***************************************************************/ //GLOBAL DEFINE, MACROS /************************************************** ***************************************************************/ //Pins

Page 94: Arm Cortex

#define PIN0 0x01 #define PIN1 0x02 #define PIN2 0x04 #define PIN3 0x08 #define PIN4 0x10 #define PIN5 0x20 #define PIN6 0x40 #define PIN7 0x80 //Ports #define PORTA 0x01 #define PORTB 0x02 #define PORTC 0x04 #define PORTD 0x08 #define PORTE 0x10 #define PORTF 0x20 #define PORTG 0x40 #define PORTH 0x80 //System activation of the interruptions #define INT_UART0 21 #define INT_GPIOA 16 #define INT_SSI0 23 //Timer 0 define #define COUNTER_20_MS 525 /************************************************** ***************************************************************/ //GENERIC API /************************************************** ***************************************************************/ extern void SYS_Enable_Interruptions (void); extern void SYS_Configuration (void); extern void SYS_Timer_Configuration (void); #endif /************************************************** ***************************************************************/ //END /************************************************** ***************************************************************/

4. PWM #include "hw_ints.h" #include "hw_memmap.h" #include "hw_types.h" #include "debug.h" #include "gpio.h" #include "interrupt.h" #include "sysctl.h" #include "lm3s2965.h" #include "system_config.h" #include "drv_pwm.h" #include "pwm.h" int main(void) { SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN); // Set the clocking to run directly from the crystal.

Page 95: Arm Cortex

MuZIC Internship Report 2009

95

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

(void) PWM_Configure(); (void) SYS_Enable_Interruptions (); while(1) // Loop forever while the PWM signals are generated. { } } /************************************************** ***************************************************************/ //END /************************************************** ***************************************************************/ //------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. drv_pwm.c //------------------------------------------------- ------- // Description ....................... // // Tasks: //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- ------- //------------------------------------------------- ------- // Include //------------------------------------------------- ------- #include "hw_ints.h" #include "hw_memmap.h" #include "hw_types.h" #include "debug.h" #include "gpio.h" #include "interrupt.h" #include "sysctl.h" #include "lm3s2965.h" #include "drv_pwm.h" #include "system_config.h" #include "pwm.h" //------------------------------------------------- ------- // Local Define, macro //------------------------------------------------- ------- //------------------------------------------------- ------- // Local enum, struct, union //------------------------------------------------- ------- //------------------------------------------------- ------- // Local type //------------------------------------------------- ------- //------------------------------------------------- ------- // Local constants, variables //------------------------------------------------- ------- int index_sinewave5000Hz = 0; //------------------------------------------------- ------- // Global constants, variables //------------------------------------------------- ------- static long Sinewave5000Hz [SINEWAVE_TABLE_SIZE] = {118,115,108,96,81,64,47,32,20,13,10,13,20,32,47,64 ,81,96,108,115}; //------------------------------------------------- -------

Page 96: Arm Cortex

// Local functions //------------------------------------------------- ------- /************************************************** **************************************************************/ //* Function: PWM_Configure //* Task: Configures the hardware in order to use t he PWM 0. //* The configured PWM has the following features: //* - Provided a the microprocessor uses a 12.8MHz clock, the PWM0 works with a 12.8 MHz clock //* - The Timer Mode used is Count-Down (from the L oaded value to zero) //* - The Dead-Band Generator is used to create the second signal. Therefore, the second signal is not independent. //* - Both Rising Edge Delay and falling Edge Delay of the Dead-Band Generator are the same (5/12.8MHz = 380ns) (see page 490, LM3S2965 Data Sh eet) //* - The PWM generates a signal every 100KHz //* - No synchronisation mode is used /************************************************** **************************************************************/ void PWM_Configure(void) { //Code SysCtlPWMClockSet(SYSCTL_PWMDIV_1); //Sets the PWM Clock Predivider: We directly take the System Clock SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM); // Enable the peripherals used by the PWM 0. (PWO and GPIO G) SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); GPIOPinTypePWM(GPIO_PORTG_BASE, GPIO_PIN_2 | GP IO_PIN_3); // Set GPIO G2 and G3 as PWM pins. They are used to output the PWM0 a nd PWM1 signals. PWMGenConfigure(PWM_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC); //PWM Configuration PWMGenPeriodSet(PWM_BASE, PWM_GEN_0, FREQUENCY_ PWM_100KHZ); PWMDeadBandEnable(PWM_BASE, PWM_OUT_0,WIDTH_DELAY_DEAD_BAND_RISING_EDGE, WIDTH_DELAY_DEAD_BAND_FALLING_EDGE); //Enables Dead Band PWMPulseWidthSet(PWM_BASE, PWM_OUT_0, PWM_0_DEF AULT_VALUE); // Set PWM0 to its default value PWMGenIntTrigEnable(PWM_BASE, PWM_GEN_0,PWM_INT_CN T_ZERO); //Enable interruptions from PWM Generator Block 0 PWMIntEnable(PWM_BASE, PWM_INT_GEN_0); //Enables generator and fault interruptions for PW M Module 0 IntEnable(INT_PWO_0); //Enable interruptions coming from PWM 0 PWMOutputState(PWM_BASE, PWM_OUT_0_BIT | PWM_OU T_1_BIT, true); // Enable the PWM0 and PWM1 output signals. PWMGenEnable(PWM_BASE, PWM_GEN_0); // Enable the PWM generator. } /************************************************** **************************************************************/ //* Function: InterruptPWM0 //* Task: Handler for the PWM 0 interruption. //* Every time the PWM 0 Counter reaches 0 (10 micr o seconds), an interruption is triggered. //* This interruption clears the interruption flag, takes a value from a table, and loads it into the PWM0. /************************************************** **************************************************************/ void InterruptPWM0(void) { //Variables unsigned long data;

Page 97: Arm Cortex

MuZIC Internship Report 2009

97

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

//Code PWM_0_ISC_R = CLEAR_PWM_0_INTERRUPTION; data = Sinewave5000Hz [index_sinewave5000Hz]; //Take the value from the table... PWMPulseWidthSet(PWM_BASE, PWM_OUT_0, data); //.. .Load it into the PWM... index_sinewave5000Hz++; //...Update the table index. if (index_sinewave5000Hz == SINEWAVE_TABLE_SIZE) //If we arrive to the end of the table, we reset th e index table { index_sinewave5000Hz = 0; } } // ================================================ == // End //------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. drv_pwm.h //------------------------------------------------- ------- // Description ....................... // // Tasks: //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- ------- #ifndef _DRV_PWM_H_ #define _DRV_PWM_H_ //------------------------------------------------- ------- // Glocal Define, macro //------------------------------------------------- ------- #define FREQUENCY_PWM_100KHZ 128 #define WIDTH_DELAY_DEAD_BAND_RISING_EDGE 5 #define WIDTH_DELAY_DEAD_BAND_FALLING_EDGE 5 #define INT_PWO_0 26 #define PWM_0_DEFAULT_VALUE 32 #define CLEAR_PWM_0_INTERRUPTION 0x01 #define SINEWAVE_TABLE_SIZE 20 //------------------------------------------------- ----------------- // Generic API //------------------------------------------------- ----------------- extern void PWM_Configure(void); extern void InterruptPWM0(void); #endif // ================================================ == // End //------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. system_confi g.c //------------------------------------------------- ------- //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved

Page 98: Arm Cortex

//------------------------------------------------- ------- /************************************************** *************************************/ //ISSUES /************************************************** *************************************/ //* This file contains all the functions that need to be called before using the // microprocessor. //* All the functions related with the configuratio n of the system are placed here //* Interruptions must be enabled AFTER the configu ration of the system and all the // peripherials. Otherwise, the program will not f unction properly. /************************************************** *************************************/ /************************************************** **************************************/ //INCLUDE /************************************************** **************************************/ #include "hw_ints.h" #include "hw_memmap.h" #include "hw_types.h" #include "debug.h" #include "gpio.h" #include "interrupt.h" #include "ssi.h" #include "sysctl.h" #include "lm3s2965.h" #include "timer.h" #include "system_config.h" /************************************************** ***************************************/ /************************************************** **************************************/ //* Function: SYS_Configuration //* Task: Configures the system clock and the perip herials which will be used /************************************************** **************************************/ extern void SYS_Configuration (void) { SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN); SYSCTL_RCGC2_R |= (PORTG | PORTA | PORTH); //Act ivates the use of Port A and G SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); GPIO_PORTG_DIR_R = (PIN2); //Configuration of the pin used by the LED GPIO_PORTG_DEN_R = (PIN2); } /************************************************** **************************************/ //* Function: SYS_Activate_Interruptions //* Task: Enables the use of interruptions by the s ystem, and enables the interruptions // of the peripherials in use /************************************************** **************************************/ void SYS_Enable_Interruptions (void) { IntMasterEnable(); } /************************************************** **************************************/ //* Function: SYS_Timer_Configuration //* Task: Configures the Timer 0 of the microproces sor. The Timer counts backwards starting // from a number set by the user. Once the Timer h as been configured, it starts to count. /************************************************** **************************************/ extern void SYS_Timer_Configuration (void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); //E nables the peripherial TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PE R); //Chooses the 32-bit, periodic counter TimerLoadSet(TIMER0_BASE, TIMER_A, COUNTER_20_M S); //Sets the timer to count 20ms

Page 99: Arm Cortex

MuZIC Internship Report 2009

99

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT) ; //Enable interruption due to Timeout (end of count) TimerEnable(TIMER0_BASE, TIMER_A); //Enable the Timer A from Timer 0 (the only one which is used for this t ype of configuration) IntEnable(INT_TIMER0A); //Enables interruptions from Timer A } /************************************************** *******************************************/ //END /************************************************** *******************************************/ //------------------------------------------------- ------- // Project ........................... MuZIC // Module ............................ // File .............................. system_confi g.h //------------------------------------------------- ------- //------------------------------------------------- ------- // (c) Copyright Schlumberger 2009 - All rights res erved //------------------------------------------------- ------- #ifndef _SYSTEM_CONFIG_H_ #define _SYSTEM_CONFIG_H_ /************************************************** *******************************************/ //GLOBAL DEFINE, MACROS /************************************************** *******************************************/ //Pins #define PIN0 0x01 #define PIN1 0x02 #define PIN2 0x04 #define PIN3 0x08 #define PIN4 0x10 #define PIN5 0x20 #define PIN6 0x40 #define PIN7 0x80 //Ports #define PORTA 0x01 #define PORTB 0x02 #define PORTC 0x04 #define PORTD 0x08 #define PORTE 0x10 #define PORTF 0x20 #define PORTG 0x40 #define PORTH 0x80 //System activation of the interruptions #define INT_UART0 21 #define INT_GPIOA 16 #define INT_SSI0 23 //Timer 0 define #define COUNTER_20_MS 525 /************************************************** *******************************************/ //GENERIC API /************************************************** *******************************************/ extern void SYS_Enable_Interruptions (void); extern void SYS_Configuration (void); #endif /************************************************** *******************************************/ //END /************************************************** *******************************************/

Page 100: Arm Cortex

Annex B: Petroleum exploration and production

1. Exploration

In the early days of oil exploration, the search was very hazardous. Wildcat wells were

often drilled on a hunch. Today, geologists apply earth science and modern technologies in

the search for oil.

The purpose of oil prospecting is to find rock formations that can be possible

hydrocarbon traps. They are not often visible on the surface, so methods that can reveal the

nature and structure of rock formations are necessary.

First, large areas are explored by airplanes or satellite photographs. Experts then study

these photographs to find formations that contain oil traps. These basic surveys permit the

search to be narrowed down and continued with more detailed exploration in smaller

areas.

Figure 38 – Mapping the ocean layer

To continue the search and to be able to view oil and gas reservoirs that are buried

under thousands of meters of sea or rock, seismic surveys are executed. They can be

performed on land or at sea but the principles are the same: sound waves penetrate the

many layers of rocks. When one layer meets another at a boundary, the waves are reflected.

Each boundary reflects a part of the sound back to the surface. The rest continues

downwards. On the surface, special devices – geophones – pick up the reflected sounds.

Depending on how long the reflection time is, the type of geological formation can be

inferred.

Page 101: Arm Cortex

MuZIC Internship Report 2009

101

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Figure 39 – Trucks used to map the underground

2. Well construction

The construction of a well is executed in several steps. First, the well is drilled and

logged. Then, casing is installed and cementing carried out. Since drilling, logging, casing,

and cementing are performed step-by-step, they are repeated several times. After that,

production tubing and packers are installed. Finally, perforations are done in the casing to

permit the oil to flow into the tubing.

3. Drilling

The majority of the rigs today are rotary drilling rigs. One advantage is that the rotary

drill can drill in most formations. The rotary drilling rig uses a rotary bit with rows of teeth

that penetrate the rock and scrape the rock out.

Afterwards, the cuttings of rock must be moved out of the way. Otherwise, the drill bit

would be hindered. To permit this, fluid circulates in the well. This fluid, called drilling mud,

transports the cuttings to the surface where they are sorted out so that the drilling mud can

be recycled in the borehole. The fluid enters the well through the drill pipe and goes out

through the drill bit. A huge pump on the surface moves the mud circulation system.

Page 102: Arm Cortex

Drilling mud is not just simple mud, but a complex mixture of different materials. A

better name for it would be therefore drilling fluid. The fluid also prevents the well from

collapsing, as the whole borehole is filled with fluid that supports the walls. Another

function of the drilling fluid is the cooling effect it has on the drilling bit.

Figure 40 - Drilling

4. Logging

Logging is a set of techniques which consists of collecting and registering in real time

geological information about the interior of the Earth. The logging enables eventually to

confirm the surveys that have been previously done. Only one out of seven exploration

wells is developed into a production well.

Much has occurred since the Schlumberger brothers succeeded with the first electric

log in 1927. Today, there are many different variants, each with its own specialty and field

of application. The main types are: Wireline logging and logging while drilling (LWD).

Wireline logging is used in open and cased holes. LWD is performed, as its name indicates,

while drilling.

Page 103: Arm Cortex

MuZIC Internship Report 2009

103

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Many kinds of logging tools are available. Some of them measure and record the way in

which formations respond to electric current; others measure radioactive attributes of the

rock or the speed with which sound travels through the formation. Using these different

methods, several aspects of the well can be evaluated. Examples are: porosity, shale

indicator, permeability, pressure, and the rock’s mechanical properties.

Figure 41 – A Wireline Tool

Logging is performed from a portable laboratory. It is placed in a truck for land rigs

and in a portable logging cabin offshore. To execute the logging, tools are lowered into the

well on a wireline. After reaching the bottom, they are slowly reeled back up. Formation

properties are measured during the rising.

The tools transmit the data instantly to computers in the laboratory. The data is

processed by computers in real-time and interpreted by experts. The gathered data is

displayed in logs that indicate the presence of oil and gas.

Logging can also be performed while drilling. This method is called LWD. This gives the

operators valuable information while drilling so that the drilling can be adapted more

accurately to different rock formations. All the gathered information is transmitted to the

surface in order to be analyzed. A wireline log has to be performed after the drilling anyway

to complete the logging.

Page 104: Arm Cortex

Figure 42 – Recording Wireline results

5. Casing

To prevent the well from collapsing and to isolate the rock formations from the well,

the well has to be cased. The setting of the casing is done in several steps. A well of several

hundred meters cannot be drilled in one step; it has to be stabilized regularly as the drilling

goes deeper.

After the casing has been set, the initial hole becomes smaller. A smaller bit, which fits

in the new hole, is used. This means that the well’s diameter becomes progressively smaller

as the well deepens.

6. Cementing

The objectives of cementing are to provide a complete isolation of different zones,

support the casing, and protect the casing string. It is very important that fluids cannot

migrate from one formation to another. This is to prevent, for example, oil leakage in

nearby water reservoirs.

Cement contains silica, alumina and iron oxide. Cement wells sets through a chemical

process that does not require air. This process consists of very complex chemistry.

Page 105: Arm Cortex

MuZIC Internship Report 2009

105

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

7. Production tubing and packers

Usually, a well is produced through a tubing string rather than through the casing for

several reasons:

• The tubing is not cemented in the well. When a joint of tubing fails, it can be easily

replaced. Since casing is cemented, it is very difficult to replace it.

• Tubing allows the operators to control the production by placing special tools and

devices in or on the tubing string. These devices enable the operator to make well

production more efficient.

• Tubing also protects the casing from the corrosion and erosion that normally occur.

The reservoir fluids are corrosive and during the life of a well they tend to corrode

metals. By producing through tubing, which can be easily replaced, the casing is

preserved.

Packers are installed at the same time as the production tubing. A packer is a sealing

device that is installed on the tubing string. It is placed above the perforations in the casing.

The packer then expands and seals the annular space between the tubing and the casing

above the perforations. The reservoir fluids are led into the tubing by the packers and so

the casing is protected.


Top Related