Base GPIO code to work from?

A forum for discussing the applications and implementations of the DIY general code template for the GPIO and its 25 user inputs and outputs (+ serial & CAN). The code is 99% complete, the user just has to add their own conditional I/O logic and compile (with a free special Edition of CodeWarrior).
ol boy
Posts: 5
Joined: Sat May 03, 2008 11:42 am

Base GPIO code to work from?

Post by ol boy »

I've just downloaded the codewarrior from freescale and have been playing with it for the past two hours. I'm a noob to this code writing stuff and have no idea where to start. I'll I'm wanting to do is have extra data logable inputs and control a hand full of programed outputs and maybe tie an output off of coolant, tps/map arrangment.

Thanks Ryan
Bernard Fife
Posts: 1696
Joined: Fri Apr 04, 2008 1:28 pm

Re: Base GPIO code to work from?

Post by Bernard Fife »

Ryan,

You might grab the early trans code project here: http://www.msgpio.com/manuals/mshift/GP ... E_Proj.zip The main source code with the hints is here: http://www.msgpio.com/manuals/mshift/4L60E_main.c It is for CW 4.6 (but will likely work for other versions).

There is an outline of the code flow and functions here: http://www.msgpio.com/manuals/mshift/4L60Ecode.html

It contains a ton of hints (and working examples) of how to write code for the HCS12 processor.

Lance.
"Never wrestle with pigs. You both get dirty and the pig likes it." - George Bernard Shaw
ol boy
Posts: 5
Joined: Sat May 03, 2008 11:42 am

Re: Base GPIO code to work from?

Post by ol boy »

Sweet, Thanks That helps out a bunch. The outline helps show what to look for as thumbing through the main code.
Bernard Fife
Posts: 1696
Joined: Fri Apr 04, 2008 1:28 pm

Re: Base GPIO code to work from?

Post by Bernard Fife »

With the release of the production GPIO boards now imminent, I have put a Codewarrior 'template' project (and associated INI for the tuning software) here:

http://www.msgpio.com/manuals/iocode/code.htm

This project has:
- serial and CAN comms infrastructure already in place,
- ALL the MS-II output variables are read into the GPIO and are available for use in conditions, etc. (some are not yet assigned to variables, the code shows how to do this),
- the ADC, PWM, and digital I/O all set up for a number of ports (24 of them),
- a number of 'pre-defined' user input parameters (of the form typevariableXXX, ex. charvariable007) ready to use in the program via tuning software (MT or TS),
- all the inputs are read and assigned to variables (and reported/logged in the tuning software),
- samples of how to control 12 of the outputs using various settings.

The code compiles fine with the free 'special edition' on Codewarrior (see the link for how to get this).

This should make it much easier for new programmers to get started writing their own code for the GPIO.

I haven't tested the project at all on the actual hardware (since it doesn't really do much!), but will do that soon. It's not impossible that I have some of the ports/circuits wrong (since the MegaShift code this is based on swapping a few circuits). I will check this when I get a chance. If anyone sees anything that doesn't look right, please let me know.

Lance.
"Never wrestle with pigs. You both get dirty and the pig likes it." - George Bernard Shaw
Bernard Fife
Posts: 1696
Joined: Fri Apr 04, 2008 1:28 pm

Re: Base GPIO code to work from?

Post by Bernard Fife »

Sharp eyed users at the Seattle meet last weekend spotted a number of small errors in the example code of template project (mostly in the comments). These result from the 'copy and paste' method used to generate the examples. I will go through these shortly and post an updated main.c file for everyone to use.

Lance.
"Never wrestle with pigs. You both get dirty and the pig likes it." - George Bernard Shaw
ol boy
Posts: 5
Joined: Sat May 03, 2008 11:42 am

Re: Base GPIO code to work from?

Post by ol boy »

Thanks Lance. In the past few months I've began to understand how writing code works. First with a PIXACE program and if all goes well, with codewarrior.

I want to create an airride controller using data from my MS2 and inputs into the GPIO to change ride height based on vehicle speed and other variables.

Thanks Ryan

Found out code warrior does not work with Vista X64, so now I'm on the hunt for code program for the HCS12 which will work with vistax64.
Bernard Fife
Posts: 1696
Joined: Fri Apr 04, 2008 1:28 pm

Re: Base GPIO code to work from?

Post by Bernard Fife »

Here is the updated main.c source file (as a zip file):
main.zip
I will update the project shortly (http://www.msgpio.com/manuals/iocode/code.htm).

Lance.
"Never wrestle with pigs. You both get dirty and the pig likes it." - George Bernard Shaw
427v8
Posts: 18
Joined: Sun Oct 05, 2008 6:03 pm

Re: Base GPIO code to work from?

Post by 427v8 »

I finally had time to peruse the source and have a couple of comments.
These comments apply especially to new programmers.

Firstly I think the code looks solid, I have no issues there.

There is one error though
When describing how #include files work. It's not really like that.
The Code warrior help says this;
*Note that both styles cause the directive (#include) to be replaced by the entire contents of the file, not just the quoted version..

The search for include files is governed by two environment variables: GENPATH: #include "File" Path and LIBRARYPATH: 'include <File>' Path.
Include files that are included using double quotes as in:

#include "test.h"
are searched first in the current directory, then in the directory specified by the -I: Include File Path option,
then in the directories given in the GENPATH: #include "File" Path environment variable, and finally in those listed in the LIBPATH or
LIBRARYPATH: 'include <File>' Path environment variable. The current directory is set using the IDE, the Program Manager, or
the DEFAULTDIR: Default Current Directory environment variable.

Include files that are included using angular brackets as in

#include <stdio.h>
are searched for first in the current directory, then in the directory specified by the -I option, and then
in the directories given in LIBPATH or LIBRARYPATH. The current directory is set using the IDE, the Program Manager, or
the DEFAULTDIR environment variable.


My main issue is mostly style, or lack of it.
Or is it that every possible style seems to be used?

I'm not objecting to the bracket placement as that is a personal preference issue
ie.

Code: Select all

if(...) {
}

vs

if(...)
{
}
But rather the lack of vertical whitespace, the random breaking of lines and the inconsistent style.
When you modify code that someone else has written, suck it up and use their style.

Put a blank line before and after logical blocks of code, like an if, while or just a group of variables that are related.
Crunching everything together does not make you code smaller, the compiler doesn't care :D

indent!
reverse or random indenting makes reading the code hard. Clean consistent indenting makes life SO much easier esp when reviewing new code or code you haven't seen in a year.

Which is easier to read;
This

Code: Select all

switch(txmode){
case 0:
switch(SCI0DRL){
  case 'a':				 // send back all real time ram output variables
next_txmode = 1;
txmode = getCANid;
cksum = 0;
break;
case 'w':		  // receive new ram input data and write into offset location;
// also used for forwarding CAN msgs bet. MT & auxilliary boards.
// In this CAN mode, no_bytes must be >0 and <=8.
  next_txmode = 5;
  txmode = getCANid;
rd_wr = 1;
break;
case 'e':		  // same as 'w', but verify by echoing back values. Don't use with CAN
next_txmode = 5;
txmode = getCANid;
rd_wr = 2;
break;
...
or

Code: Select all

switch(txmode)  
	{
	case 0:
		switch(SCI0DRL)  
		{
		case 'a':				 // send back all real time ram output variables
			next_txmode = 1;
			txmode = getCANid;
			cksum = 0;
			break;

		case 'w':		  // receive new ram input data and write into offset location;
			// also used for forwarding CAN msgs bet. MT & auxilliary boards.
			// In this CAN mode, no_bytes must be >0 and <=8.
			next_txmode = 5;
			txmode = getCANid;
			rd_wr = 1;
			break;

		case 'e':		  // same as 'w', but verify by echoing back values. Don't use with CAN
			next_txmode = 5;
			txmode = getCANid;
			rd_wr = 2;
			break;
Tabs vs Spaces cause many a holy war, but everyone agrees that mixing them is bad, Stick with what you started with!

Hope this isn't too much of a rant!
Keith
427v8
Posts: 18
Joined: Sun Oct 05, 2008 6:03 pm

Re: Base GPIO code to work from?

Post by 427v8 »

Here's another 'interesting' construct;

The function get_adc()

It returns an int.
The problem is the variable it returns (adcval) is a global, meaning it is defined outside the function.
The variable is not used anywhere but inside get_adc()

There are 2 better solution to this.
1. move the variable declaration inside the function
2. use the global variable and don't return anything.

For those interested the reason returning a global variable is not desireable is that it's the worst of both worlds problem.
Since it is declared global, it always exists taking up memory.
When you return it, unless the compiler is really smart, you have 2 copies of the variable, 2x the memory.
lastly, leaving the global around polutes the general codespace, making it unecessarily cluttered.

If you declare the variable inside the function and return it. It only uses memory while that function is running.
Much better

like this;

Code: Select all

int get_adc(char chan1)  
{
  signed int adcval;            // signed for possible negative temperatures
...
427v8
Posts: 18
Joined: Sun Oct 05, 2008 6:03 pm

Re: Base GPIO code to work from?

Post by 427v8 »

Here's something I'm not understanding.
Why is this done'

Code: Select all

#define pPTM     ((volatile unsigned char*)(0x0250))
...
volatile unsigned char *pPTMpin[8];
...
	//  Set pointers to real port addresses
	for(ix = 0; ix < 8; ix++)  
	{
		pPTMpin[ix] = pPTM;   // port M
		pPTTpin[ix] = pPTT;   // port T
	} // end for (ix = 0...
I admit I'm not that into the esoteric uses of C, but it looks to me like it's creating an array of char pointers that all point to the same address?

Then they are used like this;

Code: Select all

	// turn off output pins
	*pPTMpin[2] &= ~0x04;      // 0x04 = 00000100, ~0x04 = 11111011, turn off    Sol B @ PM2
	*pPTMpin[3] &= ~0x08;      // 0x08 = 00001000, ~0x08 = 11110111, turn off     LED2 @ PM3
	*pPTMpin[4] &= ~0x10;      // 0x10 = 00010000, ~0x10 = 11101111, turn off     LED1 @ PM4
	*pPTMpin[5] &= ~0x20;      // 0x20 = 00100000, ~0x20 = 11011111, turn off     LED3 @ PM5
How is this different from this;
(why make an array of pointers to the same address?)

Code: Select all

       #define PTM     (*(volatile unsigned char*)(0x0250))

       // turn off output pins
       PTM &= ~0x04;
       PTM &= ~0x08;
       PTM &= ~0x10;
       PTM &= ~0x20;

Post Reply