I need to write quite simple program which makes LED diode flashes using processor ARM AT91SAM9263. I need to run this code using QEMU emulator, which is installed on my Ubuntu machine.
I am trying to write a program with 4 functions, which are initializing LED ports and Buttons ports, which are flashing LED diodes and checks the Buttons status (if it is pulled or not).
I have defined base registers, although I have a problem with making LED diodes to switch them on/off and to check buttons status. Simply, nothing happens.
Below is my code:
#include <stdio.h>
#include "AT91SAM9263-EK.h"
#include "AT91SAM9263.h"
#include "project.h"
#include <stdint.h>
#include <stdbool.h>
#define AT91B_LED1 AT91C_PIO_PB8 /* DS1 */
#define AT91B_LED2 AT91C_PIO_PC29 /* DS2 */
#define AT91B_NB_LEB 2
#define AT91D_BASE_PIO_LED1 (AT91C_BASE_PIOB)
#define AT91D_BASE_PIO_LED2 (AT91C_BASE_PIOC)
#define AT91D_ID_PIO_LED1 (AT91C_ID_PIOB)
#define AT91D_ID_PIO_LED2 (AT91C_ID_PIOC)
#define AT91B_BP1 AT91C_PIO_PC5 // Left click#
#define AT91B_BP2 AT91C_PIO_PC4 // Right click
#define AT91D_BASE_PIO_BP AT91C_BASE_PIOC
#define AT91D_ID_PIO_BP AT91C_ID_PIOCDE
void LedPortInit()
{
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOCDE ); // peripheral clock enable register (port C, D, E)/* Set the PIO line as input */
AT91D_BASE_PIO_LED1->PIO_ODR = 0x0000000F;
AT91D_BASE_PIO_LED1->PIO_PER = AT91C_PIO_PB8;
AT91D_BASE_PIO_LED2->PIO_OER = AT91C_PIO_PC29 ;
AT91D_BASE_PIO_LED2->PIO_PER = 0xFFFFFFFF;// 1 – Enable PIO to control the pin
AT91C_BASE_PIOE->PIO_PER = AT91C_PIO_PB31;/* Disable pull-up */
AT91C_BASE_PIOA->PIO_PPUDR = 0xFFFF0000;
}
void ButonPortInit()
{
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOCDE ); // peripheral clock enable register (port C, D, E)/* Set the PIO line as input */
AT91C_BASE_PIOD->PIO_ODR = 0x0000000F;
AT91C_BASE_PIOD->PIO_PER = AT91C_PIO_PC5;
AT91C_BASE_PIOB->PIO_OER = AT91C_PIO_PC4 ;
AT91C_BASE_PIOD->PIO_PER = 0xFFFFFFFF;// 1 – Enable PIO to control the pin
AT91C_BASE_PIOE->PIO_PER = AT91C_PIO_PB31;/* Disable pull-up */
AT91C_BASE_PIOA->PIO_PPUDR = 0xFFFF0000;
}
void LedSwitch()
{
while(1)
{
AT91B_LED1->AT91C_PIO_PB8 ^= 1;
}
AT91C_PIO_PC29 << 29 ;
}
void ButtonTest()
{
AT91C_PIO_PC5 << 5;
AT91C_PIO_PC4 << 4;
}
int main(void)
{
LedPortInit();
void ButonPortInit();
void LedSwitch();
void ButtonTest();
}
These lines are mistaken by the compiler to be prototypes, i.e. function declarations without a runtime effect:
void ButonPortInit();
void LedSwitch();
void ButtonTest();
Turn them into function calls like this:
ButonPortInit();
LedSwitch();
ButtonTest();
To demonstrate I offer this MRE with a lot less environment-specific and embedded stuff. The problem and the solution are the same.
#include <stdio.h>
void test1()
{ printf("test 1!\n");}
void test2()
{ printf("test 2!\n");}
int main()
{
printf("Hello, World!\n");
void test1();
test2();
return 0;
}
Output:
Hello, World!
test 2!
You can see that as in your problem description, "Simply, nothing happens." for void test1();
but there is an output for test2();
.
Notice that keywords that are used behind the function names refers to the return value type.
But here you just want to call the function and this operation doesn't pertain to the return value type(I mean just the calling).
So just use:
ButonPortInit();
LedSwitch()
;
ButtonTest()
;
Why no effect of calling functions with void keyword?
void ButonPortInit();
void LedSwitch();
void ButtonTest();
Because these are not function calls. Expressions in this form are function prototypes. To turn them into function calls you need to remove the void
keyword.
However,
(void) ButonPortInit();
is a valid function call. (void)
in this case is not the return type, but a type conversion operator. It means to cast the return value of ButtonPortInit()
to void
. It is often used to explicitly specify that the return value of a function should be discarded.
extern void x ( unsigned int );
void one ( void )
{
x(1);
}
void two ( void )
{
x(2);
}
int test0 ( void )
{
void one();
void two();
return(0);
}
int test1 ( void )
{
one();
two();
return(0);
}
Disassembly of section .text:
00000000 <one>:
0: e92d4010 push {r4, lr}
4: e3a00001 mov r0, #1
8: ebfffffe bl 0 <x>
c: e8bd4010 pop {r4, lr}
10: e12fff1e bx lr
00000014 <two>:
14: e92d4010 push {r4, lr}
18: e3a00002 mov r0, #2
1c: ebfffffe bl 0 <x>
20: e8bd4010 pop {r4, lr}
24: e12fff1e bx lr
00000028 <test0>:
28: e3a00000 mov r0, #0
2c: e12fff1e bx lr
00000030 <test1>:
30: e92d4010 push {r4, lr}
34: e3a00001 mov r0, #1
38: ebfffffe bl 0 <x>
3c: e3a00002 mov r0, #2
40: ebfffffe bl 0 <x>
44: e3a00000 mov r0, #0
48: e8bd4010 pop {r4, lr}
4c: e12fff1e bx lr
I have found full solution, I just needed to activate additional registers PIO_SODR and PIO_CODR as below:
void LED1_SwitchOn(){
*PIOB_CODR = AT91B_LED1;
}
void LED2_SwitchOn(){
*PIOC_CODR = AT91B_LED2;
}
void LED1_SwitchOff(){
*PIOB_SODR = AT91B_LED1;
}
void LED2_SwitchOff(){
*PIOC_SODR = AT91B_LED2;
}
int BP1_Status(){
return (((*PIOC_PDSR) >> BP1 ) & 1);
}
int BP2_Status(){
return (((*PIOC_PDSR) >> BP2 ) & 1);
}
void delay(long long int time_delay){
for (volatile long long int i = 0; i < 100000 * time_delay; i++);
}
int main(void) {
LED1Port_Init();
LED2Port_Init();
enable_PMC();
Button1Port_Init();
Button2Port_Init();
long long int time_delay=0;
while (1)
{
LED1_SwitchOn();
for (volatile long long int i = 0; i < DELAY; i++)
{
if (BP1_Status() == 0) //button1 switches on diode
LED2_SwitchOn();
delay(time_delay);
if (BP2_Status() == 0) //button2 switches off diode
LED2_SwitchOff();
}
LED1_SwitchOff();
}
return 0;
}
User contributions licensed under CC BY-SA 3.0