Lab 1. Lecture 1 -- Activating the Blackfin GPIO pins
Download
Report
Transcript Lab 1. Lecture 1 -- Activating the Blackfin GPIO pins
Lab. 1 – GPIO Pin control
Using information ENEL353 and ENCM369 text
books combined with Blackfin DATA manual
What is a switch?
PRESS DOWN TO CLOSE
SPRING
TO CAUSE
SWITCH TO
OPEN AFTER
PUSH TO CLOSE
SWITCH OUTPUT
SWITCH INPUT
2 /25
Normally one side of switch is
grounded, the other side connected
to microcontroller GPIO input
INPUT IS ?????
FLOATING
BLACKFIN
INPUT IS 0V
GPIO LINES PF8, PF9, PF10, PF11
GROUND (0V)
3 /25
One side of the switch must be pulled
“softly” to 3 V / 5V (pull up resistor)
3v
10k “Pull-up”
resistor
BLACKFIN
INPUT IS 5V
INPUT IS 0V
GPIO LINES PF8, PF9, PF10, PF11
GROUND (0V)
4 /25
Blackfin has a GPIO data register
16 GPIO lines come into the register
Registers are based on flip-flops to store
whether the input is 3V (high) or zero (low)
16 flip flops put together make the FIO_FLAG_D
register
The GPIO data register is memory mapped so
no special instructions needed, you “treat it as if
it was the same as any other memory”
When you “read” from the GPIO register, you
cause a “load” of the input values into the flipflop and out onto the microcontroller’s data bus
5 /25
Registers used to control PF pins
Flag Data register (FIO_FLAG_D)
Used to read the PF bits as an input -- (1 or 0)
Need to read pins PF11 to PF8 ONLY , ignore all other pins values
Read the value, AND off unwanted bits, then use it
6 /25
What we know about the way “front
panel” switches connected to BF533
SW1 is connected to PF8
SW2 is connected to PF9
SW3 is connected to PF10
SW4 is connected to PF11
The other pins in the GPIO interface are
used for “other” purposes on the Blackfin
board and MUST not have their values
changed e.g. Video device input port
7 /25
What we want to do
Read the GPIO data register
Return ONLY the values in pins 8 to 11
which means removing (masking out) the
other values
Value read from GPIO data register = 0x4723
We only want to get the bits 0x0700 (SW1, SW2, SW3)
Value read from GPIO data register = 0x4023
We only want to get the bits 0x0000 (no switches)
Value read from GPIO data register = 0x4823
We only want to get the bits 0x0800 (SW4)
8 /25
What we have to code
MASK bit set to 1 for bits we keep, 0 for bits removed
MASK = 0x0F00 (Bits 8, 9, 10, 11 are 1, other bits are zero)
Value read from data register = 0x4723 (PF8, 9, 10)
We only want to get the bits 0x0700 -- MASK
Result = value & MASK (and operation)
Value read from data register = 0x4023 (none)
We only want to get the bits 0x0000
Result = value & MASK (and operation)
Value read from data register = 0x4823 (PF11)
We only want to get the bits 0x0500
Result = value & MASK (and operation)
9 /25
So the code required is
#include <blackfin.h>
.section program;
.global _ReadGPIOFlagsASM;
_ReadGPIOFlagsASM:
P0.L = lo(FIO_FLAG_D); P0.H = ……
R0 = W[P0] (Z); // Convert 16 bits to 32 bits via zero extension
// These are “bit settings” not a number
#define AND_MASK 0x0F00;
R1 = AND_MASK;
R0 = R0 & R1;
_ReadGPIOFlagsASM.END: RTS;
10 /25
DOES NOT WORK
We have not “initialized” the GPIO device
interface
“Initialize device” means “prepare the
device to make work”, in this case I / O
#include <blackfin.h>
.section program;
.global _ReadGPIOFlagsASM;
_ReadGPIOFlagsASM:
P0.L = lo(FIO_FLAG_D); P0.H = ……
………;
R0 = R0 & R1;
_ReadGPIOFlagsASM.END: RTS;
11 /25
Initialize the GPIO interface requires
change to many control registers
Turn the interrupts OFF for PF8 to PF11.
Do this WITHOUT changing the interrupt
behaviour for the other pins
Set the POLARITY register so that a 1
coming into pins PF8 to PF11 is read as a
HIGH (1). Do this without changing the
POLARITY behaviour of the other GPIO
pins.
Etc. etc.
12 /25
Initialize the GPIO interface
Set the DIRECTION register so that PF8
to PF11 pins are INPUT without changing
the behaviour of the other GPIO pins.
IF DONE INCORRECTLY CAN BURN OUT
THE CHIP. You don’t want a device sending a 1
to the GPIO interface, while the interface is
trying to output a 0.
AFTER all other initialization steps are
complete
Set the ENABLE register so that pins PF8 to
PF11 work without changing the behaviour of
the other GPIO pins. Power saving feature
13 /25
So the code required is
#include <blackfin.h>
.section program;
.global _InitGPIOFlagsASM;
_InitGPIOFlagsASM:
CALL TurnInterruptsOff_PF8to11;
CALL SetPolarity_PF8to11;
CALL OtherStuff_PF8to11;
CALL SetDirection_PF8to1;
CALL Enable__PF8to11;
_InitGPIOFlagsASM.END:
RTS;
14 /25
Incorrect code – contains a hidden defect
which stops the proper program operation
#include <blackfin.h>
.section program;
.global _InitGPIOFlagsASM;
_InitGPIOFlagsASM:
CALL TurnInterruptsOff_PF8to11;
// CALL means set RETS register
//
to point to instruction after CALL
//
RETS register = address of instruction labelled “next:”
next:
CALL SetPolarity_PF8to11;
next2: CALL OtherStuff_PF8to11;
Next3: CALL SetDirection_PF8to1;
Next4:
CALL Enable__PF8to11;
_InitGPIOFlagsASM.END: RTS; // RTS means JUMP RETS
// or “Change the PC to the value stored in RETS register
// What line of code will be executed?
// meaning “where does the code jump to?
15 /25
Correct code
#include <blackfin.h>
.section program;
.global _InitGPIOFlagsASM;
_InitGPIOFlagsASM:
LINK 16;
// Save (write) RETS to the stack
CALL TurnInterruptsOff_PF8to11;
// CALL means set RETS register
//
to point to instruction after CALL
//
RETS = next: in this case
next:
CALL SetPolarity_PF8to11;
next2: CALL OtherStuff_PF8to11;
Next3: CALL SetDirection_PF8to1;
Next4:
CALL Enable__PF8to11;
UNLINK;
// Recover (get back) RETS from the stack
_InitGPIOFlagsASM.END: RTS; // This means JUMP RETS
// PC set to “saved” RETS so code “returns” to the function that called it
16 /25
Other GPIO register flip flops
FIO_MASKA_D and FIO_MASKB_D
If bit X = 1, tell processor to cause an interrupt
(change program operation) when FIO_FLAG_D
bit X is active (changes to a 1 value)
17 /25
CALL TurnInterruptsOff_PF8to11ASM;
#include <blackfin.h>
.section program;
.global _TurnInterruptsOff_PF8to11ASM;
_ TurnInterruptsOff_PF8to11ASM:
P0.L = lo(FIO_MASK_A); P0.H = ……
R1 = 0;
W[P0] = R0;
ssync;
// Tell processor to do the write operation NOW
// DO same thing for FIO_MASK_B
TurnInterruptsOff_PF8to11ASM.END:
RTS
18 /25
P0.L = lo(FIO_MASK_A); P0.H = ……
R1 = 0;
W[P0] = R0;
This puts a 0 in every bit and turns ALL
interrupts off – not just bits 8 to 11
19 /25
CALL TurnInterruptsOff_PF8to11;
#include <blackfin.h>
.section program;
.global _TurnInterruptsOff_PF8to11;
_ TurnInterruptsOff_PF8to11:
P0.L = lo(FIO_MASK_A); P0.H = ……
R0 = W[P0] (Z);
// Read all the bits
#define MASK_NOCHANGE_VALUES 0xF0FF
R1 = MASK_NOCHANGE_VALUES
R0 = R1 & R1;
// Bits 8 to 11 zero
W[P0] = R0;
// But other bits still the same
// DO same thing for FIO_MASK_B
TurnInterruptsOff_PF8to11:
RTS
20 /25
Lets call a “C++” function instead of
writing the code in assembly code
.section program;
.global _InitGPIOFlagsASM;
_InitGPIOFlagsASM:
LINK 16;
CALL TurnInterruptsOff_PF8to11CPP__Fv;
// We must use “name mangling” to call C++ code
next:
next2:
Next3:
CALL SetPolarity_PF8to11;
CALL OtherStuff_PF8to11;
CALL SetDirection_PF8to1;
NEW SLIDE
#include <blackfin.h>
Next4:
CALL Enable__PF8to11;
UNLINK;
_InitGPIOFlagsASM.END: RTS;
21 /25
Lets write this code in C instead
TurnInterruptsOff_PF8to11CPP__Fv;
#include <blackfin.h>
void TurnInterruptsOff_PF8to11CPP(void) {
*pFIO_MASK_A = 0; // WRONG – need to use AND operation
Ssync( );
// DO same thing for FIO_MASK_B
}
NEW SLIDE
Place code in “InitGPIO.cpp
In assembly code the C++ function TurnInterruptsOff_PF8to11CPP( )
becomes named
_TurnInterruptsOff_PF8to11CPP__Fv
In assembly code the C function TurnInterruptsOff_PF8to11C ( ) becomes
named _TurnInterruptsOff_PF8to11C
22 /25
This convention allows the overloading of C++ functions (but not C)
Another GPIO register we need to set
correctly
23 /25
Another flip-flop group controls
whether the flip-flop outputs follow
the flip-flop inputs or are “high
impedance” – off – no useful value
24 /25
CALL EnablePins_PF8to11;
#include <blackfin.h>
.section program;
.global _EnablePins_PF8to11;
_ EnablePins_PF8to11:
P0.L = lo(FIO_INEN); P0.H = ……
#define MASK_CHANGE_VALUES 0x0F00;
R1 = MASK_CHANGE_VALUES
W[P0] = R1;
EnablePins_PF8to11.END:
RTS
WRONG: True this enables bits 8 to 11, but it also DISABLES all the
other bits
Need to use “OR” instruction after reading the enable register
25 /25
A key issue with GPIO is whether a pin is to
act as an input device (bringing things in
from the outside world into the Blackfin) or
as an output device (sending things from
the Blackfin to the outside world)
26 /25
Why do you need to know how to do
read (load) and write (store) on internal registers?
Flag Direction register (FIO_DIR)
Used to determine if the PF bit is to be used for input or
output -- WARNING SMOKE POSSIBLE ISSUE
Need to set pins PF11 to PF8 for input, leave all other pins
unchanged
27 /25
Making sure that the FIO_DIR is correct
for LAB. 1 – NOTE may need to change
for later labaoratories
Write the Blackfin assembly language instruction(s) to load the
address of the internal programmable flag FIO_DIR register into
pointer register P1 – then SET the Blackfin PF lines to act as inputs
#include <blackfin.h>
P1.L = lo (FIO_DIR); P1.H = ….
Design Error
“Changes all pins
// Check the requirements – need to have all input
// Manual says “setting a line for input means setting bit values to 0”
R0 = 0;
W[P1] = R0;
ssync;
// This changes “All pins”
// Force Blackfin to do the write (store) NOW not later
28 /25
Notice that previous slide WARNS
you about a design error in the code
We can’t do things this way as it changes
all the bits in the 16 flip-flops and we only
want to change 4 values in the flip-flops
The same design error is introduced into
Lab. 1 Task 3
However, the same design error is found
during the TDD tests – provided to look at
the test code to see what was being tested
29 /25
These tests DONOT find the design
error
30 /25
These tests DO find the design error
and in fact explain to you why it is likely that
your tests have failed.
But you have to read the message about the
Test and not ignore it
31 /25
Extra ideas you can use
Echoing Values from the switches to the
LED
32 /25
Echoing the switches to the LED
Code in main( ) – written in C++
int main( ) {
InitializeGPIOInterface( ); // Check Lab. 1 for “exact name needed”
InitializeFlashLEDInterface( ); // Check Lab. 1 for “exact name needed”
#define SWITCHBITS 0x0F00
// Look in MIPs notes about
//
using a mask and the
//
AND bit-wise operation
//
to select “desired bits”
while (1) {
// Forever loop
int GPIO_value = ReadBlackfinGPIOFlagsASM ( );
int desired_bits = GPIO_value & SWITCHBITS;
}
}
int LED_light_values = desired_bits >> 8;
// Bits in wrong position
WriteFlashLEDLights(LED_light_values);
// to display on LEDS
33 /25
Building a radio controlled car
4 Threads at least
SWITCHES ON FRONT PANEL
“INPUT COMMANDS:
LED LIGHTS ON FRONT PANEL
“CONTROLSIGNALS TO RF TRANS:
PROGRAMMABLE FLAGS
LED-CONTROLREGISTER
FIO_FLAG_D Register
EBIU INTERFACE
int ReadSwitches( )
void WriteLED(int )
YOUR PROGRAM RUNNING ON THE BLACKFIN
ProcessDataASM( ) subroutine
VOICE
A/D
A/D D/A Interrupt routine
D/A
EAR
PHONES
34 /25
LEDs connected to FLASH port
BACK
FORWARD
RIGHT
LEFT
???
CONTROL ON
Might be
connected to
other things
DON’T
CHANGE
BEHAVIOUR
Blackfin BF533 I/O
35