Hi.
ich habe aktuell ein sehr merkwürdiges Problem. Ich bin aktuell ein
einfaches CAN-Protokoll am basteln.
Neben dem Hardwarepuffer habe ich noch einen Softwarepuffer
eingerichtet, ein simpler FiFo.
Zum Ablauf:
Jeden Zyklus wird CAN_Main() aufgerufen. Innerhalb davon wird
CAN_ReceiveSequenceData() augerufen.
1 | #define MAX_DATA_RECEIVE_SEQUENCES 6
|
2 |
|
3 | volatile int CanRX_Head = 0;
|
4 | volatile int CanRX_Tail = 0;
|
5 |
|
6 | ReceiveSequenceStruct ReceiveSequence[MAX_DATA_RECEIVE_SEQUENCES];
|
7 |
|
8 | void CAN_ReceiveSequenceData()
|
9 | {
|
10 | //If there is data to read...
|
11 | if (CanRX_Head != CanRX_Tail)
|
12 | {
|
13 | //uint8_t Temp_CanRX_Head = CanRX_Head;
|
14 | uint8_t Status = 0;
|
15 |
|
16 | //First test if the received ID is within the data-ID range
|
17 | if (CanRxMessage[CanRX_Head].StdId >= CAN_DATATYPE_LOWEST_ID && CanRxMessage[CanRX_Head].StdId <= CAN_DATATYPE_HIGHEST_ID)
|
18 | {
|
19 | [...]
|
20 | }
|
21 | else
|
22 | {
|
23 | for (int i = 0; i < ReceiveSequenceIDsCount; i++)
|
24 | {
|
25 | if (CanRxMessage[CanRX_Head].StdId == ReceiveSequenceIDs[i])
|
26 | {
|
27 | Status = 1; //Mark as valid sequence ID
|
28 |
|
29 | //Reset data if header is received again
|
30 | int BufferID = 0;
|
31 | BufferID = CAN_ReceiveSequence_SearchBuffer(ReceiveSequenceIDs[i]);
|
32 |
|
33 | if (BufferID >= 0)
|
34 | {
|
35 | CAN_ReceiveSequence_Reset(BufferID);
|
36 | }
|
37 | }
|
38 | }
|
39 | }
|
40 | }
|
41 | }
|
42 |
|
43 | //Search the buffer that is used
|
44 | int CAN_ReceiveSequence_SearchBuffer(uint8_t CAN_StartID)
|
45 | {
|
46 | for (int i = 0; i < MAX_DATA_RECEIVE_SEQUENCES; i++)
|
47 | {
|
48 | if (ReceiveSequence[i].CAN_StartID == CAN_StartID)
|
49 | {
|
50 | return i;
|
51 | }
|
52 | }
|
53 |
|
54 | return -1;
|
55 | }
|
Zum Problem: Nehmen wir an CanRX_Head ist 0 und CanRX_Tail ist 1, dann
ist die erste if-Bedingung erfüllt. Nehmen wir weiterhin an dass die
zweite if Bedingung nicht erfüllt wird, also springt das Programm in den
else-Zweig.
Spring das Programm nun in die Funktion
CAN_ReceiveSequence_SearchBuffer() ändert sich CanRX_Head zu 135. Und
das sobald er auf die for() schleife springt. Kopiere ich den kram aus
der Funktion raus, gehts. Dann passiert das gleiche (selber Wert von
CanRX_Head) in der nächsten Funktion in die er springt.
Daher gehe ich davon aus dass der Speicher überläuft - warum auch immer.
Ich bin bei 4% RAM-Auslastung.
Jetzt habe ich mir den Spaß gemacht und die beiden Variablen in der
Initialisierung gedreht
1 | volatile int CanRX_Tail = 0;
|
2 | volatile int CanRX_Head = 0;
|
Und siehe da, es geht. Ohne dass jetzt CanRX_Tail betroffen ist. Zuvor
habe ich mal ein uin8_t draus gemacht aus beiden Variablen, selbes
Problem. Nur das drehen der Reihenfolge brachte jetzt "Besserung".
Warum? Was ist da passiert? Kann mir das jemand erklären?
IC ist ein STM32F103RB auf einem Olimex Board.
Programmiert mit VisualGDB (GCC 7.2.0 / GDB 8.0.1)
Edit: Okay, das Problem bleibt, nur anders rum. CanRX_Tail wird jetzt
immer auf 0 gesetzt. Selbe stelle, selber Sprung in die Funktion