Archive for the ‘Programming’ Category

FreeRTOS port for XMOS XS1 processors

Monday, February 22nd, 2010

I have ported FreeRTOS to the XMOS architecture.

The project can be downloaded from the project page on the XCore website. This page will always hold the newest release of the port.

A mirror for the current release can be found here.

The danger of typo’s in a switch statement in C

Tuesday, December 1st, 2009

A typo in a case label or default label inside a switch statement can result into normal labels without the compiler complaining. This can introduce serious and hard to find bugs. This will happen in the following two situations:

1. The space in case<space><number>: is forgotten.
2. Any typo in the default: label.

Consider the following code:

/* A typo in the case labels or default label in a switch statement
 * can result into a normal label in the following situations:
 *  
 * 1. The space in case<space><number>: is forgotten.
 * 2. Any typo in the default: label.
 *  
 * What mostly happens is that the statements under the wrongly typed case label
 * will be part of statements under the case label above. These statements
 * usually end with the break statement and thus the statements under the wrongly
 * typed case label will never be executed.
 * 
 * Author: Bianco Zandbergen, november 2009      
 */  
#include <stdio.h>
 
int main(void)
{
    int i = 0;
    int t1 = 0;
    int t2 = 0;
 
    switch(i) {
        case 1:
            printf("Case 1\n");
            break;
        case2: /* A typo in 'case 2:' results into a normal label */
            printf("case2\n");
            break;
        defaultt: /* A typo in 'default:' results into a normal label */
            printf("defaultt\n");
    }
 
    /* lets test if we can jump to these labels */
    if (t1 == 0) {
        t1++; /* avoid looping */
        goto case2;
    }
 
    if (t2 == 0) {
        t2++; /* avoid looping */
        goto defaultt;
    }
 
    return 0;
}

While it is correct that the compiler does not complain (a label can be put anywhere), i think it would be wise if the compiler generates a warning when using the default options.

Output of gcc 4.3.4 on GNU/Linux with the code above:

bianco@box ~/temp/label $ gcc -o label label.c
bianco@box ~/temp/label $

Output of Borland C++ compiler 5.5.1 on Windows with the code above:

C:\dev\C\labels>bcc32 label.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
label.c:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
C:\dev\C\labels>

Binary macro for C

Thursday, August 21st, 2008

Found a usefull macro to use binary numbers in C:

#define B8__(x) ((x & 0x0000000FLU) ?   1 : 0) \
              + ((x & 0x000000F0LU) ?   2 : 0) \
              + ((x & 0x00000F00LU) ?   4 : 0) \
              + ((x & 0x0000F000LU) ?   8 : 0) \
              + ((x & 0x000F0000LU) ?  16 : 0) \
              + ((x & 0x00F00000LU) ?  32 : 0) \
              + ((x & 0x0F000000LU) ?  64 : 0) \
              + ((x & 0xF0000000LU) ? 128 : 0)
 
#define B8(d) ((unsigned char) B8__(HEX__(d)))
 
// use it
B8(10101010)

Blackfin BF533: Core and System clock

Tuesday, February 5th, 2008
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void init_PLL(void)
{
	short tmp;
 
	*pSIC_IWR=0x01; // only PLL wakeup
	ssync();
 
	*pPLL_DIV = 0x001B; //cclk=vco/1;sclk=vco/11
	ssync();
 
	tmp = cli();
 
	*pPLL_CTL=(12<<9); //vco=12*clkin, clkin=27M
	ssync();
 
	idle();
	sti(tmp);
}

Blackfin BF533: Programmable flags with interrupts example

Tuesday, February 5th, 2008
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/*
	This example shows how to use 
	interrupts with programmable flags.
	PF8 will be used. When PF8 goes from low to high
	there will be an interrupt.	
*/
 
#include<stdio.h>
#include<cdefbf533.h>
#include<sys\exception.h> // needed for interrupts
 
// prototype
EX_INTERRUPT_HANDLER(FlagA_ISR);
 
void main(void)
{
 
	// Register FlagA ISR to interrupt vector group 12
	register_handler(ik_ivg12, FlagA_ISR);
 
	// set direction of programmable flag PF8 to input
	*pFIO_DIR &= ~PF8;
	ssync();
 
	// interrupt enable PF8
	*pFIO_INEN |= PF8;
	ssync();	
 
	// give interrupt when FIO_FLAG_D PF8 changes
	*pFIO_MASKA_D |= PF8;
	ssync();
 
 
	// Bind FlagA interrupt to IVG12
	*pSIC_IAR2 |= 0x00005000; // flag A IVG12
	ssync();
 
 
	// Enable PFA in system interrupt mask register
	*pSIC_IMASK = 0x00080000;
	ssync();
 
	// enable IVG12 in core interrupt mask register
	*pIMASK |= 0x00001000;
	ssync();
 
	// wait for interrupt
	while(1);
}
 
EX_INTERRUPT_HANDLER(FlagA_ISR)
{	
	printf("\n interrupt received!");
	fflush(stdout);
 
	// or do something else...
}

Blackfin BF533: Programmable Flags example

Tuesday, February 5th, 2008

There are 5 important registers for the Programmable Flags:

FIO_DIR: I/O direction
FIO_FLAG_D: Direct access to data of the programmable flags
FIO_FLAG_S: Write 1 to set flags
FIO_FLAG_C: Write 1 to clear flags
FIO_FLAG_T: Write 1 to toggle flags

With the last three registers it is not needed anymore use bitwise functions for setting, clearing and toggling flags :)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
	This example shows how to use programmable flags of the BF533.
	The BF533 has 16 programmable flags (GPIO).
	This program toggles all flags.	
*/
 
#include <cdefBF533.h>
 
int main(void)
{
 
	int delay;
 
	// set direction of all flags to output
	*pFIO_DIR = 0xFFFF;
	ssync();
 
	// directly access data register
	// set all flags to high
	*pFIO_FLAG_D = 0xFFFF;
	ssync();	
 
	while (1) {
 
		// set all flags to high
		*pFIO_FLAG_S = 0xFFFF;
		ssync();
 
		for (delay = 0x00FFFFFF; delay>0; delay--); 
 
		// clear all flags (set to low)
		*pFIO_FLAG_C = 0xFFFF;
		ssync();
 
		for (delay = 0x00FFFFFF; delay>0; delay--);
 
		// FIO_FLAG_T register can also be used to toggle here!		
	}	
 
	// never reached
	//return 0;
}

Blackfin BF533: ADSP-BF533 EZKIT LITE LED’s example

Tuesday, February 5th, 2008
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*
	This example shows how to use the 6 LED's 
	on the ADSP-BF533 EZ-KIT LITE.
	The LED's are connected on the Flash A chip instead of GPIO.
	This program will toggle the LED's
*/
 
 
#include <cdefBF533.h>
#include <stdio.h>
 
// addresses in Flash for the LED's
#define pFlashA_PortB_Dir	(volatile unsigned char *)0x20270007
#define pFlashA_PortB_Data	(volatile unsigned char *)0x20270005
 
int main(void)
{
 
	printf("Showing how the leds work on the BF533 EZ-KIT Lite");
	fflush(stdout);
 
	// External Bus Interface Unit setup, for access to flash A
	// It is not important to understand this
	*pEBIU_AMBCTL0	= 0x7bb07bb0;
	*pEBIU_AMBCTL1	= 0x7bb07bb0;
	*pEBIU_AMGCTL	= 0x000f;
 
	// flash data direction, b 111111
	*pFlashA_PortB_Dir = 0x3f;
 
	unsigned int delay = 0;
 
	while (1) {
 
		*pFlashA_PortB_Data = 0x15;	// b 010101
		ssync();
 
		// wait some time
		for (delay = 0x00FFFFFF; delay > 0; delay--);
 
		*pFlashA_PortB_Data = 0x2A;	// b 101010	
		ssync();
 
		// wait some time
		for (delay = 0x00FFFFFF; delay > 0; delay--);
	}
 
 
	// never reached
	//return 0;
 
}

Compiled with VisualDSP++ 5.0

Circular buffer queue in C

Tuesday, February 5th, 2008
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/* CIRCULAR BUFFER QUEUE */
 
#include <stdio.h>
 
#define BUFFER_SIZE 8
 
int data_size = 0;      // number of chars in buffer
int read_pointer = 0;   // indice number of last read char
int write_pointer = 0;  // indice number of last written char
int input;              // user input 
char add;               // char to add
 
char buffer[BUFFER_SIZE];
 
// prototypes
int buffer_full(void);
int buffer_empty(void);
void push_char(char c);
void pull_char(void);
 
int main(void)
{
 
  int i; 
 
  printf("Circular Buffer Queue Implementation");  
 
  // make sure there are no random chars in array, all spaces
  for (i = 0; i < BUFFER_SIZE; i++) buffer[i] = 0x20;
 
  while (input != 4) {
 
    printf("\n    press 1 to push char");
    printf("\n    press 2 to pop char");
    printf("\n    press 3 to show queue");
    printf("\n    press 4 to exit\n");
    scanf("%d", &input);
 
    // push char
    if (input == 1) {
 
      printf("\nEnter char: ");
      scanf("%c", &add);
      scanf("%c", &add); // twice otherwise it will get the last enter as input
 
      if (! buffer_full())
        push_char(add);
      else
        printf("\nBUFFER IS FULL!");      
 
    }
    // pull char
    else if (input == 2) {
 
      if (! buffer_empty())
        pull_char();
      else
        printf("\nBUFFER IS EMPTY!");      
    }
    // display buffer info
    else if (input == 3) {
 
      printf("\n data_size: %d read_pointer: %d write_counter: %d", 
      data_size, read_pointer, write_pointer);
 
      printf("\nQueue content:\n");
      for (i = 0; i < BUFFER_SIZE; i++) printf("[%c]", buffer[i]);
 
    }
 
    printf("\n----");       
  } 
 
  return 0;
}
 
// adds a char
void push_char(char c)
{
    // increase write_pointer, check if at end of array
    if (++write_pointer >= BUFFER_SIZE) write_pointer = 0;
 
    buffer[write_pointer] = c;    
    data_size++;
}
 
// returns 1 if buffer is full, 0 if buffer is not full
int buffer_full(void) 
{
	return read_pointer == write_pointer &&
	 		data_size == BUFFER_SIZE;
}
// returns 1 if buffer is empty, 0 if buffer is not empty
int buffer_empty(void)
{
	return read_pointer == write_pointer && 
			data_size == 0;
}
 
// pull char from queue
void pull_char(void) 
{  
  if (++read_pointer >= BUFFER_SIZE) read_pointer = 0;
 
  printf("\nPopped char %c", buffer[read_pointer]);
 
  // enter space on place of read char so we can see it is removed
  buffer[read_pointer] = 0x20; 
  data_size--;  
}