Сравнение микроконтроллеров семейства MSP430 с конкурентоспособными микроконтроллерами
Резюме
В данном примере применения приведены результаты сравнения микроконтроллеров семейства MSP430 с микроконтроллерами других производителей. Для разработки кода различных простейших операций и выполнения его в режиме симулятора была использована платформа разработчика Embedded Workbench™ компании IAR Systems. Для выяснения различных параметров микроконтроллеров эти различные часто используемые приложения были выполнены на каждом микроконтроллере. Для всех рассмотренных применений были посчитаны суммарные размер кода программы и количество командных циклов, требуемых для выполнения. На рисунке 1 и рисунке 2 приведены диаграммы сравнения размеров кодов программ и количество командных циклов для каждого исследованного микроконтроллера.
Рисунок 1. Диаграмма сравнения суммарных размера кодов программ
Рисунок 2. Диаграмма сравнения суммарного количества командных циклов
В таблице 1 приведены коэффициенты деления частоты задающего генератора для формирования сигналов синхронизации вычислительного ядра исследованных микроконтроллеров. Полное время выполнения любого кода можно рассчитать как произведение количества командных циклов и коэффициента деления.
Таблица 1. Коэффициенты деления частоты задающего генератора для формирования сигналов синхронизации вычислительного ядра
Микроконтроллер |
Коэффициент деления |
MSP430F135 |
1 |
ATmega8 |
1 |
PIC18F242 |
4 |
8051 |
12 |
H8/300L |
2 |
MC68HC11 |
4 |
В таблице 2 показаны суммарные размер кода и количество командных циклов, приведенные к соответствующим суммарным размеру кода и количеству циклов микроконтроллера MSP430.
Таблица. 2. Приведенные результаты
Микроконтроллер |
Приведенный суммарный размер кода |
Приведенное суммарное количество командных циклов |
MSP430F135 |
1.00 |
1.00 |
ATmega8 |
1.82 |
1.26 |
PIC18F242 |
3.31 |
1.98 |
8051 |
2.45 |
1.58 |
H8/300L |
2.45 |
1.78 |
MC68HC11 |
2.36 |
3.76 |
Таблица 3 содержит размеры кодов программ (в байтах) и количества командных циклов исследованных прикладных программ для каждого микроконтроллера.
Таблица 3. Размер кодов и количество командных циклов
Применение |
MSP430F135 |
ATmega8 |
PIC18F242 |
8051 |
H8/300L |
MC68HC11 |
байт циклов |
8- битная математика |
172 299 |
116 157 |
386 318 |
141 112 |
354 680 |
285 387 |
8- битный коммутатор |
180 50 |
342 131 |
404 109 |
209 84 |
362 388 |
387 214 |
16- битная математика |
172 343 |
174 319 |
598 625 |
361 426 |
564 802 |
315 508 |
16- битная матрица |
156 5784 |
570 24426 |
846 27021 |
825 29468 |
450 15280 |
490 23164 |
16- битный коммутатор |
178 49 |
388 144 |
572 163 |
326 120 |
404 398 |
405 230 |
32- битная математика |
250 792 |
316 782 |
960 1818 |
723 2937 |
876 1756 |
962 1446 |
Операции с плавающей точкой |
662 1207 |
1042 1601 |
1778 1599 |
1420 2487 |
1450 2458 |
1429 4664 |
Фильтр с КИХ |
668 152193 |
1292 164793 |
2146 248655 |
1915 206806 |
1588 245588 |
1470 567139 |
Перемножение матриц |
252 6633 |
510 16027 |
936 36190 |
345 9454 |
462 26750 |
499 26874 |
Итого |
2808 170249 |
5114 213680 |
9302 336543 |
6880 269638 |
6866 303198 |
6622 640038 |
Влияние аппаратного умножителя и полной оптимизации компилятора
Для того, чтобы показать влияние аппаратного умножителя и полной оптимизации компилятора MSP430, было произведено сравнение кодов применений для MSP430F135 и MSP430F149. MSP430F149 содержит аппаратный умножитель, а MSP430F135 - нет. Для создания и выполнения исследуемых приложений был использован последний С компилятор версии 3.10A компании IAR для микроконтроллеров семейства MSP430. В таблице 4 приведены результаты тестов.
Таблица 4. Влияние аппаратного умножителя и полной оптимизации компилятора
Применение |
MSP430F135 Оптимизация: нет Аппаратный умножитель: нет |
MSP430F149 Оптимизация: нет Аппаратный умножитель: да |
MSP430F149 Оптимизация: полная Аппаратный умножитель: да |
байт циклов |
8- битная математика |
172 299 |
156 268 |
136 249 |
8- битная 2 Dim матрица |
118 2899 |
118 2899 |
124 1110 |
8- битный выборочный коммутатор |
180 50 |
180 50 |
178 49 |
16- битная математика |
172 343 |
156 268 |
134 248 |
16- битная 2 Dim матрица |
156 5784 |
156 5784 |
112 1174 |
16- битный выборочный коммутатор |
178 49 |
178 49 |
176 48 |
32- битная математика |
250 792 |
248 607 |
222 583 |
Операции с плавающей точкой |
662 1207 |
702 1012 |
678 993 |
Фильтр с КИХ |
688 152193 |
728 143694 |
732 137161 |
Перемножение матриц |
252 6633 |
236 5399 |
166 2847 |
Итого |
2828 170249 |
2858 160030 |
2658 144462 |
Приложение
Тестовые прикладные задачи
Для сравнения параметров различных микроконтроллеров для каждого из них в режиме симуляции были выполнены приведенные ниже тестовые прикладные задачи. Исходные тексты программ этих прикладных задач приведен ниже.
8-bit_math.c - исходный файл, содержащий три математических функции. Одна функция выполняет сложение двух 8- битных чисел, одна выполняет умножение и одна - деление. Вызов этих функций осуществляется из функции "main()".
16-bit_math.c - исходный файл, содержащий три математических функции. Одна функция выполняет сложение двух 16- битных чисел, одна выполняет умножение и одна - деление. Вызов этих функций осуществляется из функции "main()".
32-bit_math.c - исходный файл, содержащий три математических функции. Одна функция выполняет сложение двух 32- битных чисел, одна выполняет умножение и одна - деление. Вызов этих функций осуществляется из функции "main()".
floating_point_math.c - исходный файл, содержащий три математических функции. Одна функция выполняет сложение двух чисел с плавающей запятой, одна выполняет умножение и одна - деление. Вызов этих функций осуществляется из функции "main()".
8-bit_switch_case.c - исходный файл с одной функцией, содержащей инструкцию коммутатора, имеющего 16 вариантов выбора. В зависимости от 8- битного значения выбирается один из вариантов выбора. Функция "main()" вызывает функцию "switch" с выбранным входным параметром.
16-bit_switch_case.c - исходный файл с одной функцией, содержащей инструкцию коммутатора, имеющего 16 вариантов выбора. В зависимости от 16- битного значения выбирается один из вариантов выбора. Функция "main()" вызывает функцию "switch" с выбранным входным параметром.
8-bit_2-dim_matrix.c - исходный файл, содержащий 3 двумерных массива 8- битных значений, один из которых инициализирован. Функция "main()" копирует первый массив во второй, а потом второй - в третий.
16-bit_2-dim_matrix.c - исходный файл, содержащий 3 двумерных массива 16- битных значений, один из которых инициализирован. Функция "main()" копирует первый массив во второй, а потом второй - в третий.
fir_filter.c - исходный файл, содержащий код, который вычисляет ответ на выходе фильтра 17- ого от имитированного входного воздействия АЦП.
matrix_multiplication.c - исходный файл, содержащий код, который перемножает матрицу 3x4 и матрицу 4x5.
Компилятор
Для формирования тестовых прикладных задач использовался "С" компилятор, встроенный в интегрированную среду разработки (IDE) Embedded Workbench компании IAR Systems. Демонстрационные версии IDE для всех микроконтроллеров были получены на сайте компании IAR Systems по адресу http://www.iar.com. В таблице 5 приведены версии программы, использованные для разработки прикладных задач для каждого конкретного микроконтроллера. Для каждого прикладного решения был посчитан размер программы. Все прикладные задачи были сформированы при установленном значении оптимизатора компилятора "none". Это было сделано для того, чтобы исключить влияние оптимизатора компилятора на результаты тестов. Например, при включенном оптимизаторе компилятор для микроконтроллеров семейства 8051 был способен вычислить результаты для некоторых математических функций во время компиляции. Алгоритм оптимизации был настолько сложен, что способен был определить, что входные значения математических не изменяются. Это позволило компилятору вычислить математическую функцию и заменить ее результатом вычисления.
Все прикладные задачи были выполнены в режиме симуляции. При этом регистрировалось количество команд, требуемых для выполнения каждой прикладной задачи.
Таблица 5. Использованные версии "С" компилятора
Микроконтроллер |
Версия "С" компилятора компании IAR |
MSP430F135 |
2.21B |
Atmel ATmega8 |
3.10C |
Microchip PIC18F242 |
6.10A |
Generic 8051 |
2.12A |
Renesas H8/300L |
4.20A |
Motorola MC68HC11 |
4.45A |
Исходные тексты тестовых прикладных задач
Ниже приведены исходные тексты на "С" тестовых прикладных задач, использованных для тестирования, описанного в данном документе.
8-bit Math.c
/*******************************************************************************
*
* Имя: 8-bit Math
* Назначение: тестовая прикладная задача 8- битных математических функций.
*
*******************************************************************************/
typedef unsigned char UInt8;
UInt8 add(UInt8 a, UInt8 b)
{
return (a + b);
}
UInt8 mul(UInt8 a, UInt8 b)
{
return (a * b);
}
UInt8 div(UInt8 a, UInt8 b)
{
return (a / b);
}
void main(void)
{
volatile UInt8 result[4];
result[0] = 12;
result[1] = 3;
result[2] = add(result[0], result[1]);
result[1] = mul(result[0], result[2]);
result[3] = div(result[1], result[2]);
return;
}
8-bit 2-dim Matrix.c
/*******************************************************************************
*
* Имя: 8-bit 2-dim Matrix
* Назначение: тестовая прикладная программа копирования 8- битных значений.
*
*******************************************************************************/
typedef unsigned char UInt8;
const UInt8 m1[16][4] = {
{0x12, 0x56, 0x90, 0x34},
{0x78, 0x12, 0x56, 0x90},
{0x34, 0x78, 0x12, 0x56},
{0x90, 0x34, 0x78, 0x12},
{0x12, 0x56, 0x90, 0x34},
{0x78, 0x12, 0x56, 0x90},
{0x34, 0x78, 0x12, 0x56},
{0x90, 0x34, 0x78, 0x12},
{0x12, 0x56, 0x90, 0x34},
{0x78, 0x12, 0x56, 0x90},
{0x34, 0x78, 0x12, 0x56},
{0x90, 0x34, 0x78, 0x12},
{0x12, 0x56, 0x90, 0x34},
{0x78, 0x12, 0x56, 0x90},
{0x34, 0x78, 0x12, 0x56},
{0x90, 0x34, 0x78, 0x12}
};
void main (void)
{
int i, j;
volatile UInt8 m2[16][4], m3[16][4];
for(i = 0; i < 16; i++)
{
for(j=0; j < 4; j++)
{
m2[i][j] = m1[i][j];
m3[i][j] = m2[i][j];
}
}
return;
}
8-bit Switch Case.c
/*******************************************************************************
*
* Имя: 8-bit Switch Case
* Назначение: Тестовая прикладная задача, осуществляющая коммутацию по
* полученному 8- битному значению.
*
*******************************************************************************/
typedef unsigned char UInt8;
UInt8 switch_case(UInt8 a)
{
UInt8 output;
switch (a)
{
case 0x01:
output = 0x01;
break;
case 0x02:
output = 0x02;
break;
case 0x03:
output = 0x03;
break;
case 0x04:
output = 0x04;
break;
case 0x05:
output = 0x05;
break;
case 0x06:
output = 0x06;
break;
case 0x07:
output = 0x07;
break;
case 0x08:
output = 0x08;
break;
case 0x09:
output = 0x09;
break;
case 0x0a:
output = 0x0a;
break;
case 0x0b:
output = 0x0b;
break;
case 0x0c:
output = 0x0c;
break;
case 0x0d:
output = 0x0d;
break;
case 0x0e:
output = 0x0e;
break;
case 0x0f:
output = 0x0f;
break;
case 0x10:
output = 0x10;
break;
} /* конец коммутации*/
return (output);
}
void main(void)
{
volatile UInt8 result;
result = switch_case(0x10);
return;
}
16-bit Math.c
/*******************************************************************************
*
* Имя: 16-bit Math
* Назначение: Тестовая прикладная задача, осуществляющая вычисление
* 16- битных математических функций.
*
*******************************************************************************/
typedef unsigned short UInt16;
UInt16 add(UInt16 a, UInt16 b)
{
return (a + b);
}
UInt16 mul(UInt16 a, UInt16 b)
{
return (a * b);
}
UInt16 div(UInt16 a, UInt16 b)
{
return (a / b);
}
void main(void)
{
volatile UInt16 result[4];
result[0] = 231;
result[1] = 12;
result[2] = add(result[0], result[1]);
result[1] = mul(result[0], result[2]);
result[3] = div(result[1], result[2]);
return;
}
16-bit 2-dim Matrix.c
/*******************************************************************************
*
* Имя: 16-bit 2-dim Matrix
* Назначение: Тестовая прикладная задача копирования 16- битных значений.
*
*******************************************************************************/
typedef unsigned short UInt16;
const UInt16 m1[16][4] = {
{0x1234, 0x5678, 0x9012, 0x3456},
{0x7890, 0x1234, 0x5678, 0x9012},
{0x3456, 0x7890, 0x1234, 0x5678},
{0x9012, 0x3456, 0x7890, 0x1234},
{0x1234, 0x5678, 0x9012, 0x3456},
{0x7890, 0x1234, 0x5678, 0x9012},
{0x3456, 0x7890, 0x1234, 0x5678},
{0x9012, 0x3456, 0x7890, 0x1234},
{0x1234, 0x5678, 0x9012, 0x3456},
{0x7890, 0x1234, 0x5678, 0x9012},
{0x3456, 0x7890, 0x1234, 0x5678},
{0x9012, 0x3456, 0x7890, 0x1234},
{0x1234, 0x5678, 0x9012, 0x3456},
{0x7890, 0x1234, 0x5678, 0x9012},
{0x3456, 0x7890, 0x1234, 0x5678},
{0x9012, 0x3456, 0x7890, 0x1234}
};
void main(void)
{
int i, j;
volatile UInt16 m2[16][4], m3[16][4];
for(i = 0; i < 16; i++)
{
for(j = 0; j < 4; j++)
{
m2[i][j] = m1[i][j];
m3[i][j] = m2[i][j];
}
}
return;
}
16-bit Switch Case.c
/*******************************************************************************
*
* Имя: 16-bit Switch Case
* Назначение: Тестовая прикладная задача, осуществляющая коммутацию
* по полученному 16- битному значению.
*
*******************************************************************************/
typedef unsigned short UInt16;
UInt16 switch_case(UInt16 a)
{
UInt16 output;
switch (a)
{
case 0x0001:
output = 0x0001;
break;
case 0x0002:
output = 0x0002;
break;
case 0x0003:
output = 0x0003;
break;
case 0x0004:
output = 0x0004;
break;
case 0x0005:
output = 0x0005;
break;
case 0x0006:
output = 0x0006;
break;
case 0x0007:
output = 0x0007;
break;
case 0x0008:
output = 0x0008;
break;
case 0x0009:
output = 0x0009;
break;
case 0x000a:
output = 0x000a;
break;
case 0x000b:
output = 0x000b;
break;
case 0x000c:
output = 0x000c;
break;
case 0x000d:
output = 0x000d;
break;
case 0x000e:
output = 0x000e;
break;
case 0x000f:
output = 0x000f;
break;
case 0x0010:
output = 0x0010;
break;
} /* конец коммутации*/
return (output);
}
void main(void)
{
volatile UInt16 result;
result = switch_case(0x0010);
return;
}
32-bit Math.c
/*******************************************************************************
*
* Имя: 32-bit Math
* Назначение: Тестовая прикладная задача вычисления
* 32- битных математических функций.
*
*******************************************************************************/
#include
typedef unsigned long UInt32;
UInt32 add(UInt32 a, UInt32 b)
{
return (a + b);
}
UInt32 mul(UInt32 a, UInt32 b)
{
return (a * b);
}
UInt32 div(UInt32 a, UInt32 b)
{
return (a / b);
}
void main(void)
{
volatile UInt32 result[4];
result[0] = 43125;
result[1] = 14567;
result[2] = add(result[0], result[1]);
result[1] = mul(result[0], result[2]);
result[3] = div(result[1], result[2]);
return;
}
Floating-point Math.c
/*******************************************************************************
*
* Имя : Floating-point Math
* Назначение: Тестовая прикладная задача выполнения математических функций с плавающей запятой.
*
*******************************************************************************/
float add(float a, float b)
{
return (a + b);
}
float mul(float a, float b)
{
return (a * b);
}
float div(float a, float b)
{
return (a / b);
}
void main(void)
{
volatile float result[4];
result[0] = 54.567;
result[1] = 14346.67;
result[2] = add(result[0], result[1]);
result[1] = mul(result[0], result[2]);
result[3] = div(result[1], result[2]);
return;
}
FIR Filter.c
/*******************************************************************************
*
* Имя : FIR Filter
* Назначение: Тестовая прикладная задача фильтра с КИХ. Входным значением для
* фильтра является массив из 51 16-битного значения. Фильтр имеет 17-ый порядок
*
*******************************************************************************/
#ifdef MSP430
#include "msp430x13x.h"
#endif
#include
#define FIR_LENGTH 17
const float COEFF[FIR_LENGTH] =
{
-0.000091552734,
0.000305175781,
0.004608154297,
0.003356933594,
-0.025939941406,
-0.044006347656,
0.063079833984,
0.290313720703,
0.416748046875,
0.290313720703,
0.063079833984,
-0.044006347656,
-0.025939941406,
0.003356933594,
0.004608154297,
0.000305175781,
-0.000091552734
};
/* Текущий массив симулирует входные значения от АЦП */
const unsigned int INPUT[] =
{
0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000,
0x2400, 0x2000, 0x1C00, 0x1800, 0x1400, 0x1000, 0x0C00, 0x0800,
0x0400, 0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800, 0x1C00,
0x2000, 0x2400, 0x2000, 0x1C00, 0x1800, 0x1400, 0x1000, 0x0C00,
0x0800, 0x0400, 0x0400, 0x0800, 0x0C00, 0x1000, 0x1400, 0x1800,
0x1C00, 0x2000, 0x2400, 0x2000, 0x1C00, 0x1800, 0x1400, 0x1000,
0x0C00, 0x0800, 0x0400
};
void main(void)
{
int i, y; /* Счетчик циклов*/
volatile float OUTPUT[36];
#ifdef MSP430
WDTCTL = WDTPW + WDTHOLD; /* Остановка сторожевого таймера */
#endif
for(y = 0; y < 36; y++)
{
for(i = 0; i < FIR_LENGTH/2; i++)
{
OUTPUT[y] = COEFF[i] * ( INPUT[y + 16 - i] + INPUT[y + i] );
};
OUTPUT[y] = OUTPUT[y] + ( INPUT[y + 16 - i] * COEFF[i] );
}
return;
}
Matrix Multiplication.c
/*******************************************************************************
*
* Имя: Matrix Multiplication
* Назначение: Тестовая прикладная программа перемножения матриц 3x4 и 4x5.
* матрицы содержат 16- битные значения.
*
*******************************************************************************/
typedef unsigned short UInt16;
const UInt16 m1[3][4] = {
{0x01, 0x02, 0x03, 0x04},
{0x05, 0x06, 0x07, 0x08},
{0x09, 0x0A, 0x0B, 0x0C}
};
const UInt16 m2[4][5] = {
{0x01, 0x02, 0x03, 0x04, 0x05},
{0x06, 0x07, 0x08, 0x09, 0x0A},
{0x0B, 0x0C, 0x0D, 0x0E, 0x0F},
{0x10, 0x11, 0x12, 0x13, 0x14}
};
void main(void)
{
int m, n, p;
volatile UInt16 m3[3][5];
for(m = 0; m < 3; m++)
{
for(p = 0; p < 5; p++)
{
m3[m][p] = 0;
for(n = 0; n < 4; n++)
{
m3[m][p] += m1[m][n] * m2[n][p];
}
}
}
return;
}
/*******************************************************************************
*******************************************************************************/
|