Vous êtes sur la page 1sur 105

MuZIC Internship Report

Guillermo ALEJANDRE ALBA 8/21/2009

MuZIC Internship Report 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 JeanFranois 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.

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 lneas generales, el trabajo realizado dentro del equipo de desarrollo de firmware ha sido la implementacin de diferentes mdulos de un mdem. Dicho mdem es utilizado para un sistema de transmisin entre distintas localizaciones. El microprocesador en cuestin se trata de un Luminary LM3S2965. As, podemos distinguir tres grandes ejes dentro del presente trabajo. El primero de ellos consisti en la implementacin de una UART (acrnimo del trmino ingls Universal Asynchronous Receiver/Transmitter, Transmisor-Receptor Asncrono 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 travs de los puertos (ver Figure 1).

Figure 1 Conexin PC-Microcontrolador

MuZIC Internship Report 2009


El mtodo utilizado para desarrollar esta aplicacin podra denominarse como creciente. As, se empez con un programa ms sencillo que llevara a cabo nicamente la lectura y escritura de puertos, al que se le fueron aadiendo elementos ms complejos hasta llegar a la versin 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. Adems, 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 recepcin y transmisin disponibles en el microprocesador, as como algunas de las interrupciones internas. La interrupcin de recepcin se activa una funcin de recepcin que se encarga de almacenar los datos en un buffer de recepcin. Si el tamao de los datos enviados es inferior a un determinado tamao, se activa una interrupcin de tipo Time-Out. Esta interrupcin avisa al microprocesador de que hay elementos en la FIFO de recepcin que no han sido tratados, y se procede a la lectura de la FIFO hasta que sta queda vaca. Despus, se escriben los datos en el buffer de transmisin y se envan. Finalmente, para garantizar que no hay problemas de entrecruzado de informacin (debido a informacin que haya podido quedar almacenada accidentalmente en cualquiera de las FIFOs), se procede a un reseteo sistemtico de los buffers, las FIFOs, y los contadores. La segunda fase de programacin de la UART consisti simplemente en la integracin de las funciones previamente implementadas dentro de un sistema tiempo real. En este caso, la comunicacin entre microprocesador y ordenador se realiza va un protocolo previamente establecido.

Figure 2 Conexin FPGA-Microcontrolador

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

La segunda lnea de trabajo consisti en la programacin de un bus SPI (Serial Protocol Interface) entre una FPGA (Field Programmable Gate Array) y el microprocesador. El bus SPI es un estndar de comunicaciones implementado por Motorola y utilizado para la transferencia de informacin entre circuitos integrados en equipos electrnicos. 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 lnea con el reloj que regula las comunicaciones del bus, una lnea de dato entrante, una de dato saliente, y un pin de activacin (chip select). El cdigo programado en el interior de la FPGA ha sido realizado por una empresa externa, y el objetivo principal de la implementacin de dicho bus fue verificar que la lgica de la FPGA cumpla con las especificaciones dadas a la empresa externa. En lneas generales, la FPGA recoge datos procedentes de un conversor A/D (tambin llamado ADC, Analog to Digital Conversor), los trata, y se los pasa al microprocesador. Adems, ha de ser capaz de enviar seales a un PWM (Pulse-With Modulator). La lgica implementada en el interior de la FPGA esta compuesta por diferentes mdulos por lo que para proceder a su validacin se implementaron diversas funciones. La metodologa utilizada es similar a la de la implementacin de la UART: Siguiendo las especificaciones recibidas por el programador, se implement un simple programa que generara una seal de PWM constante y de valor conocido, que luego se fue mejorando para permitir la interaccin con todos los mdulos de la FPGA. Ello permiti encontrar algunos fallos en el cdigo de la FPGA, que fueron transmitidos a la empresa encargada. El resultado de este mdulo ha sido una aplicacin que permite interaccionar al microprocesador con la FPGA. Configura la FPGA para el tratamiento de datos del ADC y permite controlar el PWM a travs de la FPGA.

Figure 3 Conexin ADC-Microcontrolador

MuZIC Internship Report 2009


Por ltimo, se llev a cabo la programacin 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, enva una seal al microprocesador. La configuracin de base de dicho bus es similar a la utilizada para la comunicacin con la FPGA. Sin embargo, el microprocesador no necesita enviar ninguna instruccin al ADC, por lo que la lnea de transmisin no es utilizada. Finalmente, aparecen dos lneas ms: una (que llamaremos SYNC, de sincronizacin) se encarga de sincronizar el ADC con el microprocesador antes de comenzar con la recepcin de datos; la otra (DRDY, del ingls Data ReaDY) avisa al microprocesador de que hay nuevos datos disponibles en el ADC para el microprocesador. El funcionamiento de este mdulo es el siguiente: primero se realiza una configuracin de los puertos que sern utilizados. Despus, se sincroniza el ADC con el microprocesador. Y finalmente, se espera la generacin de una interrupcin 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 travs de DRDY). Esta aplicacin permite la comunicacin entre el ADC y el microprocesador y almacena los datos procedentes del ADC en la memoria del microprocesador. En conclusin, las aplicaciones implementadas para el microprocesador permiten interaccionar con diferentes perifricos, todos ellos necesarios para el funcionamiento de nuestro mdem. Trabajan de forma casi exclusiva con interrupciones, lo que optimiza la gestin del tiempo del microprocesador al hacer posible un tratamiento en funcin 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.

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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

MuZIC Internship Report 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

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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

MuZIC Internship Report 2009


Contents
Acknowledgments ..............................................................................................................3 Abstract/ Resumen ............................................................................................................4 Schlumberger Company Overview .................................................................................. 15
1. 2. a. b. c. d. e. f. g. 3. History ............................................................................................................................ 15 Schlumberger oilfield services ......................................................................................... 15 Western Geco ........................................................................................................................ 16 Drilling & Measurements ...................................................................................................... 16 Reservoir Evaluation Wireline .............................................................................................. 16 Well Services ......................................................................................................................... 17 Well Completion and Productivity ........................................................................................ 17 Schlumberger Information Services ...................................................................................... 17 Integrated Product Management ............................................................................................ 17 Schlumberger Ribaud Product Centre.......................................................................... 17

Petroleum Well Vocabulary............................................................................................. 19 The MuZIC Project ......................................................................................................... 21


1. 2. 3. 4. 1. 2. 3. 4. 5. 1. 2. 3. 4. 5. 6. 7. 1. 2. 3. 4. 5. 6. 7. Team composition ........................................................................................................... 21 Presentation of the project............................................................................................... 21 Description of the project ................................................................................................ 22 The internship in the project ........................................................................................... 22 Introduction .................................................................................................................... 24 LM3S2965: A short Description ...................................................................................... 24 Microcontrollers choice .................................................................................................. 25 The company: Luminary Micro, Inc................................................................................ 25 Project Overview ............................................................................................................. 26 Introduction .................................................................................................................... 27 Main definitions .............................................................................................................. 27 Objective ......................................................................................................................... 27 Specifications................................................................................................................... 28 Procedure used to attain the specifications ...................................................................... 29 Results ............................................................................................................................. 29 Remarks .......................................................................................................................... 35 Introduction .................................................................................................................... 37 Main definitions .............................................................................................................. 37 Objectives ........................................................................................................................ 38 Specifications................................................................................................................... 41 Procedure used to attain the specifications ...................................................................... 42 Results ............................................................................................................................. 42 Remarks .......................................................................................................................... 48

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

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

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

11

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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


1. 2. 3. 4. 5. 6. 7. 1. 2. 3. 4. 5. 6. 7. Introduction .................................................................................................................... 50 Main Definitions .............................................................................................................. 50 Objectives ........................................................................................................................ 50 Specifications................................................................................................................... 51 Procedure used to attain the specifications ...................................................................... 51 Results ............................................................................................................................. 52 Remarks .......................................................................................................................... 54 Introduction .................................................................................................................... 55 Main Definitions .............................................................................................................. 55 Objectives ........................................................................................................................ 55 Specifications................................................................................................................... 56 Procedure used to attain the specifications ...................................................................... 57 Results ............................................................................................................................. 57 Remarks .......................................................................................................................... 60

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

Conclusion ....................................................................................................................... 61 References........................................................................................................................ 62


1. 2. 3. 1. Manuals........................................................................................................................... 62 Websites .......................................................................................................................... 62 Software .......................................................................................................................... 62

Annex A: Peripherals Code ............................................................................................ 63


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 Exploration ..................................................................................................................... 100 Well construction ........................................................................................................... 101 Drilling ........................................................................................................................... 101 Logging........................................................................................................................... 102 Casing ............................................................................................................................ 104 Cementing ...................................................................................................................... 104 Production tubing and packers ........................................................................................ 105

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


1. 2. 3. 4. 5. 6. 7.

Table 1: Format of messages ..................................................................................................... 28 Table 2: FPGA Pin Assignment ................................................................................................ 47

MuZIC Internship Report 2009


Figure 1 Conexin PC-Microcontrolador ................................................................................. 4 Figure 2 Conexin FPGA-Microcontrolador ........................................................................... 5 Figure 3 Conexin 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

13

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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

MuZIC Internship Report 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. Schlumbergers 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.

15

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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.

MuZIC Internship Report 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.

17

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 wells 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:

MuZIC Internship Report 2009

Figure 6- Schlumberger Ribaud Product Center organization

SRPC is organized in mtiers 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 mtiers are organized under: Chemistry, Electrical, Mechanical, Software & Appl.Maths, Physics and Manufacturing. The Mtier manager is responsible for developing technologies and competences of mtier 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.

19

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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.

MuZIC Internship Report 2009


The MuZIC Project
1. Team composition

Project Manager

Physicists

Mechanical Engineers

Firmware Engineer

Telecommunications Engineer

Software Engineer

Electronic Engineers

Mechanical Intern

Firmware Intern

Electronic Technician

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,

21

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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.

Physical Concepts

Mechanics

Firmware

Electronics

Telecommunication

Surface Software

Simulations

Lab Tests

Field Tests

Figure 9 Parts of the MuZIC project The tasks performed in each of these parts were:

MuZIC Internship Report 2009


Firmware: This section took most of the internships time. It implied a deep study of the microcontrollers 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.

23

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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

MuZIC Internship Report 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. Microcontrollers 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 Luminarys 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.

25

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 older microcontrollers which have been used in industry for much more applications. We will see trollers 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 ibernation 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 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.

5. Project Overview
Figure 10 shows a small diagram of how the different electronics are communicated between them.

Figure 10 Connections Overview

MuZIC Internship Report 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 UARTs 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 users messages in a protocol shared with other tools used in downhole testing, and sends

27

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 SOF A0h 1 byte Length 2 to 255 1 byte Device 1 byte Command N bytes Data 1 byte Checksum

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 users 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).

MuZIC Internship Report 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 transmissions 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: Peripherals 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: Peripherals Code). Figure 11 shows the UART access module structure:

29

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Figure 11 - The UART module

The communication between the PC and the LM3S2965 is done through a RS232 through 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 be added. The maximum possible baud rate was 57600. The implemented UART works with a baud implemented 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 Applications Note. 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 16-byte microcontroller 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 level. The interruption will then alert the microcontroller, who will read the FIFO (in the case of nterruption , 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. Figure 12 shows a small diagram of how the reception works l works.

MuZIC Internship Report 2009 ship

Figure 12- Reception process All the interruptions from the UART are managed by the function UART0_Handler. This 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 treatment. 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 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 StartTransmission. This function will wait until the UART is free to be used by checking the tion UART flag register. Then, it partially fills in the FIFO, in order to enable the Transmission interruption. The microcontroller has implemented some interruptions that can be used to perform the communication between the PC and the LM3S2965. The FIFO needs to be partially 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 whenever the amount of data whenever inside the FIFO goes below a pre determined level (in this case, 1/8 of the total FIFO, 2 bytes). nside pre-determined 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 inferior FIFO. Hence, the transmission works automatically after the first call of StartTransmission. StartTransmission

31

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 hasnt 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.

MuZIC Internship Report 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.

33

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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

MuZIC Internship Report 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

35

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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.

MuZIC Internship Report 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

37

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 master (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 means sample on the 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: g

Figure 19 Clock Polarity and Phase For detailed information about the SPIs characteristics of the LM3S2965, please refer to the LM3S2965 Datasheet.

3. Objectives
As we have seen in the Mu MuZIC Presentation of the project, this project tries to bring communication in oilfield operations. Part of the signal processing associated with the transmission (TX) and reception (RX) functions are implemented on the embedded FPGA. FPGA There are two ways in which the TX can function, and one way for the RX. In all modes, the communication between microcontroller and FPGA are done via SPI.

MuZIC Internship Report 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. diagram of the steps followed by data inside the FPGA in this mode: Figure 20 shows a

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.

39

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 microcontrollers oscillator). nCS: SPIs microcontrollers chip select. SCLK: SPIs microcontrollers clock. SDin: SPIs microcontrollers data in. Outputs: ADC_CLK: ADCs main clock. ADC_MODE: ADCs functioning mode ADC_FORM ADC_SCLK: SPIs ADCs clock. ADC_nSYNC: ADCs synchronization pin. PWMout: PWM output. SDout: SPIs microcontrollers data out. DRQ: FPGAs Data Request. RQ50k: FPGAs PWMs data request.

MuZIC Internship Report 2009


Error: For debugging purposes. RSTout: Microcontrollers and/or ADCs 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.

41

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

All the modules which compose the FPGA program have to be verified, and have to work according to the specifications: o o o o The SPI between the FPGA and the ADC. (adc_if.v) The Transmitter processing block. (coder.v) The Receiver processing block. (decoder.v) The PLL that generates the clock for the ADC and the FPGA (using the one from the micro). (PLL12_8.v) o o o o The Power On Reset module. (por.v) The PWM generator. (pwm.v) The SPI interface with the microcontroller. (spi.v) 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 FPGAs 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: Peripherals Code). This task manages and controls all low level SPI communications between the FPGA and the LM3S2965. It has been designed to:

MuZIC Internship Report 2009 ship


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), and the 2) PWM gain and offset. Configure gure the interruption triggers for each TX processing mode using

ConfigurationTriggerRQ50k and ConfigurationTriggerDRQ, and handle the interruption , using IntRQ50KHandler and IntDRQHandler. Reset the FPGA using the function SSI_ResetFPGA. Start TX transmission using the function SSI_SendStart. sion Transmit data using the functions SSI_Send8 and SSI_Send16. Stop the SPI transmission using the function SSI_Stop. Figure 23 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 (spi_fpga_test_bench.c). This enables the user to choose between both modes before programming the 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 FPGAs program) supported 3.20MHz was chosen because it was faster. It is also compatible with the FPGAs

43

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 SPIs FIFOs because no data coming from the FPGA was expected and the TXs FIFOs 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 Luminarys SPIs 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

MuZIC Internship Report 2009 ship


the different tables. In order to prevent TX FIFO overflow, a state flag (called is the TX FIFO not full?) 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. In order to start a transmission, the function SSI_SendStart has to be called. This function rt simply tells the FPGA that the transmission is going to start e 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 the RQ50k or in the DRQ pin (depending on the TX processing mode we are testing). We can see in Figure 24 and Figure 25 what happens when an interruption is triggered in both modes.

Figure 24 First TX mode

45

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 values interruption. 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 ), the same actions. When any of these functions is called, the interruption is cleared and new data is sent. In the case of IntRQ50KHandler the index from the sine wave table is incremented (or IntRQ50KHandler, reset if the end of the table has been reached). If the values asked by the FPGA are duly sent, a PWM signal can be seen coming out from PWMout. Figure 26 and Figure 27 show some transmissions using the different TX processing modes.

MuZIC Internship Report 2009

Figure 26 First TX Mode

Figure 27 Second TX mode While programming the FPGA with the contractors 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 Input/Output Pin Number ADC_DIN ADC_nDRDY 152 143 RST CLK SYSTEM PINS Input/Output Pin Number 14 134 nCS SCLK SPI PINS Input/Output Pin Number 5 21

47

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

ADC_CLK ADC_MODE ADC_FORM ADC_SCLK ADC_nSYNC

155 146 149 137 140

DRQ RQ50k Error RSTout PWMout

127 11 2 18 8

SDin SDout

31 35

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 internships time due to its complexity and the fact that third partys 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 contractors 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 FPGAs memory, a reading function was implemented, with no success. Even though the FPGA specifications clearly said that the FPGAs 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

MuZIC Internship Report 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 contractors 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).

49

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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.

MuZIC Internship Report 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 FPGAs SPI, so the starting point for the ADCs SPI was the module from the previous section. The reception mode of the SPI was developed from this code, and tested afterwards.

51

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

6. Results
The result is another SPI driver that connected the ADC and the microcontroller directly. Again, this module works via interruptions (once the configuration has been done). This module uses two different types of interruptions: external interruptions (coming from is 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 DRDY signal (ADCIC is in charge of ADCIC the LM3S2965s configuration) and the interruptions are handled using InterruptIC, which configuration), 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 . 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 time-out interruption, and the overrun interruption. There is no need in sending data to the ADC (only nd dummy reads are performed), so the overrun interruption has not been treated. Unlike with the UARTs FIFOs, the trigger level cannot be configured. This means that a reception i interruption will only take place when more than half of the RXs FIFO is full (more than 16 bytes). As the nly data is only sent in 8-bit packets, this interruption will never be triggered. In fact, the only case to bit be treated is the time-out interruption. This interruption will appear if received data has not been out This 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

Figure 29 ADC 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 between this two devices. between Then, it synchronizes the ADC, and enables the interruptions coming from the SPI and the 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 test bench used to test this module is stored in o

MuZIC Internship Report 2009 ship


The SPI clock has been configured with a 2.13MHz clock. Both clock polarity and clock 2.13MHz-clock. clo phase are set to zero. The frame format is that of Motorola. As data was going to be recei received from the ADC, the SPIs FIFOs had to be enabled. Finally, the data size of the messages was s set to 8 bits. Figure 30 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 triggers the is tri reception interruption, where the first 8 bits of the 24 bit ADCs message are read and stored in 24-bit the microcontrollers memory. At the same time, a dummy write is performed to enable the next s packet to be sent. A counter is also incremented to keep track of the received parts. The reception keep interruption is called 3 times. Once the whole message has been received, the counter is reset. reset Figure 31 and Figure 32 show the SPI communication between the ADC and the he microcontroller. We can see that the whole ADC message is read before a new one arrives. .

53

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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.

MuZIC Internship Report 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 Luminarys 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 microcontrollers memory and generate a series of PWM pulses.

55

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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

MuZIC Internship Report 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 FPGAs 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 singleclock-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.

57

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 shootthrough current from damaging the power electronics. Figure 35 shows the PWM signal created using the dead-band generator.

MuZIC Internship Report 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: Peripherals 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.

59

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 LM3S2965s PWM worked in order to program the correct configuration.

MuZIC Internship Report 2009


Conclusion
This internship has enabled me to learn many things about the petroleum activity in general, as well as about Schlumbergers outstanding position in the energy market. The world petroleum industry requires the use of very advanced technologies and skills, and Schlumbergers 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.

61

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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

MuZIC Internship Report 2009


Annex A: Peripherals 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 reserved //--------------------------------------------------------

63

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

/****************************************************************************************/ //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; GPIO_PORTA_DEN_R |= 0x03; SYSCTL_RCGC1_R |= ACTIVATE_UART0; UART0_CTL_R &= DISABLE_UART0; UART0_LCRH_R &= FLUSH_UART0_FIFO; UART0_IBRD_R |= INTEGER_BDR; UART0_FBRD_R |= FRACTION_BDR; UART0_LCRH_R |= UART0_PARAMETERS; //Enable use UART 0 //Puts to zero bit 0 of UARTCTL (disables UART 0) //Puts to zero bit 4 of UARTLCRH (disables FIFO's // UART 0) //Integer portion of the Baud Rate Divisior //Fractional portion of the Baud Rate Divisior //Writing of the desired serial parameters: //Baud Rate: 19196 Data Lenght: 8bits One stop bit //No parity FIFOs enabled //Configuration of the Port A in order to be used //for the UART 0

UART0_IM_R |= UART0_INTERRUPT; UART0_IFLS_R = UART0_FIFO_LEVELS; UART0_CTL_R |= ENABLE_UART0;

//Puts to 1 bit 0 UARTCTL (enables UART 0)

UART0_ICR_R |= UART0_CLEAR_INTERRUPTIONS;

MuZIC Internship Report 2009


} /*********************************************************************************************/ //* Function: InterruptUART0Control //* Task: This function manages all the interruptions 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 ORed together before being sent to the // interrupt controller, so the UART can only generate 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 RX FIFO at the time of the reception. If this // error appears, the RX FIFO and the RXBuf are completely erased, and a message is sent to // task control. //* Break Error: NA, this error is not taken into account (not configured). //* Parity Error: NA, the UART0 is configured to work 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 appears, the RX FIFO and the RXBuf are // completely erased, and a message is sent to task control. //* Receive Time-Out Error: The receive timeout interrupt 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 becomes 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 the 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_INT)) { 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;

65

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 FIFO). 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--; TXIndex++; } } /****************************************************************************************/ //* Function: InterruptUART0Transmission //* Task: Once the Tx FIFO has been initialized, this 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 variables 'amount_of_data_left' and //Updates information regarding the amount of data and //the data that has to be sent

MuZIC Internship Report 2009


// 'data_to_be_sent' /****************************************************************************************/ void InterruptUART0Transmission (void) { //Local variables

if(TXDataCount > 0) //if there is data left, the interruption 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 computer, this fonction stores the data in a // variable for later use //ISSUES //* This function stores the received information in a variable, but it doesn't trigger any // interruption to tell anyone that it has information /****************************************************************************************/ 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 Received message... if (RXLenght > OSCAR_BUF_SIZE) //Total lenght includes 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 timeout counter and wake up serial task

67

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

//TODO RXBuf[RXDataCount] RXDataCount++; RXBuf[RXDataCount] RXDataCount++; RXBuf[RXDataCount] RXDataCount++; RXBuf[RXDataCount] RXDataCount++; RXBuf[RXDataCount] RXDataCount++; RXBuf[RXDataCount] RXDataCount++;

= UART0_DR_R; = UART0_DR_R; = UART0_DR_R; = UART0_DR_R; = UART0_DR_R; = UART0_DR_R;

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 reserved //--------------------------------------------------------

#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

MuZIC Internship Report 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 transmit 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 #define FRACTION_BDR #define #define #define #define #define #define #define UART_PARITY UART_WORD_LENGHT UART_FIFO UART_TWO_STOP_BITS UART_EVEN_PARITY UART_PARITY UART_SEND_BREAK 0x001a 0x0003 0x00 0x60 0x10 0x00 0x00 0x00 0x00 //No parity //Transmission of 8 bits //Enable FIFO buffers //One stop bit //No even parity //No parity //Normal use of the UART

#define UART0_PARAMETERS (UART_PARITY | UART_WORD_LENGHT | UART_FIFO | UART_TWO_STOP_BITS | UART_EVEN_PARITY | UART_PARITY | UART_SEND_BREAK) //UART 0 Interrupt Trigger Conditions #define UART0_RX_FIFO_LEVEL #define UART0_TX_FIFO_LEVEL #define UART0_FIFO_LEVELS 0x00 0x00 //Triggers interruption when RX FIFO is //Triggers interruption when TX FIFO is >= 1/8 full >= 1/8 full

(UART0_RX_FIFO_LEVEL | UART0_TX_FIFO_LEVEL)

//UART 0 Interrupt Configuration Define #define #define #define #define #define UART_OVERRUN_ERROR_INTERRUPT 0x400 //"1" UART_BREAK_ERROR_INTERRUPT 0x200 //"1" UART_PARITY_ERROR_INTERRUPT 0x100 //"1" UART_FRAMING_ERROR_INTERRUPT 0x080 //"1" UART_RECEIVE_TIME_OUT_INTERRUPT 0x040 0x020 0x010 enables interruptions due to Overrun Error enables interruptions due to Break Error enables interruptions due to Parity Error enables interruptions due to Framing Error //"1" enables interruptions due to Overrun // Error //"1" enables interruptions due to Overrun Error //"1" enables interruptions due to Overrun Error

#define UART_TRANSMIT_INTERRUPT #define UART_RECEIVE_INTERRUPT

#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 #define UART0_BREAK_ERROR_INT #define UART0_PARITY_ERROR_INT #define UART0_FRAMING_ERROR_INT #define UART0_TIMEOUT_ERROR_INT #define UART0_TRANSMISSION_INT #define UART0_RECEPTION_INT 0x400 0x200 0x100 0x080 0x040 0x020 0x010 //Overrun Error Interruption bit //Break Error Interruption bit //Parity Error Interruption bit //Framing Error Interruption bit //Time Out Error Interruption bit //Transmission Interruption bit //Reception Interruption 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 #define MASK_UART0_FLAG_RX_EMPTY

0x08 0x10

//If bit 3 is set, UART 0 is busy

/*********************************************************************************************/ // GLOBAL CONSTANTS, VARIABLES

69

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

/*********************************************************************************************/ #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_config.h //-------------------------------------------------------// Description what this module is used for....................... // // Tasks: //-------------------------------------------------------// (c) Copyright Schlumberger 2009 - All rights reserved //--------------------------------------------------------

#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 #define #define #define #define #define #define #define

PORTA PORTB PORTC PORTD PORTE PORTF PORTG PORTH

0x01 0x02 0x04 0x08 0x10 0x20 0x40 0x80

//System activation of the interruptions #define INT_UART0 21

MuZIC Internship Report 2009

/*********************************************************************************************/ //GENERIC API /*********************************************************************************************/ extern void SYS_Enable_Interruptions (void); extern void SYS_Configuration (void);

#endif /*********************************************************************************************/ //END /*********************************************************************************************/

system_config.c
//-------------------------------------------------------// Project ........................... MuZIC // Module ............................ // File .............................. system_config.c //-------------------------------------------------------// Description ....................... // // Tasks: //-------------------------------------------------------// (c) Copyright Schlumberger 2009 - All rights reserved //-------------------------------------------------------/***************************************************************************************/ //ISSUES /***************************************************************************************/ //* This file contains all the functions that need to be called before using the // microprocessor. //* All the functions related with the configuration of the system are placed here //* Interruptions must be enabled AFTER the configuration of the system and all the // peripherials. Otherwise, the program will not function properly. /***************************************************************************************/ /****************************************************************************************/ //INCLUDE /****************************************************************************************/ #include "common.h" #include "system_config.h" /*****************************************************************************************/

/****************************************************************************************/ //* Function: SYS_Configuration //* Task: Configures the system clock and the peripherials which will be used /****************************************************************************************/ void SYS_Configuration (void) { SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN); SYSCTL_RCGC2_R |= (PORTG | PORTA); 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; } /****************************************************************************************/ //Activates the use of Port A and G

71

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

//* Function: SYS_Activate_Interruptions //* Task: Enables the use of interruptions by the system, 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_test_bench.c //-------------------------------------------------------// Description // // Tasks: This file contains the different tests used to check if the FPGA worked correctly in // the RX and Tx modes //-------------------------------------------------------// (c) Copyright Schlumberger 2009 - All rights reserved //-------------------------------------------------------//-------------------------------------------------------// 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 | SYSCTL_OSC_MAIN); // Set the clocking to run directly from the crystal. SYSCTL_RCGC2_R |= (PORTG | PORTA); //Activates the use of Port A and G

(used by the PWM)

MuZIC Internship Report 2009


SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);

(void) ConfigurationTriggerRQ50K (); //This will configure the input signal RQ50K coming 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 FIR tables, the PWM Gain and Offset. We start //the transmission and we send a I and a Q every time the FPGA asks for one. /////////////////////////////////////////////////////////////////////////////////////////////// #ifdef TEST_TX_PWM_INDIRECT volatile unsigned long ulLoop; SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN); // Set the clocking to run directly from the crystal. SYSCTL_RCGC2_R |= (PORTG | PORTA); //Activates the use of Port A and G (used by the PWM) 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 the 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 FIR tables, the PWM Gain and Offset. We start //the transmission and we send a I and a Q every time the FPGA asks for one. //ISSUES: The Rx has not been fully tested. Furthermore, 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 write 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 crystal.

73

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

SYSCTL_RCGC2_R |= (PORTG | PORTA); //Activates the use of Port A and G (used by the PWM) 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 the 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 reserved //-------------------------------------------------------/********************************************************/ //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 the 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};

MuZIC Internship Report 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, 16, 33, 59, 92, 128, 164, 197, 223, 240}; //Most Significant Words of the Carrier Frequencies static long RxFrequenciesHigh [FIVE_CARRIER_FREQUENCIES] = { REMOVED DUE TO CONFIDENTIALITY CLAUSE //Least Significant Words of the Carrier Frequencies static long RxFrequenciesLow [FIVE_CARRIER_FREQUENCIES] = { 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 Sinewave 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); void FCParameter(void); //Configuration of the PWM Gain and Offset //Configuration of the TX Frequency Carrier

/**********************************************************************/ //* Function: SSI_Configure //* Task: Configures the hardware in order to attain 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.20MHz //Bits 15-8: SCR = 1 //Bit 7: SPH = 1 (Serial Clock Phase)

75

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

//Bit 6: SPO = 0 (Serial Clock Polarity) //Bits 5,4: FRF = 0 (Frame Format = SPI) //Bits 3-0: DSS = 16 (Data Size Select = 16 bits 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 configures 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 type of order to the FPGA //* WARNING!: In this case, the Chip Select won't be 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 be 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); 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 configures 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 been 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 Select because it was already pulled down by // SSI_Send8, so we just have put it back to its original level. /*********************************************************************************************/ void SSI_Send16(long unsigned int data_to_be_sent) { //Sending data

MuZIC Internship Report 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 until 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 triggered every time we have a rising edge in // the RQ50K signal sent by the FPGA. /*********************************************************************************************/ void ConfigurationTriggerRQ50K (void) { GPIO_PORTA_ICR_R //Clear all edge GPIO_PORTA_DEN_R GPIO_PORTA_IS_R = (PIN7 | PIN6 | PIN5 | PIN4 | PIN3 | PIN2 | PIN1 | PIN0); interruptions = PIN6; //Set pin 6 as input = 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 when rising edges GPIO_PORTA_IM_R = PIN6; //Interruptions coming from pin 6 are allowed GPIO_PORTA_ICR_R = (PIN7 | PIN6 | PIN5 | PIN4 | PIN3 | 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)+Sinewave5000Hz[index_sinewave5000Hz+1]); index_sinewave5000Hz = index_sinewave5000Hz+2;

77

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

(void) SSI_Send16(data); //Sending the 5000Hz Sinewave (for debugging purposes) if (index_sinewave5000Hz == SINEWAVE_5000HZ_LENGHT) //If we arrive to the end of the table, we reset the index table { index_sinewave5000Hz = 0; } } /*********************************************************************************************/ //* Function: SSI_ConfigureFPGA //* Task: Writes on the FPGA the Sinewave Memory Table, the FIR 1 table, the FIR 2 table, the // PWM gain and offset /*********************************************************************************************/ void SSI_ConfigureFPGA (void) { //Code (void) SSI_ResetFPGA (); //Reset FPGA before starting configuration (void)SinewaveMemory(); //Load the Sinewave Memory into the FPGA (void)FIRCoeffTable1(); //Load the FIR Coefficient Table 1 (void)FIRCoeffTable2(); //Load the FIR Coefficient Table 2 (void)PWMGainOffset (); //Load PWM Gain and Offset } /*********************************************************************************************/ //* Function: SSI_ResetFPGA //* Task: Resets the FPGA (done prior to the configuration 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; (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 Table //* WARNING!: It takes more time to send the data to the FPGA than to write them down in // the TX FIFO. For that reason, we have to wait if 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 FIFO, we check if the TX FIFO is full. If the // TX FIFO is full, we wait until some data has been 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++)

//Reset the FPGA

MuZIC Internship Report 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_table]); 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 than to write them down in the //TX FIFO. For that reason, we have to wait if we see 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 to the FPGA than to write them down in the TX // FIFO. For that reason, we have to wait if 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 FIFO, we check if the TX FIFO is full. If the // TX FIFO is full,we wait until some data has been 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; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = FIR1_MEM_ADDRESS; (void)SSI_Send16(data_to_be_sent);

//Set the pointer... //...to the FIR 1 Table address

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_table]); 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 is enough space to keep on //loading the table } SysCtlDelay(10); } /*********************************************************************************************/ //* Function: FIRCoeffTable2 //* Task: Writes on the FPGA the FIRCoeffTable1 //* WARNING!: It takes more time to send the data to the FPGA than to write them down in the TX // FIFO. For that reason, we have to wait if 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 FIFO, we check if the TX FIFO is full. If the // TX FIFO is full, we wait until some data has been transmitted to the FPGA. /*********************************************************************************************/ //FPGA Request (To be verified)

79

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

static void FIRCoeffTable2 (void) { //Local variables unsigned long data_to_be_sent; int i; //Code data_to_be_sent = CMD_SET_ADDR | FIR_COEFF; (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);

//Setting the pointer...

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_table]); 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); } /**********************************************************************/ //* 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; //Setting 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 FPGA (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 = PWM_GAIN; (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 = PWM_OFFSET; (void)SSI_Send16(data_to_be_sent); SysCtlDelay(10); //FPGA Request (To be verified) //Write PWM Gain //FPGA Request (To be verified)

//Write PWM Offset

} /********************************************************************************************/ //* Function: SSI_Simulation(void) //* Task: Launches the simulation of the Test Bench /*********************************************************************************************/ void SSI_Simulation(void) { (void)FCParameter(); (void)SSI_SendStart(); } //Send the FC Parameter for DDFS //Start Transmission

MuZIC Internship Report 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 couple (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; (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; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = Q_MESSAGE; (void)SSI_Send16(data_to_be_sent);

//Sends I

//Sends Q

IntMasterEnable(); //Enable all interruptions IntEnable(INT_GPIOG); //Enagble interruptions coming from Port G (DRQ interruptions)

81

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

} /*********************************************************************************************/ //* 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 triggered 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 | PIN3 | PIN2 | PIN1 | PIN0); //Clear all edge interruptions GPIO_PORTG_DEN_R|= PIN6; //Set pin 6 as input without touching the other pins 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 | PIN3 | 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 time the microprocessor sees a rising edge in // the data request signal coming from the FPGA. Then, it sends I and Q. /*********************************************************************************************/ void IntDRQHandler(void) { //Local Variables unsigned long data_to_be_sent; //Code GPIO_PORTG_ICR_R = PIN6;

//Clear interruptions from pin 6 //Send I

data_to_be_sent = CMD_WRITE | I_DATA; (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; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = Q_MESSAGE; (void)SSI_Send16(data_to_be_sent);

//Send Q

} /*********************************************************************************************/ //* 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, and 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; //Setting 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);

MuZIC Internship Report 2009


for (i = 0; i< FIVE_CARRIER_FREQUENCIES; i++) //We load the characteristics of the 5 carrier signals { data_to_be_sent = CMD_WRITE | FIR_COEFF; (void)SSI_Send8(data_to_be_sent); data_to_be_sent = RxFrequenciesHigh[i_frequency_high]; 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_low]; 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 FPGA /*********************************************************************************************/ 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 to 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 reception 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;

83

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

//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 reserved //-------------------------------------------------------#ifndef _DRV_SPI_FPGA_H_ #define _DRV_SPI_FPGA_H_ //-------------------------------------------------------// Glocal Define, macro //-------------------------------------------------------//Microprocessor Pins #define PIN0 0x01 #define PIN1 0x02 #define PIN2 0x04

MuZIC Internship Report 2009


#define #define #define #define #define PIN3 PIN4 PIN5 PIN6 PIN7 0x08 0x10 0x20 0x40 0x80

//Microprocessor Ports #define PORTA #define PORTB #define PORTC #define PORTD #define PORTE #define PORTF #define PORTG #define PORTH

0x01 0x02 0x04 0x08 0x10 0x20 0x40 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 #define SSI_CS #define SSI_RX #define SSI_TX //SPI Configuration #define SCR #define SPH #define SPO #define FRF #define DSS_8 #define DSS_16 //Data size configuration #define DATA_SIZE_8 #define DATA_SIZE_16 //Micro-FPGA Communication //Operational Code #define CMD_NOP #define CMD_SET_ADDR #define CMD_READ #define CMD_WRITE pointer //Channel (Generic requests) #define COMMAND #define FIR_COEFF #define MIXER_SINE_TABLE #define DIRECT_PWM #define DECODER_COEFF //Channel: I Data (nI_Q = 0) #define I_DATA #define FC_MOD_FREQ_I //Channel: Q Data (nI_Q = 1) #define Q_DATA #define FC_MOD_FREQ_Q

GPIO_PIN_2 GPIO_PIN_3 GPIO_PIN_4 GPIO_PIN_5 (1<<8) (1<<7) (0<<6) (0<<4) (0x7) (0xf) 8 16 //SCR = 1 //SPH = 1 //SPO = 0 //Freescale SPI Format //Data Size Select = 8 //Data Size Select = 16

0x00 0x10 0x20 0x40

//NOP //Set adress //Read & increment pointer //Write to adress & increment

0x00 0x04 0x06 0x08 0x0C

//Command/ Status regsiters //FIR Coefficients (128x16) //Mixer Sine table (256x16) //Direct PWM //Decoder 145 FIR Coefficients Table (256x16) 0x02 0x0A //I-Data //Fc Transmit Modulation Frequency (15:0) //Q-Data //Fc Transmit Modulation Frequency (31:16)

0x03 0x0B

//Memory Adresses of the FPGA #define SINEWAVE_ADDRESS #define FIR1_MEM_ADDRESS #define FIR2_MEM_ADDRESS #define PWM_GAIN_OFFSET_ADDRESS

0x0000 0x0000 0x00C0 0x00B4

//Masks #define LSB_MASK 0x00FF //Least Significant Bit's Mask #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 #define IS_SSI_TX_FIFO_NOT_FULL 0x02

85

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

//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 //FIR Coefficient Values #define NUMBER_FIR1_PARAMS #define NUMBER_FIR2_PARAMS //TX Messages #define START_TRANSMITTER #define START_RECEIVER #define DUMMY_WRITE #define PWM_GAIN #define PWM_OFFSET #define DDFS_MSWORD 0x4000 #define DDFS_LSWORD 0x0000 #define START_TX 0x0001 #define I_MESSAGE 30000 #define Q_MESSAGE 30000 #define RESET_FPGA 0x0000

256 145 49

//Lenght of the Sinewave Mixer Table //Lenght of the FIR 1 Table //Lenght of the FIR 2 Table

0x0001 //Starts tranmission 0x0002 //Starts reception 0xaaaa //Message sent when doing a dummy write 512 //Gain of the PWM 128 //Offset of the PWM //Frequency of the carrier (Most Significant Word) //Frequency of the carrier (Least Significant Word) //Starts Tx transmission (sets bit 0) //Message when writing to I //Message when writing to Q //Resets the FPGA

//Rx Define #define FIVE_CARRIER_FREQUENCIES 5 //Carrier frequencies used when coding and decoding //RX Messages #define PHASE_HIGH #define PHASE_LOW #define COSINUS #define SINUS #define START_DECODER

0x0000 0x0000 0x0000 0x0000 0x0002

//Other #define SINEWAVE_5000HZ_LENGHT 20 //Lenght of the 5000Hz 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

MuZIC Internship Report 2009


// ================================================== // End

3. ADC
#include #include #include #include #include #include #include #include #include #include #include #include #define #define #define #define "hw_ints.h" "hw_memmap.h" "hw_types.h" "debug.h" "gpio.h" "interrupt.h" "ssi.h" "sysctl.h" "lm3s2965.h" "timer.h" "system_config.h" "drv_spi0_adc.h" GPIO_PIN_3 GPIO_PIN_2 GPIO_PIN_5 GPIO_PIN_4 1

SSI_CS SSI_CLK SSI_TX SSI_RX

#define WAIT_1_CYCLE

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 reserved //--------------------------------------------------------

87

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

//-------------------------------------------------------// 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; acquisition of data from the ADC unsigned long int ADC_received_data [4]; the ADC unsigned short int dummy_write = DUMMY_WRITE; clock //-------------------------------------------------------// Local functions //-------------------------------------------------------void InterruptIC(void);

//Counter for the //To store the received data from //Used to give the ADC the SPI

/********************************************************************************************** ******************/ //* Function: ADC_SSI_Configure //* Task: Configures the hardware in order to attain the ADC needs on the SPI. // Inputs: RX, // Outputs: SYNC, TX, SPI Clock /********************************************************************************************** ******************/ extern void ADC_SSI_Configure (void) { //Code SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); 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_TX | 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.13MHz //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)

//Enables

MuZIC Internship Report 2009


//Bits 3-0: DSS = 16 (Data Size Select = 16 bits 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 | //SSI0_IM_R = 0x06 Enables Interrupts) SSI0_ICR_R = (INT_TIME_OUT //SSI0_ICR_R = 0x03 Clears INT_TIME_OUT); Receive FIFO and Receive Time-Out Masks (not Receive Overrun | INT_OVERRUN); all interruptions (except 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 triggered interrupt. /********************************************************************************************** ******************/ extern void ADCIC (void) { //Code GPIO_PORTA_ICR_R = (PIN7 | PIN6 | PIN5 | PIN4 | PIN3 | 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 Interrupt Event (GPIOIEV) GPIO_PORTA_IEV_R = FALLING_EDGE_INTERRUPTIONS; ` //Configure pin 6 to trigger an interruption when falling edges GPIO_PORTA_IM_R = PIN6; //Interruptions coming from pin 6 are allowed GPIO_PORTA_ICR_R = (PIN7 | PIN6 | PIN5 | PIN4 | PIN3 | PIN2 | PIN1 | PIN0); //Clear all interruptions } /********************************************************************************************** ******************/ //* Function: ADC_SSI_Send8 //* Task: Sends 8 bits data via SPI. First, it configures 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 100 ms in order to calibrate the ADC, then is set again to 1. /********************************************************************************************** ******************/

89

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

extern void ADC_Calibration (void) { //Code GPIOPinWrite(GPIO_PORTA_BASE, GPIO_PIN_7, !GPIO_PIN_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 SYNC 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 interruption 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 { } }

MuZIC Internship Report 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 reserved //-------------------------------------------------------#ifndef _DRV_SPI_FPGA_H_ #define _DRV_SPI_FPGA_H_ //-------------------------------------------------------// Glocal Define, macro //-------------------------------------------------------//SSI Configuration #define DISABLE_SSI #define ENABLE_SSI #define CLOCK_PRESCALE_2 number between 2 and 256) #define INT_RX_FIFO #define INT_TIME_OUT #define INT_OVERRUN #define SSI_CLK #define SSI_CS #define SSI_RX #define SSI_TX #define ADC_SYNC #define ADC_DRDY #define ANALOG_COMPARATOR_0 #define SSI_BASE #define #define #define #define #define #define #define SCR SPH SPO SPH FRF DSS_8 DSS_16

0x0000 0x0002 0x0002 (1<<2) (1<<1) (1) GPIO_PIN_2 GPIO_PIN_3 GPIO_PIN_4 GPIO_PIN_5 GPIO_PIN_6 GPIO_PIN_7 0 0x40008000 // SSI_BASE is the address of the SSI transmit FIFO (2<<8) (0<<7) (0<<6) (0<<7) (0<<4) (0x7) (0xf) 8 16 //SCR = 2 //SPH = 0 //SPO = 0 //SPH = 0 //Freescale SPI Format //Data Size Select = 8 //Data Size Select = 16 //Set prescale to 2 (has to be an even //Enable RX FIFO interrupt //Enable Time out interrupt //Enable Overrun interrupt

#define DATA_SIZE_8 #define DATA_SIZE_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

91

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

#define IS_RX_FIFO_EMPTY //Masks #define SSI_ADC_RECEIVE_FIFO #define SSI_ADC_TIME_OUT #define SSI_ADC_OVERRUN

0x04

0x4 0x2 0x1 0x00 0x00

#define ALL_EDGE_SENSITIVE #define CONTROLLED_BY_INTERRUPT_EVENT 0x00 #define FALLING_EDGE_INTERRUPTIONS

#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_config.c //-------------------------------------------------------// Description ....................... // // Tasks: //-------------------------------------------------------// (c) Copyright Schlumberger 2009 - All rights reserved //-------------------------------------------------------/****************************************************************************************/ //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 peripherials which will be used /****************************************************************************************/ extern void SYS_Configuration (void) { SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN); SYSCTL_RCGC2_R |= (PORTG | PORTA); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); //Activates the use of Port A and G

MuZIC Internship Report 2009


GPIO_PORTG_DIR_R = (PIN2); GPIO_PORTG_DEN_R = (PIN2); } /****************************************************************************************/ //* Function: SYS_Activate_Interruptions //* Task: Enables the use of interruptions by the system, 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 microprocessor. The Timer counts backwards starting // from a number set by the user. Once the Timer has been configured, it starts to count /****************************************************************************************/ extern void SYS_Timer_Configuration (void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); //Enables the peripherial TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER); //Chooses the 32-bit, periodic counter TimerLoadSet(TIMER0_BASE, TIMER_A, COUNTER_20_MS); //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 type of configuration) IntEnable(INT_TIMER0A); //Enables interruptions from Timer A } //Configuration of the pin used by the LED

/********************************************************************************************** *******************/ //END /********************************************************************************************** *******************/ //-------------------------------------------------------// Project ........................... MuZIC // Module ............................ // File .............................. system_config.h //-------------------------------------------------------// Description what this module is used for....................... // // Tasks: //-------------------------------------------------------// (c) Copyright Schlumberger 2009 - All rights reserved //--------------------------------------------------------

#ifndef _SYSTEM_CONFIG_H_ #define _SYSTEM_CONFIG_H_

/********************************************************************************************** *******************/ //GLOBAL DEFINE, MACROS /********************************************************************************************** *******************/ //Pins

93

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

#define #define #define #define #define #define #define #define //Ports #define #define #define #define #define #define #define #define

PIN0 PIN1 PIN2 PIN3 PIN4 PIN5 PIN6 PIN7

0x01 0x02 0x04 0x08 0x10 0x20 0x40 0x80

PORTA PORTB PORTC PORTD PORTE PORTF PORTG PORTH

0x01 0x02 0x04 0x08 0x10 0x20 0x40 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 #include #include #include #include #include #include #include #include #include #include "hw_ints.h" "hw_memmap.h" "hw_types.h" "debug.h" "gpio.h" "interrupt.h" "sysctl.h" "lm3s2965.h" "system_config.h" "drv_pwm.h" "pwm.h"

int main(void) { SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN); clocking to run directly from the crystal. // Set the

MuZIC Internship Report 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 reserved //--------------------------------------------------------

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

95

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

// Local functions //-------------------------------------------------------/********************************************************************************************** ******************/ //* Function: PWM_Configure //* Task: Configures the hardware in order to use the 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 Loaded 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 Sheet) //* - 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 | GPIO_PIN_3); G3 as PWM pins. They are used to output the PWM0 and PWM1 signals. //

// Set GPIO G2 and

PWMGenConfigure(PWM_BASE, PWM_GEN_0, PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC); 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_DEFAULT_VALUE); default value PWMGenIntTrigEnable(PWM_BASE, PWM_GEN_0,PWM_INT_CNT_ZERO); interruptions from PWM Generator Block 0 PWMIntEnable(PWM_BASE, PWM_INT_GEN_0); //Enables generator and fault interruptions for PWM Module 0 IntEnable(INT_PWO_0); //Enable interruptions coming from PWM 0

//PWM

// Set PWM0 to its

//Enable

PWMOutputState(PWM_BASE, PWM_OUT_0_BIT | PWM_OUT_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 micro 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;

MuZIC Internship Report 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); index_sinewave5000Hz++; //...Update the table index.

//...Load it into the PWM...

if (index_sinewave5000Hz == SINEWAVE_TABLE_SIZE) //If we arrive to the end of the table, we reset the index table { index_sinewave5000Hz = 0; } } // ================================================== // End //-------------------------------------------------------// Project ........................... MuZIC // Module ............................ // File .............................. drv_pwm.h //-------------------------------------------------------// Description ....................... // // Tasks: //-------------------------------------------------------// (c) Copyright Schlumberger 2009 - All rights reserved //-------------------------------------------------------#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_config.c //-------------------------------------------------------//-------------------------------------------------------// (c) Copyright Schlumberger 2009 - All rights reserved

97

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

//-------------------------------------------------------/***************************************************************************************/ //ISSUES /***************************************************************************************/ //* This file contains all the functions that need to be called before using the // microprocessor. //* All the functions related with the configuration of the system are placed here //* Interruptions must be enabled AFTER the configuration of the system and all the // peripherials. Otherwise, the program will not function 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 peripherials 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); A and G SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG); GPIO_PORTG_DIR_R = (PIN2); GPIO_PORTG_DEN_R = (PIN2); } /****************************************************************************************/ //* Function: SYS_Activate_Interruptions //* Task: Enables the use of interruptions by the system, 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 microprocessor. The Timer counts backwards starting // from a number set by the user. Once the Timer has been configured, it starts to count. /****************************************************************************************/ extern void SYS_Timer_Configuration (void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); //Enables the peripherial TimerConfigure(TIMER0_BASE, TIMER_CFG_32_BIT_PER); //Chooses the 32-bit, periodic counter TimerLoadSet(TIMER0_BASE, TIMER_A, COUNTER_20_MS); //Sets the timer to count 20ms //Configuration of the pin used by the LED //Activates the use of Port

MuZIC Internship Report 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 type of configuration) IntEnable(INT_TIMER0A); //Enables interruptions from Timer A }

/*********************************************************************************************/ //END /*********************************************************************************************/ //-------------------------------------------------------// Project ........................... MuZIC // Module ............................ // File .............................. system_config.h //-------------------------------------------------------//-------------------------------------------------------// (c) Copyright Schlumberger 2009 - All rights reserved //--------------------------------------------------------

#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 #define #define #define #define #define #define #define

PORTA PORTB PORTC PORTD PORTE PORTF PORTG PORTH

0x01 0x02 0x04 0x08 0x10 0x20 0x40 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 /*********************************************************************************************/

99

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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.

MuZIC Internship Report 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.

101

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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.

MuZIC Internship Report 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 rocks 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.

103

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

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 wells 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.

MuZIC Internship Report 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.

105

Proyecto Fin de Carrera Universidad Pontificia Comillas (ICAI) 2009

Vous aimerez peut-être aussi