LusoRobótica - Robótica em Português

Software => Software e Programação => Tópico iniciado por: SJD22 em 31 de Janeiro de 2012, 23:41

Título: PROGMEM problema?
Enviado por: SJD22 em 31 de Janeiro de 2012, 23:41
Boa noite,

tenho aqui um firmware que desenvolvi e que corre tudo bem, mas quando acrescento a linha "String PROGMEM bufferMsgs[100];" o firmware passa-se todo e nem sequer corre. Ou seja, o upload e a verificação está OK mas depois nao corre.

Tentei reduzir para menos posições (tentei com 10) e a mesma coisa. Se tirar o PROGMEM já dá tudo bem mas com as 100 dá problemas na mesma.

Basicamente o que eu queria era guardar 100 mensagens na memória flash.

Depois tentei com "byte PROGMEM bufferMsgs[100][80];" e ele aceita e corre tudo bem... mas se meter "byte PROGMEM bufferMsgs[500][80];" já me dá erro a compilar: error: size of array 'bufferMsgs' is too large.

Alguem sabe pq o problema do too large e o problema de usar String no PROGMEM?

Estou a usar um AT1280.

Obg.
Título: Re: PROGMEM problema?
Enviado por: senso em 01 de Fevereiro de 2012, 00:17
Como é que depois estás a ler as coisas que estão em flash?
Pode ser dai, estares por exemplo a usar demasiada ram e rebentar com a stack.
E 500x80 são 40K de flash, tenho ideia que o progmem tem algumas limitações no tamanho máximo de arrays, mas é uma questão de ires ler o manual do avr libC.
Título: Re: PROGMEM problema?
Enviado por: SJD22 em 01 de Fevereiro de 2012, 10:14
Olá senso.

Não estou a ler sequer ainda, não cheguei a essa fase porque qdo declarei o vector deu logo asneira. De qq forma ia ler da forma normal: String ola = bufferMsgs[0] por exemplo.

Título: Re: PROGMEM problema?
Enviado por: senso em 01 de Fevereiro de 2012, 15:03
Quando colocas algo em PROGMEM ou seja na flash tens de usar funções especiais para copiar isso da flash para um buffer temporário na RAM, pois maior parte das funções de formatação de strings e companhia não funcionam com dados vindos da flash.
Podes sempre declarar as mensagens separadamente em vez de um array gigantesco, porque tens limitações quanto ao tamanho máximo de um array em progmem, podes ter é muitos.
Título: Re: PROGMEM problema?
Enviado por: SJD22 em 01 de Fevereiro de 2012, 15:55
Ok mas se quiser guardar 1000 mensagens é pouco prático ter 1000 variáveis. O uso do array é importante neste caso.

Vou explorar um pouco a coisa...

Título: Re: PROGMEM problema?
Enviado por: senso em 01 de Fevereiro de 2012, 16:02
Um .txt num cartão SD é o mais adequado para tanto texto.
Título: Re: PROGMEM problema?
Enviado por: SJD22 em 01 de Fevereiro de 2012, 16:26
É verdade, tenho de ver uma biblioteca porreira de SD com FAT32.
Título: Re: PROGMEM problema?
Enviado por: SJD22 em 02 de Fevereiro de 2012, 00:50
Outro problema que tem a ver com o que falei em cima: tenho o meu firmware a funcionar porreiro... se acrescentar esta linha "byte vMensagem[128];" antes do int main() o programa entra logo num loop de resets... se tirar a linha fica tudo bem... Há coisas que não se entendem... :(
Título: Re: PROGMEM problema?
Enviado por: senso em 02 de Fevereiro de 2012, 00:58
Quanta ram estás a usar em compile time?
Isso é a stack a rebentar...
Título: Re: PROGMEM problema?
Enviado por: SJD22 em 02 de Fevereiro de 2012, 01:03
Onde vejo isso? Ou referes-te à flash? Se sim estou a usar cerca de 34k (25% do total do 1280)
Título: Re: PROGMEM problema?
Enviado por: SJD22 em 02 de Fevereiro de 2012, 01:20
AVR Memory Usage
----------------
Device: atmega1280

Program:   33954 bytes (25.9% Full)
(.text + .data + .bootloader)

Data:       7019 bytes (85.7% Full)
(.data + .bss + .noinit)
Título: Re: PROGMEM problema?
Enviado por: senso em 02 de Fevereiro de 2012, 01:28
Data é a ram usada, estás a usar 7K dos 8K disponiveis de ram, ou seja é muito pouca ram para tudo o resto, chamadas de funções, alocação de espaço para variaveis de funções, stack para as chamadas de funções e etc, toca de poupar nessa ram.
Título: Re: PROGMEM problema?
Enviado por: SJD22 em 02 de Fevereiro de 2012, 01:33
yah... já estive aqui a fazer umas experiências e se meter uma variável fora do main() ela conta como RAM ocupada, dentro de um método já não conta. Faz todo o sentido porque ele qdo nao precisa da variavel reusa o espaço...  Variáveis globais nunca foram boa politica... :)

Ideias para poupar RAM? Meter variaveis o menos globais possivel é uma boa ideia... e mais? Nao estou a ver por onde mexer mais...
Título: Re: PROGMEM problema?
Enviado por: senso em 02 de Fevereiro de 2012, 01:41
Meter variaveis o menos globais só impede que o compilador te diga que as tens lá, pois a alocação passa a ser dinamica.
Num micro-controlador não vejo nenhuma vantagem entre variaveis globais ou não, até certo ponto é claro.
Se uma função precisa de variaveis auxiliares ou indices para loops for e afins claro que isso devem ser variaveis locais, agora buffers para usar itoa's/sprintf's pelo main e funções fora costumo ter apenas um, buffers para uarts, i2c, spi e coisas que tais são globais.
7K é muita muita tralha na ram, tenho um atmega644p ligado a um display 128x64, meia duzia de termometros, dac, adc, e mais umas coisas e estou a usar 1.8k de ram, isto já com 256 bytes de ram só em buffers circulares de uart e i2c. Se tens um ecra que precise de fonte na ram, usa progmem, e se falas em montes de texto usa um cartão sd, ou usa progmem, ter um array de array's ou ter as mensagens separadas vai dar quase a mesmo, ou então separa em vários arrays para ele não se queixar, e podes sempre passar no avrfreaks e criar um tópico a perguntar se é normal ter esse erro com o progmem, eu não te posso ajudar porque sempre que o usei nunca tive qualquer chatice.
Título: Re: PROGMEM problema?
Enviado por: SJD22 em 02 de Fevereiro de 2012, 10:34
Certo! Mas como são globais o espaço está sempre alocado em memória, correcto? Ao passo que se forem locais, a memória é libertada no final do scope da variável. Isto não significa que a stack não rebente na mesma.

Tenho de averiguar melhor onde tenho os quase 7k de ram ocupados.

Título: Re: PROGMEM problema?
Enviado por: SJD22 em 02 de Fevereiro de 2012, 15:24
Bom... em parte já sei onde gasto muita RAM. Tinha alterado a bibliboteca "HardwareSerial.cpp" que vem no Arduino e meti os buffers circulares com tamanho 512 bytes. Ora como são 4 portas Serial cada uma com 2 buffers (Tx e Rx) isto dava-me um total de 4k (ia logo metade da RAM pro galheiro!).

Vou ter de alterar essa biblioteca porque o tamanho do buffer que preciso em cada Serial é diferente. Para a Serial que comunica por USB uns 128bytes para Tx deve dar e como não recebo nada penso que para o buffer de Rx chega 16 bytes.
Título: Re: PROGMEM problema?
Enviado por: senso em 02 de Fevereiro de 2012, 17:19
Basta moveres as variaveis de global para dentro do inicio do main, se as colocares ai o compilador já não te mostra que as estás a usar, mas vão estar sempre alocadas porque nunca retornas do main.
Tipicamente o buffer deve ter o tamanho da maior mensagem que queres enviar/receber, se não recebes nada metes 0 para não estragar 16 bytes em algo que nunca vai ser usado.
Título: Re: PROGMEM problema?
Enviado por: SJD22 em 02 de Fevereiro de 2012, 18:11
0 não consigo meter porque dá division by zero lá numa parte do codigo... mas meto 1.

Entao na pratica em termos de RAM ter variaveis globais ou no main é igual... Mas é diferente porque se tiver um metodo fora do main, ele nao acede à variavel se a mesma estiver declarada no main. Por isso vou manter o que puder como global e siga.

Título: Re: PROGMEM problema?
Enviado por: senso em 02 de Fevereiro de 2012, 18:20
É precisamente por isso que num sistema embedded não ganhas muito em não ter globais, passas a ter de passar carradas de variaveis ás funções, o que sobre-carrega a stack nas chamadas ás funções, e depois para retorno de variaveis se for mais que uma tens de usar arrays. Variaveis que só são usadas aquando das chamadas ficam dentro das respectivas funções, agora o que for usado em todo o lado é global e siga, pelo menos é assim que tenho feito e ainda não correu mal, mas tambem nunca tive tanta ram usada, nem de perto.
Outra coisa, estás a usar as bibliotecas todas do Arduino com o avrStudio?
Título: Re: PROGMEM problema?
Enviado por: SJD22 em 02 de Fevereiro de 2012, 18:47
Eu qdo quero retornar mais do que um valor de uma função uso uma classe / estrutura. Retornar arrays não dá, so se for passado por referência.

Estou a usar apenas a WString e o HardwareSerial e algumas poucas mais que são necessárias para compilar essas duas.
Título: Re: PROGMEM problema?
Enviado por: senso em 02 de Fevereiro de 2012, 18:52
A WString tambem não é do melhor, é pesada na ram, e tudo o que ela faz, as funções standart do C tambem o fazem de modo mais eficiente.
Título: Re: PROGMEM problema?
Enviado por: SJD22 em 02 de Fevereiro de 2012, 23:54
O problema é que usando a WString posso fazer de forma amigavel: String xpto = "ola" e com a library string.h tenho de fazer char xpto[] = "ola";

A grande desantagem é que se quiser passar uma string por argumento numa função tenho de lhe passar tb o tamanho enquanto que com a classe String da WString basta passar a propria variavel.

Neste momento pus-me a mexer no codigo e isto ja nao faz nada do que quero. Refiro-me a mostrar texto no Putty que recebo do equipamento. E neste momento so tenho 45% de RAM ocupada segundo o compilador.
Título: Re: PROGMEM problema?
Enviado por: SJD22 em 03 de Fevereiro de 2012, 00:15
Decididamente esta porcaria tira-me do sério...

Vejamos este código que estou a usar para um teste:

Código: [Seleccione]
Serial.print("GM862");
Serial.print(" | ");
Serial.print(descricao);
Serial.print(" | ");
Serial.print(comando);
Serial.print(" | ");

Serial1.flush();
//Serial1.write(comando);
//Serial1.write(0x0D);

Ou seja o Serial mostra no Putty e o Serial1 manda para o GM862. "comando" e "descricao" são variaveis do tipo "char []".

O exemplo de cima corre bem... e o código segue jogo. Mas se eu tirar o comentário das duas últimas linhas o gajo encrava e nem sequer me imprime no Putty o comando e a descricao... simplesmente pára em "GM8" (nem escreve GM862 sequer).

Porquê? Que nervos!
Título: Re: PROGMEM problema?
Enviado por: senso em 03 de Fevereiro de 2012, 01:30
Se bem me recordo a escrita do serial do Arduino é bloqueante, alguma interrupção que está a ficar bloqueada de um timer ou de uma recepção de outra uart?