Wątek przeniesiony 2018-11-08 11:16 z C/C++ przez Marooned.

Otrzymanie adresu PORTx i PINx z adresu DDRx

0

Witam,
piszę sobie bibliotekę do obsługi klawisze, chciałbym jakoś obejść konieczność podawania za każdym razem portu, pinu i rejestru, czy pomoże ktoś jakoś to wyliczyć z samego rejestru?
Przykład adresów na ATmega32:
DDRA:

*(volatile uint8_t *)((0x1A) + 0x20))

PORTA:

(*(volatile uint8_t *)((0x1B) + 0x20))

PINA:

(*(volatile uint8_t *)((0x19) + 0x20))

Adres PORT i PIN jest w przypadku innych rejestrów też różnią się o tyle samo

0

A może tak zwykłe #define ?

#define DDRA_KEY(x) *(volatile uint8_t *)((x) + 0x20))
#define PORTA_KEY(x) (*(volatile uint8_t *)((x) + 0x20))
#define PINA_KEY(x) (*(volatile uint8_t *)((x) + 0x20))

int some_func()
{
    //no i 'normalnie'
   int key = DDRA_KEY(0x123) // key == *(volatile uint8_t *)((0x123) + 0x20))
}

0

Chciałem się podczepić pod posta bo używacie słowa volatile
Wiem co ono znaczy ale chciałbym spytać jak to jest jeśli chciałbym zdefiniować taki oto typ strukturalny:

typedef volatile struct
{
    volatile uint8_t reg_address;
    volatile uint8_t rw;
    volatile uint8_t transmit_value;
    volatile uint8_t * receive_value_ptr;
} twi_data_t;

a następnie zdefiniować zmienną tego typu:

volatile twi_data_t twi_buffer[20];

Czy muszę pisać za każdym razem volatile ?
Czy mogłoby to wyglądać tak:

typedef volatile struct
{
    uint8_t reg_address;
    uint8_t rw;
    uint8_t transmit_value;
    uint8_t * receive_value_ptr;
} twi_data_t;

twi_data_t twi_buffer[20];

?

1

Ogólnie to ma szanse zadziałać, ale patrz gdzie volatile stoi przy wskaźniku, bo to się nie zachowa tak jak myślisz:
https://stackoverflow.com/questions/2044565/volatile-struct-semantics

BTW, nie używaj sufiksu _t do własnych typów. To niby nie jest jakoś bardzo groźne, ale można się naciąć.
https://stackoverflow.com/questions/10356626/c-type-naming-conventions-t-or-allcaps

0

Napisałem driver do TWI(I2C). Jestem Ci wdzięczny ponieważ poprzez tą dyskusję na temat volatile poprawiłem trochę kod z takiego:

/* program Atmega8L */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/twi.h>
#include "lcd44780.h"
#include <util/atomic.h>

/* define slave (MPU6050) address as 0x68 because AD0 is low */
#define SLAVE_ADDRESS (0x68)
#define WHO_AM_I (0x75)

#define TWI_BUFFER_SIZE (1<<5)
#define NO_ERROR (0)
#define OVERFLOW_ERROR (1)
#define READ (0)
#define WRITE (1)

uint8_t data = 0;
uint8_t data_retry = 0;

typedef enum
{
    IDLE,
    START,
    REPEATED_START,
    SLA_W_TRANSMIT,
    RA_TRANSMIT,
    DATA_TRANSMIT,
    SLA_R_TRANSMIT,
    DATA_RECEIVE,
    TRANSMISSION_ERROR
} sm_t;

typedef struct
{
    uint8_t reg_address;
    uint8_t rw;
    uint8_t transmit_value;
    uint8_t * receive_value_ptr;
} data_t;

typedef struct
{
    data_t buffer[TWI_BUFFER_SIZE];
    uint8_t head;
    uint8_t tail;
    sm_t sm;
} twi_t;

volatile twi_t twi;

/* function start TWI operations */
void twi_start()
{
    if (twi.sm == IDLE)
    {
        twi.sm = START;
        TWCR |= (1 << TWSTA) | (1 << TWINT);
        TWCR &= ~(1 << TWSTO);
    }
}

/* function add data to send to the buffer */
uint8_t twi_send(uint8_t address, uint8_t value)
{
    uint8_t return_value;
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
    {
        if (((twi.head + 1) & (TWI_BUFFER_SIZE - 1)) == twi.tail)
            return_value = OVERFLOW_ERROR;
        else
        {
            twi.buffer[twi.head].reg_address = address;
            twi.buffer[twi.head].rw = WRITE;
            twi.buffer[twi.head].transmit_value = value;
            twi.head = ((twi.head + 1) & (TWI_BUFFER_SIZE - 1));
            return_value = NO_ERROR;
            twi_start();
        }
    }
    return return_value;
}

/* function add pointer for data receive to the buffer */
uint8_t twi_receive(uint8_t address, uint8_t * ptr)
{
    uint8_t return_value;
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
    {
        if (((twi.head + 1) & (TWI_BUFFER_SIZE - 1)) == twi.tail)
            return_value = OVERFLOW_ERROR;
        else
        {
            twi.buffer[twi.head].reg_address = address;
            twi.buffer[twi.head].rw = READ;
            twi.buffer[twi.head].receive_value_ptr = ptr;
            twi.head = ((twi.head + 1) & (TWI_BUFFER_SIZE - 1));
            return_value = NO_ERROR;
            twi_start();
        }
    }
    return return_value;
}

/* TWI interrupt service routine */
ISR(TWI_vect)
{
    /* checking TWI status */
    uint8_t status = TWSR;
    switch (status)
    {
        case TW_START:
        {
            /* load SLA + W because we want to send register address first */
            TWDR = (SLAVE_ADDRESS << 1) | (0 << 0);

            /* clear start bit manually */
            TWCR &= ~(1 << TWSTA);

            /* release interrupt flag */
            TWCR |= (1 << TWINT);

            /* change state machine */
            twi.sm = SLA_W_TRANSMIT;

            break;
        }

        case TW_REP_START:
        {
            /* if state machine is on the error state than retry all buffer cycle */
            /* start next buffer cycle without releasing the bus if state machine is on data transmit or receive */
            if ((twi.sm == TRANSMISSION_ERROR) || (twi.sm == DATA_TRANSMIT) || (twi.sm == DATA_RECEIVE) || (twi.sm == START))
            {
                TWDR = (SLAVE_ADDRESS << 1) | (0 << 0);
                TWCR &= ~(1 << TWSTA);
                TWCR |= (1 << TWINT);
                twi.sm = SLA_W_TRANSMIT;
            }
            /* if state machine is on the register address transmit state than load SLA_R */
            else if (twi.sm == RA_TRANSMIT)
            {
                TWDR = (SLAVE_ADDRESS << 1) | (1 << 0);
                TWCR &= ~(1 << TWSTA);
                TWCR |= (1 << TWINT);
                twi.sm = SLA_R_TRANSMIT;
            }
            /* if state machine is on the data transmit or data receiving than start next buffer cycle */
            else if ((twi.sm == DATA_TRANSMIT) || (twi.sm == DATA_RECEIVE))
            {
                TWDR = (SLAVE_ADDRESS << 1) | (0 << 0);
                TWCR &= ~(1 << TWSTA);
                TWCR |= (1 << TWINT);
                twi.sm = SLA_W_TRANSMIT;
            }

            break;
        }

        case TW_MT_SLA_ACK:
        {
            /* load register address */
            TWDR = twi.buffer[twi.tail].reg_address;

            /* release interrupt flag */
            TWCR |= (1 << TWINT);

            /* change state machine */
            twi.sm = RA_TRANSMIT;

            break;
        }

        case TW_MT_SLA_NACK:
        {
            /* if no acknowledge than force repeated start and release interrupt flag */
            TWCR |= (1 << TWSTA) | (1 << TWINT);

            /* change state machine to error state */
            twi.sm = TRANSMISSION_ERROR;

            break;
        }

        case TW_MT_DATA_ACK:
        {
            /* if before operation was register address transmit */
            if (twi.sm == RA_TRANSMIT)
            {
                /* if current requested operation is write register */
                if (twi.buffer[twi.tail].rw == WRITE)
                {
                    /* put the essential data on the bus */
                    TWDR = twi.buffer[twi.tail].transmit_value;

                    /* release interrupt flag */
                    TWCR |= (1 << TWINT);

                    /* change state machine */
                    twi.sm = DATA_TRANSMIT;
                }
                /* if current requested operation is read register */
                else
                {
                    /* force repeated start and release interrupt flag */
                    TWCR |= (1 << TWSTA) | (1 << TWINT);
                }
            }
            /* if before operation was essential data transmit */
            else if (twi.sm == DATA_TRANSMIT)
            {
                /* transfer complete - move the tail forward */
                twi.tail = ((twi.tail + 1) & (TWI_BUFFER_SIZE - 1));

                /* check if we have another byte to send / receive */
                if (twi.head != twi.tail)
                {
                    /* force repeated start and release interrupt flag */
                    TWCR |= (1 << TWSTA) | (1 << TWINT);
                }
                else
                {
                    /* stop bit transmit and release interrupt flag */
                    TWCR |= (1 << TWSTO) | (1 << TWINT);

                    /* change state machine to idle */
                    twi.sm = IDLE;
                }
            }

            break;
        }

        case TW_MT_DATA_NACK:
        {
            /* if no acknowledge than force repeated start and release interrupt flag */
            TWCR |= (1 << TWSTA) | (1 << TWINT);

            /* change state machine to error state */
            twi.sm = TRANSMISSION_ERROR;

            break;
        }

        case TW_MR_SLA_ACK:
        {
            /* release interrupt flag */
            TWCR |= (1 << TWINT);

            /* change state machine */
            twi.sm = DATA_RECEIVE;

            break;
        }


        case TW_MR_SLA_NACK:
        {
            /* if no acknowledge than force repeated start and release interrupt flag */
            TWCR |= (1 << TWSTA) | (1 << TWINT);

            /* change state machine to error state */
            twi.sm = TRANSMISSION_ERROR;

            break;
        }

        case TW_MR_DATA_ACK:
        {
            /* if acknowledge than force repeated start and release interrupt flag */
            TWCR |= (1 << TWSTA) | (1 << TWINT);

            /* change state machine to error state */
            twi.sm = TRANSMISSION_ERROR;

            break;
        }

        case TW_MR_DATA_NACK:
        {
            /* transfer complete - move data under the pointer */
            *(twi.buffer[twi.tail].receive_value_ptr) = TWDR;

            /* move the tail forward */
            twi.tail = ((twi.tail + 1) & TWI_BUFFER_SIZE);

            /* check if we have another byte to send / receive */
            if (twi.head != twi.tail)
            {
                /* force repeated start and release interrupt flag */
                TWCR |= (1 << TWSTA) | (1 << TWINT);
            }
            else
            {
                /* stop bit transmit and release interrupt flag */
                TWCR |= (1 << TWSTO) | (1 << TWINT);

                /* change state machine to idle */
                twi.sm = IDLE;
            }

            break;
        }

        default:
        {
            break;
        }
    }
}

/* timer overflow interrupt service routine */
ISR(TIMER0_OVF_vect)
{

}

void TimerInit()
{
    /* overflow interrupt enable and start timer on frequency 8MHz / 1024 */
    TIMSK |= (1 << TOIE0);
    TCCR0 |= (1 << CS00) | (1 << CS02);
}

void TwiInit()
{
    /* 100 kHz frequency of TWI module */
    TWBR = 32;

    /* enable TWI module and interrupt from them */
    TWCR = (1 << TWEN) | (1 << TWIE);
}



int main(void)
{
    /* display initialization */
    lcd_init();

    /* TWI structure initialization */
    twi.sm = IDLE;
    twi.head = 0;
    twi.tail = 0;

    /* diodes output */
    DDRB |= (1 << PB0);
    DDRD |= (1 << PD7);

    /* diodes turn off */
    PORTB |= (1 << PB0);
    PORTD |= (1 << PD7);

    /* pull up resistor on PD5 input switch */
    PORTD |= (1 << PD5);

    TimerInit();
    TwiInit();

    sei();

    /* put interesting commands into TWI buffer */
    twi_receive(WHO_AM_I, &data);
    twi_receive(WHO_AM_I, &data_retry);

    while (1)
    {
        /* if switch pressed */
        if (!((PIND >> PD5) & 1))
        {
            if (data == 0x68)
            {
                PORTB &= ~(1 << PB0);
            }
            else
            {
                PORTB |= (1 << PB0);
            }
        }

    }
}

na taki :

/* program Atmega8L */

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/twi.h>
#include "lcd44780.h"
#include <util/atomic.h>

/* define slave (MPU6050) address as 0x68 because AD0 is low */
#define SLAVE_ADDRESS (0x68)
#define WHO_AM_I (0x75)

#define TWI_BUFFER_SIZE (1<<5)
#define NO_ERROR (0)
#define OVERFLOW_ERROR (1)
#define READ (0)
#define WRITE (1)

volatile uint8_t data = 0;
volatile uint8_t data_retry = 0;

typedef enum
{
    IDLE,
    START,
    REPEATED_START,
    SLA_W_TRANSMIT,
    RA_TRANSMIT,
    DATA_TRANSMIT,
    SLA_R_TRANSMIT,
    DATA_RECEIVE,
    TRANSMISSION_ERROR
} sm_t;

typedef struct
{
    uint8_t reg_address;
    uint8_t rw;
    uint8_t transmit_value;
    volatile uint8_t * receive_value_ptr;
} data_t;

typedef struct
{
    data_t buffer[TWI_BUFFER_SIZE];
    uint8_t head;
    uint8_t tail;
    sm_t sm;
} twi_t;

volatile twi_t twi;

/* function start TWI operations */
void twi_start()
{
    if (twi.sm == IDLE)
    {
        twi.sm = START;
        TWCR |= (1 << TWSTA) | (1 << TWINT);
        TWCR &= ~(1 << TWSTO);
    }
}

/* function add data to send to the buffer */
uint8_t twi_send(uint8_t address, volatile uint8_t value)
{
    uint8_t return_value;
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
    {
        if (((twi.head + 1) & (TWI_BUFFER_SIZE - 1)) == twi.tail)
            return_value = OVERFLOW_ERROR;
        else
        {
            twi.buffer[twi.head].reg_address = address;
            twi.buffer[twi.head].rw = WRITE;
            twi.buffer[twi.head].transmit_value = value;
            twi.head = ((twi.head + 1) & (TWI_BUFFER_SIZE - 1));
            return_value = NO_ERROR;
            twi_start();
        }
    }
    return return_value;
}

/* function add pointer for data receive to the buffer */
uint8_t twi_receive(uint8_t address, volatile uint8_t * ptr)
{
    uint8_t return_value;
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
    {
        if (((twi.head + 1) & (TWI_BUFFER_SIZE - 1)) == twi.tail)
            return_value = OVERFLOW_ERROR;
        else
        {
            twi.buffer[twi.head].reg_address = address;
            twi.buffer[twi.head].rw = READ;
            twi.buffer[twi.head].receive_value_ptr = ptr;
            twi.head = ((twi.head + 1) & (TWI_BUFFER_SIZE - 1));
            return_value = NO_ERROR;
            twi_start();
        }
    }
    return return_value;
}

/* TWI interrupt service routine */
ISR(TWI_vect)
{
    /* checking TWI status */
    uint8_t status = TWSR;
    switch (status)
    {
        case TW_START:
        {
            /* load SLA + W because we want to send register address first */
            TWDR = (SLAVE_ADDRESS << 1) | (0 << 0);

            /* clear start bit manually */
            TWCR &= ~(1 << TWSTA);

            /* release interrupt flag */
            TWCR |= (1 << TWINT);

            /* change state machine */
            twi.sm = SLA_W_TRANSMIT;

            break;
        }

        case TW_REP_START:
        {
            /* if state machine is on the error state than retry all buffer cycle */
            /* start next buffer cycle without releasing the bus if state machine is on data transmit or receive */
            if ((twi.sm == TRANSMISSION_ERROR) || (twi.sm == DATA_TRANSMIT) || (twi.sm == DATA_RECEIVE) || (twi.sm == START))
            {
                TWDR = (SLAVE_ADDRESS << 1) | (0 << 0);
                TWCR &= ~(1 << TWSTA);
                TWCR |= (1 << TWINT);
                twi.sm = SLA_W_TRANSMIT;
            }
            /* if state machine is on the register address transmit state than load SLA_R */
            else if (twi.sm == RA_TRANSMIT)
            {
                TWDR = (SLAVE_ADDRESS << 1) | (1 << 0);
                TWCR &= ~(1 << TWSTA);
                TWCR |= (1 << TWINT);
                twi.sm = SLA_R_TRANSMIT;
            }
            /* if state machine is on the data transmit or data receiving than start next buffer cycle */
            else if ((twi.sm == DATA_TRANSMIT) || (twi.sm == DATA_RECEIVE))
            {
                TWDR = (SLAVE_ADDRESS << 1) | (0 << 0);
                TWCR &= ~(1 << TWSTA);
                TWCR |= (1 << TWINT);
                twi.sm = SLA_W_TRANSMIT;
            }

            break;
        }

        case TW_MT_SLA_ACK:
        {
            /* load register address */
            TWDR = twi.buffer[twi.tail].reg_address;

            /* release interrupt flag */
            TWCR |= (1 << TWINT);

            /* change state machine */
            twi.sm = RA_TRANSMIT;

            break;
        }

        case TW_MT_SLA_NACK:
        {
            /* if no acknowledge than force repeated start and release interrupt flag */
            TWCR |= (1 << TWSTA) | (1 << TWINT);

            /* change state machine to error state */
            twi.sm = TRANSMISSION_ERROR;

            break;
        }

        case TW_MT_DATA_ACK:
        {
            /* if before operation was register address transmit */
            if (twi.sm == RA_TRANSMIT)
            {
                /* if current requested operation is write register */
                if (twi.buffer[twi.tail].rw == WRITE)
                {
                    /* put the essential data on the bus */
                    TWDR = twi.buffer[twi.tail].transmit_value;

                    /* release interrupt flag */
                    TWCR |= (1 << TWINT);

                    /* change state machine */
                    twi.sm = DATA_TRANSMIT;
                }
                /* if current requested operation is read register */
                else
                {
                    /* force repeated start and release interrupt flag */
                    TWCR |= (1 << TWSTA) | (1 << TWINT);
                }
            }
            /* if before operation was essential data transmit */
            else if (twi.sm == DATA_TRANSMIT)
            {
                /* transfer complete - move the tail forward */
                twi.tail = ((twi.tail + 1) & TWI_BUFFER_SIZE);

                /* check if we have another byte to send / receive */
                if (twi.head != twi.tail)
                {
                    /* force repeated start and release interrupt flag */
                    TWCR |= (1 << TWSTA) | (1 << TWINT);
                }
                else
                {
                    /* stop bit transmit and release interrupt flag */
                    TWCR |= (1 << TWSTO) | (1 << TWINT);

                    /* change state machine to idle */
                    twi.sm = IDLE;
                }
            }

            break;
        }

        case TW_MT_DATA_NACK:
        {
            /* if no acknowledge than force repeated start and release interrupt flag */
            TWCR |= (1 << TWSTA) | (1 << TWINT);

            /* change state machine to error state */
            twi.sm = TRANSMISSION_ERROR;

            break;
        }

        case TW_MR_SLA_ACK:
        {
            /* release interrupt flag */
            TWCR |= (1 << TWINT);

            /* change state machine */
            twi.sm = DATA_RECEIVE;

            break;
        }


        case TW_MR_SLA_NACK:
        {
            /* if no acknowledge than force repeated start and release interrupt flag */
            TWCR |= (1 << TWSTA) | (1 << TWINT);

            /* change state machine to error state */
            twi.sm = TRANSMISSION_ERROR;

            break;
        }

        case TW_MR_DATA_ACK:
        {
            /* if acknowledge than force repeated start and release interrupt flag */
            TWCR |= (1 << TWSTA) | (1 << TWINT);

            /* change state machine to error state */
            twi.sm = TRANSMISSION_ERROR;

            break;
        }

        case TW_MR_DATA_NACK:
        {
            /* transfer complete - move data under the pointer */
            *(twi.buffer[twi.tail].receive_value_ptr) = TWDR;

            /* move the tail forward */
            twi.tail = ((twi.tail + 1) & (TWI_BUFFER_SIZE - 1));

            /* check if we have another byte to send / receive */
            if (twi.head != twi.tail)
            {
                /* force repeated start and release interrupt flag */
                TWCR |= (1 << TWSTA) | (1 << TWINT);
            }
            else
            {
                /* stop bit transmit and release interrupt flag */
                TWCR |= (1 << TWSTO) | (1 << TWINT);

                /* change state machine to idle */
                twi.sm = IDLE;
            }

            break;
        }

        default:
        {
            break;
        }
    }
}

/* timer overflow interrupt service routine */
ISR(TIMER0_OVF_vect)
{

}

void TimerInit()
{
    /* overflow interrupt enable and start timer on frequency 8MHz / 1024 */
    TIMSK |= (1 << TOIE0);
    TCCR0 |= (1 << CS00) | (1 << CS02);
}

void TwiInit()
{
    /* 100 kHz frequency of TWI module */
    TWBR = 32;

    /* enable TWI module and interrupt from them */
    TWCR = (1 << TWEN) | (1 << TWIE);
}



int main(void)
{
    /* display initialization */
    lcd_init();

    /* TWI structure initialization */
    twi.sm = IDLE;
    twi.head = 0;
    twi.tail = 0;

    /* diodes output */
    DDRB |= (1 << PB0);
    DDRD |= (1 << PD7);

    /* diodes turn off */
    PORTB |= (1 << PB0);
    PORTD |= (1 << PD7);

    /* pull up resistor on PD5 input switch */
    PORTD |= (1 << PD5);

    TimerInit();
    TwiInit();

    sei();

    /* put interesting commands into TWI buffer */
    twi_receive(WHO_AM_I, &data);
    twi_receive(WHO_AM_I, &data_retry);

    while (1)
    {
        /* if switch pressed */
        if (!((PIND >> PD5) & 1))
        {
            if (data == 0x68)
            {
                PORTB &= ~(1 << PB0);
            }
            else
            {
                PORTB |= (1 << PB0);
            }
        }

    }
}

i wiecie co, po kliknięciu przycisku podłączonego do PD5 w pierwszym przypadku dioda się nie zapala (wyzwalana stanem niskim) a w drugim się zapala. Patrząc jednak na oscyloskopie na SDA i SCL to w obydwu przypadkach maszyna stanów poprawnie przechodzi przez wszystkie stany i generuje odpowiednie poprawne przebiegi protokołu. Ktoś może powiedzieć co dokładnie się stało że to zaczęło działać? PS. Kod jest prawie ten sam, dodałem w trzech miejscach tylko volatile. Przy definicji data, przy argumencie funkcji twi_receive i w deklaracji pola wskaźnikowego struktury, możecie użyć beyond compare do porównania.

1

Pamiętaj jednak, że nadużywanie volatile też nie przynosi dobrych rezultatów. Np tu:

uint8_t twi_send(uint8_t address, volatile uint8_t value)

wydaje mi się, że zastosowanie volatile jest zbędne.

Z tego co pamiętam, to semantyka volatile jest taka sama jaka const, więc łatwo jest sobie zobaczyć, jak się kod zachowa ;-)

1

@Sparrow-hawk:

Z tego co pamiętam, to semantyka volatile jest taka sama jaka const

Ośmielam się wyrażać powątpiewanie?

Z tego, co wiem, to const oznacza, że zmienna ma nie zmieniać swojej wartości (ma być stałą), natomiast volatile - że kompilatorowi nie wolno wyrzucać instrukcji zapisu wartości do zmiennej w ramach optymalizacji. Czyli raczej nie to samo?

http://en.cppreference.com/w/c/language/const

http://en.cppreference.com/w/c/language/volatile

1

Tak czy siak volatile w przekazywaniu argumentu przez wartość ma raczej ograniczoną ilość zastosowań, prawda?

0

Panowie, chciałem podziękować za cenne wypowiedzi.
Ale przyznacie że w kontekście mojego programu zastosowanie tego volatile tutaj:

uint8_t twi_receive(uint8_t address, volatile uint8_t * ptr)

ma sens, ponieważ nie dotyczy to zmiennej wskaźnikowej wewnątrz funkcji a danej pokazywanej przez nasz wskaźnik...
Podczas gdy już tutaj:

uint8_t twi_send(uint8_t address, uint8_t value)

zastosowanie tego volatile sensu raczej by nie miało ponieważ ja raczej nawet nie chcę aby optymalizator nie mógł jakoś sobie optymalizować dostępu do zmiennej lokalnej czyli kopii wartości parametru do niej przekazywanego...

0

IMO najsensowniejsze wyjaśnienie, jak działa volatile jest opisane tu: http://www.agner.org/optimize/optimizing_cpp.pdf (strona 28)
A w skrócie:

The effect of the keyword volatile is that it makes sure the variable is stored in memory
rather than in a register and prevents all optimizations on the variable. This can be useful in
test situations to avoid that some expression is optimized away.

0

W kontekście oprogramowania wbudowanego...

uint8_t const * const ptr; // Stały wskaźnik na dane tylko do odczytu.
volatile uint8_t const * const ptr; // Stały wskaźnik na dane tylko do odczytu (np. rejestr) które zmieniają się poza bieżącym wątkiem programu.
0

W porządku. Może się przydam... Przedstawiam takie coś w załączniku do zastosowań ogólnych :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1