I am trying to create a library in C for use in a ATMEL 328pu. I have made the source and header files in C but come unstuck when I try to compile the library. I think I need another AVR library containing the types:
TWDR
TWCR
Which are the i2c registers in the ATMEGA328. A shortened version of the error message can be seen below followed by a portion of the .cpp file where the error message refers too.
Error message:
Build: Debug in my_i2c (compiler: GNU GCC Compiler)
Code_blocks/my_i2c/my_i2c/my_i2c.cpp|39|error: use of undeclared identifier 'TWCR'|
Build failed: 19 error(s), 0 warning(s) (0 minute(s), 0 second(s))
Extract from.cpp file:
#include "my_i2c.h"
/////////////////////WRITE BIT////////////////////
void my_i2c :: i2cWriteBit (uint8_t i2cAdd, uint8_t i2cReg, uint8_t i2cBit, bool i2cBool) {
uint8_t writeBuff;
writeBuff = i2cRead(i2cAdd, i2cReg); //read uint8_t
i2cBool == true ? writeBuff |= 1 << i2cBit : writeBuff &= ~(1 << i2cBit);
i2cWrite (i2cAdd, i2cReg, writeBuff);
}
/////////////////////WRITE uint8_t////////////////////
void my_i2c :: i2cWrite (uint8_t i2cAdd, uint8_t i2cReg, uint8_t i2cData) {
/////START CONDITION////
TWCR = 0b10100100; //(TWINT)(TWSTA)(TWEN) - Set START condition
while (!(TWCR & 0b10000000)) { //Wait for TWI to set TWINT
}
Do I need to define the what TWCR and TWDR are for the compiler to understand the functions? and how do I do this, is it like I was thinking by including another library?
You can't refer to an undeclared identifier, that makes it impossible for the compiler to figure out what you mean.
You should probably add
#include <avr/io.h>
to your library's source code.
Related
I have a code-block, which is written in C for IAR C/C++ Compiler.
__no_init uint8_t u8ramPhysStart_startUp # 0x20000000;
__no_init uint8_t u8ramPhysEnd_startUp # 0x2002FFFF;
__no_init uint8_t u8ramTestStart_startUp # 0x20004008;
__no_init uint8_t u8ramTestEnd_startUp # 0x20008008;
#define START_ASM (&u8ramPhysStart_startUp)
#define RAMSTART_STRTUP ((uint32_t)START_ASM)
My goal is converting it or rather making it GCC compatible. For this, I rewrite above code like:
unsigned char u8ramPhysStart_startUp __asm("# 0x20000000");
unsigned char u8ramPhysEnd_startUp __asm("# 0x2002FFFF");
unsigned char u8ramTestStart_startUp __asm("# 0x20004008");
unsigned char u8ramTestEnd_startUp __asm("# 0x20008008");
But after compilation I get following error:
C:\Users\Pc\AppData\Local\Temp\ccyuCWQT.s: Assembler messages:
C:\Users\Pc\AppData\Local\Temp\ccyuCWQT.s:971: Error: expected symbol name
C:\Users\Pc\AppData\Local\Temp\ccyuCWQT.s:972: Error: expected symbol name
Do someone knows, what it means?
I believe the gcc code should be something like
uint8_t __attribute__ ((section(".my_section"))) u8ramPhysStart_startUp;
where .my_section is something you have added to the linker script.
That being said, the only way which you can make allocation at absolute addresses portable, is to stick to pure ISO C:
#define u8ramPhysStart_startUp (*(volatile uint8_t*)0x20000000u)
or in case you want a pointer to an address:
#define u8ramPhysStart_startUp ((volatile uint8_t*)0x20000000u)
The disadvantage of this is that it doesn't actually allocate any memory, but relies on a linker script to handle that part. That's preferable in most cases.
Another disadvantage is that you won't be able to view these "variable" names in a debugger, since they are actually not variables at all. And that's the main reason why some tool chains come up with things like the non-standard # syntax.
I'm trying to compile library from .c file in Xcode. (It doesn't give me any errors in Visual Studio on Windows) But Xcode gives:
Use of undeclared identifier 'byte'
in the next line:
buf[2] = (byte)(addr & 0xff);
In the .c file i have declared byte with the next code:
typedef uint8_t byte
uint8_t is similar to byte, so it compiled
I'm getting the error: recipe for target main.o failed. I'm currently programming for the ATmega 168BPB board, trying to run the following simple program:
int main(void)
{
DDRB = 0xFF;
PORTB = 1 << PORTB5;
while (1)
{
}
}
to just get the built-in LED to turn on.
Has anyone had any experience with this problem and/or knows how to solve it?
Try to turn off your antivirus : i've had that one with "Comodo internet security" After DISABLE "auto-containment", it starts working as expect (with no errors)... if it does any, you probably should add #include <avr/io.h> to beginning of your code, this is will declare your CHIP architecture and prevent errors as like 'DDRB' undeclared and same stuff.
#include <avr/io.h>
int main(void)
{
DDRB = 0xFF;
PORTB = 1 << PORTB5;
while (1)
{
}
}
this error can be occurred from corruption of header file in windows so reset your windows by saving all of necessary file & reset your windows & agin install microchip stduio there if you run your programme you should not see this error ... i solved my problem by this i hope it will help you guys
this is my main.c program and there was a build failure due to "struct/union required". I'm using pic 13f877a microcontroller. I'll be really greatful if anyone can tell me the reason for this build failure. also there was another warning saying "36.1 function declared implicit int". what does that mean too?
#include<htc.h>
#define _XTAL_FREQ 4000000
__CONFIG(0X3F39);
void main(){
int a;
TRISB = 0b00010000; //RB4 as Input PIN (ECHO)
TRISC = 0b00000000; //C as Output PINs (LED)
T1CON = 0b00010000; //Initialize Timer Module
while(1){
TMR1H = 0; //Sets the Initial Value of Timer
TMR1L = 0; //Sets the Initial Value of Timer
PORTC = 0b00000000;
PORTB.F0 = 1; //TRIGGER HIGH
Delay_us(10); //10uS Delay
PORTB.F0 = 0; //TRIGGER LOW
while(!PORTB.F4){
T1CON.F0 = 1;
}
while(PORTB.F4){
T1CON.F0 = 0;
}
a = (TMR1L | (TMR1H<<8)); //Reads Timer Value
a = a/58; //Converts Time to Distance
a = a + 1; //Distance Calibration
if(a>=2 && a<=400){
//with in the range
PORTC = 0b11111111;
} else {
//out of range
PORTC = 0b00000000;
}
Delay_ms(400);
}
}
Build C:\Users\user\Desktop\SmartDustbin for device 16F877A
Using driver C:\Program Files (x86)\HI-TECH Software\PICC\9.81\bin\picc.exe
Make: The target "C:\Users\user\Desktop\main.p1" is out of date.
Executing: "C:\Program Files (x86)\HI-TECH Software\PICC\9.81\bin\picc.exe" --pass1 C:\Users\user\Desktop\main.c -q --chip=16F877A -P --runtime=default --opt=default -D__DEBUG=1 -g --asmlist "--errformat=Error [%n] %f; %l.%c %s" "--msgformat=Advisory[%n] %s" "--warnformat=Warning [%n] %f; %l.%c %s"
Error [196] C:\Users\user\Desktop\main.c; 15.10 struct/union required
Warning [361] C:\Users\user\Desktop\main.c; 16.1 function declared implicit int
Error [196] C:\Users\user\Desktop\main.c; 17.10 struct/union required
Error [196] C:\Users\user\Desktop\main.c; 19.16 struct/union required
Error [196] C:\Users\user\Desktop\main.c; 20.10 struct/union required
Error [196] C:\Users\user\Desktop\main.c; 22.15 struct/union required
Error [196] C:\Users\user\Desktop\main.c; 23.10 struct/union required
Warning [361] C:\Users\user\Desktop\main.c; 36.1 function declared implicit int
********** Build failed! **********
You claim to be using MicroC, but the command line in your build output clearly shows you're actually using HI-Tech C 9.81, which is outdated and replaced with Microchip's XC8. HI-Tech C does not allow access to single bits in SFR's asif they were struct members, like MicroC does. You can only access registers as a full byte and need to perform bit manipulation yourself. For example, the line:
PORTB.F0 = 1;
Would need to become:
PORTB |= (1 << 0);
Which is the common way to set a single bit in C. It shifts a 1 bit to the required position and OR's it into the destination byte, not altering other bits. Google for bit manipulation in C if you don't yet understand this.
The function declared implicit int errors stem from the fact that the functions delay_us and delay_ms are not declared. HI-tech C uses the macro's __delay_ms and __delay_us. In addition, you will need to define _XTAL_FREQ with your PIC's operating frequency in Hz prior to using the delay macro's.
Update - Rephrase question:
Since I know what the bug is! How to know when statical allocation fails at compile time in embedded?
Older:
I have this simple and easy to understand code in "C" below running in Atmega328P-AU with 2K SRAM. I use a well behaved UART library( I used many during debugging ) to get debug strings in my PC terminal.
There is a bug in this code: It freezes. All I get is this output...
Hello World - Loading
I should get a '+' for every loop.
Can you explain me why is freezes and why the compiler does not inform me about allocating statically more memory than the uC can get.
In the code there are all the info you may need.
/**************************************************************************************************
Info
**************************************************************************************************/
/*
Device: Atmega328P-AU - No arduino
IDE: Atmel Studio 6.2
Compiler: AVR/GNU C Compiler : 4.8.1
F_CPU: 8000000 Hz defined in makefile
Fuses:
Extended: 0x07
High: 0xD9
Low: 0xE2
Lockbit: 0xFF
When compiled it show in build output these:
text data bss dec hex filename
1088 0 57 1145 479 Bug Catcher.elf
Done executing task "RunCompilerTask".
Task "RunOutputFileVerifyTask"
Program Memory Usage : 1088 bytes 3,3 % Full
Data Memory Usage : 57 bytes 2,8 % Full
Done executing task "RunOutputFileVerifyTask".
Done building target "CoreBuild" in project "Bug Catcher.cproj".
Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').
Target "Build" in file "C:\Program Files\Atmel\Atmel Studio 6.2\Vs\Avr.common.targets" from project "C:\Users\Tedi\Desktop\Bug Catcher\Bug Catcher\Bug Catcher.cproj" (entry point):
Done building target "Build" in project "Bug Catcher.cproj".
Done building project "Bug Catcher.cproj".
Build succeeded.
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
*/
/**************************************************************************************************
Definitions
**************************************************************************************************/
#define BIG_NUMBER 1000
// Atmega328P - Pin 12
#define SOFT_UART_RX_DDR DDRB
#define SOFT_UART_RX_DDR_bit DDB0
#define SOFT_UART_RX_PORT PORTB
#define SOFT_UART_RX_PORT_bit PORTB0
#define SOFT_UART_RX_PIN PINB
#define SOFT_UART_RX_PIN_bit PINB0
// Atmega328P Pin 13
#define SOFT_UART_TX_DDR DDRB
#define SOFT_UART_TX_DDR_bit DDB1
#define SOFT_UART_TX_PORT PORTB
#define SOFT_UART_TX_PORT_bit PORTB1
#define SOFT_UART_TX_PIN PINB
#define SOFT_UART_TX_PIN_bit PINB1
/**************************************************************************************************
Includes
**************************************************************************************************/
#include "softuart.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>
/**************************************************************************************************
Main function
**************************************************************************************************/
int main()
{
/**********************************************************************************************
Setup
**********************************************************************************************/
softuart_init( &SOFT_UART_TX_DDR, SOFT_UART_TX_DDR_bit,
&SOFT_UART_TX_PORT, SOFT_UART_TX_PORT_bit,
&SOFT_UART_RX_DDR, SOFT_UART_RX_DDR_bit,
&SOFT_UART_RX_PIN, SOFT_UART_RX_PIN_bit );
sei();
softuart_puts_P( "\r\n\r\nHello World - Loading\r\n\r\n" ); // Can use custom UART function.
_delay_ms( 200 );
/**********************************************************************************************
Forever loop
**********************************************************************************************/
while(1)
{
char temp[BIG_NUMBER];
memset( temp, '\0', sizeof( temp ) );
{
char temp[BIG_NUMBER];
memset( temp, '\0', sizeof( temp ) );
{
char temp[BIG_NUMBER];
memset( temp, '\0', sizeof( temp ) );
}
}
softuart_puts_P("+"); // BUG!!!!! It never reaches here.
_delay_ms( 500 );
}
}
The linker allocates the static storage, in your case 57 bytes (data plus bss segments). So as long as you have a too big variable with static storage, you should see an error message from the linker.
The variable temp[1000] is an automatic variable, it is allocated at run time on the stack. The RAM that is not statically allocated by the linker is used for the stack. This bug is an easy case, you are allocating a single variable that is bigger than the entire RAM of the device, but normally this kind of error is really really hard to detect. One solution is to check the available stack space at runtime. As a simple rule: don't allocate big stuff on the stack. You will only see it fail when that function is called.
temp[1000] is used for the entire runtime of the program, so you don't loose anything by just moving it into static storage. Put a "static" in front of it and you will (hopefully) see an error message from the linker.