AVR C - sträng hoppar in i annan, utan anledning!

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46967
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av TomasL »

Ja då skickar ju du data, du skickar alltså inte texten "0xYZ" (där YZ är någon siffra eller bokstav), i det läget fungerar inte din sändrutin, eftersom den inte kan hantera rena binära data, utan enbart text, dvs allt över 0x00
Användarvisningsbild
toffie
Inlägg: 1888
Blev medlem: 22 juli 2004, 21:38:07
Ort: Töreboda / Stockholm
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av toffie »

Alltså sändning och mottagning fungerar i övrigt precis som det ska, det är hanteringen efter dekrypteringen som inte kommer att fungera.

Tar jag bort AES krypteringen så har jag i dagsläget redan ett färdigt kommunikationsprotokoll som fungerar, både sända och ta emot. Men om jag ska lägga in krypteringen så kommer ju mottagningen av data behöva vara annorlunda, eftersom jag måste dela upp en hel sträng istället för att som nu ta byte för byte. I dagsläget så fungerar det ju även med krypteringen att skicka, men det är just mottagningen som inte kommer att gå särskilt bra.


Vill absolut inte säga att du har fel, men jag vet inte om du missförstår mig kanske?
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av bearing »

Om längden är känd går det att loopa genom arrayen och anropa en "send_byte" som skickar en byte, även 0. Rutiner som väntar sig textsträng stannar ju som sagt vid noll, och skickar dessutom inte nollan.
Användarvisningsbild
TomasL
EF Sponsor
Inlägg: 46967
Blev medlem: 23 september 2006, 23:54:55
Ort: Borås
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av TomasL »

Just när det gäller binärdata som i detta fallet, så är det i princip nödvändigt att använda sig av fasta längder på datagrammen, annars vet inte mottagaren när meddelandet är färdigt (såvida man inte handskakar i hårdvaran).
Dessutom bör man ju också implementera lite checksumma och sådant.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av sodjan »

> // Go through all characters sent into the send-function
> while (*s)
> ...
> Koden ovan reflekterar INTE Nerre's förslag med ett NULL tecken i slutet.

while lopen snurrar till det som står inom () blir "falskt".
I C så är just vädet 0 = "falskt" (och allt annan är "sant").
Därför fungerar while loopen på null-terminerade strängar men
inte på data som i sig kan innehålla värdet "null" i en byte.

("Strängar" är ett lite oegentligt begrepp i C eftersom det inte
finns någon specifik variabeltyp som heter "string". Det är bara en
följd av bytes <> 0 som avslutas med värdet 0. Andra "bättre" språk
har strängtyper som även håller reda på aktuell längd. Men men... :-) )

> Men du menar att om jag skickar 0x00 i datatrafiken så kommer AES
> dekrypteringen tro att det är slutet på det krypterade "paketet", även
> om det kanske inte är fallet?

Du kommer inte ens att kunna skicka dom eftersom din sändrutin
kommer att stanna vid det första null tecknet. Om mottagaren förväntar
AES data, och AES data kan innehålla även null, så tar ju självklart den
sidan hand om det. Annars kan den inte hantera AES data, helt enkelt.

> Just i detta fallet så kommer jag bara skicka - exempelvis - 0x66
> 0x66 0x66 0x99 0x99 0x99 - i hex format alltså...

Här behöver du nog backa lite och fundera på begreppen. :-)
Du skickar inget i något "format" alls. Det som skickas är bara
ettor och nollor, i detta fall seriellt över en USART. Det du kallar "hex"
är enbart en *representation* av det du skickar. Om du kallar det
för "01100110", "0x66" eller "f" har igen om helst betydelse och
det är ingenting som "syns" på själva kommunikationen. Mottagaren
har inte heller en susning om hur du kodade det i sändaren...

Att det sedan från fall till fall kan vara det ena eller det andra formatet
som gör det mer lättläst i koden, är en helt annan sak...

> plus en header på några tecken...

En AES header innehåller (bl.a) längden på det krypterade data, så i data
kan det utan problem finnas null tecken. Om du skickar AES så måste
du i headern redan veta längen på AES datat, så då kan din sändrutin
använda samma längd för att sända rätt mängd data. Och ingen null
behövs för att terminera "strängen". För övrigt så är det nog fel att
betrakta ett paket med AES data som en "sträng". Jag skulle se på
det som en "buffert" som man får hålla redan på längen på själv.

Sen så kan man ju om man vill koda hela AES paketet som hex innan
man skicker det, men då måste mottagaren också veta det så att den
kan återskapa det korrekta AES formatet innan dekrypteringen...
Nerre
Inlägg: 27228
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av Nerre »

toffie skrev:då blir det en enda lång sträng som inte är uppdelad byte för byte längre.
En sträng är mer eller mindre per defintion uppdelad i byte. Varje tecken är en byte. (Om man nu inte kör unicode, jag har aldrig pysslat med unicode-strängar så jag är inte riktigt säker på hur det fungerar där).
opatagio
Inlägg: 236
Blev medlem: 24 maj 2005, 20:19:21

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av opatagio »

Enklast i ditt fall hade varit att speca ett paket i fast längd säg 16 eller 32 bytes. Använd dina fasta address, kommando,subkommando, datavärde (payload) och fyll resten av paketet med 0x00 (eller 0xFF vad som är enklast). Dra paketet genom en CRC, lägg CRC hög och låg byte i slutet på paketet, kör allt genom din AES-rutin. Skicka genom att anropa usart_send(packet, <storlek på packet>); och skriv ut på uarten med en for-loop eller nåt.

Mottagaren vet längden på paketet så när du räknat in samma antal byte i din rxBuffer så kör den genom AES-rutinen, sedan plocka CRC hög och låg (och ersätt dessa med din "fyllnad") från slutet på paketet. Kör genom CRC och jämför resultat. Är det samma så gå vidare till pakethantering och utför arbetet som önskas. Annars NACKa skiten eller låt ACK-timeout på sändaren skicka om paketet.

Skulle du få in ett strötecken på linan som falsktriggar en start av mottagande (hamnar i rxBuffer med andra ord) så kan detta sorteras med att ha en rxTimeout som är några ms högre än tiden det tar för ett helt paket att tas emot. Tar det 20ms för ett paket från första till sista byte så sätt rxTimeout på 23-24ms. Om rxTimeout går ut så nolla rxBuffer (och ev rxIndex). Skulle det ändå bli fel kommer det sorteras bort när CRC inte överensstämmer.

Detta är ett väldigt primitivt sätt att göra på och går med säkerhet att snygga till. Jag har en liknande uppsättning som kört i några veckors tid nu och efter dryga 5,26miljoner skickade paket så har det varit 9 med CRC fel men som korrigerades med återsändning (ej ACK innan timeout).
Användarvisningsbild
toffie
Inlägg: 1888
Blev medlem: 22 juli 2004, 21:38:07
Ort: Töreboda / Stockholm
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av toffie »

Återigen stort tack för era svar!

Jag låg och tänkte på allt det innan mitt förra inlägg när jag gick och la mig igår.. De svar efter mitt meddelande visar det också ganska klart, jag kan inte de rätta begreppen/namnen på allt och det gör så jag förvirrar er med vad det är jag försöker göra - Det är givetvis inte min mening!

sodjan
Tack för beskrivningen! En representation alltså, inte format! Nej det är ju faktiskt rätt, det syns ju inte på kommunikationen, det är ju bara ettor och nollor, eller hög och låg signal i olika kombinationer. Men då kan jag säga att jag skickar och tar emot datan representerat av Hex?

Ska försöka hålla mig tillbaka och ta sak för sak, inte hoppa fram och babbla om AES delen i projektet. I brist på bättre har jag skrivit en mottagningsrutin som denna;

Kod: Markera allt

ISR(USART_RXC_vect)
{
	unsigned char data;

	/* Read the received data */
	data = UDR;

	/* Calculate buffer index */
	USART_RxHead = ( USART_RxHead + 1 ) & USART_RX_BUFFER_MASK;

	if ( USART_RxHead == USART_RxTail )
	{
		/* ERROR! Receive buffer overflow */
	}
		
	USART_RxBuf[USART_RxHead] = data; /* Store received data in buffer */

}
Denna rutin tar emot data och lägger in varje "byte" som kommer in i en;

Kod: Markera allt

unsigned char USART_RxBuf[USART_RX_BUFFER_SIZE];

Buffer size definieras av följande för närvarande;
#define USART_RX_BUFFER_SIZE		32
Det är så jag tar emot data i dagsläget, byte för byte läggs de in i en "array" som jag gärna vill kalla det och när "USART_RxHead" kommer upp till ett visst värde, säg 7 så går en if rutin igång i huvudloopen i main. Där kollar jag av ifall byte för byte är korrekt för att avgöra vad som ska göras på mottagarsidan.

Kod: Markera allt

int main(void)
{
	while(1)
	{
		if ( USART_RxHead >= 7 )
		{
			if (( USART_RxBuf[1] == 0xA5 ) && ( USART_RxBuf[2] == 0xA5 ) && ( USART_RxBuf[3] == 0xA5 ))
			{
				if (( USART_RxBuf[4] == 0x66 ) && ( USART_RxBuf[5] == 0x66 ) && ( USART_RxBuf[6] == 0x66 ) && ( USART_RxBuf[7] == 0x66 ))
				{
					PORTB &= ~(1 << PINB0);
				}
				if (( USART_RxBuf[4] == 0x99 ) && ( USART_RxBuf[5] == 0x99 ) && ( USART_RxBuf[6] == 0x99 ) && ( USART_RxBuf[7] == 0x99 ))
				{
					PORTB |= (1 << PINB0);
				}
				if (( USART_RxBuf[4] == 0x66 ) && ( USART_RxBuf[5] == 0x66 ) && ( USART_RxBuf[6] == 0x88 ) && ( USART_RxBuf[7] == 0x88 ))
				{
					PORTB &= ~(1 << PINB1);
				}
				if (( USART_RxBuf[4] == 0x99 ) && ( USART_RxBuf[5] == 0x99 ) && ( USART_RxBuf[6] == 0x77 ) && ( USART_RxBuf[7] == 0x77 ))
				{
					PORTB |= (1 << PINB1);
				}
			}
			RESETRX();
		}
	}
}
RESETRX(); nollställer bara buffert längden till 0 så att mottagningen kan börja om.

Sändningen av "data" går till genom följande kod i exempelvis main; ( antar ett paket som följande; 0x01 0x55 0xAA 0xBB 0xFF 0x32 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x04)

Kod: Markera allt

USART_SEND_BYTE(0x01);
USART_SEND_BYTE(0x55);
USART_SEND_BYTE(0xAA);
USART_SEND_BYTE(0xBB);
USART_SEND_BYTE(0xFF);
USART_SEND_BYTE(0x32);
USART_SEND_BYTE(0x00);
USART_SEND_BYTE(0x00);
USART_SEND_BYTE(0x00);
USART_SEND_BYTE(0x00);
USART_SEND_BYTE(0x00);
USART_SEND_BYTE(0x00);
USART_SEND_BYTE(0x00);
USART_SEND_BYTE(0x00);
USART_SEND_BYTE(0x04);
Själva sändfunktionen;

Kod: Markera allt

void USART_SEND_BYTE(char data)
{
	// Wait if a byte is being transmitted
	loop_until_bit_is_set(UCSRA, UDRE);

	// Send the given data
	UDR = data;
}
Detta, utan problem, kan skicka vad jag än skickar in i funktionen. Mottagningsdelen som jag skrev om ovan, kan utan problem, ta emot vad jag än skickar. Här har jag inga problem med just 0 / 0x00. Jag förmodar att jag här har ett paketsystem som är längdbestämt, som flera av er har skrivit att det är något jag borde ha för ändamålet? Har jag rätt om det? Oavsett så fungerar detta ypperligt för det "protokoll" som jag skrivit för mitt kommunikationssystem.

Givetvis ska det till en CRC/checksumma i slutet också, för att säkerställa att det jag mottagit är det som faktiskt skickades.


sodjan
Med "header" menar jag dock en egen header, inte headern i AES. Att koda hela AES paketet, efter att ha förstått din beskrivning som du skrev ovan, så skulle en hex kodning av AES paketet vara.. overkill! :D Så det blir det verkligen inte :P

Som i paketexemplet ovan så är 0x01 0x55 0xAA själva "headern". Vad 0x01 och 0x55 står för har jag inte beslutat mig för, men just 0xAA är ju adressen för mottagaren. Så att jag kan ha flera mottagare, när jag kör på ett RS485 baserat nätverk. Givetvis inte på UART eller ett RS232 baserat nät ;)


Nerre
Givetvis är en sträng uppdelad byte för byte, men du måste medge att det är en skillnad mellan följande två - när det gäller att läsa av dem;

Kod: Markera allt

charstring = "0155AABB"

chararray[1] = "01"
chararray[2] = "55"
chararray[3] = "AA"
chararray[4] = "BB"
Läsa av dem i form av, läsa av "byte" för byte. Åtminstone enligt vad jag kan och vet förstås :)


opatagio
Precis, det är väl så som du beskriver som jag beskrivit ovan på ett ungefär. Fast jag skippar just "<storlek på packet>" delen. Min tanke är att sändfunktionen inte behöver denna information, den loopar bara igenom till sista tecken som den fått inskickat i sig. Mottagaren har redan ett fast inprogrammerat värde för längden på varje paket. Själva "paketet" i sin helhet när jag sedan inkluderar AES krypteringen också borde väl kunna fungera med något liknande;
paket_design.jpg
Header har jag inte riktigt beslutat mig för vad de två byte'n står för, address är ju självklart mottagarens adress och CRC är ju inga konstigheter, möjligen att det blir två bytes.. Data däremot, här ska det finnas ett huvudkommando, subkommando och eventuell annan data som inställningar, eller som i svaren kanske en temperatur eller status för något.

Att ha det som den paketdesignen med header, adress och och crc utanför krypteringen, det kan väl inte vara några konstigheter eller "säkerhetsmässigt" dåligt? Visst, det visar paketets uppbyggnad på ett sätt, men det krypterade i "data" delen som verkligen berättar vad som ska göras, det kan ju ingen se och därmed kan de inte använda den informationen på något sätt. Vidare så kommer jag köra en sorts "rolling code" så om någon fångar ett paket eller flera för den delens skull, så kommer de inte kunna återuppspela det paketet och samma sak ska hända.

Det är ju bara de enheter som har "nyckeln" som kan avkoda AES datan och därmed veta vad som ska göras och om ett paket är korrekt med tanke på "rolling code" informationen.

Vidare tillbaka till det du skrev opatagio om ACK och NACK. Det är något som jag kommer använda i det ursprungliga kommunikationssystemet, men för just det aktuella projektet där jag använder en 433mhz länk så kommer jag inte använda mig av det då det är envägs-kommunikation. Men absolut, det är redan inräknat :D

Timeout har jag inte programmerat in däremot, det är dock något jag ska göra så inte processorn stannar i ett felaktigt läge, den måste ju kunna själv-hela sig så att säga :)

Häftigt med ditt projekt! Nu vet jag ju inte vad du har för system om det är en AVR/PIC eller mer avancerat, men hur räknar du upp till över 5 miljoner? räcker en 32-bitars int för det kanske? Har du någon mer information om det projektet? Skulle vara kul att läsa mer om :)



Nu tror jag att jag svarat på allt, började redan vid 10 på förmiddagen, sen var jag iväg någon timme och har fortsatt nu igen :) Är det något jag missat så får ni hojta till ;)



Det med att avsluta med en 0 / 0x00 verkar fungera sisådär nu idag.. titta på följande..

Kod: Markera allt

Paket
41 42 43 44 40 31 32 33

AES kodat till
6c 69 78 c0 0f f8 20 1f d6 cb 04 7e d8 b9 f1 af
När AESkey ligger under AESdataENC som följande;

Kod: Markera allt

uint8_t AESdataENC[] = { 0x41, 0x42, 0x43, 0x44,
						 0x40, 0x31, 0x32, 0x33, 0x00 };

// AES KEY - 4BFA1ABBC98751836D2A98DC98C1BEB5
uint8_t AESkey[]  = {	0x4B, 0xFA, 0x1A, 0xBB,
						0xC9, 0x87, 0x51, 0x83,
						0x6D, 0x2A, 0x98, 0xDC,
						0x98, 0xC1, 0xBE, 0xB5, 0x00 };

Om jag däremot flyttar upp AESkey[] ovanför AESdataENC[] så får jag ändå fel.

Kod: Markera allt

Paket
41 42 43 44 40 31 32 33

AES kodat till
f3 0b c4 86 7c 48 25 47 11 12 ea 10 c8 0e 4e 34 83 6d 2a 98 dc 98 c1 be b5

Kod: Markera allt

// AES KEY - 4BFA1ABBC98751836D2A98DC98C1BEB5
uint8_t AESkey[]  = {	0x4B, 0xFA, 0x1A, 0xBB,
						0xC9, 0x87, 0x51, 0x83,
						0x6D, 0x2A, 0x98, 0xDC,
						0x98, 0xC1, 0xBE, 0xB5, 0x00 };

uint8_t AESdataENC[] = { 0x41, 0x42, 0x43, 0x44,
						 0x40, 0x31, 0x32, 0x33, 0x00 };
I båda fallen så avkodas de AES kodade paketen av till samma originalpaket. Det man kan se, när AESkey ligger över AESdataENC, är att de sista 9 teckenparen i det AES kodade paketet är detsamma som de nia sista teckenparen i AESkey.. Det kan väl då inte vara bra?

Så fortfarande blandas två variabler ihop, i slutändan får jag ju ut samma paket som jag från början kodar, men längden skiljer sig ju avsevärt..

Som ni kan se så är ju både AESkey[] och AESdataENC[] "avslutade" med 0x00. Ändå går variablerna ihop.. på något sätt?


Vad kan vara fel?
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
opatagio
Inlägg: 236
Blev medlem: 24 maj 2005, 20:19:21

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av opatagio »

Är det AES128? Rutinen förväntar sig troligtvis 16 byte men du skickar bara 8 bytes? Kan det vara så att detta fallerar och fyller felaktigt ut resten med nyckeln?
Utöka dina 8 bytes till 16 ex: 41 42 43 44 40 31 32 33 FF FF FF FF FF FF FF FF och kör igen så bör det fungera korrekt. Använder man bara 8 bytes när det förväntas 16 bytes så kan man fylla resten med slumpdata (eller 0xFF om det känns bättre) som aldrig behandlas men förändrar "utseendet" på det krypterade paketet.

Angående den 0x00 i slutet på din AESKey så är detta den 17:e byten och borde aldrig användas. Bör kunna plocka bort den för att minska framtida huvudbry.

Om du lägger datan du ska skicka i en array så kan loopa genom den och slipper alla dessa USART_SEND_BYTE(); anrop.
Typ:

Kod: Markera allt

void USART_SEND_BYTE(uint8_t len )
{
for(uint8_t i=0;i<len;i++)
{
   // Wait if a byte is being transmitted
   loop_until_bit_is_set(UCSRA, UDRE);

   // Send the given data
   UDR = data[i];
}
}
För att testa kommunikation i mitt system så använder jag extern utrustning, specifikt i detta fallet en PC kopplad på datalinjen som avlyssnar all trafik med ett egenhändigt program som sorterar i antal mottagna byte, antal paket och räknar ev crc/paket-fel. Ska troligtvis utöka detta att mäta tiden mellan paketen också för att säkerställa att inga oförväntade avvikelser sker på den fronten med. Kan tyvärr inte berätta mer utöver det :/
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av sodjan »

Ja, alltså, jag läste en sida som beskrev "AES file format", eller något liknande.
Du kanske bara fixar själva "payload", den krypterade delen, och sedan
hittar på något eget för resten. Tja, kanske fungerar om man har
kontroll på hela kedjan.

När det gäller hex/dec/binwhatever så är det många som tror att det
är skillnad på t.ex.:

Kod: Markera allt

USART_SEND_BYTE(0x55)
USART_SEND_BYTE(85)
USART_SEND_BYTE("U")
vilket det så klart inte är.

> Här har jag inga problem med just 0 / 0x00. Jag förmodar att jag här har
> ett paketsystem som är längdbestämt, som flera av er har skrivit att det är
> något jag borde ha för ändamålet? Har jag rätt om det?

Ja, alltså, *problem* med 0x00 har du bara om du använder "string" funktioner
i C som *förväntar* sig "null terminated strings". Jag ser ingen anledning till att
hantera dina buffrar som "C-strängar", du kan hålla reda på storleken på datat
på andra sätt och även kunna hantera vilken data som helst inkl. "null".

Givetvis är en sträng uppdelad byte för byte, men du måste medge att det är en skillnad mellan följande två - när det gäller att läsa av dem;

Kod: Markera allt

charstring = "0155AABB"

chararray[1] = "01"
chararray[2] = "55"
chararray[3] = "AA"
chararray[4] = "BB"
Hur tänker du dig att chararray är definierad?
För det första ska det nog vara 0-3, inte 1-4.
Sen så är ju t.ex. "55" 16 bitar så chararray måste
ha datatypen int16 (eller vad det kallas), inte char.

"55" är *inte* en hexkod, om du trodde det. "55"
skrivet i hex blir 0x35 0x35. Det är alltså inte alls detsamma
som det som du skickar med dina USART_SEND_BYTE().
USART_SEND_BYTE(0x55) är inte detsamma som USART_SEND_BYTE("55").

> ...den loopar bara igenom till sista tecken som den fått inskickat i sig.

Och hur vet den vad som är "sista tecknet"?? Den har ingen längd som den
kan kolla och stanna vid. Alltså stannar den när det kommer ett "null", 0x00.

> Vad kan vara fel?

Svårt att säga utan att se ett komplett exempelprogram ("reproducer").
Sannolikt har du inte koll på allokerat minne och dina pekare, men det är en gissning.

Vad jag inte förstår är *varför* du måste ha AES kryptering, men det kanske
är känslig data eller något sådant...
Användarvisningsbild
toffie
Inlägg: 1888
Blev medlem: 22 juli 2004, 21:38:07
Ort: Töreboda / Stockholm
Kontakt:

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av toffie »

opatagio
Det är AES128, hade ingen aning om att den förväntade sig 16 bytes! Jag fyllde upp och körde med 16 bytes som följer, och då krypterar den alla 16 bytes och lägger inte till något av nyckeln i den krypterade datan!

Detta fungerade även med AESkey[] både ovanför och nedanför AESdataENC[]! Äntligen :D


Vidare då.. din USART_SEND_BYTE(); är ju helt klart en bra variant och jag ska prova på den framöver! Blir ju klart snyggare med en array! Likt denna struktur kan fungera då?

Kod: Markera allt

uint8_t data[] = {	0x41, 0x42, 0x43, 0x44,
					0x40, 0x31, 0x32, 0x33,
					0x00, 0x01, 0x02, 0x03,
					0x04, 0x05, 0x06, 0x07, 0x00 };
len blir då 16? eller blir det 17 med 0x00? Kanske man kan skippa 0x00 i slutet där då?


Definitivt spännande med ditt projekt där, mycket för att jag gillar såna här projekt men även för att det är "hemligt" ;) Framförallt roligt när medlemmar här delar med sig av sina projekt, älskar projektdelen för övrigt ;) hehe


sodjan
Aha ok! Det låter bra det, ska försöka hålla koll på hela kedjan :D

Nej självklart, det är bara olika sätt att "visa" serier av ettor och nollor. Jag är rätt duktig på att glömma detta, men jag börjar närma mig det "rätta" sättet att se på det :D

chararray som jag skrev i exemplet bör väl vara definierad som uint8_t kan jag tänka mig. Ah är det 0-3? Blandar ihop det när jag haft uppehåll från C ett tag, har för mig att det inte var samma i PHP och C, men det kanske är det. I PHP kan man dock enkelt definiera vad en array ska börja på.

Givetvis skrev jag fel med "01" "55" osv. Det skulle varit representerat i hex med 0x01 0x55 osv. Som sagt, jag börjar närma mig att tänka rätt ;) Men skrev fel där dock! :vissla:

sodjan skrev:> ...den loopar bara igenom till sista tecken som den fått inskickat i sig.

Och hur vet den vad som är "sista tecknet"?? Den har ingen längd som den
kan kolla och stanna vid. Alltså stannar den när det kommer ett "null", 0x00.
Hmm, jo fast här har ju inte jag specifikt definierat ett null. Men om jag förstår rätt så är slutet på en sträng/variabel automatiskt null - just i detta specifika fall med while(*s)? För den har väl någon egen koll i detta fall som ser att det jag skickat in i while funktionen tar slut? Rätt sätt kanske är att sätta 0x00 i slutet på det som skickas in i while också, men det är långt mer än vad jag vet :P


Just det om vad som kan vara fel, skrev lite om det i svaret till opatagio ovan, kan nog vara det med att jag var tvungen att ange 16 bytes - fast jag skickade bara in 8 bytes.


Anledningen till AES krypteringen eller kryptering oavsett är ju för att göra kommunikationen "säker" - vad man nu kan anse säkert :P Hur som, i detta projekt använder jag de här säkra 433mhz kina modulerna och "utvecklar" en liten fjärrkontroll - liknande en fjärr till bilen. De har någon sorts kryptering plus att de har en "rolling code" funktion som gör att varje datameddelande som skickas från fjärren till bilen är mer eller mindre unikt. Mottagaren har likt sändaren, koll på rolling code siffran som adderas med 1 varje gång som sändaren skickar iväg ett meddelande.

Det finns då ett accepterat intervall på kanske 50 till 100 godkända siffror säg 30-80 utav 200. Om sändaren då skickar ett paket som (header*aes(data*rollingcode:40)*crc) så kollar mottagaren om 40 ligger inom det tillåtna intervallet. Gör det de så uppdaterar mottagaren sin rolling code till 40 och det nya tillåtna intervallet blir då 41-91. Detsamma gäller då på sändaren som också uppdaterat sitt tillåtna intervall.

Om någon samtidigt lyssnar av radiotrafiken och "spelar in" sändningen så har de ett "gammal" rolling code nummer och om de då försöker skicka samma paket igen så ignorerar mottagaren det. Även om det är ett helt ok "paket", men rolling code siffran är ju gammal så den accepterar inte det.

Anledningen till intervallet är för att man kanske råkar trycka på lås eller lås upp knappen när inte bilen är i närheten eller om man trycker och tror att räckvidden räcker fast den inte gör det. Sändaren uppdaterar ju för varje gång den skickar iväg sin kod mot bilen, även om bilen inte får signalen. Det är väl nackdelen med ett kommunikationssystem som bara går åt ena hållet - man får anpassa sig efter det :P


Nu skrev jag detta för att jag själv tycker det är väldigt intressant och nyligen läst och lärt mig om det, du verkar redan ha ett ganska så stort och brett bibliotek i huvudet, så du kanske redan visste det :P men annars så kanske jag lyckats lära någon något :D Inget illa menat på något sätt alltså!
Mr Andersson
Inlägg: 1409
Blev medlem: 29 januari 2011, 21:06:30
Ort: Lapplandet

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av Mr Andersson »

sodjan skrev:När det gäller hex/dec/binwhatever så är det många som tror att det
är skillnad på t.ex.:

Kod: Markera allt

USART_SEND_BYTE(0x55)
USART_SEND_BYTE(85)
USART_SEND_BYTE("U")
vilket det så klart inte är.
Om man ska vara petig är det rätt så stor skillnad mellan de två första och den sista raden :)
De två första är heltal, men "U" är adressen* till en array med {'U','\0'}
Nu är jag rätt säker på att du har koll på det och bara gjorde en liten miss, men det kan vara värt att påpeka för dem som är nya i C att det är skillnad på 'U' och "U".

*) Vilket iofs också är ett heltal, men troligen inte med samma värde
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av sodjan »

OK, så om jag fattar rätt så är dessa rader samma sak:

Kod: Markera allt

USART_SEND_BYTE(0x55)
USART_SEND_BYTE(85)
USART_SEND_BYTE('U')
Och nej, jag skriver inte mycket C med avsikt, enbart för
att underhålla gamla rutiner som var skrivna i C... :-)

Min poäng är i alla fall ar man måste hålla isär hur man representerar
värden i själva källkoden mot vad som maskinen ser när det körs. :-)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av sodjan »

Till toffies senaste inlägg.

> Kanske man kan skippa 0x00 i slutet där då?

Ja, så länge som du inte använder "sträng funktioner" i C som
förväntar sig "null terminated strings", så gör den ju ingen nytta.
Du vet redan innan hur lång bufferten är, d.v.s. 16 bytes.

> För den har väl någon egen koll i detta fall som ser att det jag skickat in i while funktionen tar slut?

Nej nej nej... :-) Den har inte en aning om när något "tar slut", den får en
adress (pekare) till början, och det är allt den vet. Det är alltså inte
16 bytes som skickas till funktionen, enbart adressen till den första
byten i bufferten. Den kan sedan vara hur lång eller kort som helst. Detta kallas
för "call by reference", du skickar inte värdet i sig, utan en referens (i detta fallet
adressen) istället. I C kallas dessa referenser för "pekare" ("ponters").

Här har vi en av de största designmissarna över huvudtaget i C. Du kan fortsätta
och läsa och skriva hej vilt tills något kraschar (eller operativets minnesskydd
säger ifrån, om man har ett operativsystem). Se:
https://sv.wikipedia.org/wiki/Buffert%C3%B6verskridning
https://en.wikipedia.org/wiki/Buffer_overflow

> Rätt sätt kanske är att sätta 0x00 i slutet på det som skickas in i while också...

Eller så skickar du med längden också som en extra parameter. Alltså en adress
(d.v.s "pekare" i C) precis så sm du göre nu och en längd. Eller så vet du
från början att det är 16 bytes (0-15) och loopar aldrig mer än så i alla fall.

Helt OK med kryperingen som sådan, var bara nyfiken... :-)
opatagio
Inlägg: 236
Blev medlem: 24 maj 2005, 20:19:21

Re: AVR C - sträng hoppar in i annan, utan anledning!

Inlägg av opatagio »

För att bygga på Sodjans spår där med längd och pekare så kan det vara en bra idé att köra med:

Kod: Markera allt

#define packet_size 16

uint8_t data[packet_size];
Skulle du vilja köra 32bytes packet array så ändrar du bara packet_size till 32.
Då kan du hela tiden i for- och while-loopar använda dig av packet_size som ex:

Kod: Markera allt

for(uint8_t i=0;i<packet_size;i++)

while(blabla < packet_size){
 blabla++
}
Och ja, när du hanterar paket som ska in eller kommer från en AES-modul/rutin så bör detta inte köras i någon som helst "sträng-funktion" innan du antingen kopierat till separat array och säkerställer att null inte finns med samtidigt som du själv sätter null på korrekt plats i arrayen. Ex: Om din payload är i "läsbar" form ex: "hej" och denna ska köras i någon "sträng-funktion", kopiera till ny array som har plats för både packet-size och ett par reserv bytes, eller rent av packet_size*2 för att ha lite marginal om det blir längre strängar.
Så i nuläget skulle jag säga att du kan skippa den 17:e byten och istället spara lite utrymme i AVR:en :)
Skriv svar