Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: IAR 2.10.5 STM8
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
-AZ-
Кто то может уже натыкался на данную проблему, подскажите пожалуйста
Пишу:
Код
unsigned long long i;
i=(((unsigned long long)1)<<0x20);

так вот без ошибки компилирует если сдиг не более 0x1F, если 0x20 и больше выдает ошибку - Warning[Pe063]: shift count is too large
Как это победить, в чем проблема?
aiwa
Это не ошибка, а предупреждение, что разрядность типа long long в IAR STM8 - 32 бита.
Выход, например,через оформление переменной i в виде класса/структуры с соответственной обработкой.
-AZ-
То что 32 бита это я уже понял, как примерно оформить?
Непомнящий Евгений
Код
struct U64 {
  uint32_t low, hi;
};



ну и дальше пишете набор необходимых вам арифметических операций

Если у вас просто биты, то возможно будет удобнее работать с массивом байт
Код
struct Mask {
  byte d[8];
};

void mask_clear(Mask *m) { memset(m->d, 0, sizeof(m->d); }
void mask_set(Mask *m, unsigned no) { m->d[no/8] |= (1<<(no%8)); }
void mask_clear(Mask *m, unsigned no) {}
void mask_put(Mask *m, unsigned no, bool v) {}
bool mask_test(Mask *m, unsigned no) {}

-AZ-
У меня единственная операция, это сдвиг вправо(влево) в цикле 64 раза...
Вот и не пойму как разделить это дело ...
Непомнящий Евгений
Если я ничего не напутал, то что-то в таком духе
Код
struct U64 {
  uint32_t low, hi;
};

U64 u64_lshift(U64 a, unsigned b) {
  U64 r;
  if (b < 32) {
    r.low = a.low<<b;
    r.hi = (a.hi<<b) + (a.low >> (32-b));
  }
  else {
    r.low = 0;
    r.hi = a.low << (b-32);
  }
  return r;
}

А вообще можно погуглись, может что и по оптимальнее найдется
-AZ-
ну похоже..
я вот не пойму в чем прикол, IAR именно для STM8, в справке такой тип есть, если в него число больше 32 бит не записывать типа предупреждений нет и все работает....
Косяк IAR -?
Непомнящий Евгений
Цитата(phenixs @ Dec 25 2015, 12:25) *
я вот не пойму в чем прикол, IAR именно для STM8, в справке такой тип есть, если в него число больше 32 бит не записывать типа предупреждений нет и все работает....
Косяк IAR -?


посмотрите хидеры, попробуйте сделать sizeof(U64). На авр-ках uint64_t работает...
-AZ-
Цитата(Непомнящий Евгений @ Dec 25 2015, 12:28) *
посмотрите хидеры, попробуйте сделать sizeof(U64). На авр-ках uint64_t работает...

Сейчас гляну....

Цитата(phenixs @ Dec 25 2015, 12:33) *
Сейчас гляну....


А не знаете как макрос использовать __delay() и так и сяк не хочет..........


Цитата(Непомнящий Евгений @ Dec 25 2015, 12:28) *
посмотрите хидеры, попробуйте сделать sizeof(U64). На авр-ках uint64_t работает...

Непонятно, подлючаю только это #include <iostm8l152c6.h>
Там нет описания типов данных, что то подключается автоматом...
Непомнящий Евгений
Цитата(phenixs @ Dec 25 2015, 12:39) *
А не знаете как макрос использовать __delay() и так и сяк не хочет..........

Я с stm8 не сталкивался


Цитата
Непонятно, подлючаю только это #include <iostm8l152c6.h>
Там нет описания типов данных, что то подключается автоматом...

ну дык он скорее всего подключает какие-то другие хидеры и в конце концов подключаются системные хидеры с описанием типов
aiwa
Цитата(phenixs @ Dec 25 2015, 10:46) *
У меня единственная операция, это сдвиг вправо(влево) в цикле 64 раза...
Вот и не пойму как разделить это дело ...

Если у Вас единственный сдвиг 0x01 конкретно на 64 бита, то для структуры достаточно операции
Код
struct U64 {
  uint32_t low, hi;
};

low = 0x00;  
hi   = 0x01;
А если встречается различное количество сдвигов то удобнее тип оформить в виде массива 8 байт d[8] и
саму сдвижку производить на ассемблере по алгоритму:
1. d[0] - логический сдвиг для заноса в carry-флаг старшего бита
2. с d[1] - и далее - циклический сдвиг

на С сдвиг на 1 приблизительно так:
CODE
unsigned char carry;

carry = d[0];
d[0]<<=0x01;
for (i=1; i<8;i++)
{
if(carry&0x80)
{
carry=d[i];
d[i]<<=0x01;
d[i]|=0x01;
}
else
{
carry=d[i];
d[i]<<=0x01;
}
}
-AZ-
Это все ужасно долго, нужно сделать 1 сдвиг, потом передача в DMA и т.д. потом еще сдвиг и т.д. всего 60 - 62 раза, а если делать так это ай-ай ............
aiwa
Цитата(phenixs @ Dec 25 2015, 14:04) *
Это все ужасно долго, нужно сделать 1 сдвиг, потом передача в DMA и т.д. потом еще сдвиг и т.д. всего 60 - 62 раза, а если делать так это ай-ай ............


Это "ужасно долго" делает именно IAR для восьмибитных процессоров.
Только система команд STM8 имеет возможность сдвига слова, что позволяет свести операцию над 64-разрядным типом
к 4-м операторам сдвига вместо 8-ми. С предварительным оператором очистки флага carry разумеется.
И так это он повторяет в цикле 62 раза для каждого i=(0x01)<<62;

Для ускорения разумнее организовать цикл с модификацией: i<<=1;

Если Вы желаете, чтобы это выглядело коротко на экране, то можете сделать что-то подобное:

#define SimpleShift(p, n) do{memset(p,0,8); p[n/8]<<=(n%8);}while(0);


и вместо i=(0x01) << 62 вставить
SimpleShift(&i, 62);
-AZ-
Сечас попробую так временные интервалы измерить.....
scifi
Цитата(phenixs @ Dec 25 2015, 15:04) *
Это все ужасно долго, нужно сделать 1 сдвиг, потом передача в DMA и т.д. потом еще сдвиг и т.д. всего 60 - 62 раза, а если делать так это ай-ай ............

Ну тогда вам ассемблер нужен. По моему опыту яр для стм8 плохенько умеет оптимизировать. Делал i2c ногодрыгом с разгоном (порядка 2 Мбит/м) - сделал на ассемблере. Отлично получилось. Могу пример предоставить.
-AZ-
Цитата(scifi @ Dec 25 2015, 21:47) *
Ну тогда вам ассемблер нужен. По моему опыту яр для стм8 плохенько умеет оптимизировать. Делал i2c ногодрыгом с разгоном (порядка 2 Мбит/м) - сделал на ассемблере. Отлично получилось. Могу пример предоставить.


С ногодрыгом очень интересно посмотреть вашу реализацию функций delay us()
а вот получить тип 64 пока красиво не получается, чтобы можно было без заморочек выполнять операции с ними | << >> &
aiwa
Цитата(phenixs @ Dec 25 2015, 21:52) *
а вот получить тип 64 пока красиво не получается, чтобы можно было без заморочек выполнять операции с ними | << >> &

Если Вы считаете это красивым, то как пример
CODE
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ull;


class t_ULL_64
{
uchar Values[8];
public:
//----------
t_ULL_64()
{
*this=0;
}
t_ULL_64(uint a)
{
*this=a;
}
t_ULL_64 operator = (ull B )
{
*((ull*)&Values[4])=0;
*((ull*)&Values[0])=b;
return *this;
}

t_ULL_64 operator = (t_ULL_64 B )
{
*((ull*)&Values[4])=*((ull*)&b.Values[4]);
*((ull*)&Values[0])=*((ull*)&b.Values[0]);
return *this;
}

t_ULL_64 operator<<(uint B )
{
if(b==0) return *this;
if(b>64) {*this=0; return *this;}
while(B )
{
// сдвижка на 1 бит
*((ull*)&Values[4])<<=1;
if(Values[3]&0x80) Values[4]|=0x01;
*((ull*)&Values[0])<<=1;

b--;
}
return *this;
}
};


int main()
{

t_ULL_64 i;
i=((t_ULL_64)1)<<0x20;

}
-AZ-
Без С++ class не собирается, как правильно это на С сделать?
aiwa
Жестокий у Вас препод, если С++ не разрешает.
На С реализация только через структуры и функцию заменяющую "<<", потому что переопределение операторов С не поддерживает.
Поэтому у Вас, при условии на С и обязательно оставить "<<", есть два варианта:
1. Уговорить участников группы стандартизации С внести в стандарт желаемые изменения.
2. если оператор действительно работает для 64-бит как Вы это утверждаете, то попытаться использовать этот бонус, предоставленный IARом.
но я бы рекомендовал бы проверить работает ли он или только компилится с предупреждением.

P.S. Чтобы Вы не теряли время на проверку работоспособности: скорее всего IAR действительно добросовестно производит сдвиг,
но начиная с момента когда сдвигаемая единица вылазит за 32 бита в 7-й байт, переменная всегда будет равна 0, а не (1<<0x20) и т.д.
Dog Pawlowa
Цитата(aiwa @ Dec 27 2015, 21:59) *
но начиная с момента когда сдвигаемая единица вылазит за 32 бита в 7-й байт, переменная всегда будет равна 0, а не (1<<0x20) и т.д.

Я потерял нить, почему? Компилятор вдруг забыл тип переменной?
-AZ-
Цитата(scifi @ Dec 25 2015, 21:47) *
Ну тогда вам ассемблер нужен. По моему опыту яр для стм8 плохенько умеет оптимизировать. Делал i2c ногодрыгом с разгоном (порядка 2 Мбит/м) - сделал на ассемблере. Отлично получилось. Могу пример предоставить.


как вы реализовали функции delay ? на TIM4 ? а то с этим у stm8 тоже проблемы.........
aiwa
Цитата(Dog Pawlowa @ Dec 28 2015, 05:48) *
Я потерял нить, почему? Компилятор вдруг забыл тип переменной?


Потому что для STM8 IAR декларировал разрядность типа 'long long' в 32 бита в отличие например от их же AVR8, где она 64 бита.
Поэтому качестве оператора '<<' будет выступать ассемблерная подпрограмма производящая сдвижку только по 4-м байтам, т.е. 32 бита.

Картина похожая на ту, если к 'unsigned char' прибавлять число, большее 256 и результат вылазит за пределы байта,
только с тем отличием, что при сложении в переменная будет содержать кусок результата по модулю 256,
а при сдвиге механизм сдвижки обнуляет освободившийся хвост, и переменная будет = 0;


Dog Pawlowa
Цитата(aiwa @ Dec 28 2015, 12:49) *
декларировал разрядность типа 'long long' в 32 бита

Да, проверил, 64-битные переменные и в stdint не работают, даже с #pragma language=extended
Значит, только ручками.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.