Laboratory 1: Programming and Using the GPIO Lines Page | 1
As something a little different this year, I offered to open source the Lab. 1 report to a number of students who had completed Assignment. I would like to thank J. for taking the time to do this. His comments were very constructive – and I learnt a lot about which C++ syntax you guys and girls have been taught.
Task 1: Quick check of the Lab. Station Hardware and Software
- Task1.1: Check Blackfin BF533 evaluation board works with CCES software and J-TAG hardware
- Task 1.2: Configuration of Logic Lab Station (LLS) with Blackfin
Task 2: Build a test project to check functionality of uTTCOS LED and Switch Utilities (driver code)
- Task 2.1: Add a WaitAwhile( ) timer function
- Task 2.2: Write test for uTTCOS_InitLED( ), uTTCOS_WriteLED( ), uTTCOS_ReadLED( )
- Task 2.3: Write and use your test to check uTTCOS_ReadLED( ) and uTTCOS_WriteLED( ) work correctly
- Task 2.4: Write a test to check uTTCOS_InitSwitches( ) and uTTCOS_ReadSwitches( ) work.
Task 3: Start a new test file Test_My_ReadSwitchesASM in Lab1Test project and start a new Lab1Library project
- Task 3.1: Control the Blackfin GPIO registers– control the FIO_FLAG_D(GPIO data register) in ASM
- Task 3.2: Control the Blackfin GPIO registers – control the FIO_INEN (input enable) register in CPP
- Task 3.3: Control the Blackfin GPIO registers – control the FIO_POLAR (input polarity) register in ASM
- Task 3.4: Control the Blackfin GPIO registers – control the FIO_INEN (input enable) register in ASM
Task 4.0 New test file Test_InitSwitches.cpp in Lab1Test project
- Task 4.1: Check whether uTTCOS_InitSwitches( ) works as expected.
- Task 4.2:Modify test for uTTCOS_InitSwitches( ) todevelopyour versionMy_InitSwitchesASM( ) routine
- Task 4.3: Develop a My_InitSwitchesASM( ) routine
Task 5: We have been working so hard -- Here is a video game based on a previous test.
No – perhaps not a good idea.
I think we should leave the video game test for another day. I am sure that you will not be able to win – most of the time
Task 6: Making use of Lab0_LEDLibrary to demonstrate a Super Loop operating system during Lab1
- Task 6.1: Lab1SuperLoop project Preparation
- Task 6.2: Develop a Super Loop OS name
- Task 6.3: Initial TARD-OS development
- Task 6.4: Making the Lab1Superloop Project Heart Beat using LED_Flash code from Lab0_LEDLibrary
- Task 6.5: More details of the Lab1Superloop Project Heart Beat
- Task 6.6: Add in the Super-loop timing control for the tasks
- Task 6.7: Add a new super loop TARD-OS task into LOOP1 to ECHO_SWITCHES_TO_LEDs
- Task 6.8 Dr. Smith “Special Programming Tricks” Corner – Use of MACROs could simplify programmi
Task 7: Driving the virtual car (Shown on Blackfin LEDs)
- Task7.1: A new TARD-OS Task to automatically drive a “virtual car” (Shown on LEDs)
- Task7.2: TARD-OS Task to record your “commands” to drive a “virtual car” (Shown on LEDs)
- Task 7.3: TARD-OS Task to “play back your commands” to drive a “virtual car” (Shown on LEDs)
- Task 7.4: Design problem to solve – how do we decide that we should keep-recording car commands or stop recording car commands – we have 4 hardware switches and they are all in use
80% of Lab. 1 is now completed (Mark B+ / A- / A)
RECOMMENDATION – time consideration. You might want to consider reading the rest of the lab but not doing any more coding if you are struggling with the C++ coding level
- NOTE: You can’t get any more marks for the LAB 1. report by handing in a modified Lab. 1 report.
HOWEVER you can get more marks if you show an improved LAB. 1 demo later in the term when you have gained more experience
Last 20% towards A+ on Labs. Lots of work that reuse the original ideas. Possibly four times as long debugging for a quarter extra marks. You make the decision how far to go
Task 8: Controlling a “real” radio controlled (RC) car
- Task 8.1: First steps to driving the real car and virtual car at the same time
- Task 8.2: Driven the second virtual car is worth 10%
Task 8.3: Driving the real car is worth 10% (and 10% bonus – because it is hard to drive the real car correctly)
Task 1: Quick check of the Lab. Station Hardware and Software
Lab 1 Block Diagram (Opportunities for a Quiz or Exam questions are obvious)Task1.1: Check Blackfin BF533 evaluation board works with CCES software and J-TAG hardware
- Run Lab 0 Tests for LED1( ) and LED3( ) working together, or final Lab0 uTTCOS demo (If TA around – then get them to sign off on final Lab 0 demos.
- Power down Blackfin
Task 1.2 Configuration of Logic Lab Station (LLS) with Blackfin
- Power down logic lab station (LLS).
- Use a 4 pin cable to connect a set of 4 switches at the bottom of the LLS (LLS S3-S0) to a set of 4 LLS LEDs (LLS L15 – L12) at top of LLS.
- Check cable polarity – The colour edge to the right of the 4 switches should be to the right of the 4 LEDs
- Power up LLS -- check that LLS S3-0 switches turn on the LLS LED (15-12)s
- Note that LLS switches are press on and then press off
- Power down LLS.
- Plug the 50 pin cable from the Blackfin output to the Blackfin Extender board on the LLS. Say out loud “Press till it goes click” at both ends of the 50-pin cable
- Connect GROUND on Blackfin Extender board to ground on LLS – keep wires as short and neat as possible
- Use a 4-pin cable to connect the 4 LLS switches (LLS S3- S0) to the 4 PF11 to PF8 lines on the Blackfin extender board.
- Leave the connections from the same LLS switches (S3 -0) to the LLS LEDs (L15-12) as a check of the hardware
- Connect the right most LLS switch (least significant LLS S0) to the top (least significant) PF8 line
- Connect the left most LLS switch (most significant LLS S3) is connected to the bottom (most significant) PF11 line
- Later we will be making connections between PF1, 5-7 to LLS L7 - 4
- Get your partner to check all connections
- Make sure and you are not one pin off in making the cable connections and the cable is not being twisted.
- Power up Blackfin and LLS boards.
Task 2: Build a test project to check functionality of uTTCOS LED and Switch Utilities (driver code)
Task 2.1: Add a WaitAwhile( ) timer function to the Lab1 Library
- Build a Lab1Library project
- Add a Lab1.h file to the project’s src directory and add the following prototype and include file request
#include <blackfin.h>
#include <uTTCOS2013/uTTCOS.h>
void WaitAWhile(unsigned long int longer); - Add a WaitAWhile.cpp file to the library and insert the following code
- DO A CODE REVIEW, build “selected file”, record any errors missed by YOUR code review for your PSP
#include “Lab1.h”
void WaitAWhile(unsigned int longer) { // TOD – Nasty defect – don’t change anything till about Task 5
unsigned long int delay = 0xFFFF * longer;
for (int count = 0; count < delay, count++) {
count = count; // Something garbage to waste time -- compiler will indicate you can't type -- ignore it
}
Task 2.2: Write test for uTTCOS_InitLED( ), uTTCOS_WriteLED( ), uTTCOS_ReadLED( )
- Build an E-UNIT test project called Lab1Tests following Lab. 0 procedure. Check that the project builds and the default test fails
- Use Settings | Linker | General -- Link the project to the CCES uTTCOS library and Lab 1 Library
- Use Settings | Compile | Preprocessor – Add an include path to “Lab1_Library/src”and “Lab0_Library/src”
- I am not writing inside CCES and checking code as I go along
- So you had better consider this pseudo code and do lots of pair programing code review
- Do a lot of file saving and partial rebuilds to check syntax
- Make good use of CCES auto-complete capability (CNTRL-SPACE) to check the consistency of the spelling of the names
#include <blackfin.h> // WARNING -- Cutting and pasting Word quotes “this is” or ‘that’-- causes compiler error
#include <stdio.h>// You will have to use CTRL-F to find and replace with the C++ quotes
#include “Lab1.h”
TEST(DoLEDsWork) { // Get a value from the key board and display in LED
char dummyRead[250]; // Buffer used by tests
uTTCOS_InitLEDS( ); // Screen capture the error message that using the buffer[ ] causes for your Lab. 1 report
// Explain why the error message is important but is expected (can be ignored) in this particular case
int validTyping = 0;
int request = 0;
// Some people may prefer the more self-documenting while (validTyping == 0) which is more obvious when converting to ASM
while (!validTyping) { // Manual – non-automated testing – UGH!!!
printf(“Type in a hexadecimal number (0x?? format) in the pop-up window then press enter\n”);
printf(“ Bit-pattern of the number should appear in LED lights\n”);
gets(dummyRead); // Apparently some people have not used this C++ function to get a “string” from a keyboard
validTyping = sscanf(dummyRead, “0x%x”, & request);// scanf( ) converts a C++ string into variable
CHECK (validTyping == 1); // C++ check that a valid number was entered
}
CHECK(request < 0x3F);
uTTCOS_WriteLED(rrequest);
printf(“Is the correct bit pattern displayed?\n”);
printf(“Answer Yes or No and press enter\n”);
gets(dummyRead); // Get a character string from the keyboard and then check its first character for a ‘Y’ or a ‘y’
CHECK( (dummyRead[0] == ‘y’)|| (dummyRead[0] == ‘y’));
}
Task 2.3: Write and use your test to check uTTCOS_ReadLED( ) and uTTCOS_WriteLED( ) work correctly
You code
Record screen shots for your Lab 1 report
Task 2.4: Write a test to check uTTCOS_InitSwitches( ) and uTTCOS_ReadSwitches( ) work.
TEST(Do_uTTCOS_SwitchRoutines_Work) { // Check that the uTTCOS switch routines work correctly
char dummyRead[250]; // Buffer
uTTCOS_InitLEDS( );
uTTCOS_InitSwitches( );
Unsigned char numbers[ ] = {0, 2, 13, 5, 4};
for (int count = 0; count < 5; count++) {
printf(“Set this value 0x%xas a bit pattern in the switches \n” , numbers [count]););
printf(“Then type ‘GO’ in the pop-up window -- press enter\n The same bit pattern should appear in LED lights\n”
gets(dummyRead);
unsigned int switchValue = uTTCOS_ReadSwitches( ); // Grab switch value using uTTCOS utility
uTTCOS_WriteLED(switchValue); // Echo value to LEDS
CHECK(numbers [count] = = switchValue);
// From Lab 0 – we know that E-UNIT prints “char” values that are unreadable.
// So use the C++ syntax of “CAST”ing into an integer so that “unsigned char” number values print
CHECK_EQUAL((int)numbers [count], (int) switchValue);
}
}
Task 3: Start a new test file Test_My_ReadSwitchesASM in Lab1Test project and start a new Lab1Library project
TASK 3.1: Control the Blackfin GPIO registers FIO_FLAG_D (GPIO data register) in ASM
- Details were in the class notes on 3rd October
- Add My_ReadSwitchesASM( ) ASM stub to Lab1Library Project Lab1LibraryASM.asm file
- Put #include <blackfin.h> at the top of the file
- In Lab report – explain why #include <blackfin.h> is needed (or what happens if not included)
- Add extern “C” intMy_ReadSwitchesASM(void )to Lab1.h in Lab1Library
- Use the Linker settings to add Lab1Library.dlb and the Preprocessor setting to Lab1Tests/src path to the Testproject
(Took me 5 mins to see that this was what was causing me a problem in getting the Test project to link) - Add a new test file Testing_MySwitchRoutinesWork.cpp using E-UNIT GUI
- Test driven development (TDD) – Copy and modify Lab1TestTEST(Do_uTTCOS_SwitchRoutines_Work) to become TEST(Do_My_SwitchRoutines_Work)
- Make the new test call your function My_ReadSwitchesASM( ) instead of uTTCOS_ReadSwitches
- There is no valid My_ReadSwitchesASM code so the tests should fail – Test of the Test
- In your report – show a screen dump of the failed test
- Explain, using the ASM-C++ calling conventions, why it might be expected that such a value is returned by the unfinished My_ReadSwitchesASM( )?
- Now add sufficient code to My_ReadSwitchesASM( ) to pass the tests (see class notes). Demonstrate that making use of volatile registers R0 – R3 and P0 – P2 in your routine.
- This routine accesses the GPIO data register. Look in the class notes and Blackfin hardware manual for its name
- To be able to use the macros lo( ) and hi( ) you will need to use the C++/Assembler safe header file
#include <blackfin.h>at the top of the ASM file - Check that the tests pass
- NOTE: Bug in Eclipse that is inherited by CCES about interlinked projects that should cause each other to rebuild
- Make the changes to Lab1Library and rebuild
- If you now rebuild the Lab1Tests (F7) it does not “know” the Lab1Library has been rebuilt so it uses the oldeversion
- We need to force Lab1Tests to use the new library
- Method 1 – Easiest but very slow when there is a large project – Clean Lab1Tests project and rebuild
- Method 2 – Faster -- Go to Lab1Test/Debug directory – delete the Lab1Test.dxe from the project – rebuild
- Method 3 – The Open-CCES-me-Help GUI has a menu item to automate Method 2
TASK 3.2: Control the Blackfin GPIO registers– control the FIO_INEN (input enable) register in CPP
- Add My_DisableSwitchesCPP( ) and My_EnableSwitchesCPP( )CPP stubs to Lab1Library ProjectLab1LibraryCPP.cppfile
- TDD – build tests to check that the functions work.
- The tests should fail as there is no valid code
- A little bit difficult to test My_DisableSwitchesCPP( ) as the tests that switches work will always fail – so how can you test the test? WIDFI for this special instance – use an XF_CHECK( ) and try to think of a better test later
- I took a version of TEST(Do_My_SwitchRoutines_Work) and made it TEST(Do_My_DisableEnable_Work)
- I added DisableSwitchesCPP ( ) after InitSwitches( ) and XF_CHECK that a read switches test failed
- Then I add the code EnableSwitchesCPP( ) after the XF_CHECK and did another test to check that reading switches now passes.
TASK 3.2.A: Dr. Smith’s special programming corner
Here is a poorly written version of my CPP code
voidMy_DisableSwitchesCPP(void) { *pFIO_INEN = 0; }
The code worked but there was no equivalent of the ASM “ssync” function being used to force the writes to memory to occur now
– so the code may be working by luck.
So I modified the code to be
voidMy_DisableSwitchesCPP(void) { *pFIO_INEN = 0; ssync( ); }
The editor gave warning messages about ssync( ) not linked but it linked (using a definition in <blackfin.h> perhaps, but still a possible defect lerking in my code
We will be having further discussions in the class about the C++ language extensions called PRAGMAs
This particular #pragma is very commonly used anywhere somebody needs to speed up C++ code
Suppose I had typed
voidMy_DisableSwitchesCPP(void) { *pFIO_INEN = 0; Ssync( ); } then the project would not be able link as Ssync( ) does not exist
If I added the following code to Lab1.h all the problems disappear – no editor or linker error message
- Explain why the project would now link and what the code means.
- In particular how are you allowed (or in this case must put) a CPP function in an include file – normally a very VERY bad programming practice
inline voidSsync(void) {
asm("ssync;");
}
TASK 3.3: Control the Blackfin GPIO registers– control the FIO_POLAR(input polarity) registerin ASM
- Add My_AdjustSwitchPolarityASM( ) ASM stub to Lab1Library Project – This modifies the GPIO FIO_POLAR register. Very similar to My_ReadSwitchesASM( ) in its structure but needs a little more code (2 lines) – check class notes
- This modifies the switch polarity so that ON becomes OFF and OFF become ON
I have used this expression in class “switches from active high to active low”. This polarity switch capability can be very useful in many embedded system situations - This means you set the switches as b 1 1 0 0 (active high, active high, off, off) and the system reads the switches b 0 0 1 1(active low, active low, off, off)
- TDD – Copy and modify Lab1Test TEST(Do_My_SwitchRoutines_Work) to become TEST(AdjustSwitchPolarity)
- Place this define #define SWITCHMASK 0XF just outside the new test
- Modify the code to become
uTTCOS_InitSwitches( );
My_AdjustSwitchPolarityASM( ); - Modify the CHECKs to become
unsigned int expected = (~numbers [count]) & SWITCHMASK; // Invert the expected pattern
CHECK(expected = = switchValue); // I think the TEST logic is correct
CHECK_EQUAL(expected, switchValue); // If not, fix my logical defect - Run the test -- There is no valid My_AdjustSwitchPolarityASM( ) code so the tests should fail – test of the test
- Now add sufficient code to My_AdjustSwitchPolarityASM( ) to pass the tests (see class notes and manual).
- Code will be very similar to My_ReadSwitchesASM( ) except I want you to (safely) use the non-volatile registers R5 – R7 and P4 – P5 in your routine. (Safely means – don’t crash “C++” when using non-volatile registers)
- Check that the tests pass
TASK 3.4: Control the Blackfin GPIO registers– control the FIO_INEN (input enable) register in ASM
- Add My_DisableSwitchesASM( ) and My_EnableSwitchesASM( ) ASM stubs to Lab1Library Project
- Modify your tests for My_DisableSwitchesCPP( ) and My_EnableSwitchesCPP( ) so you can test My_DisableSwitchesASM( ) and My_EnableSwitchesASM( )
- Check that tests fail if no valid code present in the stubs
- Develop the code for My_DisableSwitchesASM( ) and My_EnableSwitchesASM( )
Record screen shots for your Lab 1 report
Task 4.0 New test file Test_InitSwitches.cppin Lab1Test project
Task 4.1 Check whether uTTCOS_InitSwitches( ) works as expected. We can then use the test to developa My_InitSwitchesASM( ) routine
- Make a copy of Test(Do_My_DisableEnableWork) and call it Test(Test_uTTCOSInitCPP)
- This will not the greatest test – but better than nothing as we have all the code already developed
- Build the Test Check that the new test Test(Test_uTTCOSInitCPP) works
- The code looks like this
uTTCOS_InitSwitches( );
.. Code to test Works
My_DisableSwitchesCPP( );
.. Code to test XF_Works
My_EnableSwitchesCPP( );
.. Code to test Works
Changing the My_EnableSwitchesCPP( ) to a second uTTCOS_InitSwitches( )should also pass the test (check)
- Now add an ASM stub void My_InitSwitchesASM(void) to the Lab1 library and Lab1.h file
- Change both uTTCOS_InitSwitches( ) to My_InitSwitches( ) in the test. There should be a lot of failures in the test as there is no valid code in void My_InitSwitchesASM(void)
Record screen shots for your Lab 1 report
Task 4.2 Use test for uTTCOS_InitSwitches( ) todevelopa My_InitSwitchesASM( ) routine
Task 4.3Develop a My_InitSwitchesASM( ) routine
We have the following pseudocode for My_InitSwitchesASM( ); You will need to translate into assembly code. Note that the ASM routine calls both other ASM routines and other C++ routines. Read the class notes about how to write assembly code that calls other function
void My_InitSwitchesASM(void ) { // C++ like pseudo code to assist development of ASM code
My_SetSwitchPolarityASM( ); // Very similar code to My_AdjustSwitchPolarityASM( )
// except you set switches PF8 to PF11 to active high
My_SetSwitchDirectionASM( ); // Very similar code to My_AdjustSwitchPolarityASM( )
// except you set switches PF8 to PF11 to be inputs
My_SetSwitch_MASKA_and MASKB_InteruptsOffCPP( );
// Very similar code to My_EnableSwitchesCPP( ) except you set switches PF8 to PF11
// so that the MASK_A interrupts and MASK_B interrupts are off (Check BF533 hardware manual).
// We tackle interrupts in Assignment 2 (Before Quiz 3 which is on interrupts)
My_SetSwitchSensitivityASM( ); // Very similar code to My_SetSwitchDirectionASM( );
// except you set switches PF8 to PF11 to be level sensitive inputs (Check BF533 hardware manual).
// Also important for interrupt handling (Before Quiz 3)