Author Topic: [gcc C] concatenating text to make up code  (Read 19941 times)

0 Members and 1 Guest are viewing this topic.

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #100 on: October 10, 2018, 07:19:13 am »
yea, duh of course, my excuse is copy and pasting.
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8172
  • Country: fi
Re: [gcc C] concatenating text to make up code
« Reply #101 on: October 10, 2018, 07:23:45 am »
You also need to care about the atomicity of operations indeed. Yet another possible pitfall. For this, you need to guard the read or write operation to make sure it can't get interrupted. Some processors have specific instructions for this. Most MCUs don't and you need to selectively disable and re-enable interrupts around the operation.

I personally don't like disabling interrupts because it increases interrupt latency. Usually I can figure a way to avoid disabling interrupts, such as reading the variable twice and making sure it's the same both times.

It helps if the architecture allows you to selectively disable only certain priority of interrupts (still with a single instruction), for example, on ARM with the BASEPRI. Having all the super timing critical, non-jittery interrupts on the highest priority class that won't get disabled solves the problem. This priority class, of course, cannot communicate using such shared non-atomic variables, but they often won't need to; you tend to need to perform some simple, quick operation first. Then, at the end of the timing critical ISR, if you need, you can trigger a software interrupt to effectively lower the interrupt priority to go on with the post-processing - if no other timing-critical interrupts are pending, it tail-chains with no extra penalty like it would be a longer interrupt to begin with, but it can get disabled and postponed for atomic operations.

For example, in my current project, I use 16 interrupt priorities, out of which the two highest are never masked off. The highest level is safety shutdown locking in while(1) after doing the necessary shutdown stuff (power MOSFET gate driver disables, or correct power-down sequencing order while the caps still hold some charge) quickly, and the second-highest level may be used to quickly turn signals on or off in what's considered "normal operation".

Although, if you find out that you need to communicate between your threads using such big datatypes, I would recommend trying to rethink it if you could just live the 8-bit/16-bit/32-bit (depending on your CPU) naturally atomic variable.
« Last Edit: October 10, 2018, 07:25:42 am by Siwastaja »
 

Offline TK

  • Super Contributor
  • ***
  • Posts: 1722
  • Country: us
  • I am a Systems Analyst who plays with Electronics
Re: [gcc C] concatenating text to make up code
« Reply #102 on: October 10, 2018, 10:53:39 am »
I take it that:

void pin_state(uint8_t port, uint8_t pin){
   return (*(volatile uint8_t*)(PORTS__OFFSET + PORTS__OFFSET_GAP * port + DATA_INPUT_PIN_VALUE)) & 0x01 << pin; // return state of pin.
} // Use PORT_x and PIN_n as arguments.

would work? so I'd end up with something like:

if ( pin_state( PORT_B, PIN_5 )) {
       some code;
     }

And presumably !pin_state(PORT_B, PIN_5) to negate the result.
You can define it as a macro to avoid calling a function

Code: [Select]
#define pin_state(port, pin) (*(volatile uint8_t*)(PORTS__OFFSET + PORTS__OFFSET_GAP * port + DATA_INPUT_PIN_VALUE)) & 0x01 << pin

if ( pin_state( PORT_B, PIN_5 )) {
       some code;
     }
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #103 on: October 10, 2018, 11:29:02 am »
I take it that:

void pin_state(uint8_t port, uint8_t pin){
   return (*(volatile uint8_t*)(PORTS__OFFSET + PORTS__OFFSET_GAP * port + DATA_INPUT_PIN_VALUE)) & 0x01 << pin; // return state of pin.
} // Use PORT_x and PIN_n as arguments.

would work? so I'd end up with something like:

if ( pin_state( PORT_B, PIN_5 )) {
       some code;
     }

And presumably !pin_state(PORT_B, PIN_5) to negate the result.
You can define it as a macro to avoid calling a function

Code: [Select]
#define pin_state(port, pin) (*(volatile uint8_t*)(PORTS__OFFSET + PORTS__OFFSET_GAP * port + DATA_INPUT_PIN_VALUE)) & 0x01 << pin

if ( pin_state( PORT_B, PIN_5 )) {
       some code;
     }

What and invoke the wrath of the define haters? but yes that would guarantee code efficiency as there would be no argument about how it compiles.
 

Offline cv007

  • Frequent Contributor
  • **
  • Posts: 826
Re: [gcc C] concatenating text to make up code
« Reply #104 on: October 10, 2018, 11:44:32 am »
Quote
would work?
You have a compiler, right? Why are you not testing your code by trying to compile it?

I don't have anything avr installed except arduino, so I find the bin folder, create a test file, and compile it then disassemble it. If it compiles, that's a good start. But a happy compiler does not mean the result is what I want, so I disassemble and see what happened. I haven't been slinging any code here that I have not tested. If I can do it, you can too.

Here is a simple example I just put together just to show how easy it is to test things out. This is a simple example (and no pin dir code included, so will not set the led), but simple means you can see what is happening. I also used -Os, since its both much easier to read and most likely that is what will eventually be used.

Code: [Select]
//test.c
#include <stdint.h>
#include <stdbool.h>

typedef enum {
    A0=0x00, A1, A2, A3, A4, A5, A6, A7,
    B0=0x20, B1, B2, B3, B4, B5, B6, B7,
    C0=0x40, C1, C2, C3, C4, C5, C6, C7,
    D0=0x60, D1, D2, D3, D4, D5, D6, D7,
    E0=0x80, E1, E2, E3, E4, E5, E6, E7,
    F0=0xA0, F1, F2, F3, F4, F5, F6, F7,
    //all my pin info here
    SW1=A2, LED1=B3
} PIN_t;

enum { PORTBASE = 0x400 };

static inline bool pin_get(PIN_t pin)
{
    //offset [8] is IN register
    return ((volatile uint8_t*)(PORTBASE+(pin & 0XF0)))[8] & (1<<(pin&7));
}
static inline void pin_set(PIN_t pin, bool tf){
    //offset [5] is OUTSET register, [6] is OUTCLR
    if(tf)((volatile uint8_t*)(PORTBASE+(pin & 0XF0)))[5] = 1<<(pin&7);
    else  ((volatile uint8_t*)(PORTBASE+(pin & 0XF0)))[6] = 1<<(pin&7);
}

void main()
{
    pin_set( LED1, pin_get(SW1) );

    for(;;);
}

/*
(test.c is in bin directory just to make it easier)
in avr bin directory, at command prompt (Linux in this case)
compile and disassemble (use -Os so its easier to read)
./avr-gcc -C -Os test.c && ./avr-objdump -d a.out
or Windows-
c:\pathtoavr\avr\bin>avr-gcc -C -Os test.c && avr-objdump -d a.out


Disassembly of section .text:

00000000 <main>:
   0:   80 91 08 04     lds     r24, 0x0408     ; 0x800408 <_edata+0x3a8>
   4:   82 ff           sbrs    r24, 2
   6:   04 c0           rjmp    .+8             ; 0x10 <__zero_reg__+0xf>
   8:   88 e0           ldi     r24, 0x08       ; 8
   a:   80 93 25 04     sts     0x0425, r24     ; 0x800425 <_edata+0x3c5>
   e:   03 c0           rjmp    .+6             ; 0x16 <__zero_reg__+0x15>
  10:   88 e0           ldi     r24, 0x08       ; 8
  12:   80 93 26 04     sts     0x0426, r24     ; 0x800426 <_edata+0x3c6>
  16:   ff cf           rjmp    .-2             ; 0x16 <__zero_reg__+0x15>
*/

If you can get in the habit of trying your code to see whether it compiles without error and what is produced by the compiler, you will get a better understanding of C, the compiler, and even assembly.

« Last Edit: October 10, 2018, 07:32:01 pm by cv007 »
 
The following users thanked this post: nugglix

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #105 on: October 10, 2018, 12:14:21 pm »
It compiles fine, I will be testing at the earliest opportunity.
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14470
  • Country: fr
Re: [gcc C] concatenating text to make up code
« Reply #106 on: October 10, 2018, 02:59:17 pm »
You also need to care about the atomicity of operations indeed. Yet another possible pitfall. For this, you need to guard the read or write operation to make sure it can't get interrupted. Some processors have specific instructions for this. Most MCUs don't and you need to selectively disable and re-enable interrupts around the operation.

I personally don't like disabling interrupts because it increases interrupt latency. Usually I can figure a way to avoid disabling interrupts, such as reading the variable twice and making sure it's the same both times.

It helps if the architecture allows you to selectively disable only certain priority of interrupts (still with a single instruction), for example, on ARM with the BASEPRI.

Yes, this is what I usually do when possible and needed.

Another possible approach is using flags (that themselves are small enough to be guaranteed to be accessed atomically) for guarding access to the variables in question. A bit like critical sections. This is not 100% failsafe depending on the architecture though, and adds obvious overhead, but it's often adequate.
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3146
  • Country: ca
Re: [gcc C] concatenating text to make up code
« Reply #107 on: October 10, 2018, 03:58:04 pm »
It helps if the architecture allows you to selectively disable only certain priority of interrupts (still with a single instruction), for example, on ARM with the BASEPRI. Having all the super timing critical, non-jittery interrupts on the highest priority class that won't get disabled solves the problem. This priority class, of course, cannot communicate using such shared non-atomic variables, but they often won't need to; you tend to need to perform some simple, quick operation first. Then, at the end of the timing critical ISR, if you need, you can trigger a software interrupt to effectively lower the interrupt priority to go on with the post-processing - if no other timing-critical interrupts are pending, it tail-chains with no extra penalty like it would be a longer interrupt to begin with, but it can get disabled and postponed for atomic operations.

Usually, there's only the highest priority interrupt you need to worry about. All others can be pre-empted by the highest priority ISR, and therefore they must be able to tolerate higher latencies. You cannot do two different things at the same time, so you can provide the best latency for only one interrupt. Therefore, disabling lower priority interrupts for a short time won't do any harm.

Sometimes, such as on PIC32, the interrupt priorities are switched in software, so even the higher priority interrupts may be postponed if they happen exactly when the lower priority ISR is starting. In this case, disabling lower priority interrupts is actually decreases the latency for the higher ones.
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: [gcc C] concatenating text to make up code
« Reply #108 on: October 10, 2018, 11:42:20 pm »
Quote
so in assembler how do you write to a memory location?
If writing assembler inside a C program, the main problem becomes "how do I get data from my C program to where my assembler code can see it..."   The gcc syntax for inline assembler is ... arcane.  The simpler process of writing a C-compatible subroutine in assembler means having to learn the interface (ABI) that your particular compiler uses for subroutines (and - not all assembler produce object code that is linkable with C programs.  The Atmel assemblers don't, for example (not either one of the two that they have.)  (Fortunately for gcc, they have their OWN assembler for Atmel that is "almost the same" as the Atmel assemblers.)
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #109 on: October 11, 2018, 06:31:37 pm »
This does not work:

void setup_output(uint8_t port, uint8_t pin){
   (*(volatile uint8_t*)(PORTS_OFFSET + (PORTS_OFFSET_GAP * port) + DATA_DIR_CLR)) = 0x01 << pin; // set pin as output
} // Use PORT_x and PIN_n as arguments.

How does the compiler know the difference between multiplication and a pointer?
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11255
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #110 on: October 11, 2018, 06:35:16 pm »
How exactly it does not work? And what are the values of of the constants?

Compiler knows about operators based on context. Multiplication can only occur after one expression was parsed. Pointer dereference can only happen as part of the expression.

I strongly recommend to look at the formal C grammar. It may take some time to understand, but it may clarify a lot of things. Here is one for example: https://www.lysator.liu.se/c/ANSI-C-grammar-y.html

There are way too many parenthesis here, but the expression overall looks correct.

Code: [Select]
*(volatile uint8_t *)(PORTS_OFFSET + PORTS_OFFSET_GAP * port + DATA_DIR_CLR) = 0x01 << pin;
« Last Edit: October 11, 2018, 06:38:58 pm by ataradov »
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #111 on: October 11, 2018, 06:41:53 pm »
It's ok my fault, I am trying to access the virtual ports but am using the wrong starting address as i am using the parts address not the base addresses of the special registers i can access pin at a time.
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #112 on: October 11, 2018, 08:20:30 pm »
OK setting as an output works but setting and clearing the pin does not.

// Port and pin numbers for use in programs.

#define PORT_A 0x00
#define PORT_B 0x01
#define PORT_C 0x02
#define PORT_D 0x03
#define PORT_E 0x04
#define PORT_F 0x05

#define PIN_0 0x00
#define PIN_1 0x01
#define PIN_2 0x02
#define PIN_3 0x03
#define PIN_4 0x04
#define PIN_5 0x05
#define PIN_6 0x06
#define PIN_7 0x07

// Port register addresses.

// Virtual ports
#define VIRTUAL_PORTS_START 0x0000
#define VIRTUAL_PORT_OFFSET 0x0004
#define VP_DATA_DIR_SET 0x01
#define VP_DATA_DIR_CLR 0x02
#define VP_DATA_DIR_TOGGLE 0x03
#define VP_DATA_OUTSET 0x05
#define VP_DATA_OUTCLR 0x06
#define VP_DATA_OUTPUT_TOGGLE 0x07

void clr_pin(uint8_t port, uint8_t pin){
   (*(volatile uint8_t*)(VIRTUAL_PORTS_START + (VIRTUAL_PORT_OFFSET * port) + VP_DATA_OUTCLR)) = 0x01 << pin; // clear pin low
} // Use PORT_x and PIN_n as arguments.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11255
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #113 on: October 11, 2018, 08:22:50 pm »
I have not looked at the datasheet, but VIRTUAL_PORT_OFFSET can't be 4. Assuming VP_xxx are correct, it must be at least 8. Otherwise your addresses will overlap.
Alex
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11255
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #114 on: October 11, 2018, 08:25:45 pm »
Virtual ports only have the following registers:
Code: [Select]
0x00 DIR
0x01 OUT
0x02 IN
0x03 INTFLAGS

There is no OUTSET/OUTCLR.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #115 on: October 11, 2018, 08:28:23 pm »
0x0000 VPORTA Virtual Port A
0x0004 VPORTB Virtual Port B
0x0008 VPORTC Virtual Port C
0x000C VPORTD Virtual Port D
0x0010 VPORTE Virtual Port E
0x0014 VPORTF Virtual Port F

From page 43 of the atmega 0 series manual, if the offset was wrong then the setup_output(); would not work either.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11255
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #116 on: October 11, 2018, 08:29:12 pm »
From page 43 of the atmega 0 series manual, if the offset was wrong then the setup_output(); would not work either.
Offset is correct, registers are not.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #117 on: October 11, 2018, 08:29:54 pm »
Page 148, the following page is output clear

Output Value Set
Name:  OUTSET
Offset:  0x05
Reset:  0x00
Property:  -
Bit 7 6 5 4 3 2 1 0
OUTSET[7:0]
Access R/W R/W R/W R/W R/W R/W R/W R/W
Reset 0 0 0 0 0 0 0 0
Bits 7:0 – OUTSET[7:0] Output Value Set
This bit field can be used instead of a read-modify-write to set the output value of individual pins to '1'.
Writing a '1' to OUTSET[n] will set the corresponding bit in PORTx.OUT.
Reading this bit field will alway
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11255
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #118 on: October 11, 2018, 08:30:35 pm »
This is for the real port. Virtual Ports have different layout. I'm looking at Series 0 manual. There it is described in the section "15.6 Register Summary - VPORTx".
« Last Edit: October 11, 2018, 08:32:33 pm by ataradov »
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #119 on: October 11, 2018, 08:32:15 pm »
The offsets are the same for normal or virtual ports for in/out data but there are two sets of general offsets for normal rregisters and bit accessible ones
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #120 on: October 11, 2018, 08:33:14 pm »
This is for the real port. Virtual Ports have different layout.

no it is the virtual, that is why they talk about it replacing the other (normal) one that requires read/modify/write
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11255
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #121 on: October 11, 2018, 08:35:10 pm »
no it is the virtual, that is why they talk about it replacing the other (normal) one that requires read/modify/write
I'm looking at the Series 0 manual and the section "15.6 Register Summary - VPORTx" clearly describes what registers are available for the VPORTs.

You can't have 8 registers located with intervals of 4 bytes.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #122 on: October 11, 2018, 08:40:45 pm »
This is very confusing, i need to have another look, but yes, so which ports have the set/clr registers ? like you say an address gap of 4 does not allow for all of that.
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11255
  • Country: us
    • Personal site
Re: [gcc C] concatenating text to make up code
« Reply #123 on: October 11, 2018, 08:42:56 pm »
Regular PORT peripherals have all registers. VPORTs only have the listed 4.

Look at "Register Summary" section of the peripheral description to know exactly what registers are available for the peripheral.
Alex
 

Offline SimonTopic starter

  • Global Moderator
  • *****
  • Posts: 17815
  • Country: gb
  • Did that just blow up? No? might work after all !!
    • Simon's Electronics
Re: [gcc C] concatenating text to make up code
« Reply #124 on: October 11, 2018, 08:46:40 pm »
so what is a virtual port? it has no use at all other than regular registers, the non virtual registers are the more flexible.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf