chipKIT® Development Platform

Inspired by Arduino™

Pins to PORT drawings

Created Tue, 14 Jun 2011 19:28:00 +0000 by doc_norway


doc_norway

Tue, 14 Jun 2011 19:28:00 +0000

Hello

I have made some pin-to-port drawings if anyone is interested...

/Henning


Jacob Christ

Tue, 14 Jun 2011 23:03:49 +0000

Awsome. I was thinking a community commit git repo for chipKIT documentation would be a great idea. I would be willing to contribute.

Jacob


Trev

Wed, 15 Jun 2011 10:31:15 +0000

Excellent!

How about a Wiki for documentation? Documentation does seem to be lacking, especially in respect of current limitations. There's already some nuggets posted in the forum, but as the forum post count grows, it's more like looking for needles in haystacks :)


hairymnstr

Tue, 21 Jun 2011 08:20:30 +0000

I second the call for a wiki, chipkit.cc/wiki would be a huge advantage and this is exactly the sort of thing that needs to be in there!


Jacob Christ

Tue, 21 Jun 2011 15:25:36 +0000

chipkit.cc/wiki

hairymnstr, did you set up this wiki? If so, thanks...

Jacob


hairymnstr

Tue, 21 Jun 2011 15:33:49 +0000

Wasn't me, just suggested it this morning, I'm just a ChipKit user, no admin rights or anything.


Jacob Christ

Tue, 21 Jun 2011 16:37:53 +0000

Wasn't me, just suggested it this morning, I'm just a ChipKit user, no admin rights or anything.

Wow, can you have the power of suggestion...

Jacob


Jacob Christ

Thu, 23 Jun 2011 16:06:26 +0000

It seems that the wiki does not support <source> </source> tags...

Jacob


micromac

Mon, 27 Jun 2011 23:42:34 +0000

Dug around the forum and found this thread...sorted answered my question, but had to go to the .c file mentioned and figure it out. THis thread references the MAX not the UNO:

sorry, I can't link to a thread in this forum...because it says the link looks like spam :roll:

Ok, this is great, but when I code the following:

PORTB |= (1<<PB5);

When I compile:

'PB5' was not declared in this scope

But:

PORTB |= (1<<5);

compiles fine. So PORTB is defined, but not the port bits.

In this case I wanted to toggle Arduino pin 13.

digitalWrite(13, HIGH); digitalWrite(13, LOW);

woks fine and the pin 13 in the Uno32 toggles.

But:

PORTB |= (1<<5); PORTB &= ~(1<<5);

nothing, looked a t a few other pins, didn't find any others toggling.


dangeljs

Tue, 28 Jun 2011 02:08:20 +0000

I don't have an answer as to why PB5 doesn't work for you, but look in the chipkit boards section at the topic "UNO32 port registers".

It explains toggling the port pins and may be of some help.

As with everyone else, I could post a direct link...looks to spamy!!


hairymnstr

Tue, 28 Jun 2011 12:18:07 +0000

Have you made sure the pin is output (should work okay with a pinMode() arduino call) or you can set TRISB bit 5 to 0 (output).

See the data sheet [url]http://ww1.microchip.com/downloads/en/DeviceDoc/61120D.pdf[/url]

Also, you should find if you are directly addressing the registers you'll get better performance from using the SET and CLR registers rather than doing "read-modify-write" operations.

PORTBSET = (1 &lt;&lt; 5);   // equivalent to PORTB |= (1 &lt;&lt; 5);
delay(1000);
PORTBCLR = (1 &lt;&lt; 5);   // equivalent to PORTB &amp;= ~(1 &lt;&lt; 5);
delay(1000);

Also don't forget the delay, the chipkit is FAST, when I did this without delay I got a toggle rate over 600 kHz.

Also, PORTB.RB5 is probably configured as analogue input by default, you may need to turn off the ADC peripheral. The LED is on RG6 on the Uno.


micromac

Tue, 28 Jun 2011 16:18:38 +0000

I'll need to look at the code I finally got working last night, but, I did switch to TRIS.

I think I finally figured out that Arduino PIN13 was not on PORTB of the PIC32 on the Uno32.

Between looking at the PIC32 specific .c in the ide tree and the post I tried to include previously (which had the pin map for the MAX32) I got it working.

In any case, I was testing to see how short a pulse I could generate with pin access and was able to get down to around 60nS.

Added a couple NOP's and got it to the 100nS or so I need.

Still need to experiment some more.

Thanks for the pointers!


Jacob Christ

Tue, 28 Jun 2011 16:41:20 +0000

PORTBSET = (1 &lt;&lt; 5);   // equivalent to PORTB |= (1 &lt;&lt; 5);
delay(1000);
PORTBCLR = (1 &lt;&lt; 5);   // equivalent to PORTB &amp;= ~(1 &lt;&lt; 5);
delay(1000);

I would recommend not shifting bits unless you really need to.

Unless the compiler is really smart.

(1 << 5) may generate five lines of code as to opposed to one with 0x20.

Jacob


KM6VV

Tue, 28 Jun 2011 18:22:40 +0000

It's OK if it generates 5 lines of source code, and the pre-compiler reduces it to a constant of 0x20 for you.

Alan KM6VV


hairymnstr

Tue, 28 Jun 2011 21:43:46 +0000

To clarify a little for people trying to learn;

(1 << 5) is a constant expression (no variables involved) and so will be evaluated by your host PC when GCC runs over it and will compile to identical machine code as typing 0x20 (or 32 of course ;) ) using the bit shift just makes it easier to read and understand.

Constants are actual numbers or #define values which by tradition are block capitals, as long as all the parts of an equation are constant expressions even simple assembler/compilers will deal with them at compile time.


micromac

Tue, 28 Jun 2011 22:46:26 +0000

PORTBSET and PORTBCLR I'm not familiar with and a quick search in the include folders on this machine and and the web didn't turn up where they are defined.

Are these AVR, Arduino or standard 'C' I've missed (I've never been accused of being a language lawyer... ;)

I'm assuming the assembly from build is put somewhere...but, haven't spent any time looking for it. It would be good to be able to check it when questions arise.


micromac

Tue, 28 Jun 2011 22:48:35 +0000

Just to complete my earlier post about which port is associated with Arduino/Uno pin 13, here is the code I did last night for the short pulses:

void setup() { . . TRISG |= ~(1<<6); PORTG &= ~(1<<6); . . }

void loop() { . . PORTG |= (1<<6); asm volatile("nop\n\t" "nop\n\t" ::); PORTG &= ~(1<<6); . . }


hairymnstr

Wed, 29 Jun 2011 10:11:38 +0000

The LATBSET and LATBCLR registers are special hardware registers in the PIC32 (you'll find them on ARM as well, they seem quite common in 32bit architectures).

They are declared in the processor specific header file which is automatically included. They are special function registers (like PORTB and TRISB etc.) and as such are a feature of the CPU not the language or library.

They perform the bitwise or (xxSET) or bitwise and not (xxCLR) in hardware and therefore operate in a single cycle. So writing a 1 to a bit in a xxSET register will make sure the corresponding register bit is set to 1 without affecting any of the other bits. The xxSET register doesn't store this mask so next time you use it you can set different bits without affecting the bits you set last time. Same for clear, except that writing a 1 to a xxCLR register clears the corresponding bit.

so using the software method: LATB |= (1 << 5);

will work as read LATB bitwise or with literal (1 << 5) write LATB

with the hardware method:

LATBSET = (1 << 5);

will work as write LATBSET literal (1 << 5) (this does the bitwise or and store in hardware no more processing)


I also noticed while writing that explanation that you say you're writing to PORT registers. Technically they are read only and writing will perform undefined results, you should write to LATB (latch B) A, C, D... and read from PORTx.


micromac

Wed, 29 Jun 2011 11:18:37 +0000

Hmm, I'm thinking there is some things getting mixed around here.

  1. Your example above used PORTBSET and PORTBCLR, so I still don't grock that.

  2. TRISx, PORTx, LATx are defined in the datasheet and are mnemonics for the addresses of these registers. The datasheet also states:

"12.1.1 CLR, SET AND INV REGISTERS Every I/O module register has a corresponding CLR (clear), SET (set) and INV (invert) register designed to provide fast atomic bit manipulations."

Though there is no mention of LATxSET, etc in the instruction set. (nor SET, CLR, etc.) So where does it get parsed? In the compiler, assembler, preprocessor...?

The LATBSET and LATBCLR registers are special hardware registers in the PIC32 (you'll find them on ARM as well, they seem quite common in 32bit architectures). They are declared in the processor specific header file which is automatically included. They are special function registers (like PORTB and TRISB etc.) and as such are a feature of the CPU not the language or library. They perform the bitwise or (xxSET) or bitwise and not (xxCLR) in hardware and therefore operate in a single cycle. So writing a 1 to a bit in a xxSET register will make sure the corresponding register bit is set to 1 without affecting any of the other bits. The xxSET register doesn't store this mask so next time you use it you can set different bits without affecting the bits you set last time. Same for clear, except that writing a 1 to a xxCLR register clears the corresponding bit. so using the software method: LATB |= (1 << 5); will work as read LATB bitwise or with literal (1 << 5) write LATB with the hardware method: LATBSET = (1 << 5); will work as write LATBSET literal (1 << 5) (this does the bitwise or and store in hardware no more processing)


I also noticed while writing that explanation that you say you're writing to PORT registers. Technically they are read only and writing will perform undefined results, you should write to LATB (latch B) A, C, D... and read from PORTx.


hairymnstr

Wed, 29 Jun 2011 12:03:10 +0000

I appologise the PORTBSET/CLR etc was my mistake, PORTx is a read only register not writeable so has not SET/CLR/INV matching. Where I mentioned them I should have said LATxSET/CLR/INV.

These aren't instructions, they are "special function registers" that is memory locations that have special functionality when you read or write them. They are accessed like a variable would be i.e. you can use it on the left of an assignment operator (e.g. LATx = 0x20;)

The special LATxSET/CLR/INV registers are designed to allow you to perform what are known as "atomic bit operations" by using a mask to SET or CLeaR or INVert specific bits without reading the others. These are still just registers, you can affect them by assigning them values as if they were variables.


micromac

Wed, 29 Jun 2011 13:08:29 +0000

I appologise the PORTBSET/CLR etc was my mistake, PORTx is a read only register not writeable so has not SET/CLR/INV matching. Where I mentioned them I should have said LATxSET/CLR/INV.

Ok, that clears that water. :)

These aren't instructions, they are "special function registers" that is memory locations that have special functionality when you read or write them. They are accessed like a variable would be i.e. you can use it on the left of an assignment operator (e.g. LATx = 0x20;) The special LATxSET/CLR/INV registers are designed to allow you to perform what are known as "atomic bit operations" by using a mask to SET or CLeaR or INVert specific bits without reading the others. These are still just registers, you can affect them by assigning them values as if they were variables.

Agreed, but, they still have to ultimately be translated to an opcode, no? And if they aren't listed in the instruction set (thus no mnemonic or opcode), what tells the processor to act on said register.

Hence, can anyone tell me where the resulting asm file gets generated?

Also, in the Arduino IDE holding down the shift key (I think) causes the build process to show all the "stuff" that gets included,linked, etc. does this work in mpide (not at a machine where I can try it).


hairymnstr

Wed, 29 Jun 2011 14:31:00 +0000

You appear to mis-understand the nature of memory-mapped I/O and assembly languages. Those are registers, registers aren't op-codes they're addresses.

So an opcode is typically something very simple but an operation e.g. add, subtract, move etc. Typically they take a couple of arguments often labelled source and destination. The LATxCLR just like PORTx or LATx or TRISx is an address, so can be used as the source or destination. In pseudo assembler then:

MOVE LATxCLR, 0x20

(assuming the syntax is MOVE dest, src)

will move the value 0x20 into the LATxCLR register hence clearing bit 5 of LATx. The "opcode" is just a move instruction, nothing special about it, it's the memory address that matters and that is defined deep in one of the hardware specific header files and is simply a memory address that can be written to to affect that I/O port.

Note I've never looked into MIPS assembler this is based on a handful of other ones I know and the way that the 8-bit PIC chips all work so the details may be a little fuzzy but the principal is that it's just a memory address that gets read/written.

Further details:

[url]http://ww1.microchip.com/downloads/en/DeviceDoc/61113C.pdf[/url] Section 2.8: SET/CLEAR/INVERT

[url]http://ww1.microchip.com/downloads/en/DeviceDoc/61115F.pdf[/url] Memory Organization (this is very heavy going but does explain that all SFRs are allocated an address within the 32bit address space.)


micromac

Wed, 29 Jun 2011 16:30:49 +0000

You appear to mis-understand the nature of memory-mapped I/O and assembly languages. Those are registers, registers aren't op-codes they're addresses.

More like I'm not explaining myself clearly...I've been writing assembly language since the mid 1970's. :lol:

So an opcode is typically something very simple but an operation e.g. add, subtract, move etc. Typically they take a couple of arguments often labelled source and destination. The LATxCLR just like PORTx or LATx or TRISx is an address, so can be used as the source or destination. In pseudo assembler then: MOVE LATxCLR, 0x20 (assuming the syntax is MOVE dest, src)

I see that LATxCLR is a register. Using it as an operand IS what I expected, but (probably due to a limited read of the data sheet on my part) didn't get that from what did read.

It is clearly a register address, so must be translated to an address value, probably in the assembler.


elproducts

Wed, 29 Jun 2011 18:59:00 +0000

Doc_Norway,

I'm working on an entry level book using chipKIT and I'd like to include your pin mapping in the appendix. Can I have your permission to use these?


KM6VV

Wed, 29 Jun 2011 19:22:34 +0000

I haven't seen this before in PICs, but it appears to me that there are four (4) addresses for a register.

the "base" address, then three other addresses (alias) that when referenced, set, clear or invert. Clever!

Is that it?

Alan KM6VV


doc_norway

Wed, 29 Jun 2011 22:16:13 +0000

Doc_Norway, I'm working on an entry level book using chipKIT and I'd like to include your pin mapping in the appendix. Can I have your permission to use these?

Feel free to include them :)

I would like a mention of my website to go along with them, but it is not a requirement. Website: PM me for address. This stupid forum will not let me post the URL (There will be chipKit-stuff there aswell. I just don't have the time right now.)

/Henning


micromac

Thu, 30 Jun 2011 11:05:56 +0000

The docs refer to them as "virtual" addresses. I haven't taken the initiative to look into the register structure, but the docs say they appear as registers, but are really just different ways of addressing the base register.

I haven't seen this before in PICs, but it appears to me that there are four (4) addresses for a register. the "base" address, then three other addresses (alias) that when referenced, set, clear or invert. Clever! Is that it? Alan KM6VV


hairymnstr

Thu, 30 Jun 2011 11:49:07 +0000

Yeah, all they really mean by "virtual registers" in this case is that there's no actual memory associated with them. They just affect the main register.

This hasn't been seen in other PIC micros as far as I'm aware, but I've seen the same thing in ARM chips. The critical factor is address space, because these have got a 4GB address map you can do a lot more with some extra addresses and save CPU cycles.


KM6VV

Thu, 30 Jun 2011 19:16:46 +0000

I did an ARM7 (Atmel) project a few years back. It was nice in that you could "remap" peripherals to some extend. I don't remember seeing this "virtual register" trick, but I like it!

Alan KM6VV

Yeah, all they really mean by "virtual registers" in this case is that there's no actual memory associated with them. They just affect the main register. This hasn't been seen in other PIC micros as far as I'm aware, but I've seen the same thing in ARM chips. The critical factor is address space, because these have got a 4GB address map you can do a lot more with some extra addresses and save CPU cycles.


red24dog

Fri, 01 Jul 2011 03:58:27 +0000

Are any of the new Pins, over and above the D0-D13 PWM capable? Is a drawing available designated with digital and analog pins?