Glowing an LED using GPIO in craneboard - embedded

I'd like to use GPIO to turn on an LED in a craneboard (ARM processor). I'm very new to embedded programming. But, I'm quite good at C. I referred in some websites and learnt about GPIO related commands. I wrote a code, but I'm not quite sure in how to integrate it to the u-boot coding of the craneboard. I don't know where to start. Kindly guide me.
#define LED1 (1 << 6)
int getPinState(int pinNumber);
int main(void)
{
GPIO0_IODIR |= LED1;
GPIO0_IOSET |= LED1;
while (1)
{
GPIO0_IOCLR |= LED1;
}
}
int getPinState(int pinNumber)
{
int pinBlockState = GPIO0_IOPIN;
int pinState = (pinBlockState & (1 << pinNumber)) ? 1 : 0;
return pinState;
}

First of all, learn common bit (also pin in your case) manipulation expressions that you will use A LOT in embedded programming:
/* Set bit to 1 */
GPIO0_IODIR |= LED1; //output
/* Clear bit (set to 0) */
GPIO0_IOSET &= ~LED1; //low
/* Toggle bit */
GPIO0_IOSET ^= LED1;
Your while() loop actually does nothing, except for the first iteration, because the same logical OR operations do no change bit state (see logical table of this op). Also you should add delay, because if pin toggles too fast, LED might look like off all the time. Simple solution would look like:
while(1)
{
GPIO0_IOSET ^= LED1;
sleep(1); //or replace with any other available delay command
}
I do not have source files of U-Boot for Craneboard, so cannot tell you the exact place where to put your code, but basically there are several options: 1) add it in main(), where U-Boot start, thus hanging it (but you still have LED blinking!). 2) implement separate command to switch LED on/off (see command.c and cmd_ prefixed files for examples) 3) Integrate it in serial loop, so pin could be switched while waiting user input 4) build it as an application over U-Boot.
Get used to a lot of reading and documentation, TRM is your friend here (sometimes the only one). Also there are some great guides for embedded starters, just google around. Few to mention:
http://www.microbuilder.eu/Tutorials/LPC2148/GPIO.aspx (basics with examples)
http://beagleboard.org/ (great resource for BeagleBoard, but much applies to CraneBoard as they share the same SoC, includes great community).
http://free-electrons.com/ (more towards embedded Linux and other advanced topics, but some basics can also be found)
http://processors.wiki.ti.com/index.php/CraneBoard (official CraneBoard wiki, probably know this, but just in case)
P.S. Good luck in and don't give up!

If you want to do it in u-boot (and not in Linux), then you have to write an application for u-boot.
$5.12 of u-boot manual explains how to do it.
The source of u-boot provides some examples that you can use.

I'd like to add my answer. The coding that I have done previously was a generalized one. In craneboard, there are certain functions, that does the operation. So, I rewrote it accordingly. I included the file cmd_toggle.c in 'common' directory in the u-boot directory. And added it to the Makefile. The following code will make the LED to blink.
int glow_led(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
int ret,i=0,num=0,ctr=0;
int lpin;
lpin=(int)strtoul(argv[1]);
ret=set_mmc_mux();
if(ret<0)
printf("\n\nLED failed to glow!\n\n");
else{
if(!omap_request_gpio(lpin))
{
omap_set_gpio_direction(lpin,0);
for(i=1;i<21;i++)
{
ctr=0;
if((i%2)==0)
{
num=num-1;
omap_set_gpio_dataout(lpin,num);
}
else
{
num=num+1;
omap_set_gpio_dataout(lpin,num);
}
udelay(3000000);
}
}
}
return 0;
}
U_BOOT_CMD(toggle,2,1,glow_led,"Glow an LED","pin_number");
I could've made this a little simpler by just using a while loop to repeatedly set it as 1 and 0.
This can be executed from the u-boot console as toggle 142, as I have connected the LED to the pin 142.
P.S
Thanks for all your guidance. A special thanks to KBart

Related

Read running processes' virtual memory from mm_struct in linux

I'm trying to write a kernel module that uses the proc file system to read the total memory of each running process. This is for an assignment and it is suggested that use the information of the "mm_struct" which is inside " "task_struct". I should compare the output of content of the proc file with what I obtain from running "ps -ef". I'm using the seq_file API to read from the proc file. My current read function looks like this:
static int proc_show(struct seq_file *m, void *v){
struct task_struct *task;
/*struct mm_struct *mm; Commented this since it's inside task_struct
*struct vm_area_struct *mmap; Commented this since it's inside task_struct */
unsigned long size;
for_each_process(task){
seq_printf(m,"Task = %s PID = %d\n",task->comm,task->pid);
down_read(&task->mm->mmap_sem);
if(task->mm){
size = (task->mm->mmap->vm_end - task->mm->mmap->vm_start );
seq_printf(m," VIRT = %lu\n",size);
}else{
seq_printf(m," VIRT = 0\n");
}
up_read(&task->mm->mmap_sem);
}
return 0;
}
The message "Killed" is promted as soon I try "~# cat proc/my_proc_file". So far what I think I now is that vm_area_struct is inside of mm_struct which is inside task_struct, all of them defined in the include /linux/sched.h.
A similar question, which is the one I partially based this code on, was posted by #confusedkid (see the post Linux Kernel programming: trying to get vm_area_struct->vm_start crashes kernel). However the replies contradict each other and no one actually explains the reasoning behind the code.
Could anyone please point out what the problem might be or suggest any documentation that explains how to access these structure correctly?

Getting GPS to Work on SIM5320A 3G/GPS Module

I have a Adafruit FONA 3G/GPS module (American Version). I have gotten the cellular functionality to work but I am struggling with GPS. I have tried both passive and active antennas.
This is a list of AT commands that are available to the SIM5320A module (pdf). The Adafruit example code uses AT commands that don't run on this SIM module. I send the following sequence:
AT+CGPS=1,1
AT+CGPSINFO
and I am receiving:
+CGPSINFO: ,,,,,,,,
AmpI/AmpQ: 4xx/4xx
What exactly is going wrong? I am connected but am not getting any data out. Also, I understand the mathematical significance of AmpI/AmpQ but what does that mean in terms of connection to GPS network?
First, if you're using the FONATest example from Adafruit, you need to look around line 48. Comment out the line that declares a variable of type Adafruit_FONA and uncomment the line that declares a variable of type Adafruit_FONA_3G.
Also, if you haven't run the FONA_3G setbaud program to set the baud rate to something other than 115,200, you need to run it. (This isn't made very clear by Adafruit, and I thought my board was bad before I found that information.)
Second, unless you bridge the pads labeled bias on the board, you will have to use a passive GPS antenna. The SIMCOM module's GPS is pretty sensitive though. I had a uFL-to-SMA adapter plugged into the board, and stuck a 5-inch jumper wire into the SMA's center pin. The GPS acquired a position within a minute!
I tried the following command: AT+CGPS=1 and then used AT+CGPS? to query the GPS status. It reported +CGPS: 1,1 back to me.
The first few attempts at sending AT+CGPSINFO gave me the same info that you got, i.e. no position.
However, after a few minutes with a wire (or passive antenna), AT+CGPSINFO started returning valid time and position information.
Hope this helps.
UPDATE:
You've asked for code, and I'm happy to oblige. This code is designed to just be a terminal-like relay for serial data between the Arduino (using Tools -> Serial Monitor) and the Fona. So the commands I described above, I just entered by hand. Still, some folks may find it useful.
#include <Adafruit_FONA.h>
#include <SoftwareSerial.h>
#define RX_FROM_FONA 2
#define TX_TO_FONA 3
#define FONA_RST 4
#define FONA_PWR_KEY 5
#define FONA_PWR_STATUS 7
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
SoftwareSerial fonaSerial = SoftwareSerial(TX_TO_FONA, RX_FROM_FONA);
void setup() {
pinMode(FONA_RST, OUTPUT);
pinMode(FONA_PWR_KEY, OUTPUT);
pinMode(FONA_PWR_STATUS, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(FONA_RST, HIGH);
digitalWrite(FONA_PWR_KEY, HIGH);
resetFona();
Serial.begin(115200);
fonaSerial.begin(4800);
}
void resetFona() {
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(FONA_RST, LOW);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(FONA_RST, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, HIGH);
digitalWrite(FONA_PWR_KEY, LOW);
delay(5000);
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(FONA_PWR_KEY, HIGH);
delay(100);
}
char buffer[255];
int crIndex = 0;
int bufferIndex = 0;
int foundCR = 0;
void loop() {
if (Serial.available()) {
buffer[bufferIndex++] = Serial.read();
if (buffer[bufferIndex - 1] == 13) {
crIndex = bufferIndex - 1;
foundCR = 1;
}
}
if (bufferIndex > 255) { bufferIndex = 0; }
while (fonaSerial.available()) { Serial.write(fonaSerial.read()); }
if (foundCR > 0) {
for (int i = 0; i <= crIndex; i++) {
fonaSerial.write(buffer[i]);
}
foundCR = 0;
bufferIndex = 0;
crIndex = 0;
}
}
I don't think this is a software problem, I think you have a hardware problem.
I had this same problem. The sensitivity of the SIM5320A is pretty good, but Adafruit hasn't really followed their design guide in implementing the carrier board, and this hurts its sensitivity.
For example, you can read the application notes for the board here. Check out the PDFs on "SMT Module Design" and "Hardware Design."
First thing you'll notice is SIMCOM recommends a LC tuning network to tune your particular antenna to 50-ohm impedance.
Here is the SIMCOM recommended diagram:
And here is the Adafruit design, with no tuning network anywhere to be found:
Now, if you're going to be using this in your own PCB later, you of course are free to make improvements here yourself.
To test your design, you're going to want to know more about what the module is saying, otherwise you're flying blind. You can read the GPS NMEA sequences and decipher them, but there's a lot to it. Another way is to use the GPS demo tool that SIMCOM support offers. To download this, go to:
ftp://simcom.exavault.com/SIM5320A/GPS tool
username=myd
psd=simcommyd
It will show you how many satellites you're connected to, what signal strength they have, etc. You are going to need at least 3 satellites for a lock (technically you should have 4, but some modules will toss out an impossible triangulation solution with just 3, not sure which the SIM5320A has). You want each satellite to have strengths in the 30+ range.
Here is my Before screenshot, you can see I only had one satellite and hence no lock. This was after giving half an hour after cold start to download the almanac and ephemeris tables (will take about 15min on average from cold start). Satellite 21 (with signal of also 21 strength, coincidentally).
What I did to fix my signal gain was add an LNA (Low Noise Amplifier) in series with my passive antenna. I used the BGA524N6BOARDTOBO1 breakout board, which you can get at DigiKey/Mouser/others, and adds 19dB of gain, and an incredibly-low 0.55dB noise figure.
After hooking up my antenna, and waiting some time, I got a lock!
Hope this helps you and others to use this otherwise great module.

Acoustic Echo Cancellation (AEC) in embedded software

I am doing a VoIP project on embedded device. I have built a sample using a 32bits MCU with a low grade audio codec. Now I found that there is echo issue on my device, that is I can hear what I said from the speaker. I have do some research and found that most appliaction use a DSP codec with acoustic echo cancellation feature. However, is it possible that I do the acoustic echo cancellation in the software, using my 32bits MCU?
Can you adive the algorithm, or even source code:P, for doing acoustic echo cancellation? I know sophisticated method is not possible on a MCU, whereas a simple algorithm is also welcomed.
Thank you
[Follow up] : I have tried some AEC code but they can not work well in my MCU, probably it is the limit of the MCU power. I found that my device become non-real-time when implemented these codes (but a VoIP need a real-time respond). At last I implemented a analog hardware solution by adding an AEC chips, because I do not want to write the code again in another DSP chip.
I had a heck of a time with echo cancellation. I wrote a softphone, and the user can switch their audio input and output devices around to suit their fancy. I tried the Speex echo cancellation library, and several other open source libs I found online. None worked well for me. I tried different speaker/mike configuration and the echo was always there in some form or fashion.
I believe it would be very hard to create AEC code that would work for all possible speaker configurations / room sizes / background noises..etc. Finally I sat down and wrote my own echo cancellation module for my softphone with this algorithm.
It's somewhat crude, but it has worked well and is reliable.
variable1:
Keep a record of what the average amplitude is of when the person to whom you're talking is speaking. (Don't factor quiet-time)
variable2:
Keep a record of what the average amplitude is on the input (mike), but only when there is voice- again- don't factor quiet time.
As soon as there's audio to play- cut the mike. And assuming the person listening is not talking, turn the mike on 150-300ms after the last audible audio frame comes in to be played.
If the audio from the microphones (that you're dropping during playback) is greater than oh- say (variable2 * 1.5), start sending the audio input frames for a specified duration, resetting that duration every time the input amplitude reaches (variable2 * 1.5).
That way the person talking will know they are being interrupted, and stop to see what the person is saying. If the person talking doesn't have too noisy of a background, they will probably hear most if not all of the interruption.
Like I said, not the most graceful, but it doesn't use a lot of resources (CPU, memory) and it actually works pretty darn well. I am very pleased with how mine sounds.
To implement it, I just made a few functions.
On a received audio frame, I call a function I called:
void audioin( AEC *ec, short *frame ) {
unsigned int tas=0; /* Total sum of all audio in frame (absolute value) */
int i=0;
for (;i<160;i++)
tas+=ABS(frame[i]);
tas/=160; /* 320 byte frames muLaw */
if (tas>300) { /* I assume this is audiable */
lockecho(ec);
ec->lastaudibleframe=GetTickCount64();
unlockecho(ec);
}
return;
}
and before sending a frame, I do:
#define ECHO_THRESHOLD 300 /* Time to keep suppression alive after last audible frame */
#define ONE_MINUTE 3000 /* 3000 20ms samples */
#define AVG_PERIOD 250 /* 250 20ms samples */
#define ABS(x) (x>0?x:-x)
char removeecho( AEC *ec, short *aecinput ) {
int tas=0; /* Average absolute amplitude in this signal */
int i=0;
unsigned long long *tot=0;
unsigned int *ctr=0;
unsigned short *avg=0;
char suppressframe=0;
lockecho(ec);
if (ec->lastaudibleframe+ECHO_THRESHOLD > GetTickCount64() ) {
/* If we're still within the threshold for echo (speaker state is ON) */
tot=&ec->t_aiws;
ctr=&ec->c_aiws;
avg=&ec->aiws;
} else {
/* If we're outside the threshold for echo (speaker state is OFF) */
tot=&ec->t_aiwos;
ctr=&ec->c_aiwos;
avg=&ec->aiwos;
}
for (;i<160;i++) {
tas+=ABS(aecinput[i]);
}
tas/=160;
if (tas>200) {
(*tot)+=tas;
(*avg)=(unsigned short)((*tot)/( (*ctr)?(*ctr):1));
(*ctr)++;
if ((*ctr)>AVG_PERIOD) {
(*tot)=(*avg);
(*ctr)=0;
}
}
if ( (avg==&ec->aiws) ) {
tas-=ec->aiwos;
if (tas<0) {
tas=0;
}
if ( ((unsigned short) tas > (ec->aiws*1.5)) && ((unsigned short)tas>=ec->aiwos) && (ec->aiwos!=0) ) {
suppressframe=0;
} else {
suppressframe=1;
}
}
if (suppressframe) { /* Silence frame */
memset(aecinput, 0, 320);
}
unlockecho(ec);
return suppressframe;
}
Which will silence the frame if it needs to. I keep all my variables, like the timers, and amplitude averages in the AEC struct, which I return from a call to
AEC *initecho( void ) {
AEC *ec=0;
ec=(AEC *)malloc(sizeof(AEC));
memset(ec, 0, sizeof(AEC));
ec->aiws=200; /* Just a default guess as to what the average amplitude would be */
return ec;
}
typedef struct aec {
unsigned long long lastaudibleframe; /* time stamp of last audible frame */
unsigned short aiws; /* Average mike input when speaker is playing */
unsigned short aiwos; /*Average mike input when speaker ISNT playing */
unsigned long long t_aiws, t_aiwos; /* Internal running total (sum of PCM) */
unsigned int c_aiws, c_aiwos; /* Internal counters for number of frames for averaging */
unsigned long lockthreadid; /* Thread ID with lock */
int stlc; /* Same thread lock-count */
} AEC;
You can adapt as you need to and play with the idea, but like I said. It actually sounds pretty dang good. The only problem I have is if they have a lot of background noise. But for me, if they pick up their USB handset or are using a headset, they can turn echo cancellation off, and not worry about it...but though PC speakers with a mike...I'm pretty happy with it.
I hope it helps, or gives you something to build on...
If you are doing a commercial project that this should be easy. You can integrate a commercial audio cancellation software in your VoIP application.

Input setting using Registers

I have a simple c program for printing n Fibonacci numbers and I would like to compile it to ELF object file. Instead of setting the number of fibonacci numbers (n) directly in my c code, I would like to set them in the registers since I am simulating it for an ARM processor.How can I do that?
Here is the code snippet
#include <stdio.h>
#include <stdlib.h>
#define ITERATIONS 3
static float fib(float i) {
return (i>1) ? fib(i-1) + fib(i-2) : i;
}
int main(int argc, char **argv) {
float i;
printf("starting...\n");
for(i=0; i<ITERATIONS; i++) {
printf("fib(%f) = %f\n", i, fib(i));
}
printf("finishing...\n");
return 0;
}
I would like to set the ITERATIONS counter in my Registers rather than in the code.
Thanks in advance
The register keyword can be used to suggest to the compiler that it uses a registers for the iterator and the number of iterations:
register float i;
register int numIterations = ITERATIONS;
but that will not help much. First of all, the compiler may or may not use your suggestion. Next, values will still need to be placed on the stack for the call to fib(), and, finally, depending on what functions you call within your loop, code in the procedure are calling could save your register contents in the stack frame at procedure entry, and restore them as part of the code implementing the procedure return.
If you really need to make every instruction count, then you will need to write machine code (using an assembly language). That way, you have direct control over your register usage. Assembly language programming is not for the faint of heart. Assembly language development is several times slower than using higher level languages, your risk of inserting bugs is greater, and they are much more difficult to track down. High level languages were developed for a reason, and the C language was developed to help write Unix. The minicomputers that ran the first Unix systems were extremely slow, but the reason C was used instead of assembly was that even then, it was more important to have code that took less time to code, had fewer bugs, and was easier to debug than assembler.
If you want to try this, here are the answers to a previous question on stackoverflow about resources for ARM programming that might be helpful.
One tactic you might take is to isolate your performance-critical code into a procedure, write the procedure in C, the capture the generated assembly language representation. Then rewrite the assembler to be more efficient. Test thoroughly, and get at least one other set of eyeballs to look the resulting code over.
Good Luck!
Make ITERATIONS a variable rather than a literal constant, then you can set its value directly in your debugger/simulator's watch or locals window just before the loop executes.
Alternatively as it appears you have stdio support, why not just accept the value via console input?

How do I implement a bit array in C / Objective C

iOS / Objective-C: I have a large array of boolean values.
This is an inefficient way to store these values – at least eight bits are used for each element when only one is needed.
How can I optimise?
see CFMutableBitVector/CFBitVector for a CFType option
Try this:
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op ((size_t)1<<((size_t)(b)%(8*sizeof *(a)))))
Then for any array of unsigned integer elements no larger than size_t, the BITOP macro can access the array as a bit array. For example:
unsigned char array[16] = {0};
BITOP(array, 40, |=); /* sets bit 40 */
BITOP(array, 41, ^=); /* toggles bit 41 */
if (BITOP(array, 42, &)) return 0; /* tests bit 42 */
BITOP(array, 43, &=~); /* clears bit 43 */
etc.
You use the bitwise logical operations and bit-shifting. (A Google search for these terms might give you some examples.)
Basically you declare an integer type (including int, char, etc.), then you "shift" integer values to the bit you want, then you do an OR or an AND with the integer.
Some quick illustrative examples (in C++):
inline bool bit_is_on(int bit_array, int bit_number)
{
return ((bit_array) & (1 << bit_number)) ? true : false;
}
inline void set_bit(int &bit_array, int bit_number)
{
bit_array |= (1 << bit_number);
}
inline void clear_bit(int &bit_array, int bit_number)
{
bit_array &= ~(1 << bit_number);
}
Note that this provides "bit arrays" of constant size (sizeof(int) * 8 bits). Maybe that's OK for you, or maybe you will want to build something on top of this. (Or re-use whatever some library provides.)
This will use less memory than bool arrays... HOWEVER... The code the compiler generates to access these bits will be larger and slower. So unless you have a large number of objects that need to contain these bit arrays, it might have a net-negative impact on both speed and memory usage.
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
will not work ...
Fix:
#define BITOP(a,b,op) \
((a)[(size_t)(b)/(8*sizeof *(a))] op ((size_t)1<<((size_t)(b)%(8*sizeof *(a)))))
I came across this question as I am writing a bit array framework that is intent to manage large amounts of 'bits' similar to Java BitSet. I was looking to see if the name I decided on was in conflict with other Objective-C frameworks.
Anyway, I'm just starting this and am deciding whether to post it on SourceForge or other open source hosting sites.
Let me know if you are interested
Edit: I've created the project, called BitArray, on SourceForge. The source is in the SF SVN repository and I've also uploaded a compiled framework. This LINK will get your there.
Frank