AndronikosKostas / AndronikosKostas/Koenigsegg-Application
Test
- 主要语言
- C
- 星标
- 0
- 派生
- 0
- PR 合并指标
- 30 天内没有已合并 PR
描述
### CubeMX tasks
- [x] Normal CAN modules share the same message RAM, so find how many words are needed for the CAN1 to work properly. Use this number as an offset for the CAN2. Check [here](https://controllerstech.com/fdcan-normal-mode-stm32/).
**Update:** (1 x extended filter x 10 words) + (16 x Rx Fifo elements x 18 words) + (16 x Tx Fifo elements x 18 words) = 586 words
- [x] Check the clock calibration (we had it disabled).
**Update**: We probably don't need it. Just leave it disabled.
### Main Tasks
- [x] Integrate the CAN files on the new repo (there are not all the ECSS functions enabled yet)
- [x] Check functions like `HAL_FDCAN_ErrorCallback()`, `HAL_FDCAN_ActivateNotification((&hcan, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_ERROR)`...The last currently enables only the FDCAN_IE_RF0NE , FDCAN_IE_RF1NE flags...we should have more here.
**Update:**
* Receive: no need for error handling. No response will automatically mean NACK.
* Transmit: There is a check in the driver level. If we need to pass it to a higher layer the logic will probably need to change. Again though, no response will mean NACK.
- [x] The `portYIELD_FROM_ISR(xHigherPriorityTaskWoken);` inside the callback.
**Update:** Added
- [x] Data Handling Logic: incoming FIFO contains the pointer that points to the buffer that holds the payload data. Can hold data up to num of items.
```struct incomingFIFO {
uint8_t* buffer;
uint32_t NOfItems;
uint32_t lastItemPointer;
incomingFIFO() : buffer(nullptr), NOfItems(0), lastItemPointer(0) {}
incomingFIFO(uint8_t* externalBuffer, uint32_t NOfItems) : buffer(externalBuffer), NOfItems(NOfItems), lastItemPointer(0) {}
};
```
```
newFrame.pointerToData = &incomingFIFO.buffer[CANMessageSize * (incomingFIFO.lastItemPointer)];
if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &newFrame.header, newFrame.pointerToData) != HAL_OK) {
/* Reception Error */
Error_Handler();
}
```
Inside the callback, we increment the lastItemPointer to point to a different location on the local buffer to accommodate each Frame payload of 8 bytes.
`CAN::Frame newFrame;` holds exactly what you need to find the CAN messages (Main or redundant CAN, pointer to data HAL Header)
`xQueueSendToBackFromISR(canGatekeeperTask->incomingFrameQueue, &newFrame, NULL);` Then you send the data other canGatekeeperTask.
- [x] Address the scenario of a full queue.
**Update:**
Changed tx logic. Send functions are changed to **blocking** to ensure no array is overflowing (check TPProtocol at the createCANTPMessage). As for the RX, there is no issue with the queues because no one can send if he has not received ACK, so this delay will prevent RX queue from overflowing. In case something goes wrong, the message will just be ignored.
- [x] Can the packets of one message be mixed with the packets of another message?
**Update:**
No. The next multi-frame message can only start after the ACK is received (protected by a mutex).
- [x] Store CAN messages in the eMMC
**Update:** Every CAN packet is stored in the eMMC and a handler is put in a queue and pushed to the Application layer. Handling is then done by the application layer.
- [x] Find the Application Error Codes and see if we need them.
**Update:**
- [x] Error Reporting on COMMS CAN. Check maybe the: `HAL_StatusTypeDef HAL_FDCAN_GetProtocolStatus(const FDCAN_HandleTypeDef *hfdcan,
FDCAN_ProtocolStatusTypeDef *ProtocolStatus);`
- [x] Error Reporting on OBC. Check MCAN_Errors.
**Update:**
The OBC CAN bud enters an unrecoverable state after the COMMS is powered off. The only way we found to make it work again is to reinitialize the CAN peripheraal. COMMS recovers just fine so reinitializing was not necessary.
- [x] So what happens when a frame is received with order number 21 while we were expecting the 19th to arrive? Is that possible?
**Update**: Yes but we don't care for the order of the consecutive frames but we do care about receiving the first and and the final frame.
- [ ] Scenarios that the receiver has to send to NACK to the sender and when the sender has to retransmit the frame. NACK: when you have received the first and the final but you either received more or fewer frames compared to the length of the CAN packet (max size of 1024 bytes (without metadata, actual info). Sender: if the sender does not get an ACK from the receiver after a specific amount of time. The receiver can send two different types of NACKs, one for the wrong size of data (application NACK) and another one for CAN protocol errors. Find how to test that.
**Update:** The NACK would be useful only for efficiency reasons - the OBC for example will not need to wait for the timeout to end in blocking mode. It is not ideal, but we will use the timeout of 1s as a baseline and the capability of having this as a variable in the database.
**Note**
The first frame has only metadata and all the other frames (both consecutive and final) have 6 bytes of actual info and 2 bytes of metadata (as for the consecutive: the first one is the frame type and the second one is frame number while the final has as the second one the number of data in bytes).
**Packet:** 1024 bytes of usable info
**Frame:** CAN header + 8 bytes of usable info
**Frame Payload:** 8 bytes of usable info
**Message:** whatever we send
- [x] Find where the source address is stored in the CAN frame. COMMS and OBC will communicate with the addressing design that is currently implemented in the application layer (we ran a test where OBC sends to ACDS ID and COMMS did not listen). As for the ADCS we will ensure that will not listen to messages that are not for itself by configuring its internal filters correctly.
**Update:**
The frame ID now does not hold any metadata about the message. The message ID is the first byte of the packet.
- [x] Address the scenario of having an incoming message and a sent message at the same time. Maybe create a mutex for that. Send large CAN messages (multiple packets) to see if we have issues.
**Update:**
Tested with simultaneous rx/tx. It can handle it just fine.
- [x] Use correctly the Logger. When it is an error write LOG_ERROR. For example:
```
// Message not received correctly
LOG_DEBUG << "DROPPED CAN MESSAGE";
```
### Test Tasks
- [x] Verify that errors are displayed on **both boards** by simulating a CAN bus failure, such as disconnecting the power supply to one of the boards.
- [ ] Verify the functionality of the CANTransactionHandler, particularly the mutex mechanism, by attempting to send random messages to the CAN bus simultaneously from two different tasks.
- [x] Ensure that sending large messages does not cause any issues. The driver supports 1024 bytes, with the first byte reserved for the message type (e.g., TC, TM, etc.). Perform this test on both boards and ideally, send a message **exceeding 1024 bytes** to verify that it is correctly segmented into smaller chunks of 1024 bytes, which the driver can process.
- [x] Test the old code of COMMS with the updated code of the OBC
Findings: The FIFO 1 does not work in the old repo.
**Update:**
- [x] Test if the processing multiple frame function works. For example, try to send packets with more than 64 bytes.
**Update** The function is working.
- [x] Ensure that the CAN BUS remains operational even after a crash occurs on either the OBC or COMMS system.
**Update:** Correct use of MCAN_Initialize() on the OBC side.
- [x] OBC may send zeros or COMMS have the issue. Check it with the oscilloscope or with the CAN PCBs.
**Update:**
Found a way to ignore these frames from the COMMS.
{01 10 11}: First two bits of the first byte of the payload on a multi-frame packet, so after running some tests we found that if these bits are equal to 00 we have an error so we drop them.
The single frames will not have 00 in the second byte, so that's why we have the following code in the ISR
```
if (newFrame.pointerToData[0] == 0 && newFrame.pointerToData[1] == 0) {
__NOP();
if (newFrame.bus->Instance == FDCAN1) {
__NOP();
} else if (newFrame.bus->Instance == FDCAN2) {
__NOP();
}
}
```
### CAN BUS Errors
- Bit Error [Transmitter]
- Bit Stuffing Error [Receiver]
- Form Error [Receiver]
- ACK Error (Acknowledgement) [Transmitter]
The module (CAN controller) handles the error autonomously, typically by retransmitting the message (even if it is on Error Active State or Error Passive State, not when it is one Bus-off state)
- CRC Error (Cyclic Redundancy Check) [Receiver]
**Error Handling**
After detecting one of the above-described errors an error frame will be transmitted immediately. The error frame consists of 2 different fields. The first field is given by the superposition of error flags contributed from different nodes. The second field is the error delimiter. A node detecting an error condition signals this by transmission of an active error flag. The error flag's form violates the rule of bit stuffing or destroys the bit field requiring a fixed form. As a consequence, all other nodes also detect an error condition and likewise start transmission of an error flag. So the sequence of dominant bits, which actually can be monitored on the bus, results from a superposition of different error flags transmitted by individual nodes. The total length of this sequence varies between a minimum of 6 and a maximum of 12 bits. Passive error flags initiated by a transmitter cause errors at the receivers when they start in a frame field which is encoded by the method of bit stuffing, because they then lead to stuff errors detected by the receivers. This requires, however, that such an error flag does not start during arbitration and another node continues transmitting, or that it starts very few bits before the end of the CRC sequence and the last bits of the CRC sequence happen to be all recessive. Passive error flags initiated by receivers are not able to prevail in any activity on the bus line. Therefore, "error passive" receivers always have to wait 6 subsequent equal bits after detecting an error condition, until they have completed their error flag. The error delimiter consists of 8 recessive bits. After transmission of an error flag, each node sends recessive bits and monitors the bus until it detects a recessive bit. It then starts transmitting 7 more recessive bits.
The error handling happens in the following order:
1. Error detected.
2. An error frame will be transmitted.
3. The message will be discarded by every network node.
4. The error counters of every bus node are incremented.
5. The message transmission will be repeated.
#### Error Counters
- Transmit Error Counter (TEC)
Increases for transmission errors.
- Receive Error Counter (REC)
Increases for reception errors.
**Error States - Error Limitation**
- Error Active: Normal operation (errors below threshold).
- Error Passive: Node communicates with restrictions (errors exceed a threshold).
- Bus Off: Node is disconnected from the bus (excessive errors).
In this case, the CAN module **must be reset via software somehow**, as switching to the redundant bus will not suffice; the issue could recur on the redundant bus, leading to a deadlock.
### BUS Switch Over
**AcubeSat Logic**
_Το OBC αποστέλλει μηνύματα Ping σε κάϑε κόμβο με την ίδια περίοδο THB = 5 δευτερολέπτων, τα οποία απαιτούν πάντηση Pong από τον εκάστοτε κόμβο. Η πρακτική αυτή βοηϑά στη διευκρίνιση της αστοχία στις γραμμές TX ή RX.
• Σε περίπτωση που δεν ληφθεί μήνυμα καρδιακού παλμού ή απάντηση σε ένα μήνυμα Ping, από όλους τους κόμβους σε παράϑυρο TT = 30 δευτερολέπτων, το OBC ϑεωρεί ότι ο δίαυλος απέτυχε και αποστέλλει μήνυμα Bus Switchover το οποίο ανακοινώνει τον πλέον εν λειτουργία δίαυλο. Το μήνυμα αυτό
μεταδίδεται και στους δύο κόμβους.
• Για να αποφευχϑούν περιπτώσεις που κάποιος από τους κόμβους βρίσκεται εκτός συγχρονισμού όσον αφορά τον ενεργό δίαυλο, το OBC περιοδικά ανακοινώνει την παράμετρο που περιλαμβάνει την πληροφορία. Η περίοδος αυτής της ανακοίνωσης δεν έχει αποφασιστεί ακόμα._
**PeakSat Logic**
I think it is better for the COMMS to listen to both channels.
### References
Note: On a CAN bus, a frame is the basic unit of messaging. For a classic CAN bus, a frame consists of an 11-bit identifier along with an 8-byte message payload. For CAN FD, a frame is labelled with a 29-bit identifier and carries a 64-byte message payload.
```
* @example @code
* uint32_t id = 0x4; // Specify the sending Node ID.
* etl::vector data = {0,1,2,3,4,5,6,7}; // Specify an array of data, up to 64 bytes.
* CAN::Frame message = {id, data}; // Create a CAN::Frame object.
* CAN::Driver::send(message, Application::Main); // Use the included send function to send a message on the Main bus.
* @endcode
```
[CAN-TP Protocol](https://piembsystech.com/can-tp-protocol/)
https://controllerstech.com/stm32-fdcan-in-loopback-mode/
[STM32 CAN Application Note](https://www.st.com/resource/en/application_note/an5348-introduction-to-fdcan-peripherals-for-stm32-mcus-stmicroelectronics.pdf)
[bit timing parameters](http://bittiming.can-wiki.info/)
[sos](https://istarik.ru/blog/stm32/159.html)
[thesis](https://ikee.lib.auth.gr/record/354365/files/Keremidis%20Antonios.pdf)
[CAN Wiki - Acubesat](https://gitlab.com/acubesat/software-management/-/wikis/CAN-Wiki)
[CAN Bus Errors Exmplained](https://www.csselectronics.com/pages/can-bus-errors-intro-tutorial)
[An Introduction to CAN](https://caxapa.ru/thumbs/721101/CAN.pdf)
### Questions
- single frame buffer only 512 bytes? The single frame will be less than 1024
- eMMCPacketTailPointer += 2; Each packet has a length of 1024 but the memory handles 512 bytes.
贡献指南
这个仓库没有索引到贡献指南
评估
这个 Issue 还没有评估数据。