AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR... |
19.06.2014, 19:43
|
|
Частый гость
Регистрация: 17.06.2014
Сообщений: 30
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Выяснить причину затирания данных
Что имею:
Структура для реализации динамического массива:
Код:
|
typedef struct {
uchar * data;
unsigned char size;
} ByteArray; |
Периферия для обслуживания:
Код:
|
void BA_pushback(ByteArray * array,uchar data){
if(array-›size==0){
free(array-›data);
array-›data = calloc(1,sizeof(ByteArray));
}else{
array-›data = realloc(array-›data,(array-›size+1)*sizeof(uchar));
}
array-›data[array-›size]=data;
array-›size++;
}
void BA_clear(ByteArray * array){
free(array-›data);
array-›size=0;
} |
И адское место, в котором происходит неясные для меня вещи:
Код:
|
if(sendID003Cmd(ID003_GET_STATUS,0,answer)){
convertAnswerData(ID003_CCNET,answer,data);
//Комманда выше, возвращает правильные данные, она вернула мне индекс переданный устройством, что я проверил способом ниже
BA_clear(answer);
DDRC=0xFF;
PORTC=data-›data[0];
//Теперь погружаемся в процедуру getCCNetAnswPack
if(getCCNetAnswPack(CCNET_POLL, answer, data)){
return 0x1;
}
} |
Вот эта процедура
Код:
|
bool getCCNetAnswPack(uchar cmd, ByteArray * answPack, ByteArray * answData){
ushort crc;
// Здесь данные по прежнему целые...
BA_pushback(answPack,CCNET_PREFIX); //Префикс пакета
BA_pushback(answPack,CCNET_BV_ADD); //Адресс устройства
BA_pushback(answPack,0x0); //Готовим место для размера пакета
// А уже здесь они поврежденные
DDRD|=(0xFF‹‹2);
PORTD=(answData-›data[0]‹‹2);
switch(cmd){
..... |
Где я допустил косяк, в чем моя ошибка?
|
|
|
|
19.06.2014, 21:49
|
|
Вид на жительство
Регистрация: 05.07.2006
Адрес: Tashkent
Сообщений: 454
Сказал спасибо: 24
Сказали Спасибо 67 раз(а) в 44 сообщении(ях)
|
Re: Выяснить причину затирания данных
Реализация конечно красивая, но насколько помню в ID003 размер типичного пакета исчисляется длиной в несколько байт и игры с динамическим выделением памяти скорее усложняют задачу. По этой причине может просто выделить буфер фиксированной длины?
|
|
|
|
19.06.2014, 23:15
|
|
Почётный гражданин KAZUS.RU
Регистрация: 02.03.2011
Адрес: Россия, КБР
Сообщений: 629
Сказал спасибо: 108
Сказали Спасибо 596 раз(а) в 334 сообщении(ях)
|
Re: Выяснить причину затирания данных
Сообщение от qweentet
|
Структура для реализации динамического массива:
Код:
typedef struct {
uchar * data;
unsigned char size;
} ByteArray;
|
лучше так, на мой взгляд
Код:
|
typedef struct {
unsigned char size;
uchar * data;
} ByteArray; |
а ещё лучше сделать как написал uk8amk
какой камень? может ОЗУ кончилось...
|
|
|
|
20.06.2014, 00:10
|
|
Прописка
Регистрация: 18.01.2006
Сообщений: 268
Сказал спасибо: 81
Сказали Спасибо 476 раз(а) в 127 сообщении(ях)
|
Re: Выяснить причину затирания данных
Сообщение от qweentet
|
Что имею:
Структура для реализации динамического массива:
Код:
|
typedef struct {
uchar * data;
unsigned char size;
} ByteArray; |
Периферия для обслуживания:
Код:
|
void BA_pushback(ByteArray * array,uchar data){
if(array-›size==0){
free(array-›data);
array-›data = calloc(1,sizeof(ByteArray));
}else{
array-›data = realloc(array-›data,(array-›size+1)*sizeof(uchar));
}
array-›data[array-›size]=data;
array-›size++;
}
void BA_clear(ByteArray * array){
free(array-›data);
array-›size=0;
} |
И адское место, в котором происходит неясные для меня вещи:
Код:
|
if(sendID003Cmd(ID003_GET_STATUS,0,answer)){
convertAnswerData(ID003_CCNET,answer,data);
//Комманда выше, возвращает правильные данные, она вернула мне индекс переданный устройством, что я проверил способом ниже
BA_clear(answer);
DDRC=0xFF;
PORTC=data-›data[0];
//Теперь погружаемся в процедуру getCCNetAnswPack
if(getCCNetAnswPack(CCNET_POLL, answer, data)){
return 0x1;
}
} |
Вот эта процедура
Код:
|
bool getCCNetAnswPack(uchar cmd, ByteArray * answPack, ByteArray * answData){
ushort crc;
// Здесь данные по прежнему целые...
BA_pushback(answPack,CCNET_PREFIX); //Префикс пакета
BA_pushback(answPack,CCNET_BV_ADD); //Адресс устройства
BA_pushback(answPack,0x0); //Готовим место для размера пакета
// А уже здесь они поврежденные
DDRD|=(0xFF‹‹2);
PORTD=(answData-›data[0]‹‹2);
switch(cmd){
..... |
Где я допустил косяк, в чем моя ошибка?
|
вот это жесть, давно не видел такого, ну во первых
Код:
|
void BA_pushback(ByteArray * array,uchar data){
if(array-›size==0){
free(array-›data);
... |
это что, освобождаем то, чего нет? А вообще, не слишком ли расточительно, при добавлении каждого байта перевыделять память, выделение памяти длительная процедура, и количество ее вызовов желательно минимизировать. В общем ваш динамический массив не годится для практического использования, возможные направления улучшения - выделять память блоками по 64 байта например, или на 25% больше чем уже использовано (как в stl) и хранить размер буфера и количество данных в нем.
|
|
|
|
20.06.2014, 02:06
|
|
Заблокирован
Регистрация: 21.01.2014
Сообщений: 589
Сказал спасибо: 7
Сказали Спасибо 267 раз(а) в 206 сообщении(ях)
|
Re: Выяснить причину затирания данных
Вот у Вас два указателя answer и data. Должно быть ещё также 2 места в памяти зарезервировано за двумя структурами типа ByteArray, и потом начальные адреса этих областей памяти записаны в указатели соответственно. Из приведённых фрагментов программы этого не видно. Можно посмотреть как инициализируются переменные answer и data?
Последний раз редактировалось Yurkin2014; 20.06.2014 в 02:10.
|
|
|
|
20.06.2014, 09:57
|
|
Частый гость
Регистрация: 17.06.2014
Сообщений: 30
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Выяснить причину затирания данных
Самое первое - камень ATMega8 работает на 8 MHz
Сообщение от Raptor1
|
вот это жесть, давно не видел такого, ну во первых
Код:
|
void BA_pushback(ByteArray * array,uchar data){
if(array-›size==0){
free(array-›data);
... |
это что, освобождаем то, чего нет? А вообще, не слишком ли расточительно, при добавлении каждого байта перевыделять память, выделение памяти длительная процедура, и количество ее вызовов желательно минимизировать. В общем ваш динамический массив не годится для практического использования, возможные направления улучшения - выделять память блоками по 64 байта например, или на 25% больше чем уже использовано (как в stl) и хранить размер буфера и количество данных в нем.
|
Код:
|
void BA_pushback(ByteArray * array,uchar data){
if(array-›size==0){
free(array-›data);
... |
Это я вставил тогда, когда уже не знал что делать, и лепил самые не разумные вещи. На счет размерности учту ,спасибо!=)
Цитата:
|
Реализация конечно красивая, но насколько помню в ID003 размер типичного пакета исчисляется длиной в несколько байт и игры с динамическим выделением памяти скорее усложняют задачу. По этой причине может просто выделить буфер фиксированной длины?
|
При среднестатистических командах до 14 байт, НО, также присутсвует работа с 256 байтами у ID003 и 64к у CCNet (по документации), Это сделано для передачи пакетов данных (прошивка или статистика) а не команд. Вот я и пытался предусмотреть все нюансы...
Цитата:
|
Вот у Вас два указателя answer и data. Должно быть ещё также 2 места в памяти зарезервировано за двумя структурами типа ByteArray, и потом начальные адреса этих областей памяти записаны в указатели соответственно. Из приведённых фрагментов программы этого не видно. Можно посмотреть как инициализируются переменные answer и data?
|
Вот весь процесс:
Код:
|
void main(void){
ByteArray tmpPackage,tmpAnswer,tmpData;
SUART_Init(); //Инициализация софтового UART
USART_Init(); //Инициализация физического USART
while(1){
BA_clear(&tmpPackage);
BA_clear(&tmpAnswer);
BA_clear(&tmpData);
if(collectCCNetPackage(&tmpPackage)){
if(convertAndSend(CCNET_ID003,&tmpPackage,&tmpData,&tmpAnswer)){
SUART_Transmit(&tmpAnswer);
}
}
}
} |
Код:
|
bool convertAndSend(uchar direct,ByteArray * package,ByteArray * data,ByteArray * answer){
uchar status=0;
BA_clear(data);
BA_clear(answer);
switch(direct){
case CCNET_ID003: //Направление конвертации от CCNet к ID003
switch(package-›data[3]){
case CCNET_RESET:
if(sendID003Cmd(ID003_RESET,0,answer)){
if(answer-›data[2]==ID003_ACK){
BA_clear(answer);
if(getCCNetAnswPack(CCNET_ACK, answer, 0))
status=1;
}
}
break;
case CCNET_GET_STATUS: //Получить статус. По версии CCNet в ответе должны прийты таблица номиналов
//и уровни безопасности к ним, в ID003 это два запроса
if(sendID003Cmd(ID003_GET_BILL_TABLE,0,answer)){
BA_pushback(data,0);
BA_pushback(data,~(uchar)answer-›data[3]);
BA_pushback(data,~(uchar)answer-›data[4]);
BA_clear(answer);
}
else{
break;
}
if(sendID003Cmd(ID003_GET_SECURITY,0,answer)){
BA_pushback(data,0);
BA_pushback(data,answer-›data[3]);
BA_pushback(data,answer-›data[4]);
BA_clear(answer);
}
else{
break;
}
if(getCCNetAnswPack(CCNET_GET_STATUS, answer, data)){
status=1;
}
break;
case CCNET_SET_SECURITY: //По версии CCNet в ответ приходит ACK
// PR - ADD - LNG - CMD - D1 - D2 - D3
// 0 1 2 3 4 5 6
BA_pushback(data,package-›data[5]);
BA_pushback(data,package-›data[6]);
if(sendID003Cmd(ID003_SET_SECURITY,data,answer)){
BA_clear(answer);
BA_clear(data);
if(getCCNetAnswPack(CCNET_ACK, answer, 0))
status=1;
}
break;
case CCNET_POLL:
if(sendID003Cmd(ID003_GET_STATUS,0,answer)){
convertAnswerData(ID003_CCNET,answer,data);
BA_clear(answer);
DDRC=0xFF;
PORTC=data-›data[0];
if(getCCNetAnswPack(CCNET_POLL, answer, data)){
return 0x1;
}
}
break;
default:
return 0;
}
break;
case ID003_CCNET:
break;
default:
return 0;
}
BA_clear(data);
if(!status)
BA_clear(answer);
return status;
}; |
//Вот откуда берутся answer и data
//Раньше data брала свое начало в функции выше, но я подумал, может проблема из-за того, что данные не в той области видимости, и решил вынести наверх - нифига не помогло...
Вот такие вот дела,если проблему не решу, то буду пытатсья со статикой работать, хотя не хотелось бы=(
|
|
|
|
20.06.2014, 10:44
|
|
Гражданин KAZUS.RU
Регистрация: 06.04.2010
Адрес: Санкт-Петербург - Волжский
Сообщений: 529
Сказал спасибо: 74
Сказали Спасибо 56 раз(а) в 45 сообщении(ях)
|
Re: Выяснить причину затирания данных
ATMega8 - 1kb SRAM , не стал бы я использовать на таком камне команды подобные calloc. Не забывайте что есть еще стек, и неизвестно как его насилует ваша программа.
Код:
|
void BA_pushback(ByteArray * array,uchar data){
if(array-›size==0){
free(array-›data);
array-›data = calloc(1,sizeof(ByteArray));
}else{
array-›data = realloc(array-›data,(array-›size+1)*sizeof(uchar));
}
array-›data[array-›size]=data;
array-›size++;
} |
+ После распределения памяти рекомендуют делать проверку:
Код:
|
if(array-›size==0){
free(array-›data);
array-›data = calloc(1,sizeof(ByteArray));
if (array-›data ==NULL) return 0;
} |
|
|
|
|
20.06.2014, 10:58
|
|
Почётный гражданин KAZUS.RU
Регистрация: 08.06.2008
Сообщений: 1,394
Сказал спасибо: 4
Сказали Спасибо 183 раз(а) в 167 сообщении(ях)
|
Re: Выяснить причину затирания данных
Вот как бы во "взрослом " C/C++ память добавляется, но не переписывается. Она ж из кучи берется . Надо ручками переписывать из старого в новое
Prototype
void *calloc(size_t nitems, size_t size);
Description
Allocates main memory.
calloc provides access to the C memory heap. The heap is available for dynamic allocation of variable-sized blocks of memory. Many data structures, such as trees and lists, naturally employ heap memory allocation.
calloc allocates a block of size nitems * size. The block is initialized to 0.
Иль у Вас С/C++ какой иной?
|
|
|
|
20.06.2014, 11:17
|
|
Почётный гражданин KAZUS.RU
Регистрация: 08.06.2008
Сообщений: 1,394
Сказал спасибо: 4
Сказали Спасибо 183 раз(а) в 167 сообщении(ях)
|
Re: Выяснить причину затирания данных
Прощу прпощения, погорячился. Все корректно.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 05:40.
|
|